1 /*****************************************************************************\
2 colormatch.cpp : Implimentation for the ColorMatcher class
4 Copyright (c) 1996 - 2001, Hewlett-Packard Co.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of Hewlett-Packard nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
22 NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \*****************************************************************************/
31 #include "CommonDefinitions.h"
32 #include "Processor.h"
33 #include "ColorMatcher.h"
35 ColorMatcher::ColorMatcher
38 unsigned int DyeCount,
39 unsigned int iInputWidth
40 ) : ColorPlaneCount(DyeCount),
41 InputWidth(iInputWidth),
44 constructor_error = NO_ERROR;
45 ASSERT((cmap.ulMap1 != NULL || cmap.ulMap3 != NULL));
46 StartPlane = K; // most common case
48 if (ColorPlaneCount == 3) // CMY pen
53 EndPlane = Y; // most common case
54 if (ColorPlaneCount == 6)
58 if (ColorPlaneCount == 1)
63 Contone = (BYTE *) new BYTE[InputWidth * ColorPlaneCount];
69 Restart(); // this zeroes buffers and sets nextraster counter
74 constructor_error=ALLOCMEM_ERROR;
80 ColorMatcher::~ColorMatcher()
86 void ColorMatcher::Restart()
87 // also reset cache when we have one
89 memset(Contone, 0, InputWidth*ColorPlaneCount);
94 void ColorMatcher::Flush()
95 // needed to reset cache
104 void ColorMatcher::FreeBuffers()
109 bool ColorMatcher::NextOutputRaster(RASTERDATA &next_raster)
111 if (iRastersReady == 0)
116 if (raster.rasterdata[COLORTYPE_COLOR] != NULL)
118 next_raster.rastersize[COLORTYPE_COLOR] = raster.rastersize[COLORTYPE_COLOR];
119 next_raster.rasterdata[COLORTYPE_COLOR] = Contone;
123 next_raster.rastersize[COLORTYPE_COLOR] = 0;
124 next_raster.rasterdata[COLORTYPE_COLOR] = raster.rasterdata[COLORTYPE_COLOR];
126 next_raster.rastersize[COLORTYPE_BLACK] = raster.rastersize[COLORTYPE_BLACK];
127 next_raster.rasterdata[COLORTYPE_BLACK] = raster.rasterdata[COLORTYPE_BLACK];
132 unsigned int ColorMatcher::GetMaxOutputWidth()
134 if (myplane == COLORTYPE_COLOR)
136 if (raster.rasterdata[myplane] == NULL)
139 return InputWidth*ColorPlaneCount;
143 return raster.rastersize[myplane];
145 } //GetMaxOutPutWidth
147 void ColorMatcher::ColorMatch
152 unsigned char *kplane,
153 unsigned char *cplane,
154 unsigned char *mplane,
155 unsigned char *yplane
158 static uint32_t prev_red = 255, prev_green = 255, prev_blue = 255;
159 static BYTE bcyan, bmagenta, byellow, bblack;
165 for (unsigned long i = 0; i < width; i++)
171 if(i == 0 || ( (prev_red != r) || (prev_green != g) || (prev_blue != b) ))
177 Interpolate(map, (BYTE)r, (BYTE)g,(BYTE)b, &bblack, &bcyan, &bmagenta, &byellow);
180 *(kplane + i) = bblack;
182 *(cplane + i) = bcyan;
184 *(mplane + i) = bmagenta;
186 *(yplane + i) = byellow;
192 void ColorMatcher::ColorMatch
195 const unsigned char *map,
197 unsigned char *kplane,
198 unsigned char *cplane,
199 unsigned char *mplane,
200 unsigned char *yplane
203 static BYTE prev_red = 255, prev_green = 255, prev_blue = 255;
204 static BYTE bcyan, bmagenta, byellow, bblack;
210 for (unsigned long i = 0; i < width; i++)
215 if(i == 0 || ( (prev_red != r) || (prev_green != g) || (prev_blue != b) ))
221 Interpolate(map, (BYTE)r, (BYTE)g,(BYTE)b, &bblack, &bcyan, &bmagenta, &byellow);
224 *(kplane + i) = bblack;
226 *(cplane + i) = bcyan;
228 *(mplane + i) = bmagenta;
230 *(yplane + i) = byellow;
236 uint32_t Packed(unsigned int k,unsigned int c,unsigned int m,unsigned int y)
249 DRIVER_ERROR ColorMatcher::MakeGrayMap(const uint32_t *colormap, uint32_t* graymap)
251 unsigned long ul_MapPtr;
252 for (unsigned int r = 0; r < 9; r++)
254 unsigned long ul_RedMapPtr = r * 9 * 9;
255 for (unsigned int g = 0; g < 9; g++)
257 unsigned long ul_GreenMapPtr = g * 9;
258 for (unsigned int b = 0; b < 9; b++)
260 unsigned long mapptr = b + (g * 9) + (r * 9 * 9); // get address in map
261 ul_MapPtr = b + ul_GreenMapPtr + ul_RedMapPtr;
262 ASSERT(mapptr == ul_MapPtr);
263 // put r,g,b in monitor range
264 unsigned int oldR = r * 255 >> 3;
265 unsigned int oldG = g * 255 >> 3;
266 unsigned int oldB = b * 255 >> 3;
268 // calculate gray equivalence
269 unsigned int gray = ((30 * oldR + 59 * oldG + 11 * oldB + 50) / 100);
273 ( ((gray & 0xE0) <<1) + ((gray & 0xE0)>>1) + (gray>>5) +
274 ((gray & 0xE0) >>2) + (gray>>5) + (gray>>5) + colormap);
277 Interpolate(start, gray, gray, gray, &k, &c, &m, &y);
279 // second interpolate if Clight/Mlight
281 *(graymap + mapptr) = Packed(k, c, m, y);
289 bool ColorMatcher::Process(RASTERDATA* pbyInputKRGBRaster)
291 if (pbyInputKRGBRaster == NULL || (pbyInputKRGBRaster->rasterdata[COLORTYPE_BLACK] == NULL && pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR] == NULL))
294 return false; // no output
298 if (pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR])
310 buff2 = buff1 + InputWidth;
311 buff3 = buff2 + InputWidth;
312 buff4 = buff3 + InputWidth;
318 buff3 = buff2 + InputWidth;
319 buff4 = buff3 + InputWidth;
324 ColorMatch( InputWidth, // ASSUMES ALL INPUTWIDTHS EQUAL
325 (const unsigned char *) cmap.ulMap3,
326 pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR],
335 // colormatching -- can only handle 4 planes at a time
336 ColorMatch( InputWidth, // ASSUMES ALL INPUTWIDTHS EQUAL
337 (const uint32_t *) cmap.ulMap1,
338 pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR],
346 if (EndPlane > Y && cmap.ulMap2)
348 BYTE* buff5 = buff4 + InputWidth;
349 BYTE* buff6 = buff5 + InputWidth;
351 ColorMatch( InputWidth,
352 (const uint32_t *) cmap.ulMap2, // 2nd map is for lighter inks
353 pbyInputKRGBRaster->rasterdata[COLORTYPE_COLOR],
354 NULL, // don't need black again
356 NULL // don't need yellow again
362 iRastersDelivered = 0;
363 return true; // one raster in, one raster out
366 #define INTERPOLATE_5_BITS(a, b, d) a + ( ( ( (long)b - (long)a ) * d) >> 5)
367 #define INTERPOLATE_4_BITS(a, b, d) a + ( ( ( (long)b - (long)a ) * d) >> 4)
369 // Spatial Interpolation
370 #define INTERPOLATE_CUBE(r,g,b, cube, DOCALC) \
371 DOCALC( (DOCALC( (DOCALC( cube[0], cube[4], (r))), \
372 (DOCALC( cube[2], cube[6], (r))), (g))), \
373 (DOCALC( (DOCALC( cube[1], cube[5], (r))), \
374 (DOCALC( cube[3], cube[7], (r))), (g))), \
377 void ColorMatcher::Interpolate
389 static int cube_location[] = {0, 1, 9, 10, 81, 82, 90, 91 };
390 const uint32_t *start;
392 BYTE cyan[8], magenta[8],yellow[8],black[8];
393 start = (const uint32_t *)
394 (((r & 0xE0) << 1) + ((r & 0xE0) >> 1) + (r >> 5) +
395 ((g & 0xE0) >> 2) + (g >> 5) + (b >> 5) + map);
398 for (int j = 0; j < 8; j++)
400 cValue = *(start + cube_location[j]);
401 cyan[j] = GetCyanValue (cValue);
402 magenta[j] = GetMagentaValue (cValue);
403 yellow[j] = GetYellowValue (cValue);
404 black[j] = GetBlackValue (cValue);
407 ////////////////this is the 8 bit 9cube operation /////////////
408 BYTE diff_red = r & 0x1f;
409 BYTE diff_green = g & 0x1f;
410 BYTE diff_blue = b & 0x1f;
412 *cyanout = INTERPOLATE_CUBE(diff_red,diff_green,diff_blue, cyan, INTERPOLATE_5_BITS );
413 *magentaout = INTERPOLATE_CUBE(diff_red,diff_green,diff_blue, magenta, INTERPOLATE_5_BITS );
414 *yellowout = INTERPOLATE_CUBE(diff_red,diff_green,diff_blue, yellow, INTERPOLATE_5_BITS );
415 *blackout = INTERPOLATE_CUBE(diff_red,diff_green,diff_blue, black, INTERPOLATE_5_BITS );
418 void ColorMatcher::Interpolate
420 const unsigned char *map,
430 BYTE cyan[8], magenta[8],yellow[8],black[8];
432 // static int cube_location[] = {0, 1, 17, 18, 289, 290, 306, 307};
433 static int cube_location[] = {0, 4, 68, 72, 1156, 1160, 1224, 1228};
438 start = (const unsigned char *)
439 ((((r & 0xF0) << 4) + ((r & 0xF0) << 1) + (r >> 4) +
440 ((g & 0xF0)) + (g >> 4) + (b >> 4)) * 4 + map);
442 // use (start) to determine the surrounding cube values
443 for (int j = 0; j < 8; ++j )
445 node_ptr = (BYTE *) (start + cube_location[j]);
446 black[j] = *node_ptr++;
447 cyan[j] = *node_ptr++;
448 magenta[j] = *node_ptr++;
449 yellow[j] = *node_ptr;
453 // interpolate using the 4 LSBs
454 BYTE diff_red = r & 0x0f;
455 BYTE diff_green = g & 0x0f;
456 BYTE diff_blue = b & 0x0f;
458 *cyanout = INTERPOLATE_CUBE(diff_red,diff_green,diff_blue, cyan, INTERPOLATE_4_BITS );
459 *magentaout = INTERPOLATE_CUBE(diff_red,diff_green,diff_blue, magenta, INTERPOLATE_4_BITS );
460 *yellowout = INTERPOLATE_CUBE(diff_red,diff_green,diff_blue, yellow, INTERPOLATE_4_BITS );
461 *blackout = INTERPOLATE_CUBE(diff_red,diff_green,diff_blue, black, INTERPOLATE_4_BITS );