Arduino PNG image decoder library

Overview

PNGdec

Copyright (c) 2021 BitBank Software, Inc.
Written by Larry Bank
[email protected]

What is it?

An 'embedded-friendly' (aka Arduino) PNG image decoding library

Why did you write it?

Starting in the late 80's I wrote my own imaging codecs for the existing standards (CCITT G3/G4 was the first). I soon added GIF, JPEG and not long after that, the PNG specification was ratified. All of this code was "clean room" - written just from the specification. I used my imaging library in many projects and products over the years and recently decided that some of my codecs could get a new lease on life as open source, embedded-friendly libraries for microcontrollers.

What's special about it?

The PNG image specification was written at a time when computers had megabytes of RAM and conserving memory wasn't a big priority. The memory allocated for decoding the compressed data (zlib) and for holding the uncompressed image can be quite a bit more than is available on modern microcontrollers (usually measured in K bytes). Three goals for this project are: easy to compile+use on all embedded systems, use a minimal amount of RAM and be self-contained. One of the dependencies I like to remove when working on embedded software is malloc/free. When compiling on a system with a tiny amount of RAM, heap memory management might not even exist.

Feature summary:
----------------

  • Runs on any MCU with at least 48K of free RAM
  • No external dependencies (including malloc/free)
  • Decode an image line by line with a callback function
  • Decode an image to a user supplied buffer (no callback needed)
  • Supports all standard options except interlacing (too much RAM needed)
  • Function provided to turn any pixel format into RGB565 for LCD displays
  • Optionally disable zlib's internal CRC check - improves speed by 10-30%
  • Arduino-style C++ library class with simple API
  • Can by built as straight C as well

How fast is it?
---------------
The examples folder contains a sketch to measure the performance of decoding a 240x200 image of varying bit depths. Here's the results when run on a few common MCUs:


Documentation:
---------------
Detailed information about the API is in the Wiki
See the examples folder for easy starting points

Issues
  • PNG.decode() returns 0, but PNG_DRAW_CALLBACK is never called

    PNG.decode() returns 0, but PNG_DRAW_CALLBACK is never called

    I started from the png_transparency.ino sketch as a base, and I am trying to load a PNG from OpenWatherMap.org. The PNG data is opened and stored in a buffer

        snprintf(url, 256, "/img/wn/%s.png", doc["weather"][0]["icon"].as<String>().c_str());
        Serial.printf("Icon URL: %s\n", url);
        httpIconData = HttpClient(wifi, "openweathermap.org", 80);
        httpIconData.get(url);
        if (httpIconData.responseStatusCode() == 200)
        {
          Serial.println("Icon successfully retrieved");
          if (httpIconData.isResponseChunked() == true)
          {
          }
          else
          {
            unsigned int length = httpIconData.contentLength();
            Serial.printf("Icon size is %d\n Allocatibng memory.\n", length);
            pngData = (uint8_t *)malloc((size_t)length);
            httpIconData.responseBody().getBytes(pngData, length, 0);
            Serial.println("About to show icon");
            ShowPNG(pngData, length, dma_display, 0, 0);
            Serial.println("Freeing PNG data buffer");
            free(pngData);
          }
        }
        else
        {
          Serial.printf("Failed to retrieve icon: %d\n", httpWeatherData.responseStatusCode());
        }
    

    Serial output:

    Icon URL: /img/wn/02d.png
    Icon successfully retrieved
    Icon size is 852
     Allocatibng memory.
    About to show icon
    

    That buffer is then sent to the code derived from png_transparency.ino:

    #include <PNGdec.h>
    #include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
    #include "png.h"
    
    typedef struct private_png_struct
    {
        int16_t x_offset = 0;
        int16_t y_offset = 0;
        MatrixPanel_I2S_DMA *displayPanel = NULL;
        PNG *png = NULL;
    } Private_PNG;
    
    void PNGDraw(PNGDRAW *pDraw)
    {
        Serial.println("About to draw PNG line");
        uint16_t usPixels[pDraw->iWidth];
        uint8_t ucMask[40];
        Private_PNG *pp = (Private_PNG *)pDraw->pUser;
    
        pp->png->getLineAsRGB565(pDraw, usPixels, PNG_RGB565_BIG_ENDIAN, 0xffffffff);
        for (uint16_t x = 0; x < pDraw->iWidth; x++)
        {
            pp->displayPanel->drawPixel(x + pp->x_offset, pDraw->y + pp->y_offset, usPixels[x]);
            Serial.printf("(%d+%d, %d+%d): %0x%04x\n ", x, pp->x_offset, pDraw->y, pp->y_offset, usPixels[x]);
        }
    }
    
    PNG *ShowPNG(uint8_t *pngData, uint16_t length, MatrixPanel_I2S_DMA *display, int16_t x, int16_t y)
    {
        PNG *png = new PNG();
    
        Serial.printf("Preparing to show icon of length %d\n", length);
        int rc = png->openRAM(pngData, length, PNGDraw);
        if (rc == PNG_SUCCESS)
        {
            Serial.println("Successfully opened icon from buffer");
            Private_PNG *pp = (Private_PNG *)malloc((size_t)sizeof(Private_PNG));
            if (x == -1)
            {
                pp->x_offset = (64 - png->getWidth()) / 2;
            }
            else
            {
                pp->x_offset = x;
            }
            if (y == -1)
            {
                pp->y_offset = (32 - png->getHeight()) / 2;
            }
            else
            {
                pp->y_offset = y;
            }
            Serial.printf("Offsets calculated: (%d, %d)\n", pp->x_offset, pp->y_offset);
            pp->displayPanel = display;
            pp->png = png;
            Serial.println("Private data set.");
            Serial.println("Drawing PNG now!");
            rc = png->decode((void *)pp, 0);
            Serial.printf("Draw result: %d\n", rc);
            free(pp);
            delete png;
        }
        return png;
    }
    

    Serial output:

    Preparing to show icon of length 852
    Successfully opened icon from buffer
    Offsets calculated: (0, 0)
    Private data set.
    Drawing PNG now!
    Draw result: 0
    
    opened by han-fastolfe 5
  • Cannot parse some png fetched from web

    Cannot parse some png fetched from web

    Thanks for this well-coded library! It works well on most png file. However, there's a certain type of png files that I didn't manage to decode properly so far.

    I received rc code == 6 when running "rc = png.open()" function in the example of LittleFS_PNG given in this repo.

    In developer tool of Chrome web browser, if you look into the data obtained after GET, some differences can be found. === For your re-building this problem === The parse_OK png data can GET from this url The parse_fail png data can GET from this url

    The code I used for testing: for PNG fetching: LittleFS_Web_Jpg (modified for png instead of jpg) for PNG parsing: https://github.com/Bodmer/TFT_eSPI/blob/master/examples/PNG%20Images/LittleFS_PNG/LittleFS_PNG.ino The png fetched from url above (http://restapi.amap.com/) is neccessary for me. Any suggestions and fixing method will be very appreciated! Thank you!!

    opened by sonictl 4
  • Strange result when decode 8-bit gray+alpha

    Strange result when decode 8-bit gray+alpha

    Hello I can't decode this PNG kapa1.0.png: PNG image data, 25 x 28, 8-bit gray+alpha, non-interlaced https://static-cdn.jtvnw.net/emoticons/v2/25/default/dark/1.0 In PNGDraw(PNGDRAW* pDraw) I use img->png->getLineAsRGB565(pDraw, usPixels, PNG_RGB565_LITTLE_ENDIAN, 0x000000);

    https://github.com/spectrenoir06/Twitch_emote_hub75/blob/63f36034d0e02860393104d5d037c6f8720f9df6/src/main.cpp#L139

    opened by spectrenoir06 3
  • PNG Scaling

    PNG Scaling

    First want to say been looking for this for a long time and want to say thank you for putting this together. Used it as soon as I found it!

    Now for the question at hand. Most of my PNGs are larger than what will it in a display and was looking for some sort of scaling ability. Do you have any plans for a scaling option like you have in the JPEG library. Or point me to some sort of way to do PNG scaling without having to read the whole image in first?

    Thanks Mike

    opened by mjs513 2
  • How to decode this image?

    How to decode this image?

    Thanks for this well documented library! Works great, also for transparent images.

    However, there's a certain type of png files that I didn't manage to decode properly so far. For example: https://tiles.wmflabs.org/hillshading/10/526/340.png

    Looks like it's being rendered as fully transparent, although hasAlpha() returns 0. The library further reports: image specs: (256 x 256), 8 bpp, pixel type: 3;

    I should add that the image from the above link is strange anyway, as it looks OK in web browsers and in Microsoft applications (e.g MS Paint), but not in tools like Gimp or Irfanview. Wonder if there's a way to decode it properly with PNGdec?

    opened by perlix 2
  • Alternatives for using a global file variable

    Alternatives for using a global file variable

    Hi,

    I have successfully gotten your library working on an ESP32 that displays to an RGB matrix using @mrfaptastic's Matrix library.

    I am trying to find an alternative to having to define my File variable globally such as in: https://github.com/bitbank2/PNGdec/blob/master/examples/sdcard_slideshow/sdcard_slideshow.ino

    I am looking to encapsulate the PNG Drawing capability within a higher level image function that I can use for dynamically loading and drawing new images to the LED Matrix. The specific number of class instantiations I will need will never be known at compile time, but I will have multiple files open at once.

    Essentially I want a class like the following:

    image1 = ImageManager("filename.png") image2 = ImageManager("file2.png")

    image1.render() image2.render()

    Where ImageManager calls the png.Open() function when initialized.

    I have tried to encapsulate the PNG class and the File variable within a higher level class along with my callback functions inside it but then the compiler complains because the callback functions are not static. If I set the functions to static I can no longer access the unique File variable that belongs to each instantiation.

    Essentially I want to be able to pass in a File object to the Open() callback without having to explicitly define it as a global variable.

    I am not extremely knowledgeable about C++ so maybe I am missing an obvious solution here...

    Thanks!

    opened by lmurdock12 1
  • Is it possible to make PNG decoder without callbacks?

    Is it possible to make PNG decoder without callbacks?

    Hi The most popular graphics library now is LVGL and it also works with callbacks: rendering callback is called multiple times with different rendering areas (usually from top to bottom) and I am supposed to render the next portion of the PNG to that rectangle. The only way I found to marry LVGL with PNGdec (or pngle) is to create a second thread for PNG decoding. When LVGL calls my callback on the first thread, I have to block it and awaken the PNG thread, which calls PNG decoder and start receiving callbacks until the rendering area requested by LVGL is filled. Then I freeze PNG task and awaken the first task, which calls rendering callback again with the next rendering area, etc. It works, but requires numerous task switches to finish screen rendering - very clumsy.

    So, the ideal PNG decoder for low-memory systems will not have any callbacks, but will have API like that:

    • open
    • get_next_row(char * buffer, int size) or get_next_pixels(char * buffer, int size)
    • close

    Do you think it is possible to write such decoder? Thank you

    opened by jhnlmn 1
  • The likelihood of an infinite decoding cycle of a damaged file due to the lack of verification of how much data was read in the read callback function

    The likelihood of an infinite decoding cycle of a damaged file due to the lack of verification of how much data was read in the read callback function

    Hi, Found your PNG decoding library and now I am trying to embed it into a microcontroller on a 3D printer board. And I found one flaw in the library :) During the decoding process, there is no check for an unexpected end of file. So if the read callback returns 0 or -1, the decoding process continues. The return result of this function is not checked. It turns out that if the file ends unexpectedly (damaged), then the decoding process loops endlessly. Like in this piece of code:

                case 0x49444154: //'IDAT' image data block
                    while (iLen) {
                        if (iOffset >= iBytesRead) {
                            // we ran out of data; get some more
                            iBytesRead = (*pPage->pfnRead)(&pPage->PNGFile, pPage->ucFileBuf, (iLen > PNG_FILE_BUF_SIZE) ? PNG_FILE_BUF_SIZE : iLen);
                            iFileOffset += iBytesRead;
                            iOffset = 0;
                        } else {
                            // number of bytes remaining in buffer
                            iBytesRead -= iOffset;
                        }
    
    

    It would be nice to check the return value by 0 or -1 after calling the read callback function everywhere. If the data is expected to be read and it has not been read, then the file is corrupted or a read error.

                case 0x49444154: //'IDAT' image data block
                    while (iLen) {
                        if (iOffset >= iBytesRead) {
                            // we ran out of data; get some more
                            iBytesRead = (*pPage->pfnRead)(&pPage->PNGFile, pPage->ucFileBuf, (iLen > PNG_FILE_BUF_SIZE) ? PNG_FILE_BUF_SIZE : iLen);
                            if (iBytesRead < 1)
                            {
                                pPage->iError = PNG_INVALID_FILE;
                                return pPage->iError;
                            }
                            iFileOffset += iBytesRead;
                            iOffset = 0;
                        } else {
                            // number of bytes remaining in buffer
                            iBytesRead -= iOffset;
                        }
    
    
    opened by Andy-Big 1
  • BUGS FOUND

    BUGS FOUND

    hi, i found something unusual in this repo, are they new bugs ? To reproduce the crash please use command: ./png_demo @@ /dev/null (replace @@ to the sample's path)

    FPE

    crash sample

    id0-FPE-sample1.zip

    crash info

    AddressSanitizer:DEADLYSIGNAL
    ==22761==ERROR: AddressSanitizer: FPE on unknown address 0x0000004f4665 (pc 0x0000004f4665 bp 0x7fffaf2c27f0 sp 0x7fffaf2c19e0 T0)
        #0 0x4f4665 in SaveBMP(char*, unsigned char*, unsigned char*, int, int, int) /home/bupt/Desktop/PNGdec/linux/main.cpp:56:21
        #1 0x4f5311 in main /home/bupt/Desktop/PNGdec/linux/main.cpp:144:9
        #2 0x7f42d9d84c86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310
        #3 0x41c129 in _start (/home/bupt/Desktop/PNGdec/linux/png_demo+0x41c129)
    
    AddressSanitizer can not provide additional info.
    SUMMARY: AddressSanitizer: FPE /home/bupt/Desktop/PNGdec/linux/main.cpp:56:21 in SaveBMP(char*, unsigned char*, unsigned char*, int, int, int)
    ==22761==ABORTING
    

    heap-buffer-overflow

    crash sample No.1

    id1-heap-buffer-overflow-sample1.zip

    crash info of sample No.1

    ==22802==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000011 at pc 0x00000043b61c bp 0x7ffefb2a1690 sp 0x7ffefb2a0e40
    READ of size 40 at 0x602000000011 thread T0
        #0 0x43b61b in __interceptor_fwrite.part.57 /home/bupt/Desktop/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:1143
        #1 0x4f491a in SaveBMP(char*, unsigned char*, unsigned char*, int, int, int) /home/bupt/Desktop/PNGdec/linux/main.cpp:89:13
        #2 0x4f5311 in main /home/bupt/Desktop/PNGdec/linux/main.cpp:144:9
        #3 0x7f0ed9adfc86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310
        #4 0x41c129 in _start (/home/bupt/Desktop/PNGdec/linux/png_demo+0x41c129)
    
    0x602000000011 is located 0 bytes to the right of 1-byte region [0x602000000010,0x602000000011)
    allocated by thread T0 here:
        #0 0x4ae6f0 in malloc /home/bupt/Desktop/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145
        #1 0x4f51ec in main /home/bupt/Desktop/PNGdec/linux/main.cpp:128:34
    
    SUMMARY: AddressSanitizer: heap-buffer-overflow /home/bupt/Desktop/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:1143 in __interceptor_fwrite.part.57
    Shadow bytes around the buggy address:
      0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>0x0c047fff8000: fa fa[01]fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07 
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
      Shadow gap:              cc
    ==22802==ABORTING
    

    crash sample No.2

    id2-heap-buffer-overflow-sample2.zip

    crash info of sample No.2

    ==22853==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6220000017b0 at pc 0x0000004ad554 bp 0x7ffc9c610730 sp 0x7ffc9c60fee0
    WRITE of size 132 at 0x6220000017b0 thread T0
        #0 0x4ad553 in __asan_memcpy /home/bupt/Desktop/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22
        #1 0x4fc310 in DecodePNG(png_image_tag*, void*, int) /home/bupt/Desktop/PNGdec/linux/../src/png.inl:801:33
        #2 0x4fc310 in PNG::decode(void*, int) /home/bupt/Desktop/PNGdec/linux/../src/PNGdec.cpp:194:12
        #3 0x4f5207 in main /home/bupt/Desktop/PNGdec/linux/main.cpp:129:18
        #4 0x7f6fa7b19c86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310
        #5 0x41c129 in _start (/home/bupt/Desktop/PNGdec/linux/png_demo+0x41c129)
    
    0x6220000017b0 is located 0 bytes to the right of 5808-byte region [0x622000000100,0x6220000017b0)
    allocated by thread T0 here:
        #0 0x4ae6f0 in malloc /home/bupt/Desktop/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145
        #1 0x4f51ec in main /home/bupt/Desktop/PNGdec/linux/main.cpp:128:34
    
    SUMMARY: AddressSanitizer: heap-buffer-overflow /home/bupt/Desktop/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22 in __asan_memcpy
    Shadow bytes around the buggy address:
      0x0c447fff82a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c447fff82b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c447fff82c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c447fff82d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c447fff82e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>0x0c447fff82f0: 00 00 00 00 00 00[fa]fa fa fa fa fa fa fa fa fa
      0x0c447fff8300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c447fff8310: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c447fff8320: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c447fff8330: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c447fff8340: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07 
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
      Shadow gap:              cc
    ==22853==ABORTING
    

    crash sample No.3

    id8-heap-buffer-overflow-sample3.zip

    crash info of sample No.3

    ==23090==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7fad078fceb2 at pc 0x0000004f4e69 bp 0x7ffe0c9898b0 sp 0x7ffe0c9898a8
    READ of size 1 at 0x7fad078fceb2 thread T0
        #0 0x4f4e68 in SaveBMP(char*, unsigned char*, unsigned char*, int, int, int) /home/bupt/Desktop/PNGdec/linux/main.cpp:84:24
        #1 0x4f5311 in main /home/bupt/Desktop/PNGdec/linux/main.cpp:144:9
        #2 0x7fad0ae1dc86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310
        #3 0x41c129 in _start (/home/bupt/Desktop/PNGdec/linux/png_demo+0x41c129)
    
    0x7fad078fceb2 is located 2 bytes to the right of 2013271728-byte region [0x7fac8f8fb800,0x7fad078fceb0)
    allocated by thread T0 here:
        #0 0x4ae6f0 in malloc /home/bupt/Desktop/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145
        #1 0x4f51ec in main /home/bupt/Desktop/PNGdec/linux/main.cpp:128:34
    
    SUMMARY: AddressSanitizer: heap-buffer-overflow /home/bupt/Desktop/PNGdec/linux/main.cpp:84:24 in SaveBMP(char*, unsigned char*, unsigned char*, int, int, int)
    Shadow bytes around the buggy address:
      0x0ff620f17980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0ff620f17990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0ff620f179a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0ff620f179b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0ff620f179c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>0x0ff620f179d0: 00 00 00 00 00 00[fa]fa fa fa fa fa fa fa fa fa
      0x0ff620f179e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0ff620f179f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0ff620f17a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0ff620f17a10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0ff620f17a20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07 
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
      Shadow gap:              cc
    ==23090==ABORTING
    

    stack-buffer-overflow

    crash sample No.1

    id12-stack-buffer-overflow-sample1.zip

    crash info of sample No.1

    ==26778==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc0d703c40 at pc 0x0000004f4e82 bp 0x7ffc0d702f90 sp 0x7ffc0d702f88
    WRITE of size 1 at 0x7ffc0d703c40 thread T0
        #0 0x4f4e81 in SaveBMP(char*, unsigned char*, unsigned char*, int, int, int) /home/bupt/Desktop/PNGdec/linux/main.cpp:84:48
        #1 0x4f5311 in main /home/bupt/Desktop/PNGdec/linux/main.cpp:144:9
        #2 0x7fd91072ac86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310
        #3 0x41c129 in _start (/home/bupt/Desktop/PNGdec/linux/png_demo+0x41c129)
    
    Address 0x7ffc0d703c40 is located in stack of thread T0 at offset 3232 in frame
        #0 0x4f425f in SaveBMP(char*, unsigned char*, unsigned char*, int, int, int) /home/bupt/Desktop/PNGdec/linux/main.cpp:26
    
      This frame has 2 object(s):
        [32, 1056) 'ucTemp' (line 31)
        [1184, 3232) 'ucTemp76' (line 80) <== Memory access at offset 3232 overflows this variable
    HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
          (longjmp and C++ exceptions *are* supported)
    SUMMARY: AddressSanitizer: stack-buffer-overflow /home/bupt/Desktop/PNGdec/linux/main.cpp:84:48 in SaveBMP(char*, unsigned char*, unsigned char*, int, int, int)
    Shadow bytes around the buggy address:
      0x100001ad8730: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x100001ad8740: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x100001ad8750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x100001ad8760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x100001ad8770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>0x100001ad8780: 00 00 00 00 00 00 00 00[f3]f3 f3 f3 f3 f3 f3 f3
      0x100001ad8790: f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
      0x100001ad87a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x100001ad87b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x100001ad87c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x100001ad87d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07 
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
      Shadow gap:              cc
    ==26778==ABORTING
    
    

    global-buffer-overflow

    crash sample

    id13-global-buffer-overflow-sample1.zip

    crash info of the sample

    ==26922==ERROR: AddressSanitizer: global-buffer-overflow on address 0x00000101b510 at pc 0x00000051493d bp 0x7ffe4b62fc20 sp 0x7ffe4b62fc18
    WRITE of size 1 at 0x00000101b510 thread T0
        #0 0x51493c in inflate_fast /home/bupt/Desktop/PNGdec/linux/../src/inffast.c:275:36
        #1 0x5180f8 in inflate /home/bupt/Desktop/PNGdec/linux/../src/inflate.c:1055:17
        #2 0x4f74e0 in DecodePNG(png_image_tag*, void*, int) /home/bupt/Desktop/PNGdec/linux/../src/png.inl:783:31
        #3 0x4f74e0 in PNG::decode(void*, int) /home/bupt/Desktop/PNGdec/linux/../src/PNGdec.cpp:194:12
        #4 0x4f5207 in main /home/bupt/Desktop/PNGdec/linux/main.cpp:129:18
        #5 0x7f5825c48c86 in __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:310
        #6 0x41c129 in _start (/home/bupt/Desktop/PNGdec/linux/png_demo+0x41c129)
    
    0x00000101b510 is located 0 bytes to the right of global variable 'png' defined in 'main.cpp:10:5' (0x100f8a0) of size 48240
    SUMMARY: AddressSanitizer: global-buffer-overflow /home/bupt/Desktop/PNGdec/linux/../src/inffast.c:275:36 in inflate_fast
    Shadow bytes around the buggy address:
      0x0000801fb650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0000801fb660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0000801fb670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0000801fb680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0000801fb690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>0x0000801fb6a0: 00 00[f9]f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x0000801fb6b0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x0000801fb6c0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x0000801fb6d0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x0000801fb6e0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x0000801fb6f0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07 
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
      Shadow gap:              cc
    ==26922==ABORTING
    

    memory allocation problem

    crash sample No.1

    id5-memory-allocation-problem-sample1.zip

    crash info of sample No.1

    ==22984==ERROR: AddressSanitizer: requested allocation size 0xffffffff837c16b0 (0xffffffff837c26b0 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x10000000000 (thread T0)
        #0 0x4ae6f0 in malloc /home/bupt/Desktop/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145
        #1 0x4f51ec in main /home/bupt/Desktop/PNGdec/linux/main.cpp:128:34
    
    ==22984==HINT: if you don't care about these errors you may set allocator_may_return_null=1
    SUMMARY: AddressSanitizer: allocation-size-too-big /home/bupt/Desktop/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145 in malloc
    ==22984==ABORTING
    
    opened by Cvjark 0
  • Use std::function for callbacks in C++ mode.

    Use std::function for callbacks in C++ mode.

    This allows lambda functions to be used (while continuing to support bare function pointers).

    This also adds a variant of decode that accepts a draw callback directly, so the same image can be drawn in multiple places without re-parsing the header.

    opened by quentinmit 2
Releases(1.0.1)
  • 1.0.1(Sep 7, 2021)

  • 1.0.0(Jun 2, 2021)

    PNGdec is a PNG image decoder designed for MCUs with at least 48k of RAM. The features are focused on Arduino devices with a RGB565 LCD display for output.

    Source code(tar.gz)
    Source code(zip)
Owner
Larry Bank
Call me Mr. Optimization. I optimize other people's code for a living.
Larry Bank
PNG encoder and decoder in C and C++.

PNG encoder and decoder in C and C++, without dependencies

Lode Vandevenne 1.7k Aug 4, 2022
pngtostl is a program that converts a PNG image into STL 3D models

pngtostl is a program that converts a PNG image into a litophane, in STL format, suitable to be printed by entry level 3D printers.

Salvatore Sanfilippo 157 Jul 27, 2022
An image and texture viewer for tga, png, apng, exr, dds, gif, hdr, jpg, tif, ico, webp, and bmp files

An image and texture viewer for tga, png, apng, exr, dds, gif, hdr, jpg, tif, ico, webp, and bmp files. Uses Dear ImGui, OpenGL, and Tacent. Useful for game devs as it displays information like the presence of an alpha channel and querying specific pixels for their colour.

Tristan Grimmer 140 Aug 4, 2022
libspng is a C library for reading and writing PNG format files with a focus on security and ease of use.

libspng (simple png) is a C library for reading and writing Portable Network Graphics (PNG) format files with a focus on security and ease of use.

Randy 520 Aug 6, 2022
PoC black/white image sequence to dumpy gif image sequence converter

PoC black/white image sequence to dumpy gif image sequence converter

null 64 Jul 28, 2022
The “Quite OK Image” format for fast, lossless image compression

The “Quite OK Image” format for fast, lossless image compression

Dominic Szablewski 5.7k Aug 6, 2022
Very fast C++ .PNG writer for 24/32bpp images.

fpng Very fast C++ .PNG writer for 24/32bpp images. fpng.cpp was written to see just how fast you can write .PNG's without sacrificing too much compre

Rich Geldreich 587 Jul 31, 2022
Demo of a fast PNG encoder.

Fast PNG Encoder This is a proof-of-concept fast PNG encoder that uses AVX2 and a special Huffman table to encode images faster. Speed on a single cor

Luca Versari 46 Aug 4, 2022
Rate-Distortion Optimized Lossy PNG Encoding Tool

rdopng is a command line tool which uses LZ match optimization, Lagrangian multiplier rate distortion optimization (RDO), a simple perceptual error tolerance model, and Oklab-based colorspace error metrics to encode 24/32bpp PNG files which are 30-80% smaller relative to lodepng/libpng.

Rich Geldreich 32 Jul 25, 2022
Fast streaming PNG<->QOI converter with some compression-improving extensions

QOIG Fast streaming PNG<->QOI converter with some compression-improving extensions. Can achieve 1%-10% better compression than QOI without sacrificing

David Rutter 4 May 31, 2022
An 'embedded-friendly' (aka Arduino) JPEG image encoding library

Starting in the late 80's I wrote my own imaging codecs for the existing standards (CCITT G3/G4 was the first). I soon added GIF, JPEG and not long after that, the PNG specification was ratified. All of this code was "clean room" - written just from the specification. I used my imaging library in many projects and products over the years and recently decided that some of my codecs could get a new lease on life as open source, embedded-friendly libraries for microcontrollers.

Larry Bank 35 Jul 11, 2022
A deblocking JPEG decoder

Knusperli The goal of Knusperli is to reduce blocking artifacts in decoded JPEG images, by interpreting quantized DCT coefficients in the image data a

Google 449 Jun 3, 2022
This library provides a cross-platform image loading library in C11 for projects based on our foundation library

Image Library - Public Domain This library provides a cross-platform image loading library in C11 for projects based on our foundation library.

Mattias Jansson 1 Jan 29, 2022
A fast image processing library with low memory needs.

libvips : an image processing library Introduction libvips is a demand-driven, horizontally threaded image processing library. Compared to similar lib

libvips 22 Jul 26, 2022
C++ image processing and machine learning library with using of SIMD: SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX-512, VMX(Altivec) and VSX(Power7), NEON for ARM.

Introduction The Simd Library is a free open source image processing and machine learning library, designed for C and C++ programmers. It provides man

Ihar Yermalayeu 1.6k Aug 4, 2022
Video++, a C++14 high performance video and image processing library.

Video++ Video++ is a video and image processing library taking advantage of the C++14 standard to ease the writing of fast video and image processing

Matthieu Garrigues 683 Jul 28, 2022
a generic C++ library for image analysis

VIGRA Computer Vision Library Copyright 1998-2013 by Ullrich Koethe This file is part of the VIGRA computer vision library. You may use,

Ullrich Koethe 368 Jun 25, 2022
Intel® Open Image Denoise library

Intel Open Image Denoise is an open source library of high-performance, high-quality denoising filters for images rendered with ray tracing

Intel® Open Image Denoise 1.3k Aug 1, 2022