mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-30 23:38:25 +01:00
125 lines
3.2 KiB
C
125 lines
3.2 KiB
C
|
// 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
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|