gif_dither.c

来自「ucOS 模拟环境」· C语言 代码 · 共 1,012 行 · 第 1/3 页

C
1,012 行
字号
// Return       :	none
// Remarks      :	
// Change Log   :	
//                Author       Date       Description	
//              -----------------------------------------------	
//=====================================================================================
static void gif_zero_far (void FAR * target, size_t bytestozero)
{
   register char FAR * ptr = (char FAR *) target;
   register size_t count;
   for (count = bytestozero; count > 0; count--) 
   {
      *ptr++ = 0;
   }
}
//====================================================================================
// Function Name:	void quantize_ord_dither (decompress_info_ptr cinfo, JSAMPARRAY input_buf,
//                               		     JSAMPARRAY output_buf, int num_rows)
// Purpose      :	General case, with ordered dithering
// Parameter    :	
// Return       :	none
// Remarks      :	
// Change Log   :	
//                Author       Date       Description	
//              -----------------------------------------------	
//=====================================================================================
void gif_quantize_ord_dither (decompress_info_ptr cinfo, uchar* input_buf,
		     uchar* output_buf, int num_rows)
{
   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
   register JSAMPROW input_ptr;
   register JSAMPROW output_ptr;
   JSAMPROW colorindex_ci;
   int * dither;			/* points to active row of dither matrix */
   int row_index, col_index;	/* current indexes into dither matrix */
   int nc = cinfo->out_color_components;
   int ci;
   int row;
   JDIMENSION col;
   JDIMENSION width = cinfo->output_width;

   for (row = 0; row < num_rows; row++) 
   {
      /* Initialize output values to 0 so can process components separately */
      
      row_index = cquantize->row_index;
      for (ci = 0; ci < nc; ci++) 
      {
         input_ptr = (uchar*)(input_buf + row  * width);
		 output_ptr = (uchar*)(output_buf + row * width);
         colorindex_ci = cquantize->colorindex[ci];
         dither = cquantize->odither[ci][row_index];
         col_index = 0;
         for (col = width; col > 0; col--) 
         {
	         /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE,
	          * select output value, accumulate into output code for this pixel.
	          * Range-limiting need not be done explicitly, as we have extended
	          * the colorindex table to produce the right answers for out-of-range
	          * inputs.  The maximum dither is +- MAXJSAMPLE; this sets the
	          * required amount of padding.
	          */
	         *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
	         input_ptr += nc;
	         output_ptr++;
	         col_index = (col_index + 1) & ODITHER_MASK;
         }
      }
      /* Advance row index for next row */
      row_index = (row_index + 1) & ODITHER_MASK;
      cquantize->row_index = row_index;
   }
}


//====================================================================================
// Function Name:	void gif_quantize3_ord_dither (decompress_info_ptr cinfo, uchar* input_buf,
//                               		      uchar* output_buf, int num_rows)
// Purpose      :	ordered dithering
// Parameter    :	
// Return       :	none
// Remarks      :	Fast path for out_color_components==3, with ordered dithering
// Change Log   :	
//                Author       Date       Description	
//              -----------------------------------------------	
//=====================================================================================
void gif_quantize3_ord_dither (decompress_info_ptr cinfo, uchar* input_buf,
		      uchar* output_buf, int num_rows)
{
   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
   register int pixcode;
   register JSAMPROW input_ptr;
   register JSAMPROW output_ptr;
   JSAMPROW colorindex0 = cquantize->colorindex[0];
   JSAMPROW colorindex1 = cquantize->colorindex[1];
   JSAMPROW colorindex2 = cquantize->colorindex[2];
   int * dither0;		/* points to active row of dither matrix */
   int * dither1;
   int * dither2;
   int row_index, col_index;	/* current indexes into dither matrix */
   int row;
   JDIMENSION col;
   JDIMENSION width = cinfo->output_width;
   for (row = 0; row < num_rows; row++) 
   {
      row_index = cquantize->row_index;
      input_ptr = (uchar*)(input_buf + row * 3 * width);
      output_ptr = (uchar*)(output_buf + row * width);
      dither0 = cquantize->odither[0][row_index];
      dither1 = cquantize->odither[1][row_index];
      dither2 = cquantize->odither[2][row_index];
      col_index = 0;
      for (col = width; col > 0; col--) 
      {
         pixcode  = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) +
			   		dither0[col_index]]);
         pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) +
			   		dither1[col_index]]);
         pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) +
			   		dither2[col_index]]);
		 *output_ptr++ = (JSAMPLE) pixcode;
		 col_index = (col_index + 1) & ODITHER_MASK;
      }
      row_index = (row_index + 1) & ODITHER_MASK;
      cquantize->row_index = row_index;
   }
}

