diff --git a/Makefile.vc b/Makefile.vc index a3f59ddb..f19305a6 100644 --- a/Makefile.vc +++ b/Makefile.vc @@ -171,6 +171,9 @@ DSP_OBJS = \ $(DIROBJ)\dsp\upsampling_sse2.obj \ $(DIROBJ)\dsp\yuv.obj \ +EX_FORMAT_DEC_OBJS = \ + $(DIROBJ)\examples/pngdec.obj \ + EX_UTIL_OBJS = \ $(DIROBJ)\examples\example_util.obj \ @@ -218,7 +221,7 @@ OUT_LIBS = $(LIBWEBP) OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe all: $(OUT_LIBS) $(OUT_EXAMPLES) -$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj +$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(EX_FORMAT_DEC_OBJS) $(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX) $(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(LIBWEBP) diff --git a/examples/Makefile.am b/examples/Makefile.am index 6fd7fc06..1c00640c 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -20,7 +20,8 @@ dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) dwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES) dwebp_LDADD = libexampleutil.la ../src/libwebp.la $(PNG_LIBS) $(JPEG_LIBS) -cwebp_SOURCES = cwebp.c metadata.h stopwatch.h +cwebp_SOURCES = cwebp.c metadata.h stopwatch.h +cwebp_SOURCES += pngdec.c pngdec.h cwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) cwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES) cwebp_LDADD = ../src/libwebp.la $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS) diff --git a/examples/cwebp.c b/examples/cwebp.c index c99e9395..fc5da760 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -18,12 +18,8 @@ #include "config.h" #endif -#ifdef WEBP_HAVE_PNG -#include <png.h> -#endif - #ifdef WEBP_HAVE_JPEG -#include <setjmp.h> // note: this must be included *after* png.h +#include <setjmp.h> #include <jpeglib.h> #endif @@ -47,6 +43,7 @@ #include "webp/encode.h" #include "./metadata.h" +#include "./pngdec.h" #include "./stopwatch.h" #ifndef WEBP_DLL #if defined(__cplusplus) || defined(c_plusplus) @@ -388,106 +385,6 @@ static int ReadJPEG(FILE* in_file, WebPPicture* const pic) { } #endif -#ifdef WEBP_HAVE_PNG -static void PNGAPI error_function(png_structp png, png_const_charp dummy) { - (void)dummy; // remove variable-unused warning - longjmp(png_jmpbuf(png), 1); -} - -static int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha) { - png_structp png; - png_infop info; - int color_type, bit_depth, interlaced; - int has_alpha; - int num_passes; - int p; - int ok = 0; - png_uint_32 width, height, y; - int stride; - uint8_t* rgb = NULL; - - png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); - if (png == NULL) { - goto End; - } - - png_set_error_fn(png, 0, error_function, NULL); - if (setjmp(png_jmpbuf(png))) { - Error: - png_destroy_read_struct(&png, NULL, NULL); - free(rgb); - goto End; - } - - info = png_create_info_struct(png); - if (info == NULL) goto Error; - - png_init_io(png, in_file); - png_read_info(png, info); - if (!png_get_IHDR(png, info, - &width, &height, &bit_depth, &color_type, &interlaced, - NULL, NULL)) goto Error; - - png_set_strip_16(png); - png_set_packing(png); - if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - if (bit_depth < 8) { - png_set_expand_gray_1_2_4_to_8(png); - } - png_set_gray_to_rgb(png); - } - if (png_get_valid(png, info, PNG_INFO_tRNS)) { - png_set_tRNS_to_alpha(png); - has_alpha = 1; - } else { - has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA); - } - - if (!keep_alpha) { - png_set_strip_alpha(png); - has_alpha = 0; - } - - num_passes = png_set_interlace_handling(png); - png_read_update_info(png, info); - stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb); - rgb = (uint8_t*)malloc(stride * height); - if (rgb == NULL) goto Error; - for (p = 0; p < num_passes; ++p) { - for (y = 0; y < height; ++y) { - png_bytep row = rgb + y * stride; - png_read_rows(png, &row, NULL, 1); - } - } - png_read_end(png, info); - png_destroy_read_struct(&png, &info, NULL); - - pic->width = width; - pic->height = height; - ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride) - : WebPPictureImportRGB(pic, rgb, stride); - free(rgb); - - if (ok && has_alpha && keep_alpha == 2) { - WebPCleanupTransparentArea(pic); - } - - End: - return ok; -} -#else -static int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha) { - (void)in_file; - (void)pic; - (void)keep_alpha; - fprintf(stderr, "PNG support not compiled. Please install the libpng " - "development package before building.\n"); - return 0; -} -#endif - #ifdef WEBP_HAVE_TIFF static int ReadTIFF(const char* const filename, WebPPicture* const pic, int keep_alpha) { diff --git a/examples/pngdec.c b/examples/pngdec.c new file mode 100644 index 00000000..ff984734 --- /dev/null +++ b/examples/pngdec.c @@ -0,0 +1,124 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// This code is licensed under the same terms as WebM: +// Software License Agreement: http://www.webmproject.org/license/software/ +// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// ----------------------------------------------------------------------------- +// +// PNG decode. + +#include "./pngdec.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> + +#ifdef WEBP_HAVE_PNG +#include <png.h> +#include <setjmp.h> // note: this must be included *after* png.h +#include <stdlib.h> + +#include "webp/encode.h" + +static void PNGAPI error_function(png_structp png, png_const_charp dummy) { + (void)dummy; // remove variable-unused warning + longjmp(png_jmpbuf(png), 1); +} + +int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha) { + png_structp png; + png_infop info; + int color_type, bit_depth, interlaced; + int has_alpha; + int num_passes; + int p; + int ok = 0; + png_uint_32 width, height, y; + int stride; + uint8_t* rgb = NULL; + + png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + if (png == NULL) { + goto End; + } + + png_set_error_fn(png, 0, error_function, NULL); + if (setjmp(png_jmpbuf(png))) { + Error: + png_destroy_read_struct(&png, NULL, NULL); + free(rgb); + goto End; + } + + info = png_create_info_struct(png); + if (info == NULL) goto Error; + + png_init_io(png, in_file); + png_read_info(png, info); + if (!png_get_IHDR(png, info, + &width, &height, &bit_depth, &color_type, &interlaced, + NULL, NULL)) goto Error; + + png_set_strip_16(png); + png_set_packing(png); + if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + if (bit_depth < 8) { + png_set_expand_gray_1_2_4_to_8(png); + } + png_set_gray_to_rgb(png); + } + if (png_get_valid(png, info, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png); + has_alpha = 1; + } else { + has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA); + } + + if (!keep_alpha) { + png_set_strip_alpha(png); + has_alpha = 0; + } + + num_passes = png_set_interlace_handling(png); + png_read_update_info(png, info); + stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb); + rgb = (uint8_t*)malloc(stride * height); + if (rgb == NULL) goto Error; + for (p = 0; p < num_passes; ++p) { + for (y = 0; y < height; ++y) { + png_bytep row = rgb + y * stride; + png_read_rows(png, &row, NULL, 1); + } + } + png_read_end(png, info); + png_destroy_read_struct(&png, &info, NULL); + + pic->width = width; + pic->height = height; + ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride) + : WebPPictureImportRGB(pic, rgb, stride); + free(rgb); + + if (ok && has_alpha && keep_alpha == 2) { + WebPCleanupTransparentArea(pic); + } + + End: + return ok; +} +#else // !WEBP_HAVE_PNG +int ReadPNG(FILE* in_file, struct WebPPicture* const pic, int keep_alpha) { + (void)in_file; + (void)pic; + (void)keep_alpha; + fprintf(stderr, "PNG support not compiled. Please install the libpng " + "development package before building.\n"); + return 0; +} +#endif // WEBP_HAVE_PNG + +// ----------------------------------------------------------------------------- diff --git a/examples/pngdec.h b/examples/pngdec.h new file mode 100644 index 00000000..5cee3ad2 --- /dev/null +++ b/examples/pngdec.h @@ -0,0 +1,31 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// This code is licensed under the same terms as WebM: +// Software License Agreement: http://www.webmproject.org/license/software/ +// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// ----------------------------------------------------------------------------- +// +// PNG decode. + +#ifndef WEBP_EXAMPLES_PNGDEC_H_ +#define WEBP_EXAMPLES_PNGDEC_H_ + +#include <stdio.h> + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +struct WebPPicture; + +// Reads a PNG from 'in_file', returning the decoded output in 'pic'. +// If 'keep_alpha' is true and the PNG has an alpha channel, the output is RGBA +// otherwise it will be RGB. +// Returns true on success. +int ReadPNG(FILE* in_file, struct WebPPicture* const pic, int keep_alpha); + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif + +#endif // WEBP_EXAMPLES_PNGDEC_H_ diff --git a/makefile.unix b/makefile.unix index 4e532010..3a93c319 100644 --- a/makefile.unix +++ b/makefile.unix @@ -124,6 +124,9 @@ ENC_OBJS = \ src/enc/vp8l.o \ src/enc/webpenc.o \ +EX_FORMAT_DEC_OBJS = \ + examples/pngdec.o \ + EX_UTIL_OBJS = \ examples/example_util.o \ @@ -189,6 +192,8 @@ endif all: ex +$(EX_FORMAT_DEC_OBJS): %.o: %.h + %.o: %.c $(HDRS) $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ @@ -202,7 +207,7 @@ src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS) ex: $(OUT_EXAMPLES) -examples/cwebp: examples/cwebp.o +examples/cwebp: examples/cwebp.o $(EX_FORMAT_DEC_OBJS) examples/dwebp: examples/dwebp.o examples/gif2webp: examples/gif2webp.o examples/vwebp: examples/vwebp.o