com.twelvemonkeys.image.inv_cmap.c Maven / Gradle / Ivy
/*
* This software is copyrighted as noted below. It may be freely copied,
* modified, and redistributed, provided that the copyright notice is
* preserved on all copies.
*
* There is no warranty or other guarantee of fitness for this software,
* it is provided solely "as is". Bug reports or fixes may be sent
* to the author, who may or may not act on them as he desires.
*
* You may not include this software in a program or other software product
* without supplying the source, or without informing the end-user that the
* source is available for no extra charge.
*
* If you modify this software, you should include a notice giving the
* name of the person performing the modification, the date of modification,
* and the reason for such modification.
*/
/*
* inv_cmap.c - Compute an inverse colormap.
*
* Author: Spencer W. Thomas
* EECS Dept.
* University of Michigan
* Date: Thu Sep 20 1990
* Copyright (c) 1990, University of Michigan
*
* $Id: inv_cmap.c,v 3.0.1.3 1992/04/30 14:07:28 spencer Exp $
*/
#include
#include
static int bcenter, gcenter, rcenter;
static long gdist, rdist, cdist;
static long cbinc, cginc, crinc;
static unsigned long *gdp, *rdp, *cdp;
static unsigned char *grgbp, *rrgbp, *crgbp;
static gstride, rstride;
static long x, xsqr, colormax;
static int cindex;
#ifdef USE_PROTOTYPES
static void maxfill( unsigned long *, long );
static int redloop( void );
static int greenloop( int );
static int blueloop( int );
#else
static void maxfill();
static int redloop();
static int greenloop();
static int blueloop();
#endif
/*****************************************************************
* TAG( inv_cmap )
*
* 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<> nbits;
gcenter = colormap[1][cindex] >> nbits;
bcenter = colormap[2][cindex] >> nbits;
rdist = colormap[0][cindex] - (rcenter * x + x/2);
gdist = colormap[1][cindex] - (gcenter * x + x/2);
cdist = colormap[2][cindex] - (bcenter * x + x/2);
cdist = rdist*rdist + gdist*gdist + cdist*cdist;
crinc = 2 * ((rcenter + 1) * xsqr - (colormap[0][cindex] * x));
cginc = 2 * ((gcenter + 1) * xsqr - (colormap[1][cindex] * x));
cbinc = 2 * ((bcenter + 1) * xsqr - (colormap[2][cindex] * x));
/* Array starting points. */
cdp = dist_buf + rcenter * rstride + gcenter * gstride + bcenter;
crgbp = rgbmap + rcenter * rstride + gcenter * gstride + bcenter;
(void)redloop();
}
}
/* redloop -- loop up and down from red center. */
static int
redloop()
{
int detect;
int r;
int first;
long txsqr = xsqr + xsqr;
static long rxx;
detect = 0;
/* Basic loop up. */
for ( r = rcenter, rdist = cdist, rxx = crinc,
rdp = cdp, rrgbp = crgbp, first = 1;
r < colormax;
r++, rdp += rstride, rrgbp += rstride,
rdist += rxx, rxx += txsqr, first = 0 )
{
if ( greenloop( first ) )
detect = 1;
else if ( detect )
break;
}
/* Basic loop down. */
for ( r = rcenter - 1, rxx = crinc - txsqr, rdist = cdist - rxx,
rdp = cdp - rstride, rrgbp = crgbp - rstride, first = 1;
r >= 0;
r--, rdp -= rstride, rrgbp -= rstride,
rxx -= txsqr, rdist -= rxx, first = 0 )
{
if ( greenloop( first ) )
detect = 1;
else if ( detect )
break;
}
return detect;
}
/* greenloop -- loop up and down from green center. */
static int
greenloop( restart )
int restart;
{
int detect;
int g;
int first;
long txsqr = xsqr + xsqr;
static int here, min, max;
static long ginc, gxx, gcdist; /* "gc" variables maintain correct */
static unsigned long *gcdp; /* values for bcenter position, */
static unsigned char *gcrgbp; /* despite modifications by blueloop */
/* to gdist, gdp, grgbp. */
if ( restart )
{
here = gcenter;
min = 0;
max = colormax - 1;
ginc = cginc;
}
detect = 0;
/* Basic loop up. */
for ( g = here, gcdist = gdist = rdist, gxx = ginc,
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;
}
detect = 1;
}
}
else if ( detect )
{
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;
detect = 1;
}
}
else if ( detect )
{
break;
}
}
return detect;
}
/* blueloop -- loop up and down from blue center. */
static int
blueloop( restart )
int restart;
{
int detect;
register unsigned long *dp;
register unsigned char *rgbp;
register long bdist, bxx;
register int b, i = cindex;
register long txsqr = xsqr + xsqr;
register int lim;
static int here, min, max;
static long binc;
if ( restart )
{
here = bcenter;
min = 0;
max = colormax - 1;
binc = cbinc;
}
detect = 0;
/* 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 )
{
if ( *dp > bdist )
{
/* Remember new 'here' and associated data! */
if ( b > here )
{
here = b;
gdp = dp;
grgbp = rgbp;
gdist = bdist;
binc = bxx;
}
detect = 1;
break;
}
}
/* Second loop fills in a run of closer cells. */
for ( ;
b <= lim;
b++, dp++, rgbp++,
bdist += bxx, bxx += txsqr )
{
if ( *dp > bdist )
{
*dp = bdist;
*rgbp = i;
}
else
{
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 )
{
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;
detect = 1;
break;
}
}
/* The 'update' loop. */
for ( ;
b >= lim;
b--, dp--, rgbp--,
bxx -= txsqr, bdist -= bxx )
{
if ( *dp > bdist )
{
*dp = bdist;
*rgbp = i;
}
else
{
break;
}
}
/* If we saw something, update the edge trackers. */
return detect;
}
static void
maxfill( buffer, side )
unsigned long *buffer;
long side;
{
register unsigned long maxv = ~0L;
register long i;
register unsigned long *bp;
for ( i = side * side * side, bp = buffer;
i > 0;
i--, bp++ )
*bp = maxv;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy