diff --git a/configure.ac b/configure.ac index d7145f83..13bb5375 100644 --- a/configure.ac +++ b/configure.ac @@ -1348,12 +1348,30 @@ if test "x$build_jpg_support" != "xno"; then fi dnl Check for PNG library. +libpng_version="no" if test "x$build_png_support" != "xno"; then - AC_CHECK_LIB(png, png_check_sig, - DEP_LIBS="$DEP_LIBS -lpng", - build_png_support=no, -lz -lm) + AC_CHECK_LIB(png12, png_check_sig, + libpng_version="12", + libpng_version="no", -lz -lm) + if test "x$libpng_version" == "xno"; then + AC_CHECK_LIB(png16, png_sig_cmp, + libpng_version="16", + libpng_version="no", -lz -lm) + fi fi +case "$libpng_version" in + 12) + DEP_LIBS="$DEP_LIBS -lpng12" + ;; + 16) + DEP_LIBS="$DEP_LIBS -lpng16" + ;; + *) + build_png_support="no" + ;; +esac + AC_DEFINE_UNQUOTED(MINIGUI_MAJOR_VERSION, $MINIGUI_MAJOR_VERSION, [Major version of MiniGUI]) AC_DEFINE_UNQUOTED(MINIGUI_MINOR_VERSION, $MINIGUI_MINOR_VERSION, @@ -2311,6 +2329,8 @@ fi if test "x$build_png_support" = "xyes"; then AC_DEFINE(_MGIMAGE_PNG, 1, [Define if support PNG bmp file format]) + AC_DEFINE_UNQUOTED(_MGLIBPNG_VER, $libpng_version, + [Define version of libpng]) fi if test "x$build_menu" = "xyes"; then diff --git a/src/mybmp/Makefile.am b/src/mybmp/Makefile.am index f2f59d7f..2d4002c4 100644 --- a/src/mybmp/Makefile.am +++ b/src/mybmp/Makefile.am @@ -2,9 +2,9 @@ AM_CPPFLAGS = -I$(abs_top_srcdir)/src/include -I$(abs_top_srcdir)/include noinst_LTLIBRARIES = libmybmp.la -SRC_FILES = mybmp.c winbmp.c gif.c jpeg.c png.c lbm.c pcx.c tga.c +SRC_FILES = mybmp.c winbmp.c gif.c jpeg.c png12.c png16.c lbm.c pcx.c tga.c -libmybmp_la_SOURCES = $(SRC_FILES) +libmybmp_la_SOURCES = $(SRC_FILES) EXTRA_DIST=makefile.ng makefile.msvc diff --git a/src/mybmp/png.c b/src/mybmp/png12.c similarity index 96% rename from src/mybmp/png.c rename to src/mybmp/png12.c index fc9638b8..eb2717dc 100644 --- a/src/mybmp/png.c +++ b/src/mybmp/png12.c @@ -1,39 +1,39 @@ /* - * This file is part of MiniGUI, a mature cross-platform windowing + * This file is part of MiniGUI, a mature cross-platform windowing * and Graphics User Interface (GUI) support system for embedded systems * and smart IoT devices. - * + * * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. * Copyright (C) 1998~2002, WEI Yongming - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * Or, - * + * * As this program is a library, any link to this program must follow * GNU General Public License version 3 (GPLv3). If you cannot accept * GPLv3, you need to be licensed from FMSoft. - * + * * If you have got a commercial license of this program, please use it * under the terms and conditions of the commercial license. - * + * * For more information about the commercial license, please refer to * . */ /* -** png.c: Low-level PNG file read routines. -** +** png12.c: Low-level PNG file read routines (based on LibPNG 1.2) +** ** Current maintainer: Wei Yongming ** ** Create date: 2001/01/10 @@ -47,6 +47,7 @@ #include "gdi.h" #ifdef _MGIMAGE_PNG +#if _MGLIBPNG_VER == 12 #include @@ -59,12 +60,12 @@ typedef struct { typedef unsigned char uch; typedef unsigned long ulg; -static void my_read_data_fn (png_structp png_ptr, png_bytep data, +static void my_read_data_fn (png_structp png_ptr, png_bytep data, png_size_t length) { png_size_t check; - check = (png_size_t)MGUI_RWread ((MG_RWops*)png_ptr->io_ptr, + check = (png_size_t)MGUI_RWread ((MG_RWops*)png_ptr->io_ptr, data, (png_size_t)1, length); if (check != length) @@ -77,8 +78,8 @@ static void my_read_data_fn (png_structp png_ptr, png_bytep data, #define _PNG_INIT_OK 0 -static int readpng_init (png_structpp png_pptr, png_infopp info_pptr, - MG_RWops* src, ulg* width, ulg* height, +static int readpng_init (png_structpp png_pptr, png_infopp info_pptr, + MG_RWops* src, ulg* width, ulg* height, int* bitdepth, int* colortype) { uch sig[9]; @@ -97,7 +98,7 @@ static int readpng_init (png_structpp png_pptr, png_infopp info_pptr, #endif } - *png_pptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, + *png_pptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if (!*png_pptr){ return _PNG_MEM_ALLOC; @@ -129,7 +130,7 @@ static int readpng_init (png_structpp png_pptr, png_infopp info_pptr, } #if 0 -static void get_transparent_info (png_structp png_ptr, png_infop info_ptr, +static void get_transparent_info (png_structp png_ptr, png_infop info_ptr, int bit_depth, int color_type, MYBITMAP* bmp) { png_bytep trans; @@ -193,7 +194,7 @@ void* __mg_init_png(MG_RWops * fp, MYBITMAP * mybmp, RGB * pal) png_ptr = &png_data->png_ptr; info_ptr = &png_data->info_ptr; - if ((rc = readpng_init(png_ptr, info_ptr, fp, &width, &height, + if ((rc = readpng_init(png_ptr, info_ptr, fp, &width, &height, &bit_depth, &color_type)) != 0) { switch (rc) { case _PNG_SIG_ERROR: @@ -266,7 +267,7 @@ void* __mg_init_png(MG_RWops * fp, MYBITMAP * mybmp, RGB * pal) _ERR_PRINTF ("__mg_init_png: bad pixel_depth: %d\n", mybmp->depth); goto err; } - + mybmp->pitch = png_get_rowbytes (*png_ptr, *info_ptr); return png_data; @@ -293,7 +294,7 @@ void __mg_cleanup_png(void * init_info) free(init_info); } -int __mg_load_png (MG_RWops * fp, void * init_info, MYBITMAP * my_bmp, +int __mg_load_png (MG_RWops * fp, void * init_info, MYBITMAP * my_bmp, CB_ONE_SCANLINE cb, void * context) { png_init_info_t * info = (png_init_info_t *)init_info; @@ -353,9 +354,10 @@ BOOL __mg_check_png (MG_RWops* fp) { unsigned char sig [9]; - MGUI_RWread (fp, sig, 8, 1); + MGUI_RWread (fp, sig, 8, 1); return png_check_sig (sig, 8); } +#endif /* _MGLIBPNG_VER == 12 */ #endif /* _MGIMAGE_PNG */ diff --git a/src/mybmp/png16.c b/src/mybmp/png16.c new file mode 100644 index 00000000..aa4e46a0 --- /dev/null +++ b/src/mybmp/png16.c @@ -0,0 +1,374 @@ +/* + * This file is part of MiniGUI, a mature cross-platform windowing + * and Graphics User Interface (GUI) support system for embedded systems + * and smart IoT devices. + * + * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 1998~2002, WEI Yongming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Or, + * + * As this program is a library, any link to this program must follow + * GNU General Public License version 3 (GPLv3). If you cannot accept + * GPLv3, you need to be licensed from FMSoft. + * + * If you have got a commercial license of this program, please use it + * under the terms and conditions of the commercial license. + * + * For more information about the commercial license, please refer to + * . + */ +/* +** png16.c: Low-level PNG file read routines (based on LibPNG 1.6) +** +** Current maintainer: Wei Yongming +** +** Create date: 2019/04/12 +*/ + +#include +#include +#include + +#include "common.h" +#include "gdi.h" + +#ifdef _MGIMAGE_PNG +#if _MGLIBPNG_VER == 16 + +#include + +typedef struct { + png_structp png_ptr; + png_infop info_ptr; + BOOL interlaced; +} PngInitInfo; + + +typedef unsigned char uch; +typedef unsigned long ulg; + +static void my_read_data_fn (png_structp png_ptr, png_bytep data, + png_size_t length) +{ + png_size_t check; + png_voidp io_ptr = png_get_io_ptr(png_ptr); + + check = (png_size_t)MGUI_RWread ((MG_RWops*)io_ptr, + data, (png_size_t)1, length); + + if (check != length) + png_error(png_ptr, "Read Error"); +} + +#define _PNG_SIG_ERROR 1 +#define _PNG_MEM_ALLOC 2 +#define _PNG_LIB_ERROR 3 + +#define _PNG_INIT_OK 0 + +static int readpng_init (png_structpp png_pptr, png_infopp info_pptr, + MG_RWops* src, png_uint_32* width, png_uint_32* height, + int* bitdepth, int* colortype) +{ + uch sig[9]; + + MGUI_RWread (src, sig, 8, 1); + if (!png_check_sig (sig, 8)) { +#ifdef PNG_DEBUG + sig[8] = '\0'; + fprintf (stderr, "%s: check error!\n", sig); +#endif + return _PNG_SIG_ERROR; + } else { +#ifdef PNG_DEBUG + sig[8]='\0'; + fprintf (stderr, "png sig is %s.\n", sig); +#endif + } + + *png_pptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL ); + if (!*png_pptr){ + return _PNG_MEM_ALLOC; + } + + *info_pptr = png_create_info_struct ( *png_pptr ); + if ( !*info_pptr ) { + png_destroy_read_struct (png_pptr, NULL,NULL); + return _PNG_MEM_ALLOC; + } + +#ifdef PNG_SETJMP_SUPPORTED + if (setjmp(png_jmpbuf(*png_pptr))) { + png_destroy_read_struct (png_pptr, info_pptr, NULL); + return _PNG_LIB_ERROR; + } +#endif + + png_set_read_fn (*png_pptr, (void*)src, my_read_data_fn); + + png_set_sig_bytes ( *png_pptr, 8 ); + + png_read_info ( *png_pptr, *info_pptr ); + + png_get_IHDR ( *png_pptr, *info_pptr, width, height, bitdepth, + colortype, NULL, NULL, NULL ); + + return _PNG_INIT_OK; +} + +#if 0 +static void get_transparent_info (png_structp png_ptr, png_infop info_ptr, + int bit_depth, int color_type, MYBITMAP* bmp) +{ + png_bytep trans; + int num_trans; + png_color_16p trans_values; + + if (png_get_tRNS (png_ptr, info_ptr, &trans, &num_trans, &trans_values) + && num_trans) { + gal_uint8 r = 0, g = 0, b = 0; + + switch (color_type) { + case PNG_COLOR_TYPE_GRAY: + if (bit_depth < 8) + trans_values->gray = trans_values->gray << (8 - bit_depth); + r = g = b = trans_values->gray; + break; + + case PNG_COLOR_TYPE_PALETTE: + { + png_colorp pal; + int num_pal; + + if (png_get_PLTE (png_ptr, info_ptr, &pal, &num_pal) && *trans < num_pal) { + r = pal [*trans].red; + g = pal [*trans].green; + b = pal [*trans].blue; + } + break; + } + + case PNG_COLOR_TYPE_RGB: + r = trans_values->red >> 8; + g = trans_values->green >> 8; + b = trans_values->blue >> 8; + break; + } + + bmp->flags |= MYBMP_TRANSPARENT; + bmp->transparent = MakeRGB (r, g, b); + } +} +#endif + +void* __mg_init_png(MG_RWops * fp, MYBITMAP * mybmp, RGB * pal) +{ + int rc; + png_structpp png_ptr; + png_infopp info_ptr; + png_uint_32 width; + png_uint_32 height; + int bit_depth, intent, color_type; + double screen_gamma; + PngInitInfo * png_data = NULL; + + png_data = (PngInitInfo *)malloc(sizeof(PngInitInfo)); + if (!png_data) { + _ERR_PRINTF ("__mg_init_png: failed to allocate memory for PngInitInfo\n"); + return NULL; + } + + png_ptr = &png_data->png_ptr; + info_ptr = &png_data->info_ptr; + + if ((rc = readpng_init(png_ptr, info_ptr, fp, &width, &height, + &bit_depth, &color_type)) != 0) { + switch (rc) { + case _PNG_SIG_ERROR: + case _PNG_MEM_ALLOC: + case _PNG_LIB_ERROR: + default: + _ERR_PRINTF ("__mg_init_png: failed to call readpng_init: %d\n", + rc); + goto err; + } + } + + mybmp->w = width; + mybmp->h = height; + mybmp->frames = 1; + + /* tell libpng to strip 16 bit/color files down to 8 bits/color */ + if (bit_depth == 16) + png_set_strip_16(*png_ptr); + + /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (bit_depth < 8) + png_set_packing(*png_ptr); + + /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ + if ((color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + && bit_depth < 8) { + png_set_expand_gray_1_2_4_to_8(*png_ptr); + } + + /* Expand paletted colors into true RGB triplets */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(*png_ptr); + else if (color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(*png_ptr); + + if (png_get_valid(*png_ptr, *info_ptr, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha (*png_ptr); + mybmp->flags |= MYBMP_FLOW_DOWN | MYBMP_ALPHA | MYBMP_TYPE_RGBA; + color_type = PNG_COLOR_TYPE_RGBA; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) { + mybmp->flags |= MYBMP_FLOW_DOWN | MYBMP_ALPHA | MYBMP_TYPE_RGBA; + } + else { + mybmp->flags |= MYBMP_FLOW_DOWN | MYBMP_TYPE_RGB; + } + + screen_gamma = 2.2; + + if (png_get_sRGB (*png_ptr, *info_ptr, &intent)) + png_set_gamma (*png_ptr, screen_gamma, 0.45455); + else { + double image_gamma; + if (png_get_gAMA (*png_ptr, *info_ptr, &image_gamma)) + png_set_gamma (*png_ptr, screen_gamma, image_gamma); + else + png_set_gamma (*png_ptr, screen_gamma, 0.45455); + } + + png_read_update_info (*png_ptr, *info_ptr); + mybmp->depth = png_get_bit_depth (*png_ptr, *info_ptr); + mybmp->depth *= png_get_channels (*png_ptr, *info_ptr); + if (mybmp->depth == 24) + mybmp->flags |= MYBMP_RGBSIZE_3; + else if (mybmp->depth == 32) + mybmp->flags |= MYBMP_RGBSIZE_4; + else { + _ERR_PRINTF ("__mg_init_png: bad pixel_depth: %d\n", mybmp->depth); + goto err; + } + + mybmp->pitch = png_get_rowbytes (*png_ptr, *info_ptr); + + if (png_get_interlace_type(*png_ptr, *info_ptr) == PNG_INTERLACE_ADAM7) + png_data->interlaced = TRUE; + else + png_data->interlaced = FALSE; + + return png_data; + +err: + _ERR_PRINTF ("__mg_init_png error!\n"); + free (png_data); + return NULL; +} + +void __mg_cleanup_png(void * init_info) +{ + PngInitInfo * info = (PngInitInfo *)init_info; + + if (!info) + return; + + if (info->png_ptr && info->info_ptr) { + png_destroy_read_struct(&info->png_ptr, &info->info_ptr, NULL); + info->png_ptr = NULL; + info->info_ptr = NULL; + } + + free(init_info); +} + +int __mg_load_png (MG_RWops * fp, void * init_info, MYBITMAP * my_bmp, + CB_ONE_SCANLINE cb, void * context) +{ + PngInitInfo * info = (PngInitInfo *)init_info; + png_bytep rp, bits = (png_bytep)my_bmp->bits; + png_uint_32 i, image_height, p, pass; + + pass = png_set_interlace_handling(info->png_ptr); + if (my_bmp->flags & MYBMP_LOAD_ALLOCATE_ONE) + p = 0; + else + p = my_bmp->pitch; + + image_height = png_get_image_height(info->png_ptr, info->info_ptr); + //info->png_ptr->num_rows = image_height; + + if (info->interlaced) { + bits = (png_bytep)malloc(my_bmp->pitch * image_height); + if (!bits) + return ERR_BMP_MEM; + p = my_bmp->pitch; + } + +#ifdef PNG_SETJMP_SUPPORTED + if (setjmp(png_jmpbuf (info->png_ptr))) { + if (info->interlaced) { + free (bits); + } + return ERR_BMP_LOAD; + } +#endif + + while (pass--) { + rp = bits; + for (i = 0; i < image_height; i++, rp += p) { + png_read_row(info->png_ptr, rp, NULL); + if (cb && !p) cb(context, my_bmp, i); + } + } + + png_read_end(info->png_ptr, NULL); + + if (info->interlaced) { + rp = (png_bytep)my_bmp->bits; + my_bmp->bits = (BYTE *)bits; + if (cb) for (i = 0; i < image_height; i++, my_bmp->bits += p) + cb(context, my_bmp, i); + else + memcpy(rp, bits, my_bmp->pitch * image_height); + my_bmp->bits = rp; + free(bits); + } + + return ERR_BMP_OK; +} + +BOOL __mg_check_png (MG_RWops* fp) +{ + unsigned char sig [9]; + + MGUI_RWread (fp, sig, 8, 1); + return png_check_sig (sig, 8); +} + +#endif /* _MGLIBPNG_VER == 16 */ +#endif /* _MGIMAGE_PNG */ +