FrogFS¶
frogfs is a read-only filesystem for packing a directory tree of files into a single "blob" which can be distributed easily or built into a firmware. It is suitable for packaging XML files into your app. See the intro to XML in LVGL if you are interested in using XML.
A copy of the frogfs source is inside LVGL. It has been reduced to a subset of the original functionality for simple loading of blobs in LVGL.
Create a frogfs blob¶
You can create a frogfs blob for use in LVGL by using the upstream
frogfs project. Get it from GitHub
with git clone
.
git clone https://github.com/jkent/frogfs
cd frogfs
Create a frogfs.yaml
file inside.
Here is the minimum required content of the file.
files
in this case is a directory next to frogfs.yaml
that has all the files you want to include in the blob.
The directory structure will be preserved.
collect:
- files/*
rm -rf build_dir
mkdir build_dir
python3 tools/mkfrogfs.py frogfs.yaml build_dir frogfs.bin
If it succeeds, you will have frogfs.bin
which is the
filesystem blob to embed in your LVGL application. One way to get it
in your C app is to convert the binary file to a C array.
echo const > frogfs_bin.c
xxd -i frogfs.bin >> frogfs_bin.c
This method will create a C file with two global variables called
frogfs_bin
and frogfs_bin_len
which can be declared in other
C files like:
extern const unsigned char frogfs_bin[];
extern unsigned int frogfs_bin_len;
See the frogfs README.md
for info about using CMake to automate
blob builds.
Usage in LVGL¶
Set LV_USE_FS_FROGFS
to 1
in your lv_conf.h
. Set
LV_FS_FROGFS_LETTER
to a letter like 'F'
.
extern const unsigned char frogfs_bin[];
lv_fs_frogfs_register_blob(frogfs_bin, "main_blob"); /* returns LV_RESULT_OK if the blob is ok */
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, "F:main_blob/my_image.png"); /* the blob is specified by the path prefix */
extern const unsigned char frogfs_bin_2[];
lv_fs_frogfs_register_blob(frogfs_bin_2, "another_blob");
lv_obj_t * img2 = lv_image_create(lv_screen_active());
lv_image_set_src(img2, "F:another_blob/my_image.png");
lv_obj_delete(img);
lv_fs_frogfs_unregister_blob("main_blob"); /* optional ability to unregister blobs */
If you have a frogfs blob stored in a different filesystem
accessible to LVGL, you can load the blob into ram and register it from there.
Ensure there is enough ram for the blob. Driver letter 'A'
in this example
could be an SD card or an OS filesystem, etc.
See the other filesystems available in LVGL.
uint32_t blob_size;
lv_fs_path_get_size("A:blobs/new_blob.bin", &blob_size);
void * blob = malloc(blob_size);
lv_fs_load_to_buf(blob, blob_size, "A:blobs/new_blob.bin");
lv_fs_frogfs_register_blob(blob, "new_blob");
Compression and Minification¶
The frogfs in LVGL does not have the decompression support that the upstream frogfs has. Typically, asset formats like PNG are already compressed.
Compared to image assets, XML files have a relatively small size even when the described UI is complex. Regardless, the XML file size can be reduced through so-called "minification". In the simplest case, it means removing all comments and insignificant whitespace. This is a form of compression that does not require a decompression step. The only drawback is that the incorrect line number relative to the un-minified version will be logged if there is a parse failure. See the intro to XML in LVGL.
You can prepare a frogfs blob with minified XML files. In your frogfs
clone directory make a copy of tools/transform-html-minifier.js
called
transform-xml-minifier.js
and set the const options = { ... };
to the below. Not all the original aggressive HTML minifications are standard
XML, so this is a subset that preserves standard XML syntax.
const options = {
keepClosingSlash: true,
collapseWhitespace: true,
removeComments: true
};
You can then add the filter to your frogfs.yaml
. Minified versions of the
XML files in the files/
directory in this example will be put in the blob.
collect:
- files/*
filter:
'*.xml':
- xml-minifier
You can create custom filters very easily. See the frogfs README.md
for
more info. Any Python or JavaScript file in
tools
that begins with transform-
will be treated as a possible
transform which will be passed the file to minify via stdin
and the
minified output is expected from stdout
. The filter-name
part of
transform-filter-name.py
shall be given in your frogfs.yaml
filter
list for certain types or all types of files.