cwebp: extract png decoding to its own module

Change-Id: I80dd09fe1f1c6317e9d0cdd422438bda11b43ed5
This commit is contained in:
James Zern 2012-12-06 13:06:37 -08:00
parent 4679db006c
commit 2ee228f9a5
6 changed files with 169 additions and 108 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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) {

124
examples/pngdec.c Normal file
View File

@ -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
// -----------------------------------------------------------------------------

31
examples/pngdec.h Normal file
View File

@ -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_

View File

@ -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