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