📄 dither2.c
字号:
{
boxp->c0min = c0min = c0;
goto have_c0min;
}
}
}
}
}
have_c0min:
if (c0max > c0min)
{
for (c0 = c0max; c0 >= c0min; c0--)
{
for (c1 = c1min; c1 <= c1max; c1++)
{
histp = & histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
{
if (*histp++ != 0)
{
boxp->c0max = c0max = c0;
goto have_c0max;
}
}
}
}
}
have_c0max:
if (c1max > c1min)
{
for (c1 = c1min; c1 <= c1max; c1++)
{
for (c0 = c0min; c0 <= c0max; c0++)
{
histp = & histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
{
if (*histp++ != 0)
{
boxp->c1min = c1min = c1;
goto have_c1min;
}
}
}
}
}
have_c1min:
if (c1max > c1min)
{
for (c1 = c1max; c1 >= c1min; c1--)
{
for (c0 = c0min; c0 <= c0max; c0++)
{
histp = & histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
{
if (*histp++ != 0)
{
boxp->c1max = c1max = c1;
goto have_c1max;
}
}
}
}
}
have_c1max:
if (c2max > c2min)
{
for (c2 = c2min; c2 <= c2max; c2++)
{
for (c0 = c0min; c0 <= c0max; c0++)
{
histp = & histogram[c0][c1min][c2];
for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
{
if (*histp != 0)
{
boxp->c2min = c2min = c2;
goto have_c2min;
}
}
}
}
}
have_c2min:
if (c2max > c2min)
{
for (c2 = c2max; c2 >= c2min; c2--)
{
for (c0 = c0min; c0 <= c0max; c0++)
{
histp = & histogram[c0][c1min][c2];
for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
{
if (*histp != 0)
{
boxp->c2max = c2max = c2;
goto have_c2max;
}
}
}
}
}
have_c2max:
/* Update box volume.
* We use 2-norm rather than real volume here; this biases the method
* against making long narrow boxes, and it has the side benefit that
* a box is splittable iff norm > 0.
* Since the differences are expressed in histogram-cell units,
* we have to shift back to JSAMPLE units to get consistent distances;
* after which, we scale according to the selected distance scale factors.
*/
dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
/* Now scan remaining volume of box and compute population */
ccount = 0;
for (c0 = c0min; c0 <= c0max; c0++)
{
for (c1 = c1min; c1 <= c1max; c1++)
{
histp = & histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++, histp++)
{
if (*histp != 0)
{
ccount++;
}
}
}
}
boxp->colorcount = ccount;
}
//====================================================================================
// Function Name: static void compute_color (decompress_info_ptr cinfo, boxptr boxp, int icolor)
// Purpose : Compute representative color for a box, put it in colormap[icolor]
// Parameter :
// Return :
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
static void compute_color (decompress_info_ptr cinfo, boxptr boxp, int icolor)
{
/* Current algorithm: mean weighted by pixels (not colors) */
/* Note it is important to get the rounding correct! */
my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize;
hist3d histogram = cquantize->histogram;
histptr histp;
int c0,c1,c2;
int c0min,c0max,c1min,c1max,c2min,c2max;
long count;
long total = 0;
long c0total = 0;
long c1total = 0;
long c2total = 0;
c0min = boxp->c0min; c0max = boxp->c0max;
c1min = boxp->c1min; c1max = boxp->c1max;
c2min = boxp->c2min; c2max = boxp->c2max;
for (c0 = c0min; c0 <= c0max; c0++)
{
for (c1 = c1min; c1 <= c1max; c1++)
{
histp = & histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
{
if ((count = *histp++) != 0)
{
total += count;
c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
}
}
}
}
cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
}
//====================================================================================
// Function Name: static int find_nearby_colors (decompress_info_ptr cinfo, int minc0, int minc1, int minc2,
// Purpose : Locate the colormap entries close enough to an update box to be candidates
// for the nearest entry to some cell(s) in the update box. The update box
// is specified by the center coordinates of its first cell. The number of
// candidate colormap entries is returned, and their colormap indexes are
// placed in colorlist[].
// This routine uses Heckbert's "locally sorted search" criterion to select
// the colors that need further consideration.
// Parameter :
// Return :
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
static int find_nearby_colors (decompress_info_ptr cinfo, int minc0, int minc1, int minc2,
JSAMPLE colorlist[])
{
int numcolors = cinfo->actual_number_of_colors;
int maxc0, maxc1, maxc2;
int centerc0, centerc1, centerc2;
int i, x, ncolors;
INT32 minmaxdist, min_dist, max_dist, tdist;
INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */
/* Compute true coordinates of update box's upper corner and center.
* Actually we compute the coordinates of the center of the upper-corner
* histogram cell, which are the upper bounds of the volume we care about.
* Note that since ">>" rounds down, the "center" values may be closer to
* min than to max; hence comparisons to them must be "<=", not "<".
*/
maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
centerc0 = (minc0 + maxc0) >> 1;
maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
centerc1 = (minc1 + maxc1) >> 1;
maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
centerc2 = (minc2 + maxc2) >> 1;
/* For each color in colormap, find:
* 1. its minimum squared-distance to any point in the update box
* (zero if color is within update box);
* 2. its maximum squared-distance to any point in the update box.
* Both of these can be found by considering only the corners of the box.
* We save the minimum distance for each color in mindist[];
* only the smallest maximum distance is of interest.
*/
minmaxdist = 0x7FFFFFFFL;
for (i = 0; i < numcolors; i++)
{
/* We compute the squared-c0-distance term, then add in the other two. */
x = GETJSAMPLE(cinfo->colormap[0][i]);
if (x < minc0)
{
tdist = (x - minc0) * C0_SCALE;
min_dist = tdist*tdist;
tdist = (x - maxc0) * C0_SCALE;
max_dist = tdist*tdist;
}
else if (x > maxc0)
{
tdist = (x - maxc0) * C0_SCALE;
min_dist = tdist*tdist;
tdist = (x - minc0) * C0_SCALE;
max_dist = tdist*tdist;
}
else
{
/* within cell range so no contribution to min_dist */
min_dist = 0;
if (x <= centerc0)
{
tdist = (x - maxc0) * C0_SCALE;
max_dist = tdist*tdist;
}
else
{
tdist = (x - minc0) * C0_SCALE;
max_dist = tdist*tdist;
}
}
x = GETJSAMPLE(cinfo->colormap[1][i]);
if (x < minc1)
{
tdist = (x - minc1) * C1_SCALE;
min_dist += tdist*tdist;
tdist = (x - maxc1) * C1_SCALE;
max_dist += tdist*tdist;
}
else if (x > maxc1)
{
tdist = (x - maxc1) * C1_SCALE;
min_dist += tdist*tdist;
tdist = (x - minc1) * C1_SCALE;
max_dist += tdist*tdist;
}
else
{
/* within cell range so no contribution to min_dist */
if (x <= centerc1)
{
tdist = (x - maxc1) * C1_SCALE;
max_dist += tdist*tdist;
}
else
{
tdist = (x - minc1) * C1_SCALE;
max_dist += tdist*tdist;
}
}
x = GETJSAMPLE(cinfo->colormap[2][i]);
if (x < minc2)
{
tdist = (x - minc2) * C2_SCALE;
min_dist += tdist*tdist;
tdist = (x - maxc2) * C2_SCALE;
max_dist += tdist*tdist;
}
else if (x > maxc2)
{
tdist = (x - maxc2) * C2_SCALE;
min_dist += tdist*tdist;
tdist = (x - minc2) * C2_SCALE;
max_dist += tdist*tdist;
}
else
{
/* within cell range so no contribution to min_dist */
if (x <= centerc2)
{
tdist = (x - maxc2) * C2_SCALE;
max_dist += tdist*tdist;
}
else
{
tdist = (x - minc2) * C2_SCALE;
max_dist += tdist*tdist;
}
}
mindist[i] = min_dist; /* save away the results */
if (max_dist < minmaxdist)
{
minmaxdist = max_dist;
}
}
/* Now we know that no cell in the update box is more than minmaxdist
* away from some colormap entry. Therefore, only colors that are
* within minmaxdist of some part of the box need be considered.
*/
ncolors = 0;
for (i = 0; i < numcolors; i++)
{
if (mindist[i] <= minmaxdist)
{
colorlist[ncolors++] = (JSAMPLE) i;
}
}
return ncolors;
}
//====================================================================================
// Function Name: void gif_select_colors (decompress_info_ptr cinfo, int desired_colors)
// Purpose : Master routine for color selection
// Parameter :
// Return :
// Remarks :
// Change Log :
// Author Date Description
// -----------------------------------------------
//=====================================================================================
Bool gif_select_colors (decompress_info_ptr cinfo, int desired_colors)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -