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 */
+