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