📄 invcmap.c
字号:
gcdp = gdp = rdp, gcrgbp = grgbp = rrgbp, first = 1;
g <= max;
g++, gdp += gstride, gcdp += gstride, grgbp += gstride, gcrgbp += gstride,
gdist += gxx, gcdist += gxx, gxx += txsqr, first = 0 )
{
if ( blueloop( first ) )
{
if ( !detect )
{
/* Remember here and associated data! */
if ( g > here )
{
here = g;
rdp = gcdp;
rrgbp = gcrgbp;
rdist = gcdist;
ginc = gxx;
#ifdef MINMAX_TRACK
thismin = here;
#endif
}
detect = 1;
}
}
else if ( detect )
{
#ifdef MINMAX_TRACK
thismax = g - 1;
#endif
break;
}
}
/* Basic loop down. */
for ( g = here - 1, gxx = ginc - txsqr, gcdist = gdist = rdist - gxx,
gcdp = gdp = rdp - gstride, gcrgbp = grgbp = rrgbp - gstride,
first = 1;
g >= min;
g--, gdp -= gstride, gcdp -= gstride, grgbp -= gstride, gcrgbp -= gstride,
gxx -= txsqr, gdist -= gxx, gcdist -= gxx, first = 0 )
{
if ( blueloop( first ) )
{
if ( !detect )
{
/* Remember here! */
here = g;
rdp = gcdp;
rrgbp = gcrgbp;
rdist = gcdist;
ginc = gxx;
#ifdef MINMAX_TRACK
thismax = here;
#endif
detect = 1;
}
}
else if ( detect )
{
#ifdef MINMAX_TRACK
thismin = g + 1;
#endif
break;
}
}
#ifdef MINMAX_TRACK
/* If we saw something, update the edge trackers. For now, only
* tracks edges that are "shrinking" (min increasing, max
* decreasing.
*/
if ( detect )
{
if ( thismax < prevmax )
max = thismax;
prevmax = thismax;
if ( thismin > prevmin )
min = thismin;
prevmin = thismin;
}
#endif
return detect;
}
/* blueloop -- loop up and down from blue center. */
int32_T
blueloop( int32_T restart )
{
int32_T detect;
register uint32_T *dp;
register int32_T *rgbp;
register int32_T bdist, bxx;
register int32_T b, i = cindex;
register int32_T txsqr = xsqr + xsqr;
register int32_T lim;
static int32_T here, min, max;
#ifdef MINMAX_TRACK
static int32_T prevmin, prevmax;
int32_T thismin, thismax;
#endif /* MINMAX_TRACK */
static int32_T binc;
if ( restart )
{
here = bcenter;
min = 0;
max = colormax - 1;
binc = cbinc;
#ifdef MINMAX_TRACK
prevmin = colormax;
prevmax = 0;
#endif /* MINMAX_TRACK */
}
detect = 0;
#ifdef MINMAX_TRACK
thismin = min;
thismax = max;
#endif
/* Basic loop up. */
/* First loop just finds first applicable cell. */
for ( b = here, bdist = gdist, bxx = binc, dp = gdp, rgbp = grgbp, lim = max;
b <= lim;
b++, dp++, rgbp++,
bdist += bxx, bxx += txsqr )
{
#ifdef INSTRUMENT_IT
outercount++;
#endif
if ( *dp > bdist )
{
/* Remember new 'here' and associated data! */
if ( b > here )
{
here = b;
gdp = dp;
grgbp = rgbp;
gdist = bdist;
binc = bxx;
#ifdef MINMAX_TRACK
thismin = here;
#endif
}
detect = 1;
#ifdef INSTRUMENT_IT
outercount--;
#endif
break;
}
}
/* Second loop fills in a run of closer cells. */
for ( ;
b <= lim;
b++, dp++, rgbp++,
bdist += bxx, bxx += txsqr )
{
#ifdef INSTRUMENT_IT
outercount++;
#endif
if ( *dp > bdist )
{
#ifdef INSTRUMENT_IT
innercount++;
#endif
*dp = bdist;
*rgbp = i;
}
else
{
#ifdef MINMAX_TRACK
thismax = b - 1;
#endif
break;
}
}
/* Basic loop down. */
/* Do initializations here, since the 'find' loop might not get
* executed.
*/
lim = min;
b = here - 1;
bxx = binc - txsqr;
bdist = gdist - bxx;
dp = gdp - 1;
rgbp = grgbp - 1;
/* The 'find' loop is executed only if we didn't already find
* something.
*/
if ( !detect )
for ( ;
b >= lim;
b--, dp--, rgbp--,
bxx -= txsqr, bdist -= bxx )
{
#ifdef INSTRUMENT_IT
outercount++;
#endif
if ( *dp > bdist )
{
/* Remember here! */
/* No test for b against here necessary because b <
* here by definition.
*/
here = b;
gdp = dp;
grgbp = rgbp;
gdist = bdist;
binc = bxx;
#ifdef MINMAX_TRACK
thismax = here;
#endif
detect = 1;
#ifdef INSTRUMENT_IT
outercount--;
#endif
break;
}
}
/* The 'update' loop. */
for ( ;
b >= lim;
b--, dp--, rgbp--,
bxx -= txsqr, bdist -= bxx )
{
#ifdef INSTRUMENT_IT
outercount++;
#endif
if ( *dp > bdist )
{
#ifdef INSTRUMENT_IT
innercount++;
#endif
*dp = bdist;
*rgbp = i;
}
else
{
#ifdef MINMAX_TRACK
thismin = b + 1;
#endif
break;
}
}
/* If we saw something, update the edge trackers. */
#ifdef MINMAX_TRACK
if ( detect )
{
/* Only tracks edges that are "shrinking" (min increasing, max
* decreasing.
*/
if ( thismax < prevmax )
max = thismax;
if ( thismin > prevmin )
min = thismin;
/* Remember the min and max values. */
prevmax = thismax;
prevmin = thismin;
}
#endif /* MINMAX_TRACK */
return detect;
}
#if 0 /* inv_cmap_1 not used by ditherc.c */
/*****************************************************************
* TAG( inv_cmap_1 )
*
* Compute an inverse colormap efficiently.
* Inputs:
* colors: Number of colors in the forward colormap.
* colormap: The forward colormap.
* bits: Number of quantization bits. The inverse
* colormap will have (2^bits)^3 entries.
* dist_buf: An array of (2^bits)^3 long integers to be
* used as scratch space.
* Outputs:
* rgbmap: The output inverse colormap. The entry
* rgbmap[(r<<(2*bits)) + (g<<bits) + b]
* is the colormap entry that is closest to the
* (quantized) color (r,g,b).
* Assumptions:
* Quantization is performed by right shift (low order bits are
* truncated). Thus, the distance to a quantized color is
* actually measured to the color at the center of the cell
* (i.e., to r+.5, g+.5, b+.5, if (r,g,b) is a quantized color).
* Algorithm:
* Uses a "distance buffer" algorithm:
* The distance from each representative in the forward color map
* to each point in the rgb space is computed. If it is less
* than the distance currently stored in dist_buf, then the
* corresponding entry in rgbmap is replaced with the current
* representative (and the dist_buf entry is replaced with the
* new distance).
*
* The distance computation uses an efficient incremental formulation.
*
* Right now, distances are computed for all entries in the rgb
* space. Thus, the complexity of the algorithm is O(K N^3),
* where K = colors, and N = 2^bits.
*/
void
inv_cmap_1( colors, colormap, bits, dist_buf, rgbmap )
int colors, bits;
unsigned char *colormap[3], *rgbmap;
unsigned long *dist_buf;
{
register unsigned long *dp;
register unsigned char *rgbp;
register long bdist, bxx;
register int b, i;
int nbits = 8 - bits;
register int colormax = 1 << bits;
register long xsqr = 1 << (2 * nbits);
int x = 1 << nbits;
int rinc, ginc, binc, r, g;
long rdist, gdist, rxx, gxx;
for ( i = 0; i < colors; i++ )
{
/*
* Distance formula is
* (red - map[0])^2 + (green - map[1])^2 + (blue - map[2])^2
*
* Because of quantization, we will measure from the center of
* each quantized "cube", so blue distance is
* (blue + x/2 - map[2])^2,
* where x = 2^(8 - bits).
* The step size is x, so the blue increment is
* 2*x*blue - 2*x*map[2] + 2*x^2
*
* Now, b in the code below is actually blue/x, so our
* increment will be 2*x*x*b + (2*x^2 - 2*x*map[2]). For
* efficiency, we will maintain this quantity in a separate variable
* that will be updated incrementally by adding 2*x^2 each time.
*/
rdist = colormap[0][i] - x/2;
gdist = colormap[1][i] - x/2;
bdist = colormap[2][i] - x/2;
rdist = rdist*rdist + gdist*gdist + bdist*bdist;
rinc = 2 * (xsqr - (colormap[0][i] << nbits));
ginc = 2 * (xsqr - (colormap[1][i] << nbits));
binc = 2 * (xsqr - (colormap[2][i] << nbits));
dp = dist_buf;
rgbp = rgbmap;
for ( r = 0, rxx = rinc;
r < colormax;
rdist += rxx, r++, rxx += xsqr + xsqr )
for ( g = 0, gdist = rdist, gxx = ginc;
g < colormax;
gdist += gxx, g++, gxx += xsqr + xsqr )
for ( b = 0, bdist = gdist, bxx = binc;
b < colormax;
bdist += bxx, b++, dp++, rgbp++,
bxx += xsqr + xsqr )
{
#ifdef INSTRUMENT_IT
outercount++;
#endif
if ( i == 0 || *dp > bdist )
{
#ifdef INSTRUMENT_IT
innercount++;
#endif
*dp = bdist;
*rgbp = i;
}
}
}
#ifdef INSTRUMENT_IT
printf( "K = %d, N = %d, outer count = %ld, inner count = %ld\n",
colors, colormax, outercount, innercount );
#endif
}
#endif /* inv_cmap_1 not used in ditherc.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -