From 68a600f67993cef488961e491f8ce3d054099786 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Tue, 29 Dec 2015 16:21:08 +0000 Subject: [PATCH] finish converting last lodepng calls to libpng --- src/cmdline_sprite.c | 19 +++----- src/image_io.c | 109 +++++++++++++++++++++++++++++++++++++++++++ src/image_io.h | 2 + 3 files changed, 118 insertions(+), 12 deletions(-) diff --git a/src/cmdline_sprite.c b/src/cmdline_sprite.c index 7f4c12974f..c7fc2eec5c 100644 --- a/src/cmdline_sprite.c +++ b/src/cmdline_sprite.c @@ -18,13 +18,12 @@ * along with this program. If not, see . *****************************************************************************/ -#include #include "cmdline.h" #include "drawing/drawing.h" #include "image_io.h" +#include "openrct2.h" #include "platform/platform.h" #include "util/util.h" -#include "openrct2.h" #define MODE_DEFAULT 0 #define MODE_CLOSEST 1 @@ -240,16 +239,10 @@ typedef struct { bool sprite_file_import(const char *path, rct_g1_element *outElement, uint8 **outBuffer, int *outBufferLength, int mode) { - unsigned char *pixels; - unsigned int width, height; - unsigned int pngError; - - memcpy(spriteFilePalette, _standardPalette, 256 * 4); - - pngError = lodepng_decode_file(&pixels, &width, &height, path, LCT_RGBA, 8); - if (pngError != 0) { - free(pixels); - fprintf(stderr, "Error creating PNG data, %u: %s", pngError, lodepng_error_text(pngError)); + uint8 *pixels; + uint32 width, height; + if (!image_io_png_read(&pixels, &width, &height, path)) { + fprintf(stderr, "Error reading PNG"); return false; } @@ -259,6 +252,8 @@ bool sprite_file_import(const char *path, rct_g1_element *outElement, uint8 **ou return false; } + memcpy(spriteFilePalette, _standardPalette, 256 * 4); + uint8 *buffer = malloc((height * 2) + (width * height * 16)); memset(buffer, 0, (height * 2) + (width * height * 16)); uint16 *yOffsets = (uint16*)buffer; diff --git a/src/image_io.c b/src/image_io.c index d6e90decbc..cc14cc012c 100644 --- a/src/image_io.c +++ b/src/image_io.c @@ -7,10 +7,113 @@ #include "image_io.h" #ifdef USE_LIBPNG + static void my_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length); static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length); static void my_png_flush(png_structp png_ptr); #endif +bool image_io_png_read(uint8 **pixels, uint32 *width, uint32 *height, const utf8 *path) +{ +#ifdef USE_LIBPNG + png_structp png_ptr; + png_infop info_ptr; + unsigned int sig_read = 0; + + // Setup PNG structures + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + return false; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return false; + } + + // Open PNG file + SDL_RWops *fp = SDL_RWFromFile(path, "rb"); + if (fp == NULL) { + return false; + } + + // Set error handling + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + SDL_RWclose(fp); + return false; + } + + // Setup png reading + png_set_read_fn(png_ptr, fp, my_png_read_data); + png_set_sig_bytes(png_ptr, sig_read); + + // To simplify the reading process, convert 4-16 bit data to 24-32 bit data + png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL); + + // Read header + png_uint_32 pngWidth, pngHeight; + int bit_depth, color_type, interlace_type; + png_get_IHDR(png_ptr, info_ptr, &pngWidth, &pngHeight, &bit_depth, &color_type, &interlace_type, NULL, NULL); + + // Read pixels as 32bpp RGBA data + png_size_t rowBytes = png_get_rowbytes(png_ptr, info_ptr); + png_bytepp rowPointers = png_get_rows(png_ptr, info_ptr); + uint8 *pngPixels = (uint8*)malloc(pngWidth * pngHeight * 4); + uint8 *dst = pngPixels; + if (color_type == PNG_COLOR_TYPE_RGB) { + // 24-bit PNG (no alpha) + const png_size_t expectedRowSize = pngWidth * 3; + for (png_uint_32 i = 0; i < pngHeight; i++) { + assert(rowBytes == expectedRowSize); + + uint8 *src = rowPointers[i]; + for (png_uint_32 x = 0; x < pngWidth; x++) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = 255; + } + } + } else { + // 32-bit PNG (with alpha) + const png_size_t expectedRowSize = pngWidth * 4; + for (png_uint_32 i = 0; i < pngHeight; i++) { + assert(rowBytes == expectedRowSize); + + memcpy(dst, rowPointers[i], rowBytes); + dst += rowBytes; + } + } + + // Close the PNG + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + SDL_RWclose(fp); + + // Return the output data + *pixels = (uint8*)pngPixels; + if (width != NULL) *width = pngWidth; + if (height != NULL) *height = pngHeight; + return true; +#else + // Read the pixels as 32bpp RGBA + unsigned char *pngPixels; + unsigned int pngWidth, pngHeight; + unsigned int pngError = lodepng_decode_file(&pngPixels, &pngWidth, &pngHeight, path, LCT_RGBA, 8); + if (pngError != 0) { + free(pngPixels); + log_error("Error creating PNG data, %u: %s", pngError, lodepng_error_text(pngError)); + return false; + } + + // Return the output data + *pixels = (uint8*)pngPixels; + if (width != NULL) *width = pngWidth; + if (height != NULL) *height = pngHeight; + return true; +#endif +} + bool image_io_png_write(const rct_drawpixelinfo *dpi, const rct_palette *palette, const utf8 *path) { #ifdef USE_LIBPNG @@ -123,6 +226,12 @@ bool image_io_png_write(const rct_drawpixelinfo *dpi, const rct_palette *palette #ifdef USE_LIBPNG +static void my_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + SDL_RWops *file = (SDL_RWops*)png_get_io_ptr(png_ptr); + SDL_RWread(file, data, length, 1); +} + static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { SDL_RWops *file = (SDL_RWops*)png_get_io_ptr(png_ptr); diff --git a/src/image_io.h b/src/image_io.h index 70ce4cdcc7..fa8c086b05 100644 --- a/src/image_io.h +++ b/src/image_io.h @@ -4,6 +4,8 @@ #include "common.h" #include "drawing/drawing.h" +bool image_io_png_read(uint8 **pixels, uint32 *width, uint32 *height, const utf8 *path); + bool image_io_png_write(const rct_drawpixelinfo *dpi, const rct_palette *palette, const utf8 *path); bool image_io_bmp_write(const rct_drawpixelinfo *dpi, const rct_palette *palette, const utf8 *path);