I've been working on several e-paper display projects recently (monochrome, tri-color, and full-color variants) and encountered a common challenge: converting images for different displays. Existing tools couldn't handle my specific needs like:
Palette customization for monochrome/limited-color displays
Real-time comparison of different dithering algorithms
Direct array output for C/Python embedded systems
After struggling with manual Python + Pillow scripting, I built img2lcd - a pure web-based solution that provides:
love that project and it's a shame that you got so little feedback here. Seeing the results of these different dithering algorithms side by side and being able to download a ready to use piece if code is just great.
For my own project, I will implement my own algorithm for ESP32, because I need dynamic conversion, but this has been a great inspiration and helped me choose my preference, which is Atkinson.
After having read up a bit about that algorithm, I wonder how you implemented it for >2 colors, particularly for 3-color B/W/R, as the original only needs to decide between B and W. I tried my own approach (well, frankly, I let chatgpt do the heavy lifting), and got a bit different results than yours, so would love to see your algorithm for that.
Thank you for your kind words! The img2lcd project started as my exploration of dithering algorithms, and it¡¯s still evolving. I¡¯m glad you found the side-by-side comparisons useful.
Color Matching: Euclidean distance in RGB space determines the closest palette color for each pixel, avoiding simple luminance thresholding.
Value Clamping: Post-error accumulation values are clamped to 0-255 instead of redistributing overflows ¨C this might explain our differing results.
If you can share specific test images or code excerpts where our outputs diverge, I¡¯d be happy to analyze them after returning from my trip (currently away from my codebase).
thanks for the explanation. As mentioned, I chose not too dig into these algorithms as deep as you did, and let chatgpt do most of the implementation. As so often, it just needed a more precise prompt and came up with a three-color implementation that did things just fine for my purposes. If you want to have a look, I just put the project on github:
The Atkinson dithering happens in this function, which is a callback from PNG decoding, and thus needs to do the dithering on a line-by-line basis with a three line buffer:
Anyways, thanks again for your project, it gave me the inspiration to include a dithering option in this project.