Skip to content

encode_png: RGB565 framebuffer to PNG - #36

Merged
bdbarnett merged 3 commits into
mainfrom
encode_png
Oct 6, 2026
Merged

bdbarnett merged 3 commits into
mainfrom
encode_png

Conversation

@bdbarnett

@bdbarnett bdbarnett commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

A PNG encoder for RGB565 framebuffers (also RGB888 and GS8), pygraphics.encode_png(fb, width=None, height=None, format=None): C in src/gfx_png.c (deflate via uzlib) with a pure-Python fallback in lib/pygraphics/_png.py. It's half of the Roku companion feature written on 2026-09-30, and Brad wants it for the casting work (2026-10-06). The examples half is PyDevices/pydevices-examples#158.

CI fixes (2026-10-06):

  • _png.py is now in pygraphics.toml, regenerated with the publisher's generator; its --check passes.
  • _png.py is now in tools/compare_graphics.py's staged files. Without it the MicroPython job failed: no module named 'pygraphics_py._png'.
  • Import order fixed (3 ruff errors).

Tested locally, 2026-10-06:

  • ruff check lib tests passes, and CPython unittest is OK.
  • On a unix build with this branch as a user C module (implementation() == native_cmod): test_area, test_subclass, test_parity (45 public names), compare_graphics_run (385 checks) and compare_framebuf_mp all pass.
  • A 40x30 four-colour RGB565 frame encoded by the native module and by the pure-Python fallback both decode in Pillow to exactly red, green, blue and white.

Known limit: MicroPython's built-in framebuf.FrameBuffer isn't recognised as a framebuffer, only pygraphics.FrameBuffer is, so pass width and height with it (that works, and is tested above).

Adds encode_png() for encoding RGB565 framebuffers to PNG byte strings,
used by roku_companion's frame server to stream display output to Roku TVs.

C implementation (src/gfx_png.c):
- Minimal PNG encoder: IHDR, IDAT (deflate via uzlib), IEND
- RGB565 to RGB888 conversion during encoding
- Exposed as pygraphics.encode_png() via MicroPython bindings

Pure-Python fallback (lib/pygraphics/_png.py):
- zlib-based PNG encoder for CPython and environments without the C module
- Same API: encode_png(buffer, width, height, format)

Build system:
- micropython.mk, micropython.cmake, circuitpython.mk updated
- qstr definitions for encode_png added

Tests:
- test_files.py updated with encode_png coverage
@bdbarnett
bdbarnett marked this pull request as ready for review October 6, 2026 07:07
…_png and FrameBuffer.to_png, MicroPython gets FrameBuffer.to_png, and every saver writes PNG for a .png name or RGB888 through one shared rule (gfx_png_wanted)
@bdbarnett
bdbarnett merged commit a8875d8 into main Oct 6, 2026
@bdbarnett
bdbarnett deleted the encode_png branch October 6, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant