aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/Xprint/pcl/PclColor.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/Xprint/pcl/PclColor.c')
-rw-r--r--nx-X11/programs/Xserver/Xprint/pcl/PclColor.c851
1 files changed, 851 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/Xprint/pcl/PclColor.c b/nx-X11/programs/Xserver/Xprint/pcl/PclColor.c
new file mode 100644
index 000000000..72c7e3f99
--- /dev/null
+++ b/nx-X11/programs/Xserver/Xprint/pcl/PclColor.c
@@ -0,0 +1,851 @@
+/* $Xorg: PclColor.c,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ */
+/*******************************************************************
+**
+** *********************************************************
+** *
+** * File: PclColorInit.c
+** *
+** * Contents:
+** * Colormap handing code of Pcl driver for the
+** * print server.
+** *
+** * Created: 4/8/96
+** *
+** *********************************************************
+**
+********************************************************************/
+/*
+(c) Copyright 1996 Hewlett-Packard Company
+(c) Copyright 1996 International Business Machines Corp.
+(c) Copyright 1996 Sun Microsystems, Inc.
+(c) Copyright 1996 Novell, Inc.
+(c) Copyright 1996 Digital Equipment Corp.
+(c) Copyright 1996 Fujitsu Limited
+(c) Copyright 1996 Hitachi, Ltd.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the names of the copyright holders shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from said
+copyright holders.
+*/
+/* $XFree86: xc/programs/Xserver/Xprint/pcl/PclColor.c,v 1.9tsi Exp $ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "colormapst.h"
+#include "windowstr.h"
+#include "resource.h"
+
+#include "Pcl.h"
+#include "cfb.h"
+
+static void lookup(unsigned char *src,
+ unsigned char *dst,
+ int num,
+ unsigned char *map,
+ int dim);
+static void trilinear(unsigned char *p,
+ unsigned char *out,
+ unsigned char *d,
+ int dim,
+ unsigned char def);
+
+
+/*
+ * This seems to be (and is) a duplication of effort; one would think
+ * that cfbCreateDefColormap would be sufficient. It almost is. The
+ * only change made in this function is that the black and white pixels
+ * are allocated with three separate variables for red, green and blue
+ * values, instead of the single variable in cfbCreateDefColormap. The
+ * single variable leads to the one value being corrected by
+ * ResolveColor three times, which leads to incorrect colors.
+ */
+
+Bool
+PclCreateDefColormap(ScreenPtr pScreen)
+{
+ unsigned short wp_red = ~0, wp_green = ~0, wp_blue = ~0;
+ unsigned short bp_red = 0, bp_green = 0, bp_blue = 0;
+ VisualPtr pVisual;
+ ColormapPtr cmap;
+ Pixel wp, bp;
+
+ for (pVisual = pScreen->visuals;
+ pVisual->vid != pScreen->rootVisual;
+ pVisual++)
+ ;
+
+ if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
+ (pVisual->class & DynamicClass) ? AllocNone : AllocAll,
+ 0)
+ != Success)
+ return FALSE;
+ wp = pScreen->whitePixel;
+ bp = pScreen->blackPixel;
+ if ((AllocColor(cmap, &wp_red, &wp_green, &wp_blue, &wp, 0) !=
+ Success) ||
+ (AllocColor(cmap, &bp_red, &bp_green, &bp_blue, &bp, 0) !=
+ Success))
+ return FALSE;
+
+ pScreen->whitePixel = wp;
+ pScreen->blackPixel = bp;
+
+ (*pScreen->InstallColormap)(cmap);
+ return TRUE;
+}
+
+/*
+ * Add colormap to list of colormaps on screen
+ */
+Bool
+PclCreateColormap(ColormapPtr pColor)
+{
+ PclCmapToContexts *new;
+ PclScreenPrivPtr sPriv;
+
+ sPriv = (PclScreenPrivPtr)pColor->pScreen
+ ->devPrivates[PclScreenPrivateIndex].ptr;
+
+ /*
+ * Use existing code to initialize the values in the colormap
+ */
+ cfbInitializeColormap( pColor );
+
+ /*
+ * Set up the mapping between the color map and the context
+ */
+ new = (PclCmapToContexts *)xalloc( sizeof( PclCmapToContexts ) );
+
+ if( new )
+ {
+ new->colormapId = pColor->mid;
+ new->contexts = NULL;
+ new->next = sPriv->colormaps;
+ sPriv->colormaps = new;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+void
+PclDestroyColormap(ColormapPtr pColor)
+{
+ PclScreenPrivPtr sPriv;
+ PclCmapToContexts *pCmap, *tCmap = 0;
+ PclContextListPtr con, tCon;
+ PclContextPrivPtr cPriv;
+ PclPaletteMapPtr pPal;
+ char t[80];
+
+ /*
+ * At DestroyContext time, colormaps may be destroyed twice, so if the
+ * pointer is NULL, just crash out.
+ */
+ if( !pColor )
+ return;
+
+ /*
+ * Find the colormap <-> contexts mapping
+ */
+ sPriv = (PclScreenPrivPtr)pColor->pScreen
+ ->devPrivates[PclScreenPrivateIndex].ptr;
+ pCmap = sPriv->colormaps;
+ while( pCmap )
+ {
+ if( pCmap->colormapId == pColor->mid )
+ break;
+ tCmap = pCmap;
+ pCmap = pCmap->next;
+ }
+
+ /*
+ * For each context, delete the palette in the printer and
+ * free the mapping.
+ */
+ if( pCmap )
+ {
+ con = pCmap->contexts;
+ while( con )
+ {
+ cPriv = con->context->devPrivates[PclContextPrivateIndex].ptr;
+
+ pPal = cPriv->palettes;
+ while( pPal )
+ {
+ if( pPal->colormapId == pColor->mid )
+ break;
+ pPal = pPal->next;
+ }
+
+ if( cPriv->pPageFile )
+ {
+ sprintf( t, "\033&p%dI\033*p2C", pPal->paletteId );
+ SEND_PCL( cPriv->pPageFile, t );
+ }
+
+ tCon = con;
+ con = con->next;
+ xfree( tCon );
+ }
+
+ /*
+ * Delete the colormap<->contexts mapping
+ */
+ if( sPriv->colormaps == pCmap )
+ /* Delete from the front */
+ sPriv->colormaps = pCmap->next;
+ else
+ /* Delete from the middle */
+ tCmap->next = pCmap->next;
+ free( pCmap );
+ }
+}
+
+void
+PclInstallColormap(ColormapPtr pColor)
+{
+}
+
+void
+PclUninstallColormap(ColormapPtr pColor)
+{
+}
+
+int
+PclListInstalledColormaps(ScreenPtr pScreen,
+ XID *pCmapList)
+{
+ return 0;
+}
+
+void
+PclStoreColors(ColormapPtr pColor,
+ int ndef,
+ xColorItem *pdefs)
+{
+ PclCmapToContexts *p;
+ PclScreenPrivPtr sPriv;
+ PclContextListPtr con;
+ PclContextPrivPtr cPriv;
+ PclPaletteMapPtr pMap;
+ char t[80];
+ int i;
+
+ sPriv = (PclScreenPrivPtr)pColor->pScreen
+ ->devPrivates[PclScreenPrivateIndex].ptr;
+ p = sPriv->colormaps;
+ while( p )
+ {
+ if( p->colormapId == pColor->mid )
+ break;
+ p = p->next;
+ }
+
+ if( p )
+ {
+ con = p->contexts;
+ while( con )
+ {
+ /*
+ * For each context, get the palette ID and update the
+ * appropriate palette.
+ */
+ cPriv = con->context
+ ->devPrivates[PclContextPrivateIndex].ptr;
+ pMap = PclFindPaletteMap( cPriv, pColor, NULL );
+
+ /*
+ * Update the palette
+ */
+ sprintf( t, "\033&p%dS", pMap->paletteId );
+ SEND_PCL( cPriv->pPageFile, t );
+
+ if( pColor->class == PseudoColor )
+ {
+ unsigned short r, g, b;
+ unsigned int pID;
+ for( i = 0; i < ndef; i++ )
+ {
+ pID = pdefs[i].pixel;
+ if ( pColor->red[i].fShared )
+ {
+ r = pColor->red[pID].co.shco.red->color;
+ g = pColor->red[pID].co.shco.green->color;
+ b = pColor->red[pID].co.shco.blue->color;
+ }
+ else
+ {
+ r = pColor->red[pID].co.local.red;
+ g = pColor->red[pID].co.local.green;
+ b = pColor->red[pID].co.local.blue;
+ }
+
+ if( pdefs[i].flags & DoRed )
+ r = pdefs[i].red;
+ if( pdefs[i].flags & DoGreen )
+ g = pdefs[i].green;
+ if( pdefs[i].flags & DoBlue )
+ b = pdefs[i].blue;
+ PclLookUp(pColor, cPriv, &r, &g, &b);
+ sprintf( t, "\033*v%ua%ub%uc%dI", r, g, b, pID);
+ SEND_PCL( cPriv->pPageFile, t );
+ }
+ }
+
+ sprintf( t, "\033&p%dS", cPriv->currentPalette );
+ SEND_PCL( cPriv->pPageFile, t );
+
+ con = con->next;
+ }
+ }
+}
+
+void
+PclResolveColor(unsigned short *pRed,
+ unsigned short *pGreen,
+ unsigned short *pBlue,
+ VisualPtr pVisual)
+{
+ /*
+ * We need to map the X color range of [0,65535] to the PCL color
+ * range of [0,32767].
+ */
+ *pRed >>= 1;
+ *pGreen >>= 1;
+ *pBlue >>= 1;
+}
+
+PclPaletteMapPtr
+PclFindPaletteMap(PclContextPrivPtr cPriv,
+ ColormapPtr cmap,
+ GCPtr gc)
+{
+ PclPaletteMapPtr p = cPriv->palettes, new;
+
+ /*
+ * If the colormap is static, grab one of the special palettes. If we come
+ * into this from StoreColors, there will be no GC, but by definition we're
+ * looking at a dynamic color map, so the special colors will not be
+ * needed.
+ */
+ if( gc )
+ {
+ if( cmap->pVisual->class == StaticGray )
+ return &( cPriv->staticGrayPalette );
+ else if( cmap->pVisual->class == TrueColor )
+ {
+ if( gc->fillStyle == FillTiled && !( gc->tileIsPixel ) )
+ return &( cPriv->specialTrueColorPalette );
+ else
+ return &( cPriv->trueColorPalette );
+ }
+ }
+
+
+ /* Look for the colormap ID <-> palette ID mapping */
+ while( p )
+ {
+ if( p->colormapId == cmap->mid )
+ return p;
+ p = p->next;
+ }
+
+ /* If the colormap isn't already there, make an entry for it */
+ new = (PclPaletteMapPtr)xalloc( sizeof( PclPaletteMap ) );
+ new->colormapId = cmap->mid;
+ new->paletteId = cPriv->nextPaletteId++;
+ new->downloaded = 0;
+ new->next = cPriv->palettes;
+ cPriv->palettes = new;
+ return new;
+}
+
+int
+PclUpdateColormap(DrawablePtr pDrawable,
+ XpContextPtr pCon,
+ GCPtr gc,
+ FILE *outFile)
+{
+ PclScreenPrivPtr sPriv;
+
+ PclContextPrivPtr cPriv;
+ PclPaletteMapPtr pMap;
+ PclCmapToContexts *pCmap;
+ PclContextListPtr new;
+ char t[80];
+ Colormap c;
+ ColormapPtr cmap;
+ WindowPtr win = (WindowPtr)pDrawable;
+ unsigned short r, g, b, rr, gg, bb;
+ int i;
+
+ cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr;
+
+ c = wColormap( win );
+ cmap = (ColormapPtr)LookupIDByType( c, RT_COLORMAP );
+ pMap = PclFindPaletteMap( cPriv, cmap, gc );
+
+ if( cPriv->currentPalette == pMap->paletteId )
+ /*
+ * If the requested colormap is already active, nothing needs to
+ * be done.
+ */
+ return FALSE;
+
+ /*
+ * Now we activate the palette in the printer
+ */
+ sprintf( t, "\033&p%dS", pMap->paletteId );
+ SEND_PCL( outFile, t );
+ cPriv->currentPalette = pMap->paletteId;
+
+ if( pMap->downloaded == 0 )
+ /*
+ * If the requested colormap has not been downloaded to the
+ * printer, we need to do that before activating it.
+ */
+ {
+ /*
+ * Add the colormap to the screen-level colormap<->context mapping.
+ */
+ sPriv = (PclScreenPrivPtr)cmap->pScreen
+ ->devPrivates[PclScreenPrivateIndex].ptr;
+ pCmap = sPriv->colormaps;
+ while( pCmap && ( pCmap->colormapId != cmap->mid ) )
+ pCmap = pCmap->next;
+ new = (PclContextListPtr)xalloc( sizeof( PclContextList ) );
+ new->context = pCon;
+ new->next = pCmap->contexts;
+ pCmap->contexts = new;
+
+ /*
+ * XXX Download the colormap
+ */
+ if( cmap->class == StaticGray )
+ {
+#ifdef XP_PCL_COLOR
+ sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 1, 1, 1, 1, 1 );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
+
+ /* Send the white reference point... */
+ sprintf( t, "%c%c%c%c%c%c", 0x7f, 0xff, 0x7f, 0xff,
+ 0x7f, 0xff );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+
+ /* ... and the black reference point */
+ sprintf( t, "%c%c%c%c%c%c", 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00 );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+
+ /* Now program the two colors */
+ sprintf( t, "\033*v0a0b0c%ldI", (long) cmap->pScreen->blackPixel );
+ SEND_PCL( cPriv->pPageFile, t );
+ sprintf( t, "\033*v32767a32767b32767c%ldI",
+ (long) cmap->pScreen->whitePixel );
+ SEND_PCL( cPriv->pPageFile, t );
+#endif /* XP_PCL_COLOR */
+ }
+ else if( cmap->class == PseudoColor )
+ {
+ sprintf( t,
+ "\033*v18W%c%c%c%c%c%c",
+ 0, 1, cmap->pVisual->nplanes, 16, 16, 16 );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
+
+ /* Send the white reference point... */
+ if ( cPriv->ctbl != NULL )
+ sprintf( t, "%c%c%c%c%c%c", 0x00, 0xff, 0x00, 0xff,
+ 0x00, 0xff );
+ else
+ sprintf( t, "%c%c%c%c%c%c", 0x7f, 0xff, 0x7f, 0xff,
+ 0x7f, 0xff );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+
+ /* ... and the black reference point */
+ sprintf( t, "%c%c%c%c%c%c", 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00 );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+
+ for(i = 0; i < cmap->pVisual->ColormapEntries; i++ )
+ {
+ if( cmap->red[i].fShared )
+ {
+ r = cmap->red[i].co.shco.red->color;
+ g = cmap->red[i].co.shco.green->color;
+ b = cmap->red[i].co.shco.blue->color;
+ }
+ else
+ {
+ r = cmap->red[i].co.local.red;
+ g = cmap->red[i].co.local.green;
+ b = cmap->red[i].co.local.blue;
+ }
+ PclLookUp(cmap, cPriv, &r, &g, &b);
+ sprintf( t, "\033*v%ua%ub%uc%dI", r, g, b, i );
+ SEND_PCL( outFile, t );
+ }
+ }
+ else if( cmap->class == TrueColor )
+ {
+ unsigned short lim;
+
+ if( gc->fillStyle == FillTiled && !( gc->tileIsPixel ) )
+ {
+ if( cPriv->ctbl != NULL )
+ {
+ /* Send the "special" colormap for 24-bit fills */
+ sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 1,
+ 8,
+ cmap->pVisual->bitsPerRGBValue,
+ cmap->pVisual->bitsPerRGBValue,
+ cmap->pVisual->bitsPerRGBValue );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
+
+ /* Send the white reference point... */
+ sprintf( t, "%c%c%c%c%c%c",
+ 0x00, 0xff,
+ 0x00, 0xff,
+ 0x00, 0xff );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+
+ /* ... and the black reference point */
+ sprintf( t, "%c%c%c%c%c%c",
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00 );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+
+ /* Now send the color entries, RRRGGGBB */
+ i=0;
+ for( r = 0; r < 8; r++ )
+ for( g = 0; g < 8; g ++ )
+ for( b = 0; b < 4; b++ )
+ {
+ rr = (r * 0xff)/7;
+ gg = (g * 0xff)/7;
+ bb = (b * 0xff)/3;
+ PclLookUp(cmap, cPriv, &rr, &gg, &bb);
+ sprintf( t, "\033*v%ua%ub%uc%dI",
+ rr, gg, bb, i );
+ SEND_PCL( outFile, t );
+ i++;
+ }
+ }
+ else
+ {
+ /* Send the "special" colormap for 24-bit fills */
+ sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 1,
+ 8,
+ cmap->pVisual->bitsPerRGBValue,
+ cmap->pVisual->bitsPerRGBValue,
+ cmap->pVisual->bitsPerRGBValue );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
+
+ /* Send the white reference point... */
+ sprintf( t, "%c%c%c%c%c%c",
+ 0x00, 0x07,
+ 0x00, 0x07,
+ 0x00, 0x03 );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+
+ /* ... and the black reference point */
+ sprintf( t, "%c%c%c%c%c%c",
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00 );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+
+ /* Now send the color entries, RRRGGGBB */
+ i=0;
+ for( r = 0; r < 8; r++ )
+ for( g = 0; g < 8; g ++ )
+ for( b = 0; b < 4; b++ )
+ {
+ sprintf( t, "\033*v%ua%ub%uc%dI",
+ r, g, b, i );
+ SEND_PCL( outFile, t );
+ i++;
+ }
+ }
+
+ }
+ else
+ {
+ lim = (1 << cmap->pVisual->bitsPerRGBValue) - 1;
+
+ /* Send the "special" colormap for 24-bit fills */
+ sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 3,
+ cmap->pVisual->nplanes,
+ cmap->pVisual->bitsPerRGBValue,
+ cmap->pVisual->bitsPerRGBValue,
+ cmap->pVisual->bitsPerRGBValue );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
+
+ /* Send the white reference point... */
+ sprintf( t, "%c%c%c%c%c%c",
+ (lim >> 8) & 0xff, lim & 0xff,
+ (lim >> 8) & 0xff, lim & 0xff,
+ (lim >> 8) & 0xff, lim & 0xff);
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+
+ /* ... and the black reference point */
+ sprintf( t, "%c%c%c%c%c%c", 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00 );
+ SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
+ }
+
+ }
+ pMap->downloaded = 1;
+ }
+ return TRUE;
+
+}
+
+void PclLookUp(
+ ColormapPtr cmap,
+ PclContextPrivPtr cPriv,
+ unsigned short *r,
+ unsigned short *g,
+ unsigned short *b
+)
+{
+ unsigned char cdata[3];
+
+ if( cmap->class == PseudoColor )
+ {
+ if( cPriv->ctbl != NULL )
+ {
+ cdata[0] = *r >> 8;
+ cdata[1] = *g >> 8;
+ cdata[2] = *b >> 8;
+ lookup(cdata, cdata, 1, cPriv->ctbl, cPriv->ctbldim);
+ *r = cdata[0];
+ *g = cdata[1];
+ *b = cdata[2];
+ }
+ else
+ {
+ *r >>= 1;
+ *g >>= 1;
+ *b >>= 1;
+ }
+ }
+ else if( cmap->class == TrueColor )
+ {
+ if( cPriv->ctbl != NULL )
+ {
+ cdata[0] = *r;
+ cdata[1] = *g;
+ cdata[2] = *b;
+ lookup(cdata, cdata, 1, cPriv->ctbl, cPriv->ctbldim);
+ *r = cdata[0];
+ *g = cdata[1];
+ *b = cdata[2];
+ }
+ }
+ return;
+}
+
+unsigned char *PclReadMap(char *name, int *dim)
+{
+ FILE *fp;
+ unsigned char *data;
+ long size;
+
+ if ((fp=fopen(name, "r")) == NULL) {
+ return(NULL);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ /* Could do this with a lookup table, if the constraint is that the
+ 3 map dimensions must be equal. */
+ switch (size) {
+ case 8*8*8*3:
+ *dim = 8;
+ break;
+ case 16*16*16*3:
+ *dim = 16;
+ break;
+ case 17*17*17*3:
+ *dim = 17;
+ break;
+ case 65*65*65*3:
+ *dim = 65;
+ break;
+ default:
+ fclose(fp);
+ return(NULL);
+ }
+
+ if ((data = (unsigned char *) xalloc(sizeof(char) * size)) == NULL) {
+ fclose(fp);
+ return(NULL);
+ }
+
+ fseek(fp, 0, SEEK_SET);
+
+ if (fread(data, sizeof(char), size, fp) != (unsigned) size) {
+ fclose(fp);
+ free(data);
+ return(NULL);
+ }
+
+ fclose(fp);
+ return(data);
+}
+
+/************************************************************************
+ *
+ * Here is the mapper.
+ *
+ ************************************************************************/
+
+#define SCL(x) ((x)*(dim-1)/255)
+/* Interleaved-map lookup */
+static void lookup(unsigned char *src, unsigned char *dst, int num, unsigned char *map, int dim)
+{
+ int i;
+
+#define _INTERPOLATE
+#ifndef _INTERPOLATE
+ unsigned char *p1, *p2, *p3;
+
+ for (i=0; i<num; i++) {
+ p1 = map + (SCL(src[0])*dim*dim + SCL(src[1])*dim + SCL(src[2])) * 3;
+ *dst++ = *p1++;
+ *dst++ = *p1++;
+ *dst++ = *p1++;
+ src += 3;
+ }
+#else
+ for (i=0; i<num; i++) {
+ trilinear(src, dst, map, dim, 128);
+ src += 3;
+ dst += 3;
+ }
+#endif
+}
+
+/*
+ * C code from the article
+ * "Tri-linear Interpolation"
+ * by Steve Hill, sah@ukc.ac.uk
+ * in "Graphics Gems IV", Academic Press, 1994
+ *
+ * Fri Feb 16 14:12:43 PST 1996
+ * Modified to use for 8-bit color mapping -- A. Fitzhugh,
+ * HP Labs, Printing Technology Department
+ */
+
+/* linear interpolation from l (when a=0) to h (when a=1)*/
+/* (equal to (a*h)+((1-a)*l) */
+#define LERP(a,l,h) ((l)+((((h)-(l))*(a))>>8))
+
+static void trilinear(unsigned char *p, unsigned char *out, unsigned char *d, int dim, unsigned char def)
+{
+#define DENS(X, Y, Z, ch) d[((X*dim+Y)*dim+Z)*3+ch]
+
+ int x0, y0, z0,
+ x1, y1, z1,
+ i;
+ unsigned char *dp,
+ fx, fy, fz,
+ d000, d001, d010, d011,
+ d100, d101, d110, d111,
+ dx00, dx01, dx10, dx11,
+ dxy0, dxy1;
+ float scale;
+
+ scale = 255.0 / (dim-1);
+
+ x0 = p[0] / scale;
+ y0 = p[1] / scale;
+ z0 = p[2] / scale;
+
+ /* Fractions should range from 0-1.0 (fixed point 8-256) */
+ fx = (((int) (p[0] - x0 * scale)) << 8) / 255;
+ fy = (((int) (p[1] - y0 * scale)) << 8) / 255;
+ fz = (((int) (p[2] - z0 * scale)) << 8) / 255;
+
+ x1 = x0 + 1;
+ y1 = y0 + 1;
+ z1 = z0 + 1;
+
+ for (i=0; i<3; i++) {
+
+ if (x0 >= 0 && x1 < dim &&
+ y0 >= 0 && y1 < dim &&
+ z0 >= 0 && z1 < dim) {
+ dp = &DENS(x0, y0, z0, i);
+ d000 = dp[0];
+ d100 = dp[3];
+ dp += dim*3;
+ d010 = dp[0];
+ d110 = dp[3];
+ dp += dim*dim*3;
+ d011 = dp[0];
+ d111 = dp[3];
+ dp -= dim*3;
+ d001 = dp[0];
+ d101 = dp[3];
+ } else {
+# define INRANGE(X, Y, Z) \
+ ((X) >= 0 && (X) < dim && \
+ (Y) >= 0 && (Y) < dim && \
+ (Z) >= 0 && (Z) < dim)
+
+ d000 = INRANGE(x0, y0, z0) ? DENS(x0, y0, z0, i) : def;
+ d001 = INRANGE(x0, y0, z1) ? DENS(x0, y0, z1, i) : def;
+ d010 = INRANGE(x0, y1, z0) ? DENS(x0, y1, z0, i) : def;
+ d011 = INRANGE(x0, y1, z1) ? DENS(x0, y1, z1, i) : def;
+
+ d100 = INRANGE(x1, y0, z0) ? DENS(x1, y0, z0, i) : def;
+ d101 = INRANGE(x1, y0, z1) ? DENS(x1, y0, z1, i) : def;
+ d110 = INRANGE(x1, y1, z0) ? DENS(x1, y1, z0, i) : def;
+ d111 = INRANGE(x1, y1, z1) ? DENS(x1, y1, z1, i) : def;
+ }
+
+ dx00 = LERP(fx, d000, d100);
+ dx01 = LERP(fx, d001, d101);
+ dx10 = LERP(fx, d010, d110);
+ dx11 = LERP(fx, d011, d111);
+
+ dxy0 = LERP(fy, dx00, dx10);
+ dxy1 = LERP(fy, dx01, dx11);
+
+ out[i] = LERP(fz, dxy0, dxy1);
+ }
+}
+