From 6d52b5d3797a7d7b34fe8717cf1ba9a8251f4f72 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Wed, 3 Dec 2003 19:54:03 +0000 Subject: [PATCH] Improvements in CIE Lab conversion code. Start moving YCbCr stuff to the tif_color.c module. --- libtiff/tif_color.c | 260 ++++++++++++++++++++++++----------------- libtiff/tif_getimage.c | 202 +++++++++++++------------------- libtiff/tiffio.h | 17 ++- 3 files changed, 251 insertions(+), 228 deletions(-) diff --git a/libtiff/tif_color.c b/libtiff/tif_color.c index f6c0e60d..2c3c2831 100644 --- a/libtiff/tif_color.c +++ b/libtiff/tif_color.c @@ -1,4 +1,4 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_color.c,v 1.1 2003-11-13 19:46:39 dron Exp $ */ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_color.c,v 1.2 2003-12-03 19:54:03 dron Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -27,7 +27,7 @@ /* * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with - * the permission of John Cupitt, the author. + * the permission of John Cupitt, the VIPS author. */ /* @@ -44,31 +44,31 @@ * reference white tristimuli can be specified. */ void -TIFFCIELabToXYZ(uint32 l, int32 a, int32 b, float *X, float *Y, float *Z, - float X0, float Y0, float Z0) +TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b, + float *X, float *Y, float *Z) { float L = (float)l * 100.0 / 255.0; float cby, tmp; if( L < 8.856 ) { - *Y = (L * Y0) / 903.292; - cby = 7.787 * (*Y / Y0) + 16.0 / 116.0; + *Y = (L * cielab->Y0) / 903.292; + cby = 7.787 * (*Y / cielab->Y0) + 16.0 / 116.0; } else { cby = (L + 16.0) / 116.0; - *Y = Y0 * cby * cby * cby; + *Y = cielab->Y0 * cby * cby * cby; } tmp = (double)a / 500.0 + cby; if( tmp < 0.2069 ) - *X = X0 * (tmp - 0.13793) / 7.787; + *X = cielab->X0 * (tmp - 0.13793) / 7.787; else - *X = X0 * tmp * tmp * tmp; + *X = cielab->X0 * tmp * tmp * tmp; tmp = cby - (double)b / 200.0; if( tmp < 0.2069 ) - *Z = Z0 * (tmp - 0.13793) / 7.787; + *Z = cielab->Z0 * (tmp - 0.13793) / 7.787; else - *Z = Z0 * tmp * tmp * tmp; + *Z = cielab->Z0 * tmp * tmp * tmp; } /* @@ -116,118 +116,170 @@ TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z, * the Yr,Yb,Yg <=> r,g,b conversions. */ int -TIFFCIELabToRGBInit(TIFFCIELabToRGB** cielab) +TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, TIFFDisplay *display, + float X0, float Y0, float Z0) { static char module[] = "TIFFCIELabToRGBInit"; int i; float gamma; - TIFFDisplay sRGB_display = { - { /* XYZ -> luminance matrix */ - { 3.2410, -1.5374, -0.4986 }, - { -0.9692, 1.8760, 0.0416 }, - { 0.0556, -0.2040, 1.0570 } - }, - 100, 100, 100, /* Light o/p for reference white */ - 255, 255, 255, /* Pixel values for ref. white */ - 1, 1, 1, /* Residual light o/p for black pixel */ - 2.4, 2.4, 2.4, /* Gamma values for the three guns */ - }; + cielab->range = 1500; - - if (!(*cielab)) { - *cielab = (TIFFCIELabToRGB *) - _TIFFmalloc(sizeof(TIFFCIELabToRGB)); - if (*cielab == NULL) { - TIFFError(module, - "No space for CIE L*a*b* control structure"); - return -1; - } - - (*cielab)->range = 1500; - - (*cielab)->display = - (TIFFDisplay *)_TIFFmalloc(sizeof(TIFFDisplay)); - if ((*cielab) == NULL) { - TIFFError(module, "No space for display structure"); - _TIFFfree(*cielab); - *cielab = 0; - return -1; - } - - (*cielab)->Yr2r = (float *) - _TIFFmalloc(((*cielab)->range + 1) * sizeof(float)); - if ((*cielab)->Yr2r == NULL) { - TIFFError(module, "No space for Red conversion array"); - _TIFFfree((*cielab)->display); - _TIFFfree(*cielab); - *cielab = 0; - return -1; - } - - (*cielab)->Yg2g = (float *) - _TIFFmalloc(((*cielab)->range + 1) * sizeof(float)); - if ((*cielab)->Yg2g == NULL) { - TIFFError(module, - "No space for Green conversion array"); - _TIFFfree((*cielab)->Yr2r); - _TIFFfree((*cielab)->display); - _TIFFfree(*cielab); - *cielab = 0; - return -1; - } - - (*cielab)->Yb2b = (float *) - _TIFFmalloc(((*cielab)->range + 1) * sizeof(float)); - if ((*cielab)->Yb2b == NULL) { - TIFFError(module, "No space for Blue conversion array"); - _TIFFfree((*cielab)->Yb2b); - _TIFFfree((*cielab)->Yr2r); - _TIFFfree((*cielab)->display); - _TIFFfree(*cielab); - *cielab = 0; - return -1; - } - - _TIFFmemcpy((*cielab)->display, &sRGB_display, - sizeof(TIFFDisplay)); + cielab->display = (TIFFDisplay *)_TIFFmalloc(sizeof(TIFFDisplay)); + if (cielab == NULL) { + TIFFError(module, "No space for display structure"); + return -1; } + cielab->Yr2r = (float *) + _TIFFmalloc((cielab->range + 1) * sizeof(float)); + if (cielab->Yr2r == NULL) { + TIFFError(module, "No space for Red conversion array"); + _TIFFfree(cielab->display); + return -1; + } + + cielab->Yg2g = (float *) + _TIFFmalloc((cielab->range + 1) * sizeof(float)); + if (cielab->Yg2g == NULL) { + TIFFError(module, + "No space for Green conversion array"); + _TIFFfree(cielab->Yr2r); + _TIFFfree(cielab->display); + return -1; + } + + cielab->Yb2b = (float *) + _TIFFmalloc((cielab->range + 1) * sizeof(float)); + if (cielab->Yb2b == NULL) { + TIFFError(module, "No space for Blue conversion array"); + _TIFFfree(cielab->Yb2b); + _TIFFfree(cielab->Yr2r); + _TIFFfree(cielab->display); + return -1; + } + + _TIFFmemcpy(cielab->display, display, sizeof(TIFFDisplay)); + /* Red */ - gamma = 1.0 / (*cielab)->display->d_gammaR ; - (*cielab)->rstep = - ((*cielab)->display->d_YCR - (*cielab)->display->d_Y0R) - / (*cielab)->range; - for(i = 0; i <= (*cielab)->range; i++) { - (*cielab)->Yr2r[i] = - (*cielab)->display->d_Vrwr - * (pow((double)i / (*cielab)->range, gamma)); + gamma = 1.0 / cielab->display->d_gammaR ; + cielab->rstep = + (cielab->display->d_YCR - cielab->display->d_Y0R) + / cielab->range; + for(i = 0; i <= cielab->range; i++) { + cielab->Yr2r[i] = cielab->display->d_Vrwr + * (pow((double)i / cielab->range, gamma)); } /* Green */ - gamma = 1.0 / (*cielab)->display->d_gammaG ; - (*cielab)->gstep = - ((*cielab)->display->d_YCR - (*cielab)->display->d_Y0R) - / (*cielab)->range; - for(i = 0; i <= (*cielab)->range; i++) { - (*cielab)->Yg2g[i] = - (*cielab)->display->d_Vrwg - * (pow((double)i / (*cielab)->range, gamma)); + gamma = 1.0 / cielab->display->d_gammaG ; + cielab->gstep = + (cielab->display->d_YCR - cielab->display->d_Y0R) + / cielab->range; + for(i = 0; i <= cielab->range; i++) { + cielab->Yg2g[i] = cielab->display->d_Vrwg + * (pow((double)i / cielab->range, gamma)); } /* Blue */ - gamma = 1.0 / (*cielab)->display->d_gammaB ; - (*cielab)->bstep = - ((*cielab)->display->d_YCR - (*cielab)->display->d_Y0R) - / (*cielab)->range; - for(i = 0; i <= (*cielab)->range; i++) { - (*cielab)->Yb2b[i] = - (*cielab)->display->d_Vrwb - * (pow((double)i / (*cielab)->range, gamma)); + gamma = 1.0 / cielab->display->d_gammaB ; + cielab->bstep = + (cielab->display->d_YCR - cielab->display->d_Y0R) + / cielab->range; + for(i = 0; i <= cielab->range; i++) { + cielab->Yb2b[i] = cielab->display->d_Vrwb + * (pow((double)i / cielab->range, gamma)); } + /* Init reference white point */ + cielab->X0 = X0; + cielab->Y0 = Y0; + cielab->Z0 = Z0; + return 0; } +/* + * Free TIFFYCbCrToRGB structure. + */ +int +TIFFCIELabToRGBEnd(TIFFCIELabToRGB* cielab) +{ + static char module[] = "TIFFCIELabToRGBEnd"; + + _TIFFfree(cielab->Yr2r); + _TIFFfree(cielab->Yg2g); + _TIFFfree(cielab->Yb2b); + _TIFFfree(cielab->display); +} + +#define SHIFT 16 +#define FIX(x) ((int32)((x) * (1L<RGB conversion tables. The conversion + * is done according to the 6.0 spec: + * + * R = Y + Cr*(2 - 2*LumaRed) + * B = Y + Cb*(2 - 2*LumaBlue) + * G = Y + * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen + * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen + * + * To avoid floating point arithmetic the fractional constants that + * come out of the equations are represented as fixed point values + * in the range 0...2^16. We also eliminate multiplications by + * pre-calculating possible values indexed by Cb and Cr (this code + * assumes conversion is being done for 8-bit samples). + */ +int +TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, + float LumaRed, float LumaGreen, float LumaBlue) +{ + TIFFRGBValue* clamptab; + int i; + + clamptab = (TIFFRGBValue*)( + (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))); + _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ + ycbcr->clamptab = (clamptab += 256); + for (i = 0; i < 256; i++) + clamptab[i] = (TIFFRGBValue) i; + _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */ + { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1); + float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2); + float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3); + float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4); + int x; + + ycbcr->Cr_r_tab = (int*) (clamptab + 3*256); + ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256; + ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256); + ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; + /* + * i is the actual input pixel value in the range 0..255 + * Cb and Cr values are in the range -128..127 (actually + * they are in a range defined by the ReferenceBlackWhite + * tag) so there is some range shifting to do here when + * constructing tables indexed by the raw pixel data. + * + * XXX handle ReferenceBlackWhite correctly to calculate + * Cb/Cr values to use in constructing the tables. + */ + for (i = 0, x = -128; i < 256; i++, x++) { + ycbcr->Cr_r_tab[i] = (int)((D1*x + ONE_HALF)>>SHIFT); + ycbcr->Cb_b_tab[i] = (int)((D3*x + ONE_HALF)>>SHIFT); + ycbcr->Cr_g_tab[i] = D2*x; + ycbcr->Cb_g_tab[i] = D4*x + ONE_HALF; + } + } + + return 0; +} +#undef SHIFT +#undef ONE_HALF +#undef FIX + diff --git a/libtiff/tif_getimage.c b/libtiff/tif_getimage.c index a57de514..12a9402d 100644 --- a/libtiff/tif_getimage.c +++ b/libtiff/tif_getimage.c @@ -1,4 +1,4 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_getimage.c,v 1.30 2003-12-03 15:40:14 dron Exp $ */ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_getimage.c,v 1.31 2003-12-03 19:54:03 dron Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler @@ -42,9 +42,28 @@ static int pickTileSeparateCase(TIFFRGBAImage*); static const char photoTag[] = "PhotometricInterpretation"; +/* + * Helper constants used in Orientation tag handling + */ #define FLIP_VERTICALLY 0x01 #define FLIP_HORIZONTALLY 0x02 +/* + * Color conversion constants. We will define display types here. + */ + +TIFFDisplay display_sRGB = { + { /* XYZ -> luminance matrix */ + { 3.2410, -1.5374, -0.4986 }, + { -0.9692, 1.8760, 0.0416 }, + { 0.0556, -0.2040, 1.0570 } + }, + 100, 100, 100, /* Light o/p for reference white */ + 255, 255, 255, /* Pixel values for ref. white */ + 1, 1, 1, /* Residual light o/p for black pixel */ + 2.4, 2.4, 2.4, /* Gamma values for the three guns */ +}; + /* * Check the image to see if TIFFReadRGBAImage can deal with it. * 1/0 is returned according to whether or not the image can @@ -174,10 +193,7 @@ TIFFRGBAImageEnd(TIFFRGBAImage* img) if (img->ycbcr) _TIFFfree(img->ycbcr), img->ycbcr = NULL; if (img->cielab) { - _TIFFfree(img->cielab->Yr2r); - _TIFFfree(img->cielab->Yg2g); - _TIFFfree(img->cielab->Yb2b); - _TIFFfree(img->cielab->display); + TIFFCIELabToRGBEnd(img->cielab); _TIFFfree(img->cielab), img->cielab = NULL; } @@ -1540,11 +1556,11 @@ DECLAREContigPutFunc(putcontig8bitCIELab) fromskew *= 3; while (h-- > 0) { for (x = w; x-- > 0;) { - TIFFCIELabToXYZ((u_char)pp[0], + TIFFCIELabToXYZ(img->cielab, + (u_char)pp[0], (signed char)pp[1], (signed char)pp[2], - &X, &Y, &Z, - D50_X0, D50_Y0, D50_Z0); + &X, &Y, &Z); TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b); *cp++ = PACK(r, g, b); pp += 3; @@ -2005,128 +2021,76 @@ DECLAREContigPutFunc(putcontig8bitYCbCr11tile) #undef YCbCrSetup #undef YCbCrtoRGB -#define LumaRed coeffs[0] -#define LumaGreen coeffs[1] -#define LumaBlue coeffs[2] -#define SHIFT 16 -#define FIX(x) ((int32)((x) * (1L<RGB conversion tables. The conversion - * is done according to the 6.0 spec: - * - * R = Y + Cr*(2 - 2*LumaRed) - * B = Y + Cb*(2 - 2*LumaBlue) - * G = Y - * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen - * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen - * - * To avoid floating point arithmetic the fractional constants that - * come out of the equations are represented as fixed point values - * in the range 0...2^16. We also eliminate multiplications by - * pre-calculating possible values indexed by Cb and Cr (this code - * assumes conversion is being done for 8-bit samples). - */ -static void -TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, TIFF* tif) -{ - TIFFRGBValue* clamptab; - float* coeffs; - int i; - - clamptab = (TIFFRGBValue*)( - (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))); - _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ - ycbcr->clamptab = (clamptab += 256); - for (i = 0; i < 256; i++) - clamptab[i] = (TIFFRGBValue) i; - _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */ - TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs); - _TIFFmemcpy(ycbcr->coeffs, coeffs, 3*sizeof (float)); - { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1); - float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2); - float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3); - float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4); - int x; - - ycbcr->Cr_r_tab = (int*) (clamptab + 3*256); - ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256; - ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256); - ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; - /* - * i is the actual input pixel value in the range 0..255 - * Cb and Cr values are in the range -128..127 (actually - * they are in a range defined by the ReferenceBlackWhite - * tag) so there is some range shifting to do here when - * constructing tables indexed by the raw pixel data. - * - * XXX handle ReferenceBlackWhite correctly to calculate - * Cb/Cr values to use in constructing the tables. - */ - for (i = 0, x = -128; i < 256; i++, x++) { - ycbcr->Cr_r_tab[i] = (int)((D1*x + ONE_HALF)>>SHIFT); - ycbcr->Cb_b_tab[i] = (int)((D3*x + ONE_HALF)>>SHIFT); - ycbcr->Cr_g_tab[i] = D2*x; - ycbcr->Cb_g_tab[i] = D4*x + ONE_HALF; - } - } -} -#undef SHIFT -#undef ONE_HALF -#undef FIX -#undef LumaBlue -#undef LumaGreen -#undef LumaRed - static tileContigRoutine initYCbCrConversion(TIFFRGBAImage* img) { - uint16 hs, vs; + static char module[] = "initCIELabConversion"; + + float *coeffs; + uint16 hs, vs; - if (img->ycbcr == NULL) { - img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( - TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)) - + 4*256*sizeof (TIFFRGBValue) - + 2*256*sizeof (int) - + 2*256*sizeof (int32) - ); if (img->ycbcr == NULL) { - TIFFError(TIFFFileName(img->tif), - "No space for YCbCr->RGB conversion state"); - return (NULL); + img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( + TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)) + + 4*256*sizeof (TIFFRGBValue) + + 2*256*sizeof (int) + + 2*256*sizeof (int32) + ); + if (img->ycbcr == NULL) { + TIFFError(module, + "No space for YCbCr->RGB conversion state"); + return (NULL); + } } - TIFFYCbCrToRGBInit(img->ycbcr, img->tif); - } else { - float* coeffs; TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs); - if (_TIFFmemcmp(coeffs, img->ycbcr->coeffs, 3*sizeof (float)) != 0) - TIFFYCbCrToRGBInit(img->ycbcr, img->tif); - } - /* - * The 6.0 spec says that subsampling must be - * one of 1, 2, or 4, and that vertical subsampling - * must always be <= horizontal subsampling; so - * there are only a few possibilities and we just - * enumerate the cases. - */ - TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); - switch ((hs<<4)|vs) { - case 0x44: return (putcontig8bitYCbCr44tile); - case 0x42: return (putcontig8bitYCbCr42tile); - case 0x41: return (putcontig8bitYCbCr41tile); - case 0x22: return (putcontig8bitYCbCr22tile); - case 0x21: return (putcontig8bitYCbCr21tile); - case 0x11: return (putcontig8bitYCbCr11tile); - } - return (NULL); + if (TIFFYCbCrToRGBInit(img->ycbcr, + coeffs[0], coeffs[1], coeffs[2]) < 0) + return NULL; + + /* + * The 6.0 spec says that subsampling must be + * one of 1, 2, or 4, and that vertical subsampling + * must always be <= horizontal subsampling; so + * there are only a few possibilities and we just + * enumerate the cases. + */ + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); + switch ((hs<<4)|vs) { + case 0x44: return (putcontig8bitYCbCr44tile); + case 0x42: return (putcontig8bitYCbCr42tile); + case 0x41: return (putcontig8bitYCbCr41tile); + case 0x22: return (putcontig8bitYCbCr22tile); + case 0x21: return (putcontig8bitYCbCr21tile); + case 0x11: return (putcontig8bitYCbCr11tile); + } + + return (NULL); } static tileContigRoutine -initCIELabToRGBConversion(TIFFRGBAImage* img) +initCIELabConversion(TIFFRGBAImage* img) { - TIFFCIELabToRGBInit(&img->cielab); + static char module[] = "initCIELabConversion"; + + if (!img->cielab) { + img->cielab = (TIFFCIELabToRGB *) + _TIFFmalloc(sizeof(TIFFCIELabToRGB)); + if (!img->cielab) { + TIFFError(module, + "No space for CIE L*a*b*->RGB conversion state."); + return NULL; + } + } + + if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, + D50_X0, D50_Y0, D50_Z0) < 0) { + TIFFError(module, + "Failed to initialize CIE L*a*b*->RGB conversion state."); + _TIFFfree(img->cielab); + return NULL; + } + return putcontig8bitCIELab; } @@ -2430,7 +2394,7 @@ pickTileContigCase(TIFFRGBAImage* img) break; case PHOTOMETRIC_CIELAB: if (img->bitspersample == 8) - put = initCIELabToRGBConversion(img); + put = initCIELabConversion(img); break; } } diff --git a/libtiff/tiffio.h b/libtiff/tiffio.h index 436e055b..23a37068 100644 --- a/libtiff/tiffio.h +++ b/libtiff/tiffio.h @@ -1,4 +1,4 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tiffio.h,v 1.21 2003-12-03 15:40:14 dron Exp $ */ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tiffio.h,v 1.22 2003-12-03 19:54:03 dron Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -153,7 +153,8 @@ typedef struct { /* YCbCr->RGB support */ int* Cb_b_tab; int32* Cr_g_tab; int32* Cb_g_tab; - float coeffs[3]; /* cached for repeated use */ + float coeffs[3]; /* XXX: no longer required. Will + be removed in the future. */ } TIFFYCbCrToRGB; typedef struct { /* CIE Lab 1976->RGB support */ @@ -163,14 +164,20 @@ typedef struct { /* CIE Lab 1976->RGB support */ float* Yg2g; /* Conversion of Yg to g */ float* Yb2b; /* Conversion of Yb to b */ float rstep, gstep, bstep; + float X0, Y0, Z0; /* Reference white point */ } TIFFCIELabToRGB; -extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB**); -extern void TIFFCIELabToXYZ(uint32, int32, int32, float *, float *, float *, - float, float, float); +extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB*, TIFFDisplay *display, + float X0, float Y0, float Z0); +extern int TIFFCIELabToRGBEnd(TIFFCIELabToRGB*); +extern void TIFFCIELabToXYZ(TIFFCIELabToRGB *, uint32, int32, int32, + float *, float *, float *); extern void TIFFXYZToRGB(TIFFCIELabToRGB *, float, float, float, uint32 *, uint32 *, uint32 *); +extern int +TIFFYCbCrToRGBInit(TIFFYCbCrToRGB*, float, float, float); + /* * RGBA-style image support. */