📄 pngrutil.c
字号:
/* pngrutil.c - utilities to read a PNG file * * libpng 1.2.5 - October 3, 2002 * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1998-2002 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * * This file contains routines that are only called from within * libpng itself during the course of reading an image. */#define PNG_INTERNAL#include "png.h"#if defined(_WIN32_WCE)/* strtod() function is not supported on WindowsCE */# ifdef PNG_FLOATING_POINT_SUPPORTED__inline double strtod(const char *nptr, char **endptr){ double result = 0; int len; wchar_t *str, *end; len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); str = (wchar_t *)malloc(len * sizeof(wchar_t)); if ( NULL != str ) { MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); result = wcstod(str, &end); len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); free(str); } return result;}# endif#endif#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */png_uint_32 /* PRIVATE */png_get_uint_32(png_bytep buf){ png_uint_32 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);}#if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)/* Grab a signed 32-bit integer from a buffer in big-endian format. The * data is stored in the PNG file in two's complement format, and it is * assumed that the machine format for signed integers is the same. */png_int_32 /* PRIVATE */png_get_int_32(png_bytep buf){ png_int_32 i = ((png_int_32)(*buf) << 24) + ((png_int_32)(*(buf + 1)) << 16) + ((png_int_32)(*(buf + 2)) << 8) + (png_int_32)(*(buf + 3)); return (i);}#endif /* PNG_READ_pCAL_SUPPORTED *//* Grab an unsigned 16-bit integer from a buffer in big-endian format. */png_uint_16 /* PRIVATE */png_get_uint_16(png_bytep buf){ png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + (png_uint_16)(*(buf + 1))); return (i);}#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED *//* Read data, and (optionally) run it through the CRC. */void /* PRIVATE */png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length){ png_read_data(png_ptr, buf, length); png_calculate_crc(png_ptr, buf, length);}/* Optionally skip data and then check the CRC. Depending on whether we are reading a ancillary or critical chunk, and how the program has set things up, we may calculate the CRC on the data and print a message. Returns '1' if there was a CRC error, '0' otherwise. */int /* PRIVATE */png_crc_finish(png_structp png_ptr, png_uint_32 skip){ png_size_t i; png_size_t istop = png_ptr->zbuf_size; for (i = (png_size_t)skip; i > istop; i -= istop) { png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); } if (i) { png_crc_read(png_ptr, png_ptr->zbuf, i); } if (png_crc_error(png_ptr)) { if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) { png_chunk_warning(png_ptr, "CRC error"); } else { png_chunk_error(png_ptr, "CRC error"); } return (1); } return (0);}/* Compare the CRC stored in the PNG file with that calculated by libpng from the data it has read thus far. */int /* PRIVATE */png_crc_error(png_structp png_ptr){ png_byte crc_bytes[4]; png_uint_32 crc; int need_crc = 1; if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ { if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) need_crc = 0; } else /* critical */ { if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) need_crc = 0; } png_read_data(png_ptr, crc_bytes, 4); if (need_crc) { crc = png_get_uint_32(crc_bytes); return ((int)(crc != png_ptr->crc)); } else return (0);}#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ defined(PNG_READ_iCCP_SUPPORTED)/* * Decompress trailing data in a chunk. The assumption is that chunkdata * points at an allocated area holding the contents of a chunk with a * trailing compressed part. What we get back is an allocated area * holding the original prefix part and an uncompressed version of the * trailing part (the malloc area passed in is freed). */png_charp /* PRIVATE */png_decompress_chunk(png_structp png_ptr, int comp_type, png_charp chunkdata, png_size_t chunklength, png_size_t prefix_size, png_size_t *newlength){ static char msg[] = "Error decoding compressed text"; png_charp text = NULL; png_size_t text_size; if (comp_type == PNG_COMPRESSION_TYPE_BASE) { int ret = Z_OK; png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size); png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; text_size = 0; text = NULL; while (png_ptr->zstream.avail_in) { ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) { if (png_ptr->zstream.msg != NULL) png_warning(png_ptr, png_ptr->zstream.msg); else png_warning(png_ptr, msg); inflateReset(&png_ptr->zstream); png_ptr->zstream.avail_in = 0; if (text == NULL) { text_size = prefix_size + sizeof(msg) + 1; text = (png_charp)png_malloc_warn(png_ptr, text_size); if (text == NULL) { png_free(png_ptr,chunkdata); png_error(png_ptr,"Not enough memory to decompress chunk"); } png_memcpy(text, chunkdata, prefix_size); } text[text_size - 1] = 0x00; /* Copy what we can of the error message into the text chunk */ text_size = (png_size_t)(chunklength - (text - chunkdata) - 1); text_size = sizeof(msg) > text_size ? text_size : sizeof(msg); png_memcpy(text + prefix_size, msg, text_size + 1); break; } if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) { if (text == NULL) { text_size = prefix_size + png_ptr->zbuf_size - png_ptr->zstream.avail_out; text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); if (text == NULL) { png_free(png_ptr,chunkdata); png_error(png_ptr,"Not enough memory to decompress chunk."); } png_memcpy(text + prefix_size, png_ptr->zbuf, text_size - prefix_size); png_memcpy(text, chunkdata, prefix_size); *(text + text_size) = 0x00; } else { png_charp tmp; tmp = text; text = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(text_size + png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); if (text == NULL) { png_free(png_ptr, tmp); png_free(png_ptr, chunkdata); png_error(png_ptr,"Not enough memory to decompress chunk.."); } png_memcpy(text, tmp, text_size); png_free(png_ptr, tmp); png_memcpy(text + text_size, png_ptr->zbuf, (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; *(text + text_size) = 0x00; } if (ret == Z_STREAM_END) break; else { png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } } } if (ret != Z_STREAM_END) {#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) char umsg[50]; if (ret == Z_BUF_ERROR) sprintf(umsg,"Buffer error in compressed datastream in %s chunk", png_ptr->chunk_name); else if (ret == Z_DATA_ERROR) sprintf(umsg,"Data error in compressed datastream in %s chunk", png_ptr->chunk_name); else sprintf(umsg,"Incomplete compressed datastream in %s chunk", png_ptr->chunk_name); png_warning(png_ptr, umsg);#else png_warning(png_ptr, "Incomplete compressed datastream in chunk other than IDAT");#endif text_size=prefix_size; if (text == NULL) { text = (png_charp)png_malloc_warn(png_ptr, text_size+1); if (text == NULL) { png_free(png_ptr, chunkdata); png_error(png_ptr,"Not enough memory for text."); } png_memcpy(text, chunkdata, prefix_size); } *(text + text_size) = 0x00; } inflateReset(&png_ptr->zstream); png_ptr->zstream.avail_in = 0; png_free(png_ptr, chunkdata); chunkdata = text; *newlength=text_size; } else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ {#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) char umsg[50]; sprintf(umsg, "Unknown zTXt compression type %d", comp_type); png_warning(png_ptr, umsg);#else png_warning(png_ptr, "Unknown zTXt compression type");#endif *(chunkdata + prefix_size) = 0x00; *newlength=prefix_size; } return chunkdata;}#endif/* read and check the IDHR chunk */void /* PRIVATE */png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, 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; png_debug(1, "in png_handle_IHDR\n"); if (png_ptr->mode & PNG_HAVE_IHDR) png_error(png_ptr, "Out of place IHDR"); /* check the length */ if (length != 13) png_error(png_ptr, "Invalid IHDR chunk"); png_ptr->mode |= PNG_HAVE_IHDR; png_crc_read(png_ptr, buf, 13); png_crc_finish(png_ptr, 0); 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]; /* 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;#if defined(PNG_MNG_FEATURES_SUPPORTED) png_ptr->filter_type = (png_byte)filter_type;#endif /* find number of channels */ switch (png_ptr->color_type) { case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_PALETTE: png_ptr->channels = 1; break; case PNG_COLOR_TYPE_RGB: png_ptr->channels = 3; break; case PNG_COLOR_TYPE_GRAY_ALPHA: png_ptr->channels = 2; break; case PNG_COLOR_TYPE_RGB_ALPHA: 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); png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth); png_debug1(3,"channels = %d\n", png_ptr->channels); png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_type, compression_type, filter_type);}/* read and check the palette */void /* PRIVATE */png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length){ png_color palette[PNG_MAX_PALETTE_LENGTH]; int num, i;#ifndef PNG_NO_POINTER_INDEXING png_colorp pal_ptr;#endif png_debug(1, "in png_handle_PLTE\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) png_error(png_ptr, "Missing IHDR before PLTE"); else if (png_ptr->mode & PNG_HAVE_IDAT) { png_warning(png_ptr, "Invalid PLTE after IDAT"); png_crc_finish(png_ptr, length); return; } else if (png_ptr->mode & PNG_HAVE_PLTE) png_error(png_ptr, "Duplicate PLTE chunk"); png_ptr->mode |= PNG_HAVE_PLTE; if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) { png_warning(png_ptr, "Ignoring PLTE chunk in grayscale PNG"); png_crc_finish(png_ptr, length); return; }#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) { png_crc_finish(png_ptr, length); return; }#endif if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) { if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) { png_warning(png_ptr, "Invalid palette chunk"); png_crc_finish(png_ptr, length); return; } else { png_error(png_ptr, "Invalid palette chunk"); } } num = (int)length / 3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -