void PngLoader::load(Image::Data &data)
{
+ png_byte **rows = 0;
+
if(setjmp(png_jmpbuf(priv->png)))
+ {
+ delete[] rows;
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_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)
}
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);
}