Two related findings from the jpegio plan (displayif issue linked in pydevices/docs/jpegio-vision.md).
1. The CircuitPython disable was a config mismatch, not a symbol clash. lv_conf.h:732 sets LV_USE_TJPGD 0 under LV_CIRCUITPYTHON_BUILD and lvgl-circuitpython/circuitpython.mk:31 filters LVGL's tjpgd.c out because CP already compiles lib/tjpgd/src/tjpgd.c (py/circuitpy_defns.mk:964) with "incompatible tjpgdcnf". Both are TJpgDec R0.03; the incompatibility is tjpgdcnf.h: CP builds JD_FORMAT 1 (RGB565) + JD_USE_SCALE 1, LVGL's vendored copy JD_FORMAT 0 (RGB888) + no scaling — and lv_tjpgd.c:207 hardcodes LV_COLOR_FORMAT_RGB888 regardless. Linking LVGL's decoder against CP's copy today would label RGB565 pixels RGB888.
Fix: (a) on CP builds set LV_USE_TJPGD 1, point lv_tjpgd.c's #include "tjpgd.h" at CP's lib/tjpgd/src (include path), keep LVGL's tjpgd.c excluded — one copy, CP's config; (b) make lv_tjpgd.c honour JD_FORMAT (RGB565 header + copy when built for it) — ~10 lines, upstreamable. Then remove the lv_tjpgd_init/lv_tjpgd_deinit target exceptions for CircuitPython in binding/api_policy.json, runtime_exports.py, docs/generator-architecture.md:69 and the smoke-test assertion at tools/test_lvgl_smoke.py:504. The org-wide TJpgDec config becomes CP's (RGB565 + scale); the MicroPython jpegio module links against LVGL's copy when lvgl is in the build.
2. is_jpg() at lv_tjpgd.c:302 requires FF D8 FF E0 00 10 "JFIF" in bytes 0..9. Measured UVC MJPEG frames (Logitech C920e) open SOI → DQT → SOF0 → DHT… with the APP0/JFIF segment after the Huffman tables, so LVGL's image decoder rejects every webcam frame before TJpgDec sees it. SOI alone is the correct sniff; jd_prepare judges the rest. Upstream LVGL bug; worth reporting there with the marker sequence (this org's emissary charter is CircuitPython-only, so that report is a human's).
Two related findings from the jpegio plan (displayif issue linked in
pydevices/docs/jpegio-vision.md).1. The CircuitPython disable was a config mismatch, not a symbol clash.
lv_conf.h:732setsLV_USE_TJPGD 0underLV_CIRCUITPYTHON_BUILDandlvgl-circuitpython/circuitpython.mk:31filters LVGL'stjpgd.cout because CP already compileslib/tjpgd/src/tjpgd.c(py/circuitpy_defns.mk:964) with "incompatible tjpgdcnf". Both are TJpgDec R0.03; the incompatibility istjpgdcnf.h: CP buildsJD_FORMAT 1(RGB565) +JD_USE_SCALE 1, LVGL's vendored copyJD_FORMAT 0(RGB888) + no scaling — andlv_tjpgd.c:207hardcodesLV_COLOR_FORMAT_RGB888regardless. Linking LVGL's decoder against CP's copy today would label RGB565 pixels RGB888.Fix: (a) on CP builds set
LV_USE_TJPGD 1, pointlv_tjpgd.c's#include "tjpgd.h"at CP'slib/tjpgd/src(include path), keep LVGL'stjpgd.cexcluded — one copy, CP's config; (b) makelv_tjpgd.chonourJD_FORMAT(RGB565 header + copy when built for it) — ~10 lines, upstreamable. Then remove thelv_tjpgd_init/lv_tjpgd_deinittarget exceptions for CircuitPython inbinding/api_policy.json,runtime_exports.py,docs/generator-architecture.md:69and the smoke-test assertion attools/test_lvgl_smoke.py:504. The org-wide TJpgDec config becomes CP's (RGB565 + scale); the MicroPythonjpegiomodule links against LVGL's copy when lvgl is in the build.2.
is_jpg()atlv_tjpgd.c:302requiresFF D8 FF E0 00 10 "JFIF"in bytes 0..9. Measured UVC MJPEG frames (Logitech C920e) openSOI → DQT → SOF0 → DHT…with the APP0/JFIF segment after the Huffman tables, so LVGL's image decoder rejects every webcam frame before TJpgDec sees it. SOI alone is the correct sniff;jd_preparejudges the rest. Upstream LVGL bug; worth reporting there with the marker sequence (this org's emissary charter is CircuitPython-only, so that report is a human's).