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 + -
显示快捷键?