📄 dither2.c
字号:
WriteToErrorFile("gif_start_pass_2_quant",ERROR_NOTIMPL,FileError);
#endif
InsertError(ERROR_NOTIMPL);
return FALSE;
}
/* Allocate the histogram/inverse colormap storage */
cquantize->histogram = (hist3d) gif_alloc_buf( HIST_C0_ELEMS * SIZEOF(hist2d));
if(cquantize->histogram == NULL)
{
return FALSE;
}
for (i = 0; i < HIST_C0_ELEMS; i++)
{
#ifdef STACK_USED
cquantize->histogram[i] = (hist2d)((uchar*)gram + i*HIST_C1_ELEMS*HIST_C2_ELEMS*SIZEOF(histcell));
#else
cquantize->histogram[i] = (hist2d)gif_alloc_buf(HIST_C1_ELEMS*HIST_C2_ELEMS*SIZEOF(histcell));
if(cquantize->histogram[i] == NULL)
{
return FALSE;
}
memset(cquantize->histogram[i], 0, HIST_C1_ELEMS*HIST_C2_ELEMS*SIZEOF(histcell));
#endif
}
/* Allocate storage for the completed colormap, if required.histcell
* We do this now since it is FAR storage and may affect
* the memory manager's space calculations.
*/
if (cinfo->enable_2pass_quant)
{
/* Make sure color count is acceptable */
int desired = cinfo->desired_number_of_colors;
/* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
if (desired < 8)
{
#ifdef PCVER
WriteToErrorFile("gif_start_pass_2_quant",ERROR_FEW_COLORS,FileError);
#endif
InsertError(ERROR_FEW_COLORS);
return FALSE;
}
/* Make sure colormap indexes can be represented by JSAMPLEs */
if (desired > MAXNUMCOLORS)
{
#ifdef PCVER
WriteToErrorFile("gif_start_pass_2_quant",ERROR_QUANT_MANY_COLORS,FileError);
#endif
InsertError(ERROR_QUANT_MANY_COLORS);
return FALSE;
}
cquantize->sv_colormap = gif_alloc_memr( 3 ,desired );
if(cquantize->sv_colormap == NULL)
{
return FALSE;
}
cquantize->desired = desired;
}
else
{
cquantize->sv_colormap = NULL;
}
cinfo->colormap = cquantize->sv_colormap;
/* Only F-S dithering or no dithering is supported. */
/* If user asks for ordered dither, give him F-S. */
if (cinfo->dither_mode != GIF_DITHER_NONE)
{
cinfo->dither_mode = GIF_DITHER_FS;
}
if(!gif_prepare_range_limit_table(cinfo))
{
return FALSE;
}
/* Allocate Floyd-Steinberg workspace if necessary.
* This isn't really needed until pass 2, but again it is FAR storage.
* Although we will cope with a later change in dither_mode,
* we do not promise to honor max_memory_to_use if dither_mode changes.
*/
if (cinfo->dither_mode == GIF_DITHER_FS)
{
size_t arraysize = (size_t) ((cinfo->output_width + 2) *
(3 * SIZEOF(FSERROR)));
cquantize->fserrors = (FSERRPTR) gif_alloc_buf(((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))));
if(cquantize->fserrors == NULL)
return FALSE;
gif_zero_far((void FAR *) cquantize->fserrors, arraysize);
/* Might as well create the error-limiting table too. */
if(!gif_init_error_limit(cinfo))
return FALSE;
}
/* Select the representative colors and fill in cinfo->colormap */
cquantize->needs_zeroed = TRUE;
return TRUE;
}
//====================================================================================
// Function Name: Bool gif_start_pass_2_quant (decompress_info_ptr cinfo, uint rows, uchar* input_buf,uchar* out_buf)
// Purpose :
// Parameter :
// Return :
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
Bool gif_start_pass_2_quant (decompress_info_ptr cinfo, uint rows, uchar* input_buf,uchar* out_buf)
{
my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize;
hist3d histogram = cquantize->histogram;
int i;
/* Only F-S dithering or no dithering is supported. */
/* If user asks for ordered dither, give him F-S. */
/* Make sure color count is acceptable */
i = cinfo->actual_number_of_colors;
if (i < 1)
{
#ifdef PCVER
WriteToErrorFile("gif_start_pass_2_quant",ERROR_FEW_COLORS,FileError);
#endif
InsertError(ERROR_FEW_COLORS);
return FALSE;
}
if (i > MAXNUMCOLORS)
{
#ifdef PCVER
WriteToErrorFile("gif_start_pass_2_quant",ERROR_QUANT_MANY_COLORS,FileError);
#endif
InsertError(ERROR_QUANT_MANY_COLORS);
return FALSE;
}
if (cquantize->needs_zeroed)
{
for (i = 0; i < HIST_C0_ELEMS; i++)
{
gif_zero_far((void FAR *) histogram[i],
HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
}
cquantize->needs_zeroed = FALSE;
}
if (cinfo->dither_mode != GIF_DITHER_NONE)
{
cinfo->dither_mode = GIF_DITHER_FS;
}
/* Set up method pointers */
if (cinfo->dither_mode == GIF_DITHER_FS)
{
/* Make the error-limit table if we didn't already. */
cquantize->on_odd_row = FALSE;
}
/* Zero the histogram or inverse color map, if necessary */
if (cinfo->dither_mode == GIF_DITHER_FS)
{
gif_pass2_fs_dither(cinfo,input_buf,out_buf,rows);
}
else
{
gif_pass2_no_dither(cinfo,input_buf,out_buf,rows);
}
return TRUE;
}
//====================================================================================
// Function Name: static void gif_init_error_limit (decompress_info_ptr cinfo)
// Purpose :
// Parameter :
// Return :
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
static Bool gif_init_error_limit (decompress_info_ptr cinfo)
/* Allocate and fill in the error_limiter table */
{
my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize;
int * table;
int in, out;
table = (int *) gif_alloc_buf((MAXJSAMPLE*2+1) * SIZEOF(int));
if(table == FALSE)
{
return FALSE;
}
table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
cquantize->error_limiter = table;
#define STEPSIZE ((MAXJSAMPLE+1)/16)
/* Map errors 1:1 up to +- MAXJSAMPLE/16 */
out = 0;
for (in = 0; in < STEPSIZE; in++, out++)
{
table[in] = out;
table[-in] = -out;
}
/* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1)
{
table[in] = out; table[-in] = -out;
}
/* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
for (; in <= MAXJSAMPLE; in++)
{
table[in] = out; table[-in] = -out;
}
#undef STEPSIZE
return TRUE;
}
//====================================================================================
// Function Name: static void gif_pass2_no_dither (decompress_info_ptr cinfo,uchar* input_buf, uchar* output_buf, int num_rows)
// Purpose : This version performs no dithering
// Parameter :
// Return :
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
static void gif_pass2_no_dither (decompress_info_ptr cinfo,
uchar* input_buf, uchar* output_buf, int num_rows)
{
my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize;
hist3d histogram = cquantize->histogram;
register JSAMPROW inptr, outptr;
register histptr cachep;
register int c0, c1, c2;
int row;
JDIMENSION col;
JDIMENSION width = cinfo->output_width;
for (row = 0; row < num_rows; row++)
{
inptr = input_buf + row * 3 * width ;
outptr = output_buf + row * width;
for (col = width; col > 0; col--)
{
/* get pixel value and index into the cache */
c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
cachep = & histogram[c0][c1][c2];
/* If we have not seen this color before, find nearest colormap entry */
/* and update the cache */
if (*cachep == 0)
{
gif_fill_inverse_cmap(cinfo, c0,c1,c2);
}
/* Now emit the colormap index for this cell */
*outptr++ = (JSAMPLE) (*cachep - 1);
}
}
}
//====================================================================================
// Function Name: static void gif_zero_far (void FAR * target, size_t bytestozero)
// Purpose : Zero out a chunk of FAR memory.
// This might be sample-array data, block-array data, or alloc_large data.
// Parameter :
// Return :
// 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: static void gif_prepare_range_limit_table (decompress_info_ptr cinfo)
// Purpose : Allocate and fill in the sample_range_limit table
// Parameter :
// Return :
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
static Bool gif_prepare_range_limit_table (decompress_info_ptr cinfo)
{
JSAMPLE * table;
int i;
table = (JSAMPLE *)gif_alloc_buf((5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
if(table == NULL)
return FALSE;
table += (MAXJSAMPLE+1);
/* allow negative subscripts of simple table */
cinfo->sample_range_limit = table;
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
/* Main part of "simple" table: limit[x] = x */
for (i = 0; i <= MAXJSAMPLE; i++)
{
table[i] = (JSAMPLE) i;
}
table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
/* End of simple table, rest of first half of post-IDCT table */
for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
{
table[i] = MAXJSAMPLE;
}
/* Second half of post-IDCT table */
MEMZERO(table + (2 * (MAXJSAMPLE+1)),
(2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
return TRUE;
}
//====================================================================================
// Function Name: void gif_prescan_quantize (decompress_info_ptr cinfo, uchar* input_buf, int num_rows)
// Purpose :
// Parameter :
// Return :
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
void gif_prescan_quantize (decompress_info_ptr cinfo, uchar* input_buf,
int num_rows)
{
my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize;
register JSAMPROW ptr;
register histptr histp;
register hist3d histogram = cquantize->histogram;
int row;
JDIMENSION col;
JDIMENSION width = cinfo->output_width;
for (row = 0; row < num_rows; row++)
{
ptr =(uchar*)( input_buf + row * 3 * width );
for (col = width; col > 0; col--)
{
/* get pixel value and index into the histogram */
histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
[GETJSAMPLE(ptr[1]) >> C1_SHIFT]
[GETJSAMPLE(ptr[2]) >> C2_SHIFT];
/* increment, check for overflow and undo increment if so. */
if (++(*histp) <= 0)
{
(*histp)--;
ptr += 3;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -