PNG decoder in C

2015 A. Tarpai

Thanks to Willem van Schaik's PngSuite I could test the decoder on a bunch of images.

This is a snapshot of my folder with PNG and decoded-converted BMP equivalents of supported images by this decoder:

Supported PNG types:

Limitations:

The decoder converts a PNG file to BMP file in-memory:

+---------------------------------+       Decoder           +-------------------+
|           PNG FILE              |    ---------------->    |                   |
+---------------------------------+                         |       BMP         |
                                                            |       FILE        |
                                                            |                   |
                                                            |                   |
                                                            |                   |
                                                            +-------------------+

BMP output of this decoder

BMP is one of these 4 direct-color formats:

Why BMP memory output?

Whatever the PNG pixel format is, it will write true-color (namely direct-color) pixels in BM-format from a given memory location.
This is set when calling PNGDecode() passing a BITPERPIXELENUM.
Note that scanlines are DWORD-padded (with possible x-padding).
This is exactly the PC video hardware frame buffer structure (I started image decoders for a GUI on PC), hence the 4 versions:

The BM pixel format:

BITPERPIXELENUM24
BM-format RGB888 (aka RGB24)
                  
     B G R               
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x x x 
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x x x 
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x x x 

             
BITPERPIXELENUM32
BM-format RGB8888 (aka RGB32)
                  
     B G R A              
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

      
BITPERPIXELENUM16
BM-format RGB565 (aka RGB16)
                  
     bgr                  
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x x 
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x x 
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x x 

      
BITPERPIXELENUM15
BM-format RGB555 (aka RGB15)
                  
     bgr                  
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x x 
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x x 
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - x x 

Decoder - big picture

+---------------------------------+       Decoder            +-------------------+
|           PNG FILE              |    ---------------->     |    BMP HEADER     |
+---------------------------------+         |                |-------------------|
                                            |                |                   |
                                            |                |      BITMAP       |
                                     +----------+            |                   |
                                     | buffers  |            |                   |
                                     |          |            +-------------------+
                                     +----------+               In memory                    
                                     - DEFLATE                  - true-color 15/16/24/32-bpp        
                                     - 2 x Image-line           - DWORD-paddes scanlines                                         

This is a per-image-line decoder

But fully inflates PNG image data before conversion. (For large PNG-s, I also experimented with a byte-by-byte inflate using call-backs, the zlib-window. It reduced memory allocations, but simply made inflate.c ugly for me.)

                                                                                  +-------------------+
                                                                                  |                   |
----------------+         filter              decoded pixel data       convert    |                   |
  inflated data |    ---------------->      +--------------------+    -------->   |xxxxxxxxxxxxxxxxxxx|
----------------+                           +--------------------+                |                   |
                                                   ||                             |                   |
                                                   ||                             |                   |
                                            +--------------------+                +-------------------+
                                            +--------------------+                        BITMAP
                                                 image line 
                                                filter buffer