1 /* PDFlib GmbH cvsid:
2  * $Id: tif_color.c,v 1.5 2005/12/19 18:36:54 rjs Exp $ */
3 
4 /*
5  * Copyright (c) 1988-1997 Sam Leffler
6  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
7  *
8  * Permission to use, copy, modify, distribute, and sell this software and
9  * its documentation for any purpose is hereby granted without fee, provided
10  * that (i) the above copyright notices and this permission notice appear in
11  * all copies of the software and related documentation, and (ii) the names of
12  * Sam Leffler and Silicon Graphics may not be used in any advertising or
13  * publicity relating to the software without the specific, prior written
14  * permission of Sam Leffler and Silicon Graphics.
15  *
16  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
18  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
21  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
22  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
24  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
25  * OF THIS SOFTWARE.
26  */
27 
28 /*
29  * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken
30  * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with
31  * the permission of John Cupitt, the VIPS author.
32  */
33 
34 /*
35  * TIFF Library.
36  *
37  * Color space conversion routines.
38  */
39 
40 #include "tiffiop.h"
41 #include <math.h>
42 
43 /*
44  * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ.
45  */
46 void
TIFFCIELabToXYZ(TIFFCIELabToRGB * cielab,uint32 l,int32 a,int32 b,float * X,float * Y,float * Z)47 TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b,
48 		float *X, float *Y, float *Z)
49 {
50 	float L = (float)l * 100.0F / 255.0F;
51 	float cby, tmp;
52 
53 	if( L < 8.856F ) {
54 		*Y = (L * cielab->Y0) / 903.292F;
55 		cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
56 	} else {
57 		cby = (L + 16.0F) / 116.0F;
58 		*Y = cielab->Y0 * cby * cby * cby;
59 	}
60 
61 	tmp = (float)a / 500.0F + cby;
62 	if( tmp < 0.2069F )
63 		*X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
64 	else
65 		*X = cielab->X0 * tmp * tmp * tmp;
66 
67 	tmp = cby - (float)b / 200.0F;
68 	if( tmp < 0.2069F )
69 		*Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
70 	else
71 		*Z = cielab->Z0 * tmp * tmp * tmp;
72 }
73 
74 #define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5)))
75 /*
76  * Convert color value from the XYZ space to RGB.
77  */
78 void
TIFFXYZToRGB(TIFFCIELabToRGB * cielab,float X,float Y,float Z,uint32 * r,uint32 * g,uint32 * b)79 TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
80 	     uint32 *r, uint32 *g, uint32 *b)
81 {
82 	int i;
83 	float Yr, Yg, Yb;
84 	float *matrix = &cielab->display.d_mat[0][0];
85 
86 	/* Multiply through the matrix to get luminosity values. */
87 	Yr =  matrix[0] * X + matrix[1] * Y + matrix[2] * Z;
88 	Yg =  matrix[3] * X + matrix[4] * Y + matrix[5] * Z;
89 	Yb =  matrix[6] * X + matrix[7] * Y + matrix[8] * Z;
90 
91 	/* Clip input */
92 	Yr = TIFFmax(Yr, cielab->display.d_Y0R);
93 	Yg = TIFFmax(Yg, cielab->display.d_Y0G);
94 	Yb = TIFFmax(Yb, cielab->display.d_Y0B);
95 
96 	/* Turn luminosity to colour value. */
97 	i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep);
98 	i = TIFFmin(cielab->range, i);
99 	*r = RINT(cielab->Yr2r[i]);
100 
101 	i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep);
102 	i = TIFFmin(cielab->range, i);
103 	*g = RINT(cielab->Yg2g[i]);
104 
105 	i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep);
106 	i = TIFFmin(cielab->range, i);
107 	*b = RINT(cielab->Yb2b[i]);
108 
109 	/* Clip output. */
110 	*r = TIFFmin(*r, cielab->display.d_Vrwr);
111 	*g = TIFFmin(*g, cielab->display.d_Vrwg);
112 	*b = TIFFmin(*b, cielab->display.d_Vrwb);
113 }
114 #undef RINT
115 
116 /*
117  * Allocate conversion state structures and make look_up tables for
118  * the Yr,Yb,Yg <=> r,g,b conversions.
119  */
120 int
TIFFCIELabToRGBInit(TIFFCIELabToRGB * cielab,TIFFDisplay * display,float * refWhite)121 TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab,
122 		    TIFFDisplay *display, float *refWhite)
123 {
124 	int i;
125         double mygamma;
126 
127 	cielab->range = CIELABTORGB_TABLE_RANGE;
128 
129 	_TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
130 
131 	/* Red */
132 	mygamma = 1.0 / cielab->display.d_gammaR ;
133 	cielab->rstep =
134 		(cielab->display.d_YCR - cielab->display.d_Y0R)	/ cielab->range;
135 	for(i = 0; i <= cielab->range; i++) {
136 		cielab->Yr2r[i] = cielab->display.d_Vrwr
137                     * ((float)pow((double)i / cielab->range, mygamma));
138 	}
139 
140 	/* Green */
141 	mygamma = 1.0 / cielab->display.d_gammaG ;
142 	cielab->gstep =
143 	    (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
144 	for(i = 0; i <= cielab->range; i++) {
145 		cielab->Yg2g[i] = cielab->display.d_Vrwg
146                     * ((float)pow((double)i / cielab->range, mygamma));
147 	}
148 
149 	/* Blue */
150 	mygamma = 1.0 / cielab->display.d_gammaB ;
151 	cielab->bstep =
152 	    (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
153 	for(i = 0; i <= cielab->range; i++) {
154 		cielab->Yb2b[i] = cielab->display.d_Vrwb
155                     * ((float)pow((double)i / cielab->range, mygamma));
156 	}
157 
158 	/* Init reference white point */
159 	cielab->X0 = refWhite[0];
160 	cielab->Y0 = refWhite[1];
161 	cielab->Z0 = refWhite[2];
162 
163 	return 0;
164 }
165 
166 /*
167  * Convert color value from the YCbCr space to CIE XYZ.
168  * The colorspace conversion algorithm comes from the IJG v5a code;
169  * see below for more information on how it works.
170  */
171 #define	SHIFT			16
172 #define	FIX(x)			((int32)((x) * (1L<<SHIFT) + 0.5))
173 #define	ONE_HALF		((int32)(1<<(SHIFT-1)))
174 #define	Code2V(c, RB, RW, CR)	\
175 	((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)) ? ((RW)-(RB)) : 1))
176 #define	CLAMP(f,min,max)	((f)<(min)?(min):(f)>(max)?(max):(f))
177 
178 void
TIFFYCbCrtoRGB(TIFFYCbCrToRGB * ycbcr,uint32 Y,int32 Cb,int32 Cr,uint32 * r,uint32 * g,uint32 * b)179 TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr,
180 	       uint32 *r, uint32 *g, uint32 *b)
181 {
182 	/* XXX: Only 8-bit YCbCr input supported for now */
183 	/* PDFlib GmbH: Y is unsigned, so don't compare it to < 0 */
184 	Y = CLAMP(((int32)Y), 0, 255),
185 		Cb = CLAMP(Cb, 0, 255),
186 		Cr = CLAMP(Cr, 0, 255);
187 
188 	*r = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]];
189 	*g = ycbcr->clamptab[ycbcr->Y_tab[Y]
190 	    + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT)];
191 	*b = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]];
192 }
193 
194 /*
195  * Initialize the YCbCr->RGB conversion tables.  The conversion
196  * is done according to the 6.0 spec:
197  *
198  *    R = Y + Cr*(2 - 2*LumaRed)
199  *    B = Y + Cb*(2 - 2*LumaBlue)
200  *    G =   Y
201  *        - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
202  *        - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
203  *
204  * To avoid floating point arithmetic the fractional constants that
205  * come out of the equations are represented as fixed point values
206  * in the range 0...2^16.  We also eliminate multiplications by
207  * pre-calculating possible values indexed by Cb and Cr (this code
208  * assumes conversion is being done for 8-bit samples).
209  */
210 int
TIFFYCbCrToRGBInit(TIFFYCbCrToRGB * ycbcr,float * luma,float * refBlackWhite)211 TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite)
212 {
213     TIFFRGBValue* clamptab;
214     int i;
215 
216 #define LumaRed	    luma[0]
217 #define LumaGreen   luma[1]
218 #define LumaBlue    luma[2]
219 
220     clamptab = (TIFFRGBValue*)(
221 	(tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)));
222     _TIFFmemset(clamptab, 0, 256);		/* v < 0 => 0 */
223     ycbcr->clamptab = (clamptab += 256);
224     for (i = 0; i < 256; i++)
225 	clamptab[i] = (TIFFRGBValue) i;
226     _TIFFmemset(clamptab+256, 255, 2*256);	/* v > 255 => 255 */
227     ycbcr->Cr_r_tab = (int*) (clamptab + 3*256);
228     ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
229     ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256);
230     ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
231     ycbcr->Y_tab = ycbcr->Cb_g_tab + 256;
232 
233     { float f1 = 2-2*LumaRed;		int32 D1 = FIX(f1);
234       float f2 = LumaRed*f1/LumaGreen;	int32 D2 = -FIX(f2);
235       float f3 = 2-2*LumaBlue;		int32 D3 = FIX(f3);
236       float f4 = LumaBlue*f3/LumaGreen;	int32 D4 = -FIX(f4);
237       int x;
238 
239 #undef LumaBlue
240 #undef LumaGreen
241 #undef LumaRed
242 
243       /*
244        * i is the actual input pixel value in the range 0..255
245        * Cb and Cr values are in the range -128..127 (actually
246        * they are in a range defined by the ReferenceBlackWhite
247        * tag) so there is some range shifting to do here when
248        * constructing tables indexed by the raw pixel data.
249        */
250       for (i = 0, x = -128; i < 256; i++, x++) {
251 	    int32 Cr = (int32)Code2V(x, refBlackWhite[4] - 128.0F,
252 			    refBlackWhite[5] - 128.0F, 127);
253 	    int32 Cb = (int32)Code2V(x, refBlackWhite[2] - 128.0F,
254 			    refBlackWhite[3] - 128.0F, 127);
255 
256 	    ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT);
257 	    ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT);
258 	    ycbcr->Cr_g_tab[i] = D2*Cr;
259 	    ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF;
260 	    ycbcr->Y_tab[i] =
261 		(int32)Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255);
262       }
263     }
264 
265     return 0;
266 }
267 #undef	CLAMP
268 #undef	Code2V
269 #undef	SHIFT
270 #undef	ONE_HALF
271 #undef	FIX
272 
273 /* vim: set ts=8 sts=8 sw=8 noet: */
274