📄 pngrutil.c
字号:
/* pngrutil.c - utilities to read a png file
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
May 25, 1996
*/
#define PNG_INTERNAL
#include "png.h"
/* grab an uint 32 from a buffer */
png_uint_32
png_get_uint_32(png_bytep buf)
{
png_uint_32 i;
i = ((png_uint_32)(*buf) << 24) +
((png_uint_32)(*(buf + 1)) << 16) +
((png_uint_32)(*(buf + 2)) << 8) +
(png_uint_32)(*(buf + 3));
return i;
}
/* grab an uint 16 from a buffer */
png_uint_16
png_get_uint_16(png_bytep buf)
{
png_uint_16 i;
i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
(png_uint_16)(*(buf + 1)));
return i;
}
/* read data, and run it through the crc */
void
png_crc_read(png_structp png_ptr, png_bytep buf, png_uint_32 length)
{
png_read_data(png_ptr, buf, length);
png_calculate_crc(png_ptr, buf, length);
}
/* skip data, but calcuate the crc anyway */
void
png_crc_skip(png_structp png_ptr, png_uint_32 length)
{
png_uint_32 i;
for (i = length; i > png_ptr->zbuf_size; i -= png_ptr->zbuf_size)
{
png_read_data(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
png_calculate_crc(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
}
if (i)
{
png_read_data(png_ptr, png_ptr->zbuf, i);
png_calculate_crc(png_ptr, png_ptr->zbuf, i);
}
}
/* read and check the IDHR chunk */
void
png_handle_IHDR(png_structp png_ptr, png_infop info, png_uint_32 length)
{
png_byte buf[13];
png_uint_32 width, height;
int bit_depth, color_type, compression_type, filter_type;
int interlace_type;
if (png_ptr->mode != PNG_BEFORE_IHDR)
png_error(png_ptr, "Out of place IHDR");
/* check the length */
if (length != 13)
png_error(png_ptr, "Invalid IHDR chunk");
png_crc_read(png_ptr, buf, 13);
width = png_get_uint_32(buf);
height = png_get_uint_32(buf + 4);
bit_depth = buf[8];
color_type = buf[9];
compression_type = buf[10];
filter_type = buf[11];
interlace_type = buf[12];
/* check for width and height valid values */
if (width == 0 || height == 0)
png_error(png_ptr, "Invalid image size in IHDR");
/* check other values */
if (bit_depth != 1 && bit_depth != 2 &&
bit_depth != 4 && bit_depth != 8 &&
bit_depth != 16)
png_error(png_ptr, "Invalid bit depth in IHDR");
if (color_type < 0 || color_type == 1 ||
color_type == 5 || color_type > 6)
png_error(png_ptr, "Invalid color type in IHDR");
if (color_type == PNG_COLOR_TYPE_PALETTE &&
bit_depth == 16)
png_error(png_ptr, "Invalid color type and bit depth combination in IHDR");
if ((color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
bit_depth < 8)
png_error(png_ptr, "Invalid color type and bit depth in IHDR");
if (interlace_type > 1)
png_error(png_ptr, "Invalid interlace method in IHDR");
if (compression_type > 0)
png_error(png_ptr, "Invalid compression method in IHDR");
if (filter_type > 0)
png_error(png_ptr, "Invalid filter method in IHDR");
/* set internal variables */
png_ptr->width = width;
png_ptr->height = height;
png_ptr->bit_depth = (png_byte)bit_depth;
png_ptr->interlaced = (png_byte)interlace_type;
png_ptr->color_type = (png_byte)color_type;
/* find number of channels */
switch (png_ptr->color_type)
{
case 0:
case 3:
png_ptr->channels = 1;
break;
case 2:
png_ptr->channels = 3;
break;
case 4:
png_ptr->channels = 2;
break;
case 6:
png_ptr->channels = 4;
break;
}
/* set up other useful info */
png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
png_ptr->channels);
png_ptr->rowbytes = ((png_ptr->width *
(png_uint_32)png_ptr->pixel_depth + 7) >> 3);
/* call the IHDR callback (which should just set up info) */
png_read_IHDR(png_ptr, info, width, height, bit_depth,
color_type, compression_type, filter_type, interlace_type);
png_ptr->mode |= PNG_HAVE_IHDR;
}
/* read and check the palette */
void
png_handle_PLTE(png_structp png_ptr, png_infop info, png_uint_32 length)
{
int num, i;
png_colorp palette;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before PLTE");
else if (png_ptr->mode & PNG_HAVE_PLTE)
png_error(png_ptr, "Multiple PLTE");
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
png_crc_skip(png_ptr, length);
return;
}
#endif
if (length % 3)
{
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
png_warning(png_ptr, "Invalid palette chunk");
png_crc_skip(png_ptr, length);
return;
}
else
{
png_error(png_ptr, "Invalid palette chunk");
}
}
num = (int)length / 3;
palette = (png_colorp)png_large_malloc(png_ptr, num * sizeof (png_color));
png_ptr->do_free |= PNG_FREE_PALETTE;
for (i = 0; i < num; i++)
{
png_byte buf[3];
png_crc_read(png_ptr, buf, 3);
/* don't depend upon png_color being any order */
palette[i].red = buf[0];
palette[i].green = buf[1];
palette[i].blue = buf[2];
}
png_ptr->palette = palette;
png_ptr->num_palette = (png_uint_16)num;
png_read_PLTE(png_ptr, info, palette, num);
png_ptr->mode |= PNG_HAVE_PLTE;
}
#if defined(PNG_READ_gAMA_SUPPORTED)
void
png_handle_gAMA(png_structp png_ptr, png_infop info, png_uint_32 length)
{
png_uint_32 igamma;
float gamma;
png_byte buf[4];
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before gAMA");
else if (png_ptr->mode & PNG_HAVE_PLTE)
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Out of place gAMA chunk");
if (length != 4)
{
png_warning(png_ptr, "Incorrect gAMA chunk length");
png_crc_skip(png_ptr, length);
return;
}
png_crc_read(png_ptr, buf, 4);
igamma = png_get_uint_32(buf);
/* check for zero gamma */
if (!igamma)
return;
gamma = (float)igamma / (float)100000.0;
png_read_gAMA(png_ptr, info, gamma);
png_ptr->gamma = gamma;
}
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
void
png_handle_sBIT(png_structp png_ptr, png_infop info, png_uint_32 length)
{
int slen;
png_byte buf[4];
buf[0] = buf[1] = buf[2] = buf[3] = 0;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before sBIT");
else if (png_ptr->mode & PNG_HAVE_PLTE)
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Out of place sBIT chunk");
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
slen = 3;
else
slen = png_ptr->channels;
if (length != (png_uint_32)slen)
{
png_warning(png_ptr, "Incorrect sBIT chunk length");
png_crc_skip(png_ptr, length);
return;
}
png_crc_read(png_ptr, buf, length);
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
{
png_ptr->sig_bit.red = buf[0];
png_ptr->sig_bit.green = buf[1];
png_ptr->sig_bit.blue = buf[2];
png_ptr->sig_bit.alpha = buf[3];
}
else
{
png_ptr->sig_bit.gray = buf[0];
png_ptr->sig_bit.alpha = buf[1];
}
png_read_sBIT(png_ptr, info, &(png_ptr->sig_bit));
}
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
void
png_handle_cHRM(png_structp png_ptr, png_infop info, png_uint_32 length)
{
png_byte buf[4];
png_uint_32 v;
float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before sBIT");
else if (png_ptr->mode & PNG_HAVE_PLTE)
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Missing PLTE before cHRM");
if (length != 32)
{
png_warning(png_ptr, "Incorrect cHRM chunk length");
png_crc_skip(png_ptr, length);
return;
}
png_crc_read(png_ptr, buf, 4);
v = png_get_uint_32(buf);
white_x = (float)v / (float)100000.0;
png_crc_read(png_ptr, buf, 4);
v = png_get_uint_32(buf);
white_y = (float)v / (float)100000.0;
png_crc_read(png_ptr, buf, 4);
v = png_get_uint_32(buf);
red_x = (float)v / (float)100000.0;
png_crc_read(png_ptr, buf, 4);
v = png_get_uint_32(buf);
red_y = (float)v / (float)100000.0;
png_crc_read(png_ptr, buf, 4);
v = png_get_uint_32(buf);
green_x = (float)v / (float)100000.0;
png_crc_read(png_ptr, buf, 4);
v = png_get_uint_32(buf);
green_y = (float)v / (float)100000.0;
png_crc_read(png_ptr, buf, 4);
v = png_get_uint_32(buf);
blue_x = (float)v / (float)100000.0;
png_crc_read(png_ptr, buf, 4);
v = png_get_uint_32(buf);
blue_y = (float)v / (float)100000.0;
png_read_cHRM(png_ptr, info,
white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
}
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
void
png_handle_tRNS(png_structp png_ptr, png_infop info, png_uint_32 length)
{
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before tRNS");
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
if (!(png_ptr->mode & PNG_HAVE_PLTE))
{
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Missing PLTE before tRNS");
}
else if (length > png_ptr->num_palette)
{
png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_skip(png_ptr, length);
return;
}
png_ptr->trans = (png_bytep)png_large_malloc(png_ptr, length);
png_ptr->do_free |= PNG_FREE_TRANS;
png_crc_read(png_ptr, png_ptr->trans, length);
png_ptr->num_trans = (png_uint_16)length;
}
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
{
png_byte buf[6];
if (length != 6)
{
png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_skip(png_ptr, length);
return;
}
png_crc_read(png_ptr, buf, length);
png_ptr->num_trans = 3;
png_ptr->trans_values.red = png_get_uint_16(buf);
png_ptr->trans_values.green = png_get_uint_16(buf + 2);
png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
}
else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
{
png_byte buf[6];
if (length != 2)
{
png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_skip(png_ptr, length);
return;
}
png_crc_read(png_ptr, buf, 2);
png_ptr->num_trans = 1;
png_ptr->trans_values.gray = png_get_uint_16(buf);
}
else
{
png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
png_crc_skip(png_ptr, length);
return;
}
png_read_tRNS(png_ptr, info, png_ptr->trans, png_ptr->num_trans,
&(png_ptr->trans_values));
}
#endif
#if defined(PNG_READ_bKGD_SUPPORTED)
void
png_handle_bKGD(png_structp png_ptr, png_infop info, png_uint_32 length)
{
int truelen;
png_byte buf[6];
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before bKGD");
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
!(png_ptr->mode & PNG_HAVE_PLTE))
{
png_warning(png_ptr, "Missing PLTE before bKGD");
png_crc_skip(png_ptr, length);
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
truelen = 1;
else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
truelen = 6;
else
truelen = 2;
if (length != (png_uint_32)truelen)
{
png_warning(png_ptr, "Incorrect bKGD chunk length");
png_crc_skip(png_ptr, length);
return;
}
png_crc_read(png_ptr, buf, length);
/* We convert the index value into RGB components so that we can allow
* arbitrary RGB values for background when we have transparency, and
* so it is easy to determine the RGB values of the background color
* from the info_ptr. */
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
png_ptr->background.index = buf[0];
png_ptr->background.red = (png_uint_16)png_ptr->palette[buf[0]].red;
png_ptr->background.green = (png_uint_16)png_ptr->palette[buf[0]].green;
png_ptr->background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue;
}
else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
{
png_ptr->background.red =
png_ptr->background.green =
png_ptr->background.blue =
png_ptr->background.gray = png_get_uint_16(buf);
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -