lvglimg
Decode LVGL .bin image files to PNG — including v8 + v9 headers and
NONE / RLE / LZ4 / LZ4_HC compression.
LVGL's own LVGLImage.py is a one-way encoder: it can write compressed bins,
but from_bin ignores the flags field and cannot decompress them back. lvglimg
fills that gap, producing pixel-accurate PNGs from real device asset bins.
- Self-contained — depends only on Pillow + lz4. No LVGL source tree, no
LVGLImage.pyon disk. - All v9 color formats — L8, indexed (I1/2/4/8), alpha-only (A1/2/4/8), RGB565, RGB888, ARGB8888, XRGB8888, ARGB8565, RGB565A8.
- v8 true-color —
TRUE_COLOR/TRUE_COLOR_ALPHA(BGRA). - CLI + library — use it on the command line or import the decoder.
Install
pip install lvglimg
CLI
# single file → sibling .png
lvglimg image.bin
# explicit output path
lvglimg image.bin out.png
# batch a directory (recursive) → out/<same subdirs>/*.png
lvglimg assets/ out/
# default: a sibling '<input>_preview/' dir next to the input
lvglimg assets/ # → assets_preview/ (sibling of assets/)
# finds assets/*.bin AND assets/**/<sub>/*.bin; mirrors the subdir layout
# in the output dir (avoids name collisions across folders)
$ lvglimg --version
lvglimg 0.0.1
Library
from lvglimg.decoder import decode, decode_file
# from bytes
img = decode(bin_bytes)
img.save("out.png")
# from a file path
img = decode_file("image.bin")
decode() returns a PIL.Image.Image (mode RGBA, RGB, or L depending on
the source format), so you can inspect, transform, or re-encode it however you
like.
How it works
The LVGL v9 on-disk layout is a 12-byte header followed by a body that may be a compress block:
header: magic(0x19) cf flags w h stride reserved
body : [method u32][clen u32][raw_len u32][payload] # iff flags & 0x08
lvglimg reads the flags field to detect compression (the same bit LVGL sets
when encoding), decompresses RLE / LZ4 / LZ4_HC, then unpacks pixels to RGBA
using the same channel layout and bit_extend upscaling LVGL renders on-device —
so output matches the display. v8 files (no magic byte) are dispatched to the
4-byte bitfield header path.
Note — v8 support covers the true-color BGRA layouts (
cf=4/5) used by miwear assets. Other legacy v8 formats raise a clear error rather than silently producing garbage.
Development
pip install -e ".[dev]"
pytest # 14 tests, runs against src/ with no install
ruff check src tests main.py
mypy
./main.py image.bin # run from source, no install
License
This project is licensed under the Apache License, Version 2.0. See LICENSE or https://www.apache.org/licenses/LICENSE-2.0 for the full text.
Release files for lvglimg 0.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lvglimg-0.0.2.tar.gz | 16.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lvglimg-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.9 kB
Release files / lvglimg-0.0.2.tar.gz
| Download URL | lvglimg-0.0.2.tar.gz |
|---|---|
| Size | 16.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
77796cdd8d91d965914143c6166f8db93ee814abea98872052ccb4ea6e57219e
|
|
BLAKE2b-256 checksum How to use checksums |
c6386bf5f00b5dccaf1b9ec71d9f5bf1822a019ad02859be9f32813cb774f8ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.12
|
Release files / lvglimg-0.0.2-py3-none-any.whl
| Download URL | lvglimg-0.0.2-py3-none-any.whl |
|---|---|
| Size | 13.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3dbbab01c2a2dcf16b3d87307f9394711f84aee55a5d4e92fa83f0a2245c2047
|
|
BLAKE2b-256 checksum How to use checksums |
517b81d65807b8fdcfe40256b4be7448ca5d06a80b4c7e865e0871d52af89d4f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.12
|