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

📄 pngrtran.c

📁 深入剖析Visual C++编程技术及应用实例
💻 C
📖 第 1 页 / 共 5 页
字号:

#if defined(PNG_READ_PACK_SUPPORTED)
   if ((png_ptr->transformations & PNG_PACK) && info_ptr->bit_depth < 8)
      info_ptr->bit_depth = 8;
#endif

#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
      !(info_ptr->color_type & PNG_COLOR_MASK_COLOR))
      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
#endif
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      info_ptr->channels = 1;
   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
      info_ptr->channels = 3;
   else
      info_ptr->channels = 1;
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
      info_ptr->bit_depth);
   info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
}

/* transform the row.  The order of transformations is significant,
   and is very touchy.  If you add a transformation, take care to
   decide how it fits in with the other transformations here */
void
png_do_read_transformations(png_structp png_ptr)
{
#if defined(PNG_READ_EXPAND_SUPPORTED)
   if ((png_ptr->transformations & PNG_EXPAND) &&
      png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
   {
      png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
         png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
   }
   else if (png_ptr->transformations & PNG_EXPAND)
   {
      if (png_ptr->num_trans)
         png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
            &(png_ptr->trans_values));
      else
         png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
            NULL);
   }
#endif

#if defined(PNG_READ_BACKGROUND_SUPPORTED)
   if (png_ptr->transformations & PNG_BACKGROUND)
      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
         &(png_ptr->trans_values), &(png_ptr->background),
         &(png_ptr->background_1),
         png_ptr->gamma_table, png_ptr->gamma_from_1,
         png_ptr->gamma_to_1, png_ptr->gamma_16_table,
         png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
         png_ptr->gamma_shift);
#endif

#if defined(PNG_READ_GAMMA_SUPPORTED)
   if ((png_ptr->transformations & PNG_GAMMA) &&
      !(png_ptr->transformations & PNG_BACKGROUND))
      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
         png_ptr->gamma_table, png_ptr->gamma_16_table,
         png_ptr->gamma_shift);
#endif

#if defined(PNG_READ_16_TO_8_SUPPORTED)
   if (png_ptr->transformations & PNG_16_TO_8)
      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

#if defined(PNG_READ_DITHER_SUPPORTED)
   if (png_ptr->transformations & PNG_DITHER)
   {
      png_do_dither((png_row_infop)&(png_ptr->row_info), 
         png_ptr->row_buf + 1,
         png_ptr->palette_lookup,
         png_ptr->dither_index);
   }      
#endif

#if defined(PNG_READ_INVERT_SUPPORTED)
   if (png_ptr->transformations & PNG_INVERT_MONO)
      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

#if defined(PNG_READ_SHIFT_SUPPORTED)
   if (png_ptr->transformations & PNG_SHIFT)
      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
         &(png_ptr->shift));
#endif

#if defined(PNG_READ_PACK_SUPPORTED)
   if (png_ptr->transformations & PNG_PACK)
      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

#if defined(PNG_READ_BGR_SUPPORTED)
   if (png_ptr->transformations & PNG_BGR)
      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

#if defined(PNG_READ_SWAP_SUPPORTED)
   if (png_ptr->transformations & PNG_SWAP_BYTES)
      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif

#if defined(PNG_READ_FILLER_SUPPORTED)
   if (png_ptr->transformations & PNG_FILLER)
      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
         png_ptr->filler, png_ptr->flags);
#endif
}

#if defined(PNG_READ_PACK_SUPPORTED)
/* unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
   without changing the actual values.  Thus, if you had a row with
   a bit depth of 1, you would end up with bytes that only contained
   the numbers 0 or 1.  If you would rather they contain 0 and 255, use
   png_do_shift() after this. */
void
png_do_unpack(png_row_infop row_info, png_bytep row)
{
   int shift;
   png_bytep sp, dp;
   png_uint_32 i;
   
   if (row && row_info && row_info->bit_depth < 8)
   {
      switch (row_info->bit_depth)
      {
         case 1:
         {
            sp = row + (png_size_t)((row_info->width - 1) >> 3);
            dp = row + (png_size_t)row_info->width - 1;
            shift = 7 - (int)((row_info->width + 7) & 7);
            for (i = 0; i < row_info->width; i++)
            {
               *dp = (png_byte)((*sp >> shift) & 0x1);
               if (shift == 7)
               {
                  shift = 0;
                  sp--;
               }
               else
                  shift++;

               dp--;
            }
            break;
         }
         case 2:
         {

            sp = row + (png_size_t)((row_info->width - 1) >> 2);
            dp = row + (png_size_t)row_info->width - 1;
            shift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
            for (i = 0; i < row_info->width; i++)
            {
               *dp = (png_byte)((*sp >> shift) & 0x3);
               if (shift == 6)
               {
                  shift = 0;
                  sp--;
               }
               else
                  shift += 2;

               dp--;
            }
            break;
         }
         case 4:
         {
            sp = row + (png_size_t)((row_info->width - 1) >> 1);
            dp = row + (png_size_t)row_info->width - 1;
            shift = (int)((1 - ((row_info->width + 1) & 1)) << 2);
            for (i = 0; i < row_info->width; i++)
            {
               *dp = (png_byte)((*sp >> shift) & 0xf);
               if (shift == 4)
               {
                  shift = 0;
                  sp--;
               }
               else
                  shift = 4;

               dp--;
            }
            break;
         }
      }
      row_info->bit_depth = 8;
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
      row_info->rowbytes = row_info->width * row_info->channels;
   }
}
#endif

