This is a stream based portable PNG Loader for Embedding, Pngle.
Basically PNG is a memory consuming format from an embedded system perspective, especially on decoding, it mandatory require 32KiB working memory for a sliding window of Deflate, and a scanline buffer (its size depend on image width & format) to reconstruct the image, at least. Unfortunately, due to the memory requirements, we could say traditional Arduino boards, that uses ATmega328 or ATmega32U4 for example, lack of ability to decode standard PNG images.
Today, we have variety of SoC boards for embedded systems or Arduino that have enough memory to decode PNG images, but we need to be concerned about memory consumption sometimes. While there are many other PNG decoders, some of them always require the full size of frame-buffer, some of them don't but do require using complicated APIs instead, and some of them are hard to use in Arduino because of deep dependency. This is why I reinvent the wheel for my own.
pngle_feed
API (in the same way as write
syscall)miniz
(don't worry, battery included!)stdint.h
(but not for miniz
yet...)pngle_set_display_gamma
API with display gamma value (Typically 2.2)PNGLE_NO_GAMMA_CORRECTION
in case of emergencypngle_new()
pngle_set_draw_callback()
pngle_feed()
until exhaustedon_draw()
(for example) is called repeatedlyon_draw()
function, put the pixel on a screen (or wherever you want)void on_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4])
{
uint8_t r = rgba[0]; // 0 - 255
uint8_t g = rgba[1]; // 0 - 255
uint8_t b = rgba[2]; // 0 - 255
uint8_t a = rgba[3]; // 0: fully transparent, 255: fully opaque
if (a) printf("put pixel at (%d, %d) with color #%02x%02x%02x\n", x, y, r, g, b);
}
int main(int argc, char *argv[])
{
pngle_t *pngle = pngle_new();
pngle_set_draw_callback(pngle, on_draw);
// Feed data to pngle
char buf[1024];
int remain = 0;
int len;
while ((len = read(STDIN_FILENO, buf + remain, sizeof(buf) - remain)) > 0) {
int fed = pngle_feed(pngle, buf, remain + len);
if (fed < 0) errx(1, "%s", pngle_error(pngle));
remain = remain + len - fed;
if (remain > 0) memmove(buf, buf + fed, remain);
}
pngle_destroy(pngle);
return 0;
}
See pngle.h
kikuchan / @kikuchan98
MIT License