From 3108896b1a65288da6ae5e3e0b04a2f47c95c8b9 Mon Sep 17 00:00:00 2001 From: dinkc64 Date: Thu, 18 Jul 2019 23:31:56 -0400 Subject: [PATCH] PNGLoadBitmapBuffer(): load png from memory buffer - for future use --- src/burner/burner.h | 3 + src/burner/image.cpp | 177 +++++++++++++++++++++++++++++++ src/burner/win32/burner_win32.h | 1 + src/burner/win32/image_win32.cpp | 11 ++ 4 files changed, 192 insertions(+) diff --git a/src/burner/burner.h b/src/burner/burner.h index 6c1ad43f5..91ab256fe 100644 --- a/src/burner/burner.h +++ b/src/burner/burner.h @@ -74,8 +74,11 @@ void img_free(IMAGE* img); INT32 img_alloc(IMAGE* img); bool PNGIsImage(FILE* fp); +bool PNGIsImageBuffer(unsigned char* buffer, int bufferLength); INT32 PNGLoad(IMAGE* img, FILE* fp, INT32 nPreset); +INT32 PNGLoadBuffer(IMAGE* img, unsigned char* buffer, int bufferLength, INT32 nPreset); INT32 PNGGetInfo(IMAGE* img, FILE *fp); +INT32 PNGGetInfoBuffer(IMAGE* img, unsigned char* buffer, int bufferLength); // gami.cpp extern struct GameInp* GameInp; diff --git a/src/burner/image.cpp b/src/burner/image.cpp index 72a1dfe4e..299b579c8 100644 --- a/src/burner/image.cpp +++ b/src/burner/image.cpp @@ -575,6 +575,183 @@ INT32 PNGGetInfo(IMAGE* img, FILE *fp) png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } + memcpy(img, &temp_img, sizeof(IMAGE)); + img_free(&temp_img); + + return 0; +} + +// ----- Memory PNG v.00001 + +struct ImageSource +{ + UINT8 *data; + int size; + int offset; +}; + +bool PNGIsImageBuffer(unsigned char* buffer, int bufferLength) +{ + if (buffer && bufferLength >= PNG_SIG_CHECK_BYTES && png_sig_cmp(buffer, 0, PNG_SIG_CHECK_BYTES) == 0) { + return true; + } + + return false; +} + +static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length) +{ + ImageSource* isource = (ImageSource*)png_get_io_ptr(png_ptr); + + if (isource == NULL) { + return; + } + + if ((int)(isource->offset + length) <= isource->size) + { + memcpy(data, isource->data + isource->offset, length); + isource->offset += length; + } + else + png_error(png_ptr, "pngReaderCallback failed"); +} + + +INT32 PNGLoadBuffer(IMAGE* img, unsigned char* buffer, int bufferLength, INT32 nPreset) +{ + IMAGE temp_img; + png_uint_32 width = 0, height = 0; + INT32 bit_depth, color_type; + + if (png_sig_cmp(buffer, 0, PNG_SIG_CHECK_BYTES)) { + return 1; + } + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + return 1; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + return 1; + } + + static ImageSource imgsource; + imgsource.data = buffer; + imgsource.size = bufferLength; + imgsource.offset = 0; + png_set_read_fn(png_ptr, &imgsource, pngReadCallback); + + memset(&temp_img, 0, sizeof(IMAGE)); + png_read_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + return 1; + } + + // Instruct libpng to convert the image to 24-bit RGB format + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + } + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + } + if (bit_depth == 16) { + png_set_strip_16(png_ptr); + } + if (color_type & PNG_COLOR_MASK_ALPHA) { + png_set_strip_alpha(png_ptr); + } + + temp_img.width = width; + temp_img.height = height; + + // Initialize our img structure + if (img_alloc(&temp_img)) { + //longjmp(png_ptr->jmpbuf, 1); + png_jmpbuf(png_ptr); + } + + // If bad things happen in libpng we need to do img_free(&temp_img) as well + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + img_free(&temp_img); + return 1; + } + + // Read the .PNG image + png_set_bgr(png_ptr); + png_read_update_info(png_ptr, info_ptr); + png_read_image(png_ptr, temp_img.rowptr); + png_read_end(png_ptr, (png_infop)NULL); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + + if (img_process(&temp_img, img->width ? img->width : temp_img.width, img->height ? img->height : temp_img.height, nPreset, false)) { + img_free(&temp_img); + return 1; + } + + bPngImageOrientation = 0; + if (height && width && height > width) bPngImageOrientation = 1; + + memcpy(img, &temp_img, sizeof(IMAGE)); + + return 0; +} + +INT32 PNGGetInfoBuffer(IMAGE* img, unsigned char* buffer, int bufferLength) +{ + IMAGE temp_img; + png_uint_32 width = 0, height = 0; + INT32 bit_depth, color_type; + + if (png_sig_cmp(buffer, 0, PNG_SIG_CHECK_BYTES)) { + return 1; + } + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + return 1; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + return 1; + } + + ImageSource imgsource; + imgsource.data = buffer; + imgsource.size = bufferLength; + imgsource.offset = 0; + png_set_read_fn(png_ptr, &imgsource, pngReadCallback); + + memset(&temp_img, 0, sizeof(IMAGE)); + + png_set_sig_bytes(png_ptr, PNG_SIG_CHECK_BYTES); + png_read_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + return 1; + } + + temp_img.width = width; + temp_img.height = height; + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + return 1; + } + + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + + memcpy(img, &temp_img, sizeof(IMAGE)); img_free(&temp_img); diff --git a/src/burner/win32/burner_win32.h b/src/burner/win32/burner_win32.h index 82cb8433f..2b82885bc 100644 --- a/src/burner/win32/burner_win32.h +++ b/src/burner/win32/burner_win32.h @@ -337,6 +337,7 @@ extern TCHAR szNeoCDGamesDir[MAX_PATH]; HBITMAP ImageToBitmap(HWND hwnd, IMAGE* img); HBITMAP PNGLoadBitmap(HWND hWnd, FILE* fp, int nWidth, int nHeight, int nPreset); +HBITMAP PNGLoadBitmapBuffer(HWND hWnd, unsigned char* buffer, int bufferLength, int nWidth, int nHeight, int nPreset); HBITMAP LoadBitmap(HWND hWnd, FILE* fp, int nWidth, int nHeight, int nPreset); // cona.cpp diff --git a/src/burner/win32/image_win32.cpp b/src/burner/win32/image_win32.cpp index 1a9b24d54..f33596a15 100644 --- a/src/burner/win32/image_win32.cpp +++ b/src/burner/win32/image_win32.cpp @@ -44,6 +44,17 @@ HBITMAP PNGLoadBitmap(HWND hWnd, FILE* fp, int nWidth, int nHeight, int nPreset) return ImageToBitmap(hWnd, &img); } +HBITMAP PNGLoadBitmapBuffer(HWND hWnd, unsigned char* buffer, int bufferLength, int nWidth, int nHeight, int nPreset) +{ + IMAGE img = { nWidth, nHeight, 0, 0, NULL, NULL, 0}; + + if (PNGLoadBuffer(&img, buffer, bufferLength, nPreset)) { + return NULL; + } + + return ImageToBitmap(hWnd, &img); +} + HBITMAP LoadBitmap(HWND hWnd, FILE* fp, int nWidth, int nHeight, int nPreset) { if (hWnd == NULL || fp == NULL) {