Want to display a PNG file on a display attached to an Arduino or other microcontroller board? You’ll want to look at [Larry Bank]’s PNGdec, the Arduino-friendly PNG decoder library which makes it much easier to work with PNG files on your chosen microcontroller.
The PNG image format supports useful features like lossless compression, and was generally developed as an improved (and non-patented) alternative to GIF files. So far so great, but it turns out that decoding PNG files on a microcontroller is a challenge due to the limited amount of memory compared to desktop machines. When the PNG specification was developed in the 90s, computers easily had megabytes of memory to work with, but microcontrollers tend to have memory measured in kilobytes, and lack high-level memory management. [Larry]’s library addresses these issues.
PNGdec is self-contained and free from external dependencies, and also has some features to make converting pixel formats for different display types easy. It will run on any microcontroller that can spare at least 48 K of RAM, so if that sounds useful then check out the GitHub repository for code and examples.
We’ve seen [Larry]’s wonderful work before on optimizing GIF playback as well as rapid JPEG decoding, and these libraries have increasing relevance as hobbyists continue to see small LCD and OLED-based displays become ever more accessible and affordable.
[PNG logo: PNG Home Site]
11 thoughts on “PNG Image Decoding Library Does It With Minimal RAM”
zlib streams take a fair bit of memory to decompress. From the zlib tech page:
inflate memory usage (bytes) = (1 << windowBits) + 1440*2*sizeof(int)
I think it would be possible to make something similar to a PNG but with a compression method that is a little more microcontroller friendly.
If performance is not too critical an external SPI/QSPI RAM chip could hold the necessary data structures. Decompression fast enough for a digital picture frame is likely still possible.
8051s are immortal because of inexpensive Chinese clones.
AVR is immortal because of hobbyists
“It will run on any microcontroller that can spare at least 48 K of RAM”
This is not “minimal” RAM, so it won’t run on AVR, 8051, STM32F103C8T6 and a lot of other common µCs.
Compared to calling zlib + libpng, my library does use a ‘minimal’ amount of RAM.
I think the issue is with the article link title, not your code. It claims to be Arduino friendly, but there are few Arduino models with the capacity to run it. The older AVR based 8 bit machines lack the required capacity, and so do even some of the ARM based machines (the Zero, for example, has only 32K)
I am not familiar with PNG, maybe it is technically impossible to make the RAM footprint smaller, but 48kB is not “minimal”. This is more than the popular mega328P _FLASH_ memory size!
It would be challenging to get it smaller. The PNG spec allows up to a 15-bit (32K bytes) window size for the FLATE compressed data, plus you need buffers for the current and previous lines, palette, alpha palette, file buffers etc. I trimmed down the memory requirement as much as I could. You could potentially decode a tiny image on an ATMega328, but why would you want to? I wrote this code to be run on modern 32-bit MCUs. The main target SoCs (today in 2021) are ESP32, Cortex-M and RISC-V.
Thanks for your reply. I apologize, i should have looked at this stuff before replying. I was misleaded(??) by the picture that shows some DIP-package so i immediately thought mega328P or sth like this, not 32 bit stuff (i assume they are no or not many options in DIP for these?).
That’s a totally fair assumption! But the photo isn’t *completely* misleading (just, you know, mostly); dsPIC and PIC32 MCUs, at least, can be had in 28-pin DIPs with enough RAM to run this (though only just, in the dsPIC case).
Personally I am impressed you got it down to 48KB to be fair.
Even 100 KB is fairly small as far as the whole PNG decompression part goes.
As you have already stated, PNG needs to toss around a lot of data to do its magic.
But I do wonder if there is any caveats with going this low, as in is there any noteworthy edge cases to consider where the code fails?
I wrote a blog post detailing the how’s and why’s of the code here:
Please be kind and respectful to help make the comments section excellent. (Comment Policy)