]> git.tdb.fi Git - libs/gui.git/commitdiff
Handle interlaced PNG images
authorMikko Rasa <tdb@tdb.fi>
Mon, 13 Jul 2015 09:54:06 +0000 (12:54 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 13 Jul 2015 09:57:31 +0000 (12:57 +0300)
source/graphics/png/pngloader.cpp

index ede91b0c37be3615ae7ca9e714d93c0d3aa10d67..c2691bd5c30522a51843bc7774d4ab8453c6db1e 100644 (file)
@@ -56,15 +56,21 @@ bool PngLoader::detect(const std::string &sig)
 
 void PngLoader::load(Image::Data &data)
 {
 
 void PngLoader::load(Image::Data &data)
 {
+       png_byte **rows = 0;
+
        if(setjmp(png_jmpbuf(priv->png)))
        if(setjmp(png_jmpbuf(priv->png)))
+       {
+               delete[] rows;
                throw bad_image_data(priv->message);
                throw bad_image_data(priv->message);
+       }
 
        png_read_info(priv->png, priv->info);
        png_uint_32 width;
        png_uint_32 height;
        int depth;
        int color;
 
        png_read_info(priv->png, priv->info);
        png_uint_32 width;
        png_uint_32 height;
        int depth;
        int color;
-       png_get_IHDR(priv->png, priv->info, &width, &height, &depth, &color, 0, 0, 0);
+       int interlace;
+       png_get_IHDR(priv->png, priv->info, &width, &height, &depth, &color, &interlace, 0, 0);
        unsigned nchans = png_get_channels(priv->png, priv->info);
 
        if(depth!=8)
        unsigned nchans = png_get_channels(priv->png, priv->info);
 
        if(depth!=8)
@@ -85,8 +91,26 @@ void PngLoader::load(Image::Data &data)
        }
 
        data.data = new char[data.stride*data.height];
        }
 
        data.data = new char[data.stride*data.height];
-       for(unsigned y=0; y<data.height; ++y)
-               png_read_row(priv->png, reinterpret_cast<png_byte *>(data.data+data.stride*(data.height-1-y)), 0);
+
+       if(interlace==PNG_INTERLACE_ADAM7)
+       {
+               // ADAM7 requires all rows to be loaded at once
+               unsigned n_passes = png_set_interlace_handling(priv->png);
+               rows = new png_byte *[data.height];
+               for(unsigned y=0; y<data.height; ++y)
+                       rows[y] = reinterpret_cast<png_byte *>(data.data+data.stride*(data.height-1-y));
+
+               for(unsigned i=0; i<n_passes; ++i)
+                       png_read_rows(priv->png, rows, 0, data.height);
+
+               delete[] rows;
+               rows = 0;
+       }
+       else
+       {
+               for(unsigned y=0; y<data.height; ++y)
+                       png_read_row(priv->png, reinterpret_cast<png_byte *>(data.data+data.stride*(data.height-1-y)), 0);
+       }
 
        png_read_end(priv->png, 0);
 }
 
        png_read_end(priv->png, 0);
 }