diff --git a/Makefile.common b/Makefile.common index c3742cb58a..4623cf11e3 100644 --- a/Makefile.common +++ b/Makefile.common @@ -793,9 +793,7 @@ ifdef HAVE_RPNG endif ifeq ($(HAVE_RPNG), 1) - OBJ += libretro-common/formats/png/rpng_nbio.o \ - libretro-common/formats/png/rpng_fbio.o \ - libretro-common/formats/png/rpng_decode.o \ + OBJ += libretro-common/formats/png/rpng.o \ libretro-common/formats/png/rpng_encode.o endif diff --git a/griffin/griffin.c b/griffin/griffin.c index cafad22491..dd6eb151c9 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -174,9 +174,7 @@ VIDEO IMAGE #endif #ifdef HAVE_RPNG -#include "../libretro-common/formats/png/rpng_fbio.c" -#include "../libretro-common/formats/png/rpng_nbio.c" -#include "../libretro-common/formats/png/rpng_decode.c" +#include "../libretro-common/formats/png/rpng.c" #include "../libretro-common/formats/png/rpng_encode.c" #endif diff --git a/libretro-common/formats/png/Makefile b/libretro-common/formats/png/Makefile index 765ac4f790..b5d93e0e24 100644 --- a/libretro-common/formats/png/Makefile +++ b/libretro-common/formats/png/Makefile @@ -8,10 +8,8 @@ CFLAGS += -DHAVE_IMLIB2 LDFLAGS += -lImlib2 endif -SOURCES_C := rpng_fbio.c \ - rpng_nbio.c \ +SOURCES_C := rpng.c \ rpng_encode.c \ - rpng_decode.c \ rpng_test.c \ ../../compat/compat.c \ ../../file/nbio/nbio_stdio.c \ diff --git a/libretro-common/formats/png/rpng_decode.c b/libretro-common/formats/png/rpng.c similarity index 75% rename from libretro-common/formats/png/rpng_decode.c rename to libretro-common/formats/png/rpng.c index 95657465c6..4d537016d1 100644 --- a/libretro-common/formats/png/rpng_decode.c +++ b/libretro-common/formats/png/rpng.c @@ -21,6 +21,7 @@ */ #include +#include #include #include @@ -28,11 +29,28 @@ #include #endif +#include +#include +#include #include #include "rpng_internal.h" -#include "rpng_decode.h" +enum png_process_code +{ + PNG_PROCESS_ERROR = -2, + PNG_PROCESS_ERROR_END = -1, + PNG_PROCESS_NEXT = 0, + PNG_PROCESS_END = 1 +}; + +enum image_process_code +{ + IMAGE_PROCESS_ERROR = -2, + IMAGE_PROCESS_ERROR_END = -1, + IMAGE_PROCESS_NEXT = 0, + IMAGE_PROCESS_END = 1, +}; enum png_chunk_type png_chunk_type(const struct png_chunk *chunk) { @@ -702,3 +720,308 @@ bool rpng_load_image_argb_process_init(rpng_t *rpng, return true; } + +static bool read_chunk_header(uint8_t *buf, struct png_chunk *chunk) +{ + unsigned i; + uint8_t dword[4] = {0}; + + for (i = 0; i < 4; i++) + dword[i] = buf[i]; + + buf += 4; + + chunk->size = dword_be(dword); + + for (i = 0; i < 4; i++) + chunk->type[i] = buf[i]; + + buf += 4; + + return true; +} + +static bool png_parse_ihdr(uint8_t *buf, + struct png_ihdr *ihdr) +{ + buf += 4 + 4; + + ihdr->width = dword_be(buf + 0); + ihdr->height = dword_be(buf + 4); + ihdr->depth = buf[8]; + ihdr->color_type = buf[9]; + ihdr->compression = buf[10]; + ihdr->filter = buf[11]; + ihdr->interlace = buf[12]; + + if (ihdr->width == 0 || ihdr->height == 0) + return false; + + return true; +} + +bool rpng_nbio_load_image_argb_iterate(rpng_t *rpng) +{ + unsigned i; + unsigned ret; + uint8_t *buf = (uint8_t*)rpng->buff_data; + + struct png_chunk chunk = {0}; + + if (!read_chunk_header(buf, &chunk)) + return false; + +#if 0 + for (i = 0; i < 4; i++) + { + fprintf(stderr, "chunktype: %c\n", chunk.type[i]); + } +#endif + + switch (png_chunk_type(&chunk)) + { + case PNG_CHUNK_NOOP: + default: + break; + + case PNG_CHUNK_ERROR: + goto error; + + case PNG_CHUNK_IHDR: + if (rpng->has_ihdr || rpng->has_idat || rpng->has_iend) + goto error; + + if (chunk.size != 13) + goto error; + + if (!png_parse_ihdr(buf, &rpng->ihdr)) + goto error; + + if (!png_process_ihdr(&rpng->ihdr)) + goto error; + + rpng->has_ihdr = true; + break; + + case PNG_CHUNK_PLTE: + { + unsigned entries = chunk.size / 3; + + if (!rpng->has_ihdr || rpng->has_plte || rpng->has_iend || rpng->has_idat) + goto error; + + if (chunk.size % 3) + goto error; + + if (entries > 256) + goto error; + + buf += 8; + + if (!png_read_plte(buf, rpng->palette, entries)) + goto error; + + rpng->has_plte = true; + } + break; + + case PNG_CHUNK_IDAT: + if (!(rpng->has_ihdr) || rpng->has_iend || (rpng->ihdr.color_type == PNG_IHDR_COLOR_PLT && !(rpng->has_plte))) + goto error; + + if (!png_realloc_idat(&chunk, &rpng->idat_buf)) + goto error; + + buf += 8; + + for (i = 0; i < chunk.size; i++) + rpng->idat_buf.data[i + rpng->idat_buf.size] = buf[i]; + + rpng->idat_buf.size += chunk.size; + + rpng->has_idat = true; + break; + + case PNG_CHUNK_IEND: + if (!(rpng->has_ihdr) || !(rpng->has_idat)) + goto error; + + rpng->has_iend = true; + goto error; + } + + ret = 4 + 4 + chunk.size + 4; + rpng->buff_data += ret; + + return true; + +error: + return false; +} + +int rpng_nbio_load_image_argb_process(rpng_t *rpng, + uint32_t **data, unsigned *width, unsigned *height) +{ + if (!rpng->process.initialized) + { + if (!rpng_load_image_argb_process_init(rpng, data, width, + height)) + return PNG_PROCESS_ERROR; + return 0; + } + + if (!rpng->process.inflate_initialized) + { + int ret = rpng_load_image_argb_process_inflate_init(rpng, data, + width, height); + if (ret == -1) + return PNG_PROCESS_ERROR; + return 0; + } + + return png_reverse_filter_iterate(rpng, data); +} + +void rpng_nbio_load_image_free(rpng_t *rpng) +{ + if (!rpng) + return; + + if (rpng->idat_buf.data) + free(rpng->idat_buf.data); + if (rpng->process.inflate_buf) + free(rpng->process.inflate_buf); + if (rpng->process.stream) + { + zlib_stream_free(rpng->process.stream); + free(rpng->process.stream); + } + + free(rpng); +} + +bool rpng_nbio_load_image_argb_start(rpng_t *rpng) +{ + unsigned i; + char header[8] = {0}; + + if (!rpng) + return false; + + for (i = 0; i < 8; i++) + header[i] = rpng->buff_data[i]; + + if (memcmp(header, png_magic, sizeof(png_magic)) != 0) + return false; + + rpng->buff_data += 8; + + return true; +} + +bool rpng_is_valid(rpng_t *rpng) +{ + if (!rpng) + return false; + + if (rpng->has_ihdr) + return true; + if (rpng->has_idat) + return true; + if (rpng->has_iend) + return true; + return false; +} + +bool rpng_set_buf_ptr(rpng_t *rpng, uint8_t *data) +{ + if (!rpng) + return false; + + rpng->buff_data = data; + + return true; +} + +rpng_t *rpng_alloc(void) +{ + rpng_t *rpng = (rpng_t*)calloc(1, sizeof(rpng_t)); + if (!rpng) + return NULL; + return rpng; +} + +bool rpng_load_image_argb(const char *path, uint32_t **data, + unsigned *width, unsigned *height) +{ + int retval; + size_t file_len; + bool ret = true; + rpng_t *rpng = NULL; + void *ptr = NULL; + struct nbio_t* handle = (void*)nbio_open(path, NBIO_READ); + + if (!handle) + goto end; + + ptr = nbio_get_ptr(handle, &file_len); + + nbio_begin_read(handle); + + while (!nbio_iterate(handle)); + + ptr = nbio_get_ptr(handle, &file_len); + + if (!ptr) + { + ret = false; + goto end; + } + + rpng = rpng_alloc(); + + if (!rpng) + { + ret = false; + goto end; + } + + if (!rpng_set_buf_ptr(rpng, (uint8_t*)ptr)) + { + ret = false; + goto end; + } + + if (!rpng_nbio_load_image_argb_start(rpng)) + { + ret = false; + goto end; + } + + while (rpng_nbio_load_image_argb_iterate(rpng)); + + if (!rpng_is_valid(rpng)) + { + ret = false; + goto end; + } + + do + { + retval = rpng_nbio_load_image_argb_process(rpng, data, width, height); + }while(retval == IMAGE_PROCESS_NEXT); + + if (retval == IMAGE_PROCESS_ERROR || retval == IMAGE_PROCESS_ERROR_END) + ret = false; + +end: + if (handle) + nbio_free(handle); + if (rpng) + rpng_nbio_load_image_free(rpng); + rpng = NULL; + if (!ret) + free(*data); + return ret; +} + diff --git a/libretro-common/formats/png/rpng_decode.h b/libretro-common/formats/png/rpng_decode.h deleted file mode 100644 index 94c47a45f2..0000000000 --- a/libretro-common/formats/png/rpng_decode.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2010-2015 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (rpng.c). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _RPNG_DECODE_H -#define _RPNG_DECODE_H - -enum png_process_code -{ - PNG_PROCESS_ERROR = -2, - PNG_PROCESS_ERROR_END = -1, - PNG_PROCESS_NEXT = 0, - PNG_PROCESS_END = 1 -}; - -enum png_chunk_type png_chunk_type(const struct png_chunk *chunk); - -bool png_process_ihdr(struct png_ihdr *ihdr); - -bool png_read_plte(uint8_t *buf, - uint32_t *buffer, unsigned entries); - -bool png_realloc_idat(const struct png_chunk *chunk, struct idat_buffer *buf); - -int png_reverse_filter_iterate(rpng_t *rpng, uint32_t **data); - -bool rpng_load_image_argb_process_init(rpng_t *rpng, - uint32_t **data, unsigned *width, unsigned *height); - -#endif diff --git a/libretro-common/formats/png/rpng_fbio.c b/libretro-common/formats/png/rpng_fbio.c deleted file mode 100644 index dd582d3f9f..0000000000 --- a/libretro-common/formats/png/rpng_fbio.c +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2010-2015 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (rpng.c). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "rpng_internal.h" -#include "rpng_decode.h" - -enum image_process_code -{ - IMAGE_PROCESS_ERROR = -2, - IMAGE_PROCESS_ERROR_END = -1, - IMAGE_PROCESS_NEXT = 0, - IMAGE_PROCESS_END = 1, -}; - -bool rpng_load_image_argb(const char *path, uint32_t **data, - unsigned *width, unsigned *height) -{ - int retval; - size_t file_len; - bool ret = true; - rpng_t *rpng = NULL; - void *ptr = NULL; - struct nbio_t* handle = (void*)nbio_open(path, NBIO_READ); - - if (!handle) - goto end; - - ptr = nbio_get_ptr(handle, &file_len); - - nbio_begin_read(handle); - - while (!nbio_iterate(handle)); - - ptr = nbio_get_ptr(handle, &file_len); - - if (!ptr) - { - ret = false; - goto end; - } - - rpng = rpng_alloc(); - - if (!rpng) - { - ret = false; - goto end; - } - - if (!rpng_set_buf_ptr(rpng, (uint8_t*)ptr)) - { - ret = false; - goto end; - } - - if (!rpng_nbio_load_image_argb_start(rpng)) - { - ret = false; - goto end; - } - - while (rpng_nbio_load_image_argb_iterate(rpng)); - - if (!rpng_is_valid(rpng)) - { - ret = false; - goto end; - } - - do - { - retval = rpng_nbio_load_image_argb_process(rpng, data, width, height); - }while(retval == IMAGE_PROCESS_NEXT); - - if (retval == IMAGE_PROCESS_ERROR || retval == IMAGE_PROCESS_ERROR_END) - ret = false; - -end: - if (handle) - nbio_free(handle); - if (rpng) - rpng_nbio_load_image_free(rpng); - rpng = NULL; - if (!ret) - free(*data); - return ret; -} diff --git a/libretro-common/formats/png/rpng_nbio.c b/libretro-common/formats/png/rpng_nbio.c deleted file mode 100644 index e70f4cdf03..0000000000 --- a/libretro-common/formats/png/rpng_nbio.c +++ /dev/null @@ -1,258 +0,0 @@ -/* Copyright (C) 2010-2015 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (rpng.c). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include - -#include "rpng_internal.h" -#include "rpng_decode.h" - -static bool read_chunk_header(uint8_t *buf, struct png_chunk *chunk) -{ - unsigned i; - uint8_t dword[4] = {0}; - - for (i = 0; i < 4; i++) - dword[i] = buf[i]; - - buf += 4; - - chunk->size = dword_be(dword); - - for (i = 0; i < 4; i++) - chunk->type[i] = buf[i]; - - buf += 4; - - return true; -} - -static bool png_parse_ihdr(uint8_t *buf, - struct png_ihdr *ihdr) -{ - buf += 4 + 4; - - ihdr->width = dword_be(buf + 0); - ihdr->height = dword_be(buf + 4); - ihdr->depth = buf[8]; - ihdr->color_type = buf[9]; - ihdr->compression = buf[10]; - ihdr->filter = buf[11]; - ihdr->interlace = buf[12]; - - if (ihdr->width == 0 || ihdr->height == 0) - return false; - - return true; -} - -bool rpng_nbio_load_image_argb_iterate(rpng_t *rpng) -{ - unsigned i; - unsigned ret; - uint8_t *buf = (uint8_t*)rpng->buff_data; - - struct png_chunk chunk = {0}; - - if (!read_chunk_header(buf, &chunk)) - return false; - -#if 0 - for (i = 0; i < 4; i++) - { - fprintf(stderr, "chunktype: %c\n", chunk.type[i]); - } -#endif - - switch (png_chunk_type(&chunk)) - { - case PNG_CHUNK_NOOP: - default: - break; - - case PNG_CHUNK_ERROR: - goto error; - - case PNG_CHUNK_IHDR: - if (rpng->has_ihdr || rpng->has_idat || rpng->has_iend) - goto error; - - if (chunk.size != 13) - goto error; - - if (!png_parse_ihdr(buf, &rpng->ihdr)) - goto error; - - if (!png_process_ihdr(&rpng->ihdr)) - goto error; - - rpng->has_ihdr = true; - break; - - case PNG_CHUNK_PLTE: - { - unsigned entries = chunk.size / 3; - - if (!rpng->has_ihdr || rpng->has_plte || rpng->has_iend || rpng->has_idat) - goto error; - - if (chunk.size % 3) - goto error; - - if (entries > 256) - goto error; - - buf += 8; - - if (!png_read_plte(buf, rpng->palette, entries)) - goto error; - - rpng->has_plte = true; - } - break; - - case PNG_CHUNK_IDAT: - if (!(rpng->has_ihdr) || rpng->has_iend || (rpng->ihdr.color_type == PNG_IHDR_COLOR_PLT && !(rpng->has_plte))) - goto error; - - if (!png_realloc_idat(&chunk, &rpng->idat_buf)) - goto error; - - buf += 8; - - for (i = 0; i < chunk.size; i++) - rpng->idat_buf.data[i + rpng->idat_buf.size] = buf[i]; - - rpng->idat_buf.size += chunk.size; - - rpng->has_idat = true; - break; - - case PNG_CHUNK_IEND: - if (!(rpng->has_ihdr) || !(rpng->has_idat)) - goto error; - - rpng->has_iend = true; - goto error; - } - - ret = 4 + 4 + chunk.size + 4; - rpng->buff_data += ret; - - return true; - -error: - return false; -} - -int rpng_nbio_load_image_argb_process(rpng_t *rpng, - uint32_t **data, unsigned *width, unsigned *height) -{ - if (!rpng->process.initialized) - { - if (!rpng_load_image_argb_process_init(rpng, data, width, - height)) - return PNG_PROCESS_ERROR; - return 0; - } - - if (!rpng->process.inflate_initialized) - { - int ret = rpng_load_image_argb_process_inflate_init(rpng, data, - width, height); - if (ret == -1) - return PNG_PROCESS_ERROR; - return 0; - } - - return png_reverse_filter_iterate(rpng, data); -} - -void rpng_nbio_load_image_free(rpng_t *rpng) -{ - if (!rpng) - return; - - if (rpng->idat_buf.data) - free(rpng->idat_buf.data); - if (rpng->process.inflate_buf) - free(rpng->process.inflate_buf); - if (rpng->process.stream) - { - zlib_stream_free(rpng->process.stream); - free(rpng->process.stream); - } - - free(rpng); -} - -bool rpng_nbio_load_image_argb_start(rpng_t *rpng) -{ - unsigned i; - char header[8] = {0}; - - if (!rpng) - return false; - - for (i = 0; i < 8; i++) - header[i] = rpng->buff_data[i]; - - if (memcmp(header, png_magic, sizeof(png_magic)) != 0) - return false; - - rpng->buff_data += 8; - - return true; -} - -bool rpng_is_valid(rpng_t *rpng) -{ - if (!rpng) - return false; - - if (rpng->has_ihdr) - return true; - if (rpng->has_idat) - return true; - if (rpng->has_iend) - return true; - return false; -} - -bool rpng_set_buf_ptr(rpng_t *rpng, uint8_t *data) -{ - if (!rpng) - return false; - - rpng->buff_data = data; - - return true; -} - -rpng_t *rpng_alloc(void) -{ - rpng_t *rpng = (rpng_t*)calloc(1, sizeof(rpng_t)); - if (!rpng) - return NULL; - return rpng; -}