πΌοΈ Grayscale Rendering Boost β Release Notes
What changed: a big improvement in how photos and images are shown on your e-reader's grayscale display β especially screensaver / sleep screen images and book covers on the X4/X3 panels.
π Screensaver Fixes β Release Notes
What changed: two small but noticeable "quality of life" fixes for the
screensaver β waking it up behaves the way it should, and the shuffle doesn't
keep showing the same image first.
π No more refresh when waking the screensaver
Previously, if your power button was set to "refresh screen", waking the screensaver with a single press could also run a manual screen refresh β a flicker you didn't ask for.
π Summary
- β Real contrast, not washed-out β images now look closer to what you see on a computer, instead of pale and flat.
- β Safer, crash-free rendering β rewritten the math with explicit 16-bit variables and guarded buffers (no more negative-index writes that can corrupt memory on ESP32).
- β One shared engine β the BMP reader, JPEG/PNG covers and screensaver/sleep all use the same tuned settings, so results are consistent everywhere an image appears.
- β Faster startup β the gamma correction table is prepared once at boot.
π Under the hood (brief)
The e-ink display uses only 4 shades of gray. Old code pushed pixels through with flat quantization, which made dark images lose their shadows and highlights look washed out.
Now the pipeline is:
- ποΈ Gamma correction β lifts midtones so the 4 gray levels separate cleanly (tuned to
gamma 1.5). - βοΈ Empirical thresholds
50 / 120 / 200β chosen specifically for the X4 panel, so each shade lands where the eye expects it. - πΊοΈ Error diffusion dithering β Atkinson (and the serial Floyd-Steinberg fallback) spreads the "error" of each quantized pixel to its neighbors, producing smooth gradients instead of banding.
- π‘οΈ Overflow-safe math β everything runs in
int16_twith clamped values and offset, bounds-checked buffers. No floats in the hot loop, so it's both safe and fast on the ESP32-C3. - π§΅ Clean row edges β horizontal error is dropped at the end of each row, preventing vertical streak artifacts.
π‘οΈ Stability & safety improvements
- All per-pixel math in
int16_tβ far within range for X4-sized rows. - Error buffers allocated once per image and reused across rows β no memory churn, no per-line allocations.
- No negative index access β full audit confirms the buffers never go before index 0 (would otherwise corrupt memory on ESP32).
- Lazy-init guard on the gamma table β even if a startup hook is skipped, images can never render as a blank black screen.
π Files changed
- π
lib/GfxRenderer/DitheringConfig.hβ new shared configuration lib/GfxRenderer/BitmapHelpers.{h,cpp}β ditherers + quantizationlib/GfxRenderer/Bitmap.cpplib/JpegToBmpConverter/JpegToBmpConverter.cpplib/PngToBmpConverter/PngToBmpConverter.cppsrc/main.cppβ gamma LUT init at boot