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