diff --git a/libretro-common/formats/png/rpng_decode_common.h b/libretro-common/formats/png/rpng_decode_common.h index e1d0f4d2ca..fd0e116711 100644 --- a/libretro-common/formats/png/rpng_decode_common.h +++ b/libretro-common/formats/png/rpng_decode_common.h @@ -89,11 +89,11 @@ static void deinterlace_pass(uint32_t *data, const struct png_ihdr *ihdr, } } -static bool png_reverse_filter(uint32_t *data, const struct png_ihdr *ihdr, +static bool png_reverse_filter_init(uint32_t *data, const struct png_ihdr *ihdr, struct rpng_process_t *pngp) { - unsigned i; - bool ret = true; + if (ihdr->interlace == 1) + return true; png_pass_geom(ihdr, ihdr->width, ihdr->height, &pngp->bpp, &pngp->pitch, &pngp->pass_size); @@ -104,9 +104,22 @@ static bool png_reverse_filter(uint32_t *data, const struct png_ihdr *ihdr, pngp->decoded_scanline = (uint8_t*)calloc(1, pngp->pitch); if (!pngp->prev_scanline || !pngp->decoded_scanline) - GOTO_END_ERROR(); + { + free(pngp->decoded_scanline); + free(pngp->prev_scanline); + return false; + } - for (pngp->h = 0; pngp->h < ihdr->height; + return true; +} + +static bool png_reverse_filter(uint32_t *data, const struct png_ihdr *ihdr, + struct rpng_process_t *pngp) +{ + unsigned i; + bool ret = true; + + for (; pngp->h < ihdr->height; pngp->h++, pngp->inflate_buf += pngp->pitch, data += ihdr->width) { unsigned filter = *pngp->inflate_buf++; @@ -173,8 +186,10 @@ static bool png_reverse_filter(uint32_t *data, const struct png_ihdr *ihdr, } end: - free(pngp->decoded_scanline); - free(pngp->prev_scanline); + if (pngp->decoded_scanline) + free(pngp->decoded_scanline); + if (pngp->prev_scanline) + free(pngp->prev_scanline); return ret; } @@ -192,7 +207,7 @@ static bool png_reverse_filter_adam7(uint32_t *data, { 0, 1, 1, 2 }, }; - for (pngp->pass = 0; pngp->pass < ARRAY_SIZE(passes); pngp->pass++) + for (; pngp->pass < ARRAY_SIZE(passes); pngp->pass++) { unsigned pass_width, pass_height; struct png_ihdr tmp_ihdr; diff --git a/libretro-common/formats/png/rpng_decode_fbio.c b/libretro-common/formats/png/rpng_decode_fbio.c index 30ed070697..27758fa646 100644 --- a/libretro-common/formats/png/rpng_decode_fbio.c +++ b/libretro-common/formats/png/rpng_decode_fbio.c @@ -215,7 +215,7 @@ bool rpng_load_image_argb(const char *path, uint32_t **data, char header[8]; z_stream stream = {0}; struct rpng_t rpng = {0}; - struct rpng_process_t process = {0}; + struct rpng_process_t pngp = {0}; bool ret = true; *data = NULL; @@ -338,18 +338,23 @@ bool rpng_load_image_argb(const char *path, uint32_t **data, if (!*data) GOTO_END_ERROR(); - process.total_out = stream.total_out; - process.inflate_buf = rpng.inflate_buf; - process.palette = rpng.palette; + pngp.total_out = stream.total_out; + pngp.inflate_buf = rpng.inflate_buf; + pngp.palette = rpng.palette; + pngp.pass = 0; + pngp.h = 0; + + png_reverse_filter_init(*data, &rpng.ihdr, + &pngp); if (rpng.ihdr.interlace == 1) { if (!png_reverse_filter_adam7(*data, - &rpng.ihdr, &process)) + &rpng.ihdr, &pngp)) GOTO_END_ERROR(); } else if (!png_reverse_filter(*data, - &rpng.ihdr, &process)) + &rpng.ihdr, &pngp)) GOTO_END_ERROR(); end: diff --git a/libretro-common/formats/png/rpng_decode_fnbio.c b/libretro-common/formats/png/rpng_decode_fnbio.c index d9b9044023..11aa26ac76 100644 --- a/libretro-common/formats/png/rpng_decode_fnbio.c +++ b/libretro-common/formats/png/rpng_decode_fnbio.c @@ -257,7 +257,7 @@ bool rpng_nbio_load_image_argb_iterate(uint8_t *buf, struct rpng_t *rpng) bool rpng_nbio_load_image_argb_process(struct rpng_t *rpng, uint32_t **data, unsigned *width, unsigned *height) { - struct rpng_process_t process = {0}; + struct rpng_process_t pngp = {0}; z_stream stream = {0}; if (inflateInit(&stream) != Z_OK) @@ -297,19 +297,27 @@ bool rpng_nbio_load_image_argb_process(struct rpng_t *rpng, if (!*data) return false; - process.total_out = stream.total_out; - process.inflate_buf = rpng->inflate_buf; - process.palette = rpng->palette; + pngp.total_out = stream.total_out; + pngp.inflate_buf = rpng->inflate_buf; + pngp.palette = rpng->palette; + pngp.pass = 0; + pngp.h = 0; + + png_reverse_filter_init(*data, &rpng->ihdr, + &pngp); if (rpng->ihdr.interlace == 1) { if (!png_reverse_filter_adam7(*data, - &rpng->ihdr, &process)) + &rpng->ihdr, &pngp)) + return false; + } + else + { + if (!png_reverse_filter(*data, + &rpng->ihdr, &pngp)) return false; } - else if (!png_reverse_filter(*data, - &rpng->ihdr, &process)) - return false; return true; }