//====================================================================================
// Function Name:	void gif_quantize_fs_dither (decompress_info_ptr cinfo, uchar* input_buf,
//                               		    uchar* output_buf, int num_rows)
// Purpose      :	Floyd-Steinberg dithering for color space
// Parameter    :	
// Return       :	none
// Remarks      :	 General case, with Floyd-Steinberg dithering 
// Change Log   :	
//                Author       Date       Description	
//              -----------------------------------------------	
//=====================================================================================
void gif_quantize_fs_dither (decompress_info_ptr cinfo, uchar* input_buf,
		    uchar* output_buf, int num_rows)
{
   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
   register LOCFSERROR cur;	/* current error or pixel value */
   LOCFSERROR belowerr;		/* error for pixel below cur */
   LOCFSERROR bpreverr;		/* error for below/prev col */
   LOCFSERROR bnexterr;		/* error for below/next col */
   LOCFSERROR delta;
   register FSERRPTR errorptr;	/* => fserrors[] at column before current */
   register JSAMPROW input_ptr;
   register JSAMPROW output_ptr;
   JSAMPROW colorindex_ci;
   JSAMPROW colormap_ci;
   int pixcode;
   int nc = cinfo->out_color_components;
   int dir;			/* 1 for left-to-right, -1 for right-to-left */
   int dirnc;			/* dir * nc */
   int ci;
   int row;
   JDIMENSION col;
   JDIMENSION width = cinfo->output_width;
   JSAMPLE *range_limit = cinfo->sample_range_limit;
  
   for (row = 0; row < num_rows; row++) 
   {
      /* Initialize output values to 0 so can process components separately */
      for (ci = 0; ci < nc; ci++) 
      {
         input_ptr = (uchar*)(input_buf + row * nc * width + ci);
         output_ptr = (uchar*)(output_buf + row * width);
         if (cquantize->on_odd_row) 
         {
	         /* work right to left in this row */
	         input_ptr += (width-1) * nc; /* so point to rightmost pixel */
	         output_ptr += width-1;
	         dir = -1;
	         dirnc = -nc;
	         errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */
         }
         else 
         {
	         /* work left to right in this row */
	         dir = 1;
	         dirnc = nc;
	         errorptr = cquantize->fserrors[ci]; /* => entry before first column */
         }
         colorindex_ci = cquantize->colorindex[ci];
         colormap_ci = cquantize->sv_colormap[ci];
         /* Preset error values: no error propagated to first pixel from left */
         cur = 0;
         /* and no error propagated to row below yet */
         belowerr = bpreverr = 0;

         for (col = width; col > 0; col--) 
         {
	         /* cur holds the error propagated from the previous pixel on the
	          * current line.  Add the error propagated from the previous line
	          * to form the complete error correction term for this pixel, and
	          * round the error term (which is expressed * 16) to an integer.
	          * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
	          * for either sign of the error value.
	          * Note: errorptr points to *previous* column's array entry.
	          */
	         cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4);
	         /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
	          * The maximum error is +- MAXJSAMPLE; this sets the required size
	          * of the range_limit array.
	          */
	         cur += GETJSAMPLE(*input_ptr);
	         cur = GETJSAMPLE(range_limit[cur]);
	         /* Select output value, accumulate into output code for this pixel */
	         pixcode = GETJSAMPLE(colorindex_ci[cur]);
			 *output_ptr += (JSAMPLE) pixcode;
			 /* Compute actual representation error at this pixel */
	         /* Note: we can do this even though we don't have the final */
	         /* pixel code, because the colormap is orthogonal. */
	         cur -= GETJSAMPLE(colormap_ci[pixcode]);
	         /* Compute error fractions to be propagated to adjacent pixels.
	          * Add these into the running sums, and simultaneously shift the
	          * next-line error sums left by 1 column.
	          */
	         bnexterr = cur;
	         delta = cur * 2;
	         cur += delta;		/* form error * 3 */
	         errorptr[0] = (FSERROR) (bpreverr + cur);
	         cur += delta;		/* form error * 5 */
	         bpreverr = belowerr + cur;
	         belowerr = bnexterr;
	         cur += delta;		/* form error * 7 */
	         /* At this point cur contains the 7/16 error value to be propagated
	          * to the next pixel on the current line, and all the errors for the
	          * next line have been shifted over. We are therefore ready to move on.
	          */
	         input_ptr += dirnc;	/* advance input ptr to next column */
	         output_ptr += dir;	/* advance output ptr to next column */
	         errorptr += dir;	/* advance errorptr to current column */
         }
         /* Post-loop cleanup: we must unload the final error value into the
          * final fserrors[] entry.  Note we need not unload belowerr because
          * it is for the dummy column before or after the actual array.
          */
         errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
      }
      cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
   }
}

