InfiniTimeOrg / InfiniTime

Firmware for Pinetime smartwatch written in C++ and based on FreeRTOS
GNU General Public License v3.0
2.64k stars 903 forks source link

lv_img_conv_py: minimal python port of node module #1863

Closed NeroBurner closed 8 months ago

NeroBurner commented 9 months ago

Create a minimal python port of the node.js module lv_img_conv. Only the currently in use color formats CF_INDEXED_1_BIT and CF_TRUE_COLOR_ALPHA are implemented.

Output only as binary with format ARGB8565_RBSWAP (and ARGB8888 for debugging).

This is enough to create the resources-1.13.0.zip.

In the simulator the pinecone in Casio is visible, and the navigation symbol is visible as well in the simulator when the resource zip is loaded

The new lv_img_conv.py script needs python3-pil python module as runtime dependency. The runtime dependency is added to the docker container image.

InfiniSim_2023-09-21_230253_casio InfiniSim_2023-09-21_230304_nav

github-actions[bot] commented 9 months ago
Build size and comparison to main: Section Size Difference
text 376784B -16B
data 940B 0B
bss 63420B 0B
NeroBurner commented 9 months ago

I've fixed part of the differences between the original nodejs script and the python based port. It was the usage of round() in the helper function classify_pixel(). Python3 implements "propper" "banker's rounding" by rounding to the nearest even number. Javascript rounds to the nearest integer as we've learned in school. To have the same output as the original JavaScript implementation add a custom rounding function, which does "school" rounding (to the nearest integer).


After that there is still a difference between the binaries. Therefore I implemented the ARGB8888 binary-output-format to compare the rgba values read by the scripts from the png.

./lv_img_conv.js pine_logo.png --force --output-file pine_small_js_8888.bin --color-format CF_TRUE_COLOR_ALPHA --output-format bin --binary-format ARGB8888
xxd pine_small_js_8888.bin > pine_small_js_8888.bin.hex

Same with the current python port

python3 lv_img_conv.py  --force --output-file pine_small_js_8888.bin --color-format CF_TRUE_COLOR_ALPHA --output-format bin --binary-format ARGB8888
xxd pine_small_py_8888.bin > pine_small_py_8888.bin.hex

Uploaded the hex files for comparison:

Comparing the two hex files shows there are differences in how the PNG file is read in (because ARGB8888 just outputs the read rgba values) Screenshot_20230928_222816

The first different pixel is at x==10, y==0. Looking at that pixel nodejs returns rgba=[19, 19, 19, 26] compared to python rgba=[20, 20, 20, 26]

Opened the pine-logo.png in Gimp and it shows the same values as the python script

gimp rgba color values

This off-by-one input differences results in some differences in the normal ARGB8565_RBSWAP output binary format as well. As the difference is small and I believe the value from Gimp I'd keep the python script as it is (as I don't know how to "fix" it to be like the node input)


The only difference for the navigation0.png and navigation1.png files is the hard coded color palette. The remaining bits are the same for nodejs and python implementation

NeroBurner commented 8 months ago

code review incorporated, squashed and pushed, gonna merge as soon as possible

NeroBurner commented 8 months ago

User MorsMortium informed me on Matrix, that there is a full port available at https://github.com/W-Mai/lvgl_image_converter

Still using this minimum port, and if we need more we could either switch to the full port or use the full port as inspiration to implement the newly needed parts