Home | History | Annotate | Download | only in libtiff
      1 /* $Id: tif_color.c,v 1.23 2017-05-13 18:17:34 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 "tiffiop.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 * 64, 128.0F * 64);
    279 	    int32 Cb = (int32)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0F,
    280 			    refBlackWhite[3] - 128.0F, 127),
    281                             -128.0F * 64, 128.0F * 64);
    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 * 64, 128.0F * 64);
    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