//====================================================================================
// Function Name:	Bool gif_start_pass_1_quant (decompress_info_ptr cinfo, uint rows, uchar* input_buf,uchar* out_buf)
// Purpose      :	start to  improve color quality
// Parameter    :	
// Return       :	true or false	
// Remarks      :	
// Change Log   :	
//                Author       Date       Description	
//              -----------------------------------------------	
//=====================================================================================

Bool gif_start_pass_1_quant (decompress_info_ptr cinfo, uint rows, uchar* input_buf,uchar* out_buf)
{
   my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
    /* Install my colormap. */
   cinfo->colormap = cquantize->sv_colormap;
   cinfo->actual_number_of_colors = cquantize->sv_actual;
   /* Initialize for desired dithering mode. */
   switch (cinfo->dither_mode) 
   {
   case GIF_DITHER_NONE:
      if (cinfo->out_color_components == 3)
      {
         gif_color_quantize3(cinfo,input_buf,out_buf,rows);
      }
      else
      {
   		 gif_color_quantize(cinfo,input_buf,out_buf,rows);
      }
	   break;
   case GIF_DITHER_ORDERED:
      /* initialize state for ordered dither */
      /* If user changed to ordered dither from another mode,
      * we must recreate the color index table with padding.
      * This will cost extra space, but probably isn't very likely.
      */
      if (! cquantize->is_padded)
      {
         if(!gif_create_colorindex(cinfo))
			 return FALSE;
		 /* Create ordered-dither tables if we didn't already. */
      }
      if (cquantize->odither[0] == NULL)
      {
         if(!create_odither_tables(cinfo))
		 {
			 return FALSE;
		 }
      }
	   if (cinfo->out_color_components == 3)
      {
         gif_quantize3_ord_dither(cinfo,input_buf,out_buf,rows);
      }
      else
      {
		   gif_quantize_ord_dither(cinfo,input_buf,out_buf,rows);
      }
       break;

   case GIF_DITHER_FS:
     
	   //start Floyd-Steinberg
		gif_quantize_fs_dither(cinfo,input_buf,out_buf,rows);
      break;
   default:
	   return FALSE;
   }
	return TRUE;
}
#endif


















⌨️ 快捷键说明

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