]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/libtiff/tif_color.c
3 * Copyright (c) 1988-1997 Sam Leffler
4 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6 * Permission to use, copy, modify, distribute, and sell this software and
7 * its documentation for any purpose is hereby granted without fee, provided
8 * that (i) the above copyright notices and this permission notice appear in
9 * all copies of the software and related documentation, and (ii) the names of
10 * Sam Leffler and Silicon Graphics may not be used in any advertising or
11 * publicity relating to the software without the specific, prior written
12 * permission of Sam Leffler and Silicon Graphics.
14 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
16 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
19 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
20 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
22 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
27 * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken
28 * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with
29 * the permission of John Cupitt, the VIPS author.
35 * Color space conversion routines.
42 * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ.
45 TIFFCIELabToXYZ(TIFFCIELabToRGB
*cielab
, uint32 l
, int32 a
, int32 b
,
46 float *X
, float *Y
, float *Z
)
48 float L
= (float)l
* 100.0F
/ 255.0F
;
52 *Y
= (L
* cielab
->Y0
) / 903.292F
;
53 cby
= 7.787F
* (*Y
/ cielab
->Y0
) + 16.0F
/ 116.0F
;
55 cby
= (L
+ 16.0F
) / 116.0F
;
56 *Y
= cielab
->Y0
* cby
* cby
* cby
;
59 tmp
= (float)a
/ 500.0F
+ cby
;
61 *X
= cielab
->X0
* (tmp
- 0.13793F
) / 7.787F
;
63 *X
= cielab
->X0
* tmp
* tmp
* tmp
;
65 tmp
= cby
- (float)b
/ 200.0F
;
67 *Z
= cielab
->Z0
* (tmp
- 0.13793F
) / 7.787F
;
69 *Z
= cielab
->Z0
* tmp
* tmp
* tmp
;
72 #define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5)))
74 * Convert color value from the XYZ space to RGB.
77 TIFFXYZToRGB(TIFFCIELabToRGB
*cielab
, float X
, float Y
, float Z
,
78 uint32
*r
, uint32
*g
, uint32
*b
)
82 float *matrix
= &cielab
->display
.d_mat
[0][0];
84 /* Multiply through the matrix to get luminosity values. */
85 Yr
= matrix
[0] * X
+ matrix
[1] * Y
+ matrix
[2] * Z
;
86 Yg
= matrix
[3] * X
+ matrix
[4] * Y
+ matrix
[5] * Z
;
87 Yb
= matrix
[6] * X
+ matrix
[7] * Y
+ matrix
[8] * Z
;
90 Yr
= TIFFmax(Yr
, cielab
->display
.d_Y0R
);
91 Yg
= TIFFmax(Yg
, cielab
->display
.d_Y0G
);
92 Yb
= TIFFmax(Yb
, cielab
->display
.d_Y0B
);
94 /* Avoid overflow in case of wrong input values */
95 Yr
= TIFFmin(Yr
, cielab
->display
.d_YCR
);
96 Yg
= TIFFmin(Yg
, cielab
->display
.d_YCG
);
97 Yb
= TIFFmin(Yb
, cielab
->display
.d_YCB
);
99 /* Turn luminosity to colour value. */
100 i
= (int)((Yr
- cielab
->display
.d_Y0R
) / cielab
->rstep
);
101 i
= TIFFmin(cielab
->range
, i
);
102 *r
= RINT(cielab
->Yr2r
[i
]);
104 i
= (int)((Yg
- cielab
->display
.d_Y0G
) / cielab
->gstep
);
105 i
= TIFFmin(cielab
->range
, i
);
106 *g
= RINT(cielab
->Yg2g
[i
]);
108 i
= (int)((Yb
- cielab
->display
.d_Y0B
) / cielab
->bstep
);
109 i
= TIFFmin(cielab
->range
, i
);
110 *b
= RINT(cielab
->Yb2b
[i
]);
113 *r
= TIFFmin(*r
, cielab
->display
.d_Vrwr
);
114 *g
= TIFFmin(*g
, cielab
->display
.d_Vrwg
);
115 *b
= TIFFmin(*b
, cielab
->display
.d_Vrwb
);
120 * Allocate conversion state structures and make look_up tables for
121 * the Yr,Yb,Yg <=> r,g,b conversions.
124 TIFFCIELabToRGBInit(TIFFCIELabToRGB
* cielab
,
125 const TIFFDisplay
*display
, float *refWhite
)
130 cielab
->range
= CIELABTORGB_TABLE_RANGE
;
132 _TIFFmemcpy(&cielab
->display
, display
, sizeof(TIFFDisplay
));
135 gamma
= 1.0 / cielab
->display
.d_gammaR
;
137 (cielab
->display
.d_YCR
- cielab
->display
.d_Y0R
) / cielab
->range
;
138 for(i
= 0; i
<= cielab
->range
; i
++) {
139 cielab
->Yr2r
[i
] = cielab
->display
.d_Vrwr
140 * ((float)pow((double)i
/ cielab
->range
, gamma
));
144 gamma
= 1.0 / cielab
->display
.d_gammaG
;
146 (cielab
->display
.d_YCR
- cielab
->display
.d_Y0R
) / cielab
->range
;
147 for(i
= 0; i
<= cielab
->range
; i
++) {
148 cielab
->Yg2g
[i
] = cielab
->display
.d_Vrwg
149 * ((float)pow((double)i
/ cielab
->range
, gamma
));
153 gamma
= 1.0 / cielab
->display
.d_gammaB
;
155 (cielab
->display
.d_YCR
- cielab
->display
.d_Y0R
) / cielab
->range
;
156 for(i
= 0; i
<= cielab
->range
; i
++) {
157 cielab
->Yb2b
[i
] = cielab
->display
.d_Vrwb
158 * ((float)pow((double)i
/ cielab
->range
, gamma
));
161 /* Init reference white point */
162 cielab
->X0
= refWhite
[0];
163 cielab
->Y0
= refWhite
[1];
164 cielab
->Z0
= refWhite
[2];
170 * Convert color value from the YCbCr space to CIE XYZ.
171 * The colorspace conversion algorithm comes from the IJG v5a code;
172 * see below for more information on how it works.
175 #define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5))
176 #define ONE_HALF ((int32)(1<<(SHIFT-1)))
177 #define Code2V(c, RB, RW, CR) ((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)) ? ((RW)-(RB)) : 1))
178 #define CLAMP(f,min,max) ((f)<(min)?(min):(f)>(max)?(max):(f))
179 #define HICLAMP(f,max) ((f)>(max)?(max):(f))
182 TIFFYCbCrtoRGB(TIFFYCbCrToRGB
*ycbcr
, uint32 Y
, int32 Cb
, int32 Cr
,
183 uint32
*r
, uint32
*g
, uint32
*b
)
187 /* XXX: Only 8-bit YCbCr input supported for now */
188 Y
= HICLAMP(Y
, 255), Cb
= CLAMP(Cb
, 0, 255), Cr
= CLAMP(Cr
, 0, 255);
190 i
= ycbcr
->Y_tab
[Y
] + ycbcr
->Cr_r_tab
[Cr
];
191 *r
= CLAMP(i
, 0, 255);
193 + (int)((ycbcr
->Cb_g_tab
[Cb
] + ycbcr
->Cr_g_tab
[Cr
]) >> SHIFT
);
194 *g
= CLAMP(i
, 0, 255);
195 i
= ycbcr
->Y_tab
[Y
] + ycbcr
->Cb_b_tab
[Cb
];
196 *b
= CLAMP(i
, 0, 255);
200 * Initialize the YCbCr->RGB conversion tables. The conversion
201 * is done according to the 6.0 spec:
203 * R = Y + Cr*(2 - 2*LumaRed)
204 * B = Y + Cb*(2 - 2*LumaBlue)
206 * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
207 * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
209 * To avoid floating point arithmetic the fractional constants that
210 * come out of the equations are represented as fixed point values
211 * in the range 0...2^16. We also eliminate multiplications by
212 * pre-calculating possible values indexed by Cb and Cr (this code
213 * assumes conversion is being done for 8-bit samples).
216 TIFFYCbCrToRGBInit(TIFFYCbCrToRGB
* ycbcr
, float *luma
, float *refBlackWhite
)
218 TIFFRGBValue
* clamptab
;
221 #define LumaRed luma[0]
222 #define LumaGreen luma[1]
223 #define LumaBlue luma[2]
225 clamptab
= (TIFFRGBValue
*)(
226 (uint8
*) ycbcr
+TIFFroundup_32(sizeof (TIFFYCbCrToRGB
), sizeof (long)));
227 _TIFFmemset(clamptab
, 0, 256); /* v < 0 => 0 */
228 ycbcr
->clamptab
= (clamptab
+= 256);
229 for (i
= 0; i
< 256; i
++)
230 clamptab
[i
] = (TIFFRGBValue
) i
;
231 _TIFFmemset(clamptab
+256, 255, 2*256); /* v > 255 => 255 */
232 ycbcr
->Cr_r_tab
= (int*) (clamptab
+ 3*256);
233 ycbcr
->Cb_b_tab
= ycbcr
->Cr_r_tab
+ 256;
234 ycbcr
->Cr_g_tab
= (int32
*) (ycbcr
->Cb_b_tab
+ 256);
235 ycbcr
->Cb_g_tab
= ycbcr
->Cr_g_tab
+ 256;
236 ycbcr
->Y_tab
= ycbcr
->Cb_g_tab
+ 256;
238 { float f1
= 2-2*LumaRed
; int32 D1
= FIX(f1
);
239 float f2
= LumaRed
*f1
/LumaGreen
; int32 D2
= -FIX(f2
);
240 float f3
= 2-2*LumaBlue
; int32 D3
= FIX(f3
);
241 float f4
= LumaBlue
*f3
/LumaGreen
; int32 D4
= -FIX(f4
);
249 * i is the actual input pixel value in the range 0..255
250 * Cb and Cr values are in the range -128..127 (actually
251 * they are in a range defined by the ReferenceBlackWhite
252 * tag) so there is some range shifting to do here when
253 * constructing tables indexed by the raw pixel data.
255 for (i
= 0, x
= -128; i
< 256; i
++, x
++) {
256 int32 Cr
= (int32
)Code2V(x
, refBlackWhite
[4] - 128.0F
,
257 refBlackWhite
[5] - 128.0F
, 127);
258 int32 Cb
= (int32
)Code2V(x
, refBlackWhite
[2] - 128.0F
,
259 refBlackWhite
[3] - 128.0F
, 127);
261 ycbcr
->Cr_r_tab
[i
] = (int32
)((D1
*Cr
+ ONE_HALF
)>>SHIFT
);
262 ycbcr
->Cb_b_tab
[i
] = (int32
)((D3
*Cb
+ ONE_HALF
)>>SHIFT
);
263 ycbcr
->Cr_g_tab
[i
] = D2
*Cr
;
264 ycbcr
->Cb_g_tab
[i
] = D4
*Cb
+ ONE_HALF
;
266 (int32
)Code2V(x
+ 128, refBlackWhite
[0], refBlackWhite
[1], 255);
279 /* vim: set ts=8 sts=8 sw=8 noet: */