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

📄 pngwutil.c

📁 Linux下的基于X11的图形开发环境。
💻 C
📖 第 1 页 / 共 5 页
字号:
      }   }#ifdef PNG_WRITE_INTERLACING_SUPPORTED   /* if interlaced, we need to set up width and height of pass */   if (png_ptr->interlaced)   {      if (!(png_ptr->transformations & PNG_INTERLACE))      {         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -            png_pass_ystart[0]) / png_pass_yinc[0];         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -            png_pass_start[0]) / png_pass_inc[0];      }      else      {         png_ptr->num_rows = png_ptr->height;         png_ptr->usr_width = png_ptr->width;      }   }   else#endif   {      png_ptr->num_rows = png_ptr->height;      png_ptr->usr_width = png_ptr->width;   }   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;   png_ptr->zstream.next_out = png_ptr->zbuf;}/* Internal use only.  Called when finished processing a row of data. */void /* PRIVATE */png_write_finish_row(png_structp png_ptr){#ifdef PNG_USE_LOCAL_ARRAYS   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */   /* start of interlace block */   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};   /* offset to next interlace block */   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};   /* start of interlace block in the y direction */   int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};   /* offset to next interlace block in the y direction */   int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};#endif   int ret;   png_debug(1, "in png_write_finish_row\n");   /* next row */   png_ptr->row_number++;   /* see if we are done */   if (png_ptr->row_number < png_ptr->num_rows)      return;#ifdef PNG_WRITE_INTERLACING_SUPPORTED   /* if interlaced, go to next pass */   if (png_ptr->interlaced)   {      png_ptr->row_number = 0;      if (png_ptr->transformations & PNG_INTERLACE)      {         png_ptr->pass++;      }      else      {         /* loop until we find a non-zero width or height pass */         do         {            png_ptr->pass++;            if (png_ptr->pass >= 7)               break;            png_ptr->usr_width = (png_ptr->width +               png_pass_inc[png_ptr->pass] - 1 -               png_pass_start[png_ptr->pass]) /               png_pass_inc[png_ptr->pass];            png_ptr->num_rows = (png_ptr->height +               png_pass_yinc[png_ptr->pass] - 1 -               png_pass_ystart[png_ptr->pass]) /               png_pass_yinc[png_ptr->pass];            if (png_ptr->transformations & PNG_INTERLACE)               break;         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);      }      /* reset the row above the image for the next pass */      if (png_ptr->pass < 7)      {         if (png_ptr->prev_row != NULL)            png_memset(png_ptr->prev_row, 0,               (png_size_t) (((png_uint_32)png_ptr->usr_channels *               (png_uint_32)png_ptr->usr_bit_depth *               png_ptr->width + 7) >> 3) + 1);         return;      }   }#endif   /* if we get here, we've just written the last row, so we need      to flush the compressor */   do   {      /* tell the compressor we are done */      ret = deflate(&png_ptr->zstream, Z_FINISH);      /* check for an error */      if (ret == Z_OK)      {         /* check to see if we need more room */         if (!(png_ptr->zstream.avail_out))         {            png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);            png_ptr->zstream.next_out = png_ptr->zbuf;            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;         }      }      else if (ret != Z_STREAM_END)      {         if (png_ptr->zstream.msg != NULL)            png_error(png_ptr, png_ptr->zstream.msg);         else            png_error(png_ptr, "zlib error");      }   } while (ret != Z_STREAM_END);   /* write any extra space */   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)   {      png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -         png_ptr->zstream.avail_out);   }   deflateReset(&png_ptr->zstream);}#if defined(PNG_WRITE_INTERLACING_SUPPORTED)/* Pick out the correct pixels for the interlace pass. * The basic idea here is to go through the row with a source * pointer and a destination pointer (sp and dp), and copy the * correct pixels for the pass.  As the row gets compacted, * sp will always be >= dp, so we should never overwrite anything. * See the default: case for the easiest code to understand. */void /* PRIVATE */png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass){#ifdef PNG_USE_LOCAL_ARRAYS   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */   /* start of interlace block */   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};   /* offset to next interlace block */   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};#endif   png_debug(1, "in png_do_write_interlace\n");   /* we don't have to do anything on the last pass (6) */#if defined(PNG_USELESS_TESTS_SUPPORTED)   if (row != NULL && row_info != NULL && pass < 6)#else   if (pass < 6)#endif   {      /* each pixel depth is handled separately */      switch (row_info->pixel_depth)      {         case 1:         {            png_bytep sp;            png_bytep dp;            int shift;            int d;            int value;            png_uint_32 i;            png_uint_32 row_width = row_info->width;            dp = row;            d = 0;            shift = 7;            for (i = png_pass_start[pass]; i < row_width;               i += png_pass_inc[pass])            {               sp = row + (png_size_t)(i >> 3);               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;               d |= (value << shift);               if (shift == 0)               {                  shift = 7;                  *dp++ = (png_byte)d;                  d = 0;               }               else                  shift--;            }            if (shift != 7)               *dp = (png_byte)d;            break;         }         case 2:         {            png_bytep sp;            png_bytep dp;            int shift;            int d;            int value;            png_uint_32 i;            png_uint_32 row_width = row_info->width;            dp = row;            shift = 6;            d = 0;            for (i = png_pass_start[pass]; i < row_width;               i += png_pass_inc[pass])            {               sp = row + (png_size_t)(i >> 2);               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;               d |= (value << shift);               if (shift == 0)               {                  shift = 6;                  *dp++ = (png_byte)d;                  d = 0;               }               else                  shift -= 2;            }            if (shift != 6)                   *dp = (png_byte)d;            break;         }         case 4:         {            png_bytep sp;            png_bytep dp;            int shift;            int d;            int value;            png_uint_32 i;            png_uint_32 row_width = row_info->width;            dp = row;            shift = 4;            d = 0;            for (i = png_pass_start[pass]; i < row_width;               i += png_pass_inc[pass])            {               sp = row + (png_size_t)(i >> 1);               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;               d |= (value << shift);               if (shift == 0)               {                  shift = 4;                  *dp++ = (png_byte)d;                  d = 0;               }               else                  shift -= 4;            }            if (shift != 4)               *dp = (png_byte)d;            break;         }         default:         {            png_bytep sp;            png_bytep dp;            png_uint_32 i;            png_uint_32 row_width = row_info->width;            png_size_t pixel_bytes;            /* start at the beginning */            dp = row;            /* find out how many bytes each pixel takes up */            pixel_bytes = (row_info->pixel_depth >> 3);            /* loop through the row, only looking at the pixels that               matter */            for (i = png_pass_start[pass]; i < row_width;               i += png_pass_inc[pass])            {               /* find out where the original pixel is */               sp = row + (png_size_t)i * pixel_bytes;               /* move the pixel */               if (dp != sp)                  png_memcpy(dp, sp, pixel_bytes);               /* next pixel */               dp += pixel_bytes;            }            break;         }      }      /* set new row width */      row_info->width = (row_info->width +         png_pass_inc[pass] - 1 -         png_pass_start[pass]) /         png_pass_inc[pass];         row_info->rowbytes = ((row_info->width *            row_info->pixel_depth + 7) >> 3);   }}#endif/* This filters the row, chooses which filter to use, if it has not already * been specified by the application, and then writes the row out with the * chosen filter. */#define PNG_MAXSUM (~((png_uint_32)0) >> 1)#define PNG_HISHIFT 10#define PNG_LOMASK ((png_uint_32)0xffffL)#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))void /* PRIVATE */png_write_find_filter(png_structp png_ptr, png_row_infop row_info){   png_bytep prev_row, best_row, row_buf;   png_uint_32 mins, bpp;   png_byte filter_to_do = png_ptr->do_filter;   png_uint_32 row_bytes = row_info->rowbytes;#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)   int num_p_filters = (int)png_ptr->num_prev_filters;#endif   png_debug(1, "in png_write_find_filter\n");   /* find out how many bytes offset each pixel is */   bpp = (row_info->pixel_depth + 7) / 8;   prev_row = png_ptr->prev_row;   best_row = row_buf = png_ptr->row_buf;   mins = PNG_MAXSUM;   /* The prediction method we use is to find which method provides the    * smallest value when summing the absolute values of the distances    * from zero, using anything >= 128 as negative numbers.  This is known    * as the "minimum sum of absolute differences" heuristic.  Other    * heuristics are the "weighted minimum sum of absolute differences"    * (experimental and can in theory improve compression), and the "zlib    * predictive" method (not implemented yet), which does test compressions    * of lines using different filter methods, and then chooses the    * (series of) filter(s) that give minimum compressed data size (VERY    * computationally expensive).    *    * GRR 980525:  consider also    *   (1) minimum sum of absolute differences from running average (i.e.,    *       keep running sum of non-absolute differences & count of bytes)    *       [track dispersion, too?  restart average if dispersion too large?]    *  (1b) minimum sum of absolute differences from sliding average, probably    *       with window size <= deflate window (usually 32K)    *   (2) minimum sum of squared differences from zero or running average    *       (i.e., ~ root-mean-square approach)    */   /* We don't need to test the 'no filter' case if this is the only filter    * that has been chosen, as it doesn't actually do anything to the data.    */   if ((filter_to_do & PNG_FILTER_NONE) &&       filter_to_do != PNG_FILTER_NONE)   {      png_bytep rp;      png_uint_32 sum = 0;      png_uint_32 i;      int v;      for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)      {         v = *rp;         sum += (v < 128) ? v : 256 - v;      }#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)      {         png_uint_32 sumhi, sumlo;         int j;         sumlo = sum & PNG_LOMASK;         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */         /* Reduce the sum if we match any of the previous rows */         for (j = 0; j < num_p_filters; j++)         {            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)            {               sumlo = (sumlo * png_ptr->filter_weights[j]) >>                  PNG_WEIGHT_SHIFT;               sumhi = (sumhi * png_ptr->filter_weights[j]) >>                  PNG_WEIGHT_SHIFT;            }         }         /* Factor in the cost of this filter (this is here for completeness,          * but it makes no sense to have a "cost" for the NONE filter, as          * it has the minimum possible computational cost - none).          */         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>            PNG_COST_SHIFT;         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>            PNG_COST_SHIFT;         if (sumhi > PNG_HIMASK)            sum = PNG_MAXSUM;         else            sum = (sumhi << PNG_HISHIFT) + sumlo;      }#endif      mins = sum;   }   /* sub filter */   if (filter_to_do == PNG_FILTER_SUB)   /* it's the only filter so no testing is needed */   {      png_b

⌨️ 快捷键说明

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