1 /* $Id: tif_color.c,v 1.24 2017-05-29 10:12:54 erouault Exp $ */ 2 3 /* 4 * Copyright (c) 1988-1997 Sam Leffler 5 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 6 * 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. 14 * 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. 18 * 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 24 * OF THIS SOFTWARE. 25 */ 26 27 /* 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. 31 */ 32 33 /* 34 * TIFF Library. 35 * 36 * Color space conversion routines. 37 */ 38 39 #include <precomp.h> 40 #include <math.h> 41 42 /* 43 * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ. 44 */ 45 void 46 TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b, 47 float *X, float *Y, float *Z) 48 { 49 float L = (float)l * 100.0F / 255.0F; 50 float cby, tmp; 51 52 if( L < 8.856F ) { 53 *Y = (L * cielab->Y0) / 903.292F; 54 cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F; 55 } else { 56 cby = (L + 16.0F) / 116.0F; 57 *Y = cielab->Y0 * cby * cby * cby; 58 } 59 60 tmp = (float)a / 500.0F + cby; 61 if( tmp < 0.2069F ) 62 *X = cielab->X0 * (tmp - 0.13793F) / 7.787F; 63 else 64 *X = cielab->X0 * tmp * tmp * tmp; 65 66 tmp = cby - (float)b / 200.0F; 67 if( tmp < 0.2069F ) 68 *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F; 69 else 70 *Z = cielab->Z0 * tmp * tmp * tmp; 71 } 72 73 #define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5))) 74 /* 75 * Convert color value from the XYZ space to RGB. 76 */ 77 void 78 TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z, 79 uint32 *r, uint32 *g, uint32 *b) 80 { 81 int i; 82 float Yr, Yg, Yb; 83 float *matrix = &cielab->display.d_mat[0][0]; 84 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; 89 90 /* Clip input */ 91 Yr = TIFFmax(Yr, cielab->display.d_Y0R); 92 Yg = TIFFmax(Yg, cielab->display.d_Y0G); 93 Yb = TIFFmax(Yb, cielab->display.d_Y0B); 94 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); 99 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]); 104 105 i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep); 106 i = TIFFmin(cielab->range, i); 107 *g = RINT(cielab->Yg2g[i]); 108 109 i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep); 110 i = TIFFmin(cielab->range, i); 111 *b = RINT(cielab->Yb2b[i]); 112 113 /* Clip output. */ 114 *r = TIFFmin(*r, cielab->display.d_Vrwr); 115 *g = TIFFmin(*g, cielab->display.d_Vrwg); 116 *b = TIFFmin(*b, cielab->display.d_Vrwb); 117 } 118 #undef RINT 119 120 /* 121 * Allocate conversion state structures and make look_up tables for 122 * the Yr,Yb,Yg <=> r,g,b conversions. 123 */ 124 int 125 TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, 126 const TIFFDisplay *display, float *refWhite) 127 { 128 int i; 129 double dfGamma; 130 131 cielab->range = CIELABTORGB_TABLE_RANGE; 132 133 _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay)); 134 135 /* Red */ 136 dfGamma = 1.0 / cielab->display.d_gammaR ; 137 cielab->rstep = 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, dfGamma)); 142 } 143 144 /* Green */ 145 dfGamma = 1.0 / cielab->display.d_gammaG ; 146 cielab->gstep = 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, dfGamma)); 151 } 152 153 /* Blue */ 154 dfGamma = 1.0 / cielab->display.d_gammaB ; 155 cielab->bstep = 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, dfGamma)); 160 } 161 162 /* Init reference white point */ 163 cielab->X0 = refWhite[0]; 164 cielab->Y0 = refWhite[1]; 165 cielab->Z0 = refWhite[2]; 166 167 return 0; 168 } 169 170 /* 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. 174 */ 175 #define SHIFT 16 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)!=0) ? ((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)) 181 182 void 183 TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr, 184 uint32 *r, uint32 *g, uint32 *b) 185 { 186 int32 i; 187 188 /* XXX: Only 8-bit YCbCr input supported for now */ 189 Y = HICLAMP(Y, 255); 190 Cb = CLAMP(Cb, 0, 255); 191 Cr = CLAMP(Cr, 0, 255); 192 193 i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]; 194 *r = CLAMP(i, 0, 255); 195 i = ycbcr->Y_tab[Y] 196 + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT); 197 *g = CLAMP(i, 0, 255); 198 i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]; 199 *b = CLAMP(i, 0, 255); 200 } 201 202 /* Clamp function for sanitization purposes. Normally clamping should not */ 203 /* occur for well behaved chroma and refBlackWhite coefficients */ 204 static float CLAMPw(float v, float vmin, float vmax) 205 { 206 if( v < vmin ) 207 { 208 /* printf("%f clamped to %f\n", v, vmin); */ 209 return vmin; 210 } 211 if( v > vmax ) 212 { 213 /* printf("%f clamped to %f\n", v, vmax); */ 214 return vmax; 215 } 216 return v; 217 } 218 219 /* 220 * Initialize the YCbCr->RGB conversion tables. The conversion 221 * is done according to the 6.0 spec: 222 * 223 * R = Y + Cr*(2 - 2*LumaRed) 224 * B = Y + Cb*(2 - 2*LumaBlue) 225 * G = Y 226 * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen 227 * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen 228 * 229 * To avoid floating point arithmetic the fractional constants that 230 * come out of the equations are represented as fixed point values 231 * in the range 0...2^16. We also eliminate multiplications by 232 * pre-calculating possible values indexed by Cb and Cr (this code 233 * assumes conversion is being done for 8-bit samples). 234 */ 235 int 236 TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite) 237 { 238 TIFFRGBValue* clamptab; 239 int i; 240 241 #define LumaRed luma[0] 242 #define LumaGreen luma[1] 243 #define LumaBlue luma[2] 244 245 clamptab = (TIFFRGBValue*)( 246 (uint8*) ycbcr+TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long))); 247 _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ 248 ycbcr->clamptab = (clamptab += 256); 249 for (i = 0; i < 256; i++) 250 clamptab[i] = (TIFFRGBValue) i; 251 _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */ 252 ycbcr->Cr_r_tab = (int*) (clamptab + 3*256); 253 ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256; 254 ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256); 255 ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; 256 ycbcr->Y_tab = ycbcr->Cb_g_tab + 256; 257 258 { float f1 = 2-2*LumaRed; int32 D1 = FIX(CLAMP(f1,0.0F,2.0F)); 259 float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(CLAMP(f2,0.0F,2.0F)); 260 float f3 = 2-2*LumaBlue; int32 D3 = FIX(CLAMP(f3,0.0F,2.0F)); 261 float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(CLAMP(f4,0.0F,2.0F)); 262 int x; 263 264 #undef LumaBlue 265 #undef LumaGreen 266 #undef LumaRed 267 268 /* 269 * i is the actual input pixel value in the range 0..255 270 * Cb and Cr values are in the range -128..127 (actually 271 * they are in a range defined by the ReferenceBlackWhite 272 * tag) so there is some range shifting to do here when 273 * constructing tables indexed by the raw pixel data. 274 */ 275 for (i = 0, x = -128; i < 256; i++, x++) { 276 int32 Cr = (int32)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0F, 277 refBlackWhite[5] - 128.0F, 127), 278 -128.0F * 32, 128.0F * 32); 279 int32 Cb = (int32)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0F, 280 refBlackWhite[3] - 128.0F, 127), 281 -128.0F * 32, 128.0F * 32); 282 283 ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT); 284 ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT); 285 ycbcr->Cr_g_tab[i] = D2*Cr; 286 ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF; 287 ycbcr->Y_tab[i] = 288 (int32)CLAMPw(Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255), 289 -128.0F * 32, 128.0F * 32); 290 } 291 } 292 293 return 0; 294 } 295 #undef HICLAMP 296 #undef CLAMP 297 #undef Code2V 298 #undef SHIFT 299 #undef ONE_HALF 300 #undef FIX 301 302 /* vim: set ts=8 sts=8 sw=8 noet: */ 303 /* 304 * Local Variables: 305 * mode: c 306 * c-basic-offset: 8 307 * fill-column: 78 308 * End: 309 */ 310