#if defined(PNG_READ_SHIFT_SUPPORTED)
/* reverse the effects of png_do_shift.  This routine merely shifts the
   pixels back to their significant bits values.  Thus, if you have
   a row of bit depth 8, but only 5 are significant, this will shift
   the values back to 0 through 31 */
void
png_do_unshift(png_row_infop row_info, png_bytep row,
   png_color_8p sig_bits)
{
   png_bytep bp;
   png_uint_16 value;
   png_uint_32 i;
   if (row && row_info && sig_bits &&
      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
   {
      int shift[4];
      int channels;

      channels = 0;
      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
      {
         shift[channels++] = row_info->bit_depth - sig_bits->red;
         shift[channels++] = row_info->bit_depth - sig_bits->green;
         shift[channels++] = row_info->bit_depth - sig_bits->blue;
      }
      else
      {
         shift[channels++] = row_info->bit_depth - sig_bits->gray;
      }
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
      {
         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
      }

      value = 0;

      for (i = 0; i < channels; i++)
      {
         if (shift[(png_size_t)i] <= 0)
            shift[(png_size_t)i] = 0;
         else
            value = 1;
      }

      if (!value)
         return;

      switch (row_info->bit_depth)
      {
         case 2:
         {
            for (bp = row, i = 0;
               i < row_info->rowbytes;
               i++, bp++)
            {
               *bp >>= 1;
               *bp &= 0x55;
            }
            break;
         }
         case 4:
         {
            png_byte  mask;
            mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) |
               (png_byte)((int)0xf >> shift[0]);
            for (bp = row, i = 0;
               i < row_info->rowbytes;
               i++, bp++)
            {
               *bp >>= shift[0];
               *bp &= mask;
            }
            break;
         }
         case 8:
         {
            for (bp = row, i = 0;
               i < row_info->width; i++)
            {
               int c;

               for (c = 0; c < row_info->channels; c++, bp++)
               {
                  *bp >>= shift[c];
               }
            }
            break;
         }
         case 16:
         {
            for (bp = row, i = 0;
               i < row_info->width; i++)
            {
               int c;

               for (c = 0; c < row_info->channels; c++, bp += 2)
               {
                  value = (png_uint_16)((*bp << 8) + *(bp + 1));
                  value >>= shift[c];
                  *bp = (png_byte)(value >> 8);
                  *(bp + 1) = (png_byte)(value & 0xff);
               }
            }
            break;
         }
      }
   }
}
#endif

#if defined(PNG_READ_16_TO_8_SUPPORTED)
/* chop rows of bit depth 16 down to 8 */
void
png_do_chop(png_row_infop row_info, png_bytep row)
{
   png_bytep sp, dp;
   png_uint_32 i;
   if (row && row_info && row_info->bit_depth == 16)
   {
      sp = row;
      dp = row;
      for (i = 0; i < row_info->width * row_info->channels; i++)
      {
         *dp = *sp;
/* not yet, as I'm afraid of overflow here
         *dp = ((((((png_uint_16)(*sp) << 8)) |
            (png_uint_16)((*(sp + 1) - *sp) & 0xff) +
            0x7f) >> 8) & 0xff);
*/
         sp += 2;
         dp++;
      }
      row_info->bit_depth = 8;
      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
      row_info->rowbytes = row_info->width * row_info->channels;
   }
}
#endif

#if defined(PNG_READ_FILLER_SUPPORTED)
/* add filler byte */
void
png_do_read_filler(png_row_infop row_info, png_bytep row,
   png_byte filler, png_byte flags)
{
   png_bytep sp, dp;
   png_uint_32 i;
   if (row && row_info && row_info->color_type == 2 &&
      row_info->bit_depth == 8)
   {
      if (flags & PNG_FLAG_FILLER_AFTER)
      {
         for (i = 1, sp = row + (png_size_t)row_info->width * 3,
            dp = row + (png_size_t)row_info->width * 4;
            i < row_info->width;
            i++)
         {
            *(--dp) = filler;
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
         }
         *(--dp) = filler;
         row_info->channels = 4;
         row_info->pixel_depth = 32;
         row_info->rowbytes = row_info->width * 4;
      }
      else
      {
         for (i = 0, sp = row + (png_size_t)row_info->width * 3,
            dp = row + (png_size_t)row_info->width * 4;
            i < row_info->width;
            i++)
         {
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = *(--sp);
            *(--dp) = filler;
         }
         row_info->channels = 4;
         row_info->pixel_depth = 32;
         row_info->rowbytes = row_info->width * 4;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -