⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pngrutil.c

📁 一套图像处理程序,支持三种图像文件格式,我调试过了,很好用
💻 C
📖 第 1 页 / 共 3 页
字号:

/* 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 + -