Improvements in CIE Lab conversion code. Start moving YCbCr stuff to the
tif_color.c module.
This commit is contained in:
parent
77010a7c62
commit
6d52b5d379
@ -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
|
* 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
|
* 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
|
* 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.
|
* reference white tristimuli can be specified.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
TIFFCIELabToXYZ(uint32 l, int32 a, int32 b, float *X, float *Y, float *Z,
|
TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b,
|
||||||
float X0, float Y0, float Z0)
|
float *X, float *Y, float *Z)
|
||||||
{
|
{
|
||||||
float L = (float)l * 100.0 / 255.0;
|
float L = (float)l * 100.0 / 255.0;
|
||||||
float cby, tmp;
|
float cby, tmp;
|
||||||
|
|
||||||
if( L < 8.856 ) {
|
if( L < 8.856 ) {
|
||||||
*Y = (L * Y0) / 903.292;
|
*Y = (L * cielab->Y0) / 903.292;
|
||||||
cby = 7.787 * (*Y / Y0) + 16.0 / 116.0;
|
cby = 7.787 * (*Y / cielab->Y0) + 16.0 / 116.0;
|
||||||
} else {
|
} else {
|
||||||
cby = (L + 16.0) / 116.0;
|
cby = (L + 16.0) / 116.0;
|
||||||
*Y = Y0 * cby * cby * cby;
|
*Y = cielab->Y0 * cby * cby * cby;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = (double)a / 500.0 + cby;
|
tmp = (double)a / 500.0 + cby;
|
||||||
if( tmp < 0.2069 )
|
if( tmp < 0.2069 )
|
||||||
*X = X0 * (tmp - 0.13793) / 7.787;
|
*X = cielab->X0 * (tmp - 0.13793) / 7.787;
|
||||||
else
|
else
|
||||||
*X = X0 * tmp * tmp * tmp;
|
*X = cielab->X0 * tmp * tmp * tmp;
|
||||||
|
|
||||||
tmp = cby - (double)b / 200.0;
|
tmp = cby - (double)b / 200.0;
|
||||||
if( tmp < 0.2069 )
|
if( tmp < 0.2069 )
|
||||||
*Z = Z0 * (tmp - 0.13793) / 7.787;
|
*Z = cielab->Z0 * (tmp - 0.13793) / 7.787;
|
||||||
else
|
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.
|
* the Yr,Yb,Yg <=> r,g,b conversions.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
TIFFCIELabToRGBInit(TIFFCIELabToRGB** cielab)
|
TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, TIFFDisplay *display,
|
||||||
|
float X0, float Y0, float Z0)
|
||||||
{
|
{
|
||||||
static char module[] = "TIFFCIELabToRGBInit";
|
static char module[] = "TIFFCIELabToRGBInit";
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
float gamma;
|
float gamma;
|
||||||
|
|
||||||
TIFFDisplay sRGB_display = {
|
cielab->range = 1500;
|
||||||
{ /* 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->display = (TIFFDisplay *)_TIFFmalloc(sizeof(TIFFDisplay));
|
||||||
if (!(*cielab)) {
|
if (cielab == NULL) {
|
||||||
*cielab = (TIFFCIELabToRGB *)
|
TIFFError(module, "No space for display structure");
|
||||||
_TIFFmalloc(sizeof(TIFFCIELabToRGB));
|
return -1;
|
||||||
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->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 */
|
/* Red */
|
||||||
gamma = 1.0 / (*cielab)->display->d_gammaR ;
|
gamma = 1.0 / cielab->display->d_gammaR ;
|
||||||
(*cielab)->rstep =
|
cielab->rstep =
|
||||||
((*cielab)->display->d_YCR - (*cielab)->display->d_Y0R)
|
(cielab->display->d_YCR - cielab->display->d_Y0R)
|
||||||
/ (*cielab)->range;
|
/ cielab->range;
|
||||||
for(i = 0; i <= (*cielab)->range; i++) {
|
for(i = 0; i <= cielab->range; i++) {
|
||||||
(*cielab)->Yr2r[i] =
|
cielab->Yr2r[i] = cielab->display->d_Vrwr
|
||||||
(*cielab)->display->d_Vrwr
|
* (pow((double)i / cielab->range, gamma));
|
||||||
* (pow((double)i / (*cielab)->range, gamma));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Green */
|
/* Green */
|
||||||
gamma = 1.0 / (*cielab)->display->d_gammaG ;
|
gamma = 1.0 / cielab->display->d_gammaG ;
|
||||||
(*cielab)->gstep =
|
cielab->gstep =
|
||||||
((*cielab)->display->d_YCR - (*cielab)->display->d_Y0R)
|
(cielab->display->d_YCR - cielab->display->d_Y0R)
|
||||||
/ (*cielab)->range;
|
/ cielab->range;
|
||||||
for(i = 0; i <= (*cielab)->range; i++) {
|
for(i = 0; i <= cielab->range; i++) {
|
||||||
(*cielab)->Yg2g[i] =
|
cielab->Yg2g[i] = cielab->display->d_Vrwg
|
||||||
(*cielab)->display->d_Vrwg
|
* (pow((double)i / cielab->range, gamma));
|
||||||
* (pow((double)i / (*cielab)->range, gamma));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Blue */
|
/* Blue */
|
||||||
gamma = 1.0 / (*cielab)->display->d_gammaB ;
|
gamma = 1.0 / cielab->display->d_gammaB ;
|
||||||
(*cielab)->bstep =
|
cielab->bstep =
|
||||||
((*cielab)->display->d_YCR - (*cielab)->display->d_Y0R)
|
(cielab->display->d_YCR - cielab->display->d_Y0R)
|
||||||
/ (*cielab)->range;
|
/ cielab->range;
|
||||||
for(i = 0; i <= (*cielab)->range; i++) {
|
for(i = 0; i <= cielab->range; i++) {
|
||||||
(*cielab)->Yb2b[i] =
|
cielab->Yb2b[i] = cielab->display->d_Vrwb
|
||||||
(*cielab)->display->d_Vrwb
|
* (pow((double)i / cielab->range, gamma));
|
||||||
* (pow((double)i / (*cielab)->range, gamma));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Init reference white point */
|
||||||
|
cielab->X0 = X0;
|
||||||
|
cielab->Y0 = Y0;
|
||||||
|
cielab->Z0 = Z0;
|
||||||
|
|
||||||
return 0;
|
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<<SHIFT) + 0.5))
|
||||||
|
#define ONE_HALF ((int32)(1<<(SHIFT-1)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the YCbCr->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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
* Copyright (c) 1991-1997 Sam Leffler
|
||||||
@ -42,9 +42,28 @@ static int pickTileSeparateCase(TIFFRGBAImage*);
|
|||||||
|
|
||||||
static const char photoTag[] = "PhotometricInterpretation";
|
static const char photoTag[] = "PhotometricInterpretation";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper constants used in Orientation tag handling
|
||||||
|
*/
|
||||||
#define FLIP_VERTICALLY 0x01
|
#define FLIP_VERTICALLY 0x01
|
||||||
#define FLIP_HORIZONTALLY 0x02
|
#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.
|
* Check the image to see if TIFFReadRGBAImage can deal with it.
|
||||||
* 1/0 is returned according to whether or not the image can
|
* 1/0 is returned according to whether or not the image can
|
||||||
@ -174,10 +193,7 @@ TIFFRGBAImageEnd(TIFFRGBAImage* img)
|
|||||||
if (img->ycbcr)
|
if (img->ycbcr)
|
||||||
_TIFFfree(img->ycbcr), img->ycbcr = NULL;
|
_TIFFfree(img->ycbcr), img->ycbcr = NULL;
|
||||||
if (img->cielab) {
|
if (img->cielab) {
|
||||||
_TIFFfree(img->cielab->Yr2r);
|
TIFFCIELabToRGBEnd(img->cielab);
|
||||||
_TIFFfree(img->cielab->Yg2g);
|
|
||||||
_TIFFfree(img->cielab->Yb2b);
|
|
||||||
_TIFFfree(img->cielab->display);
|
|
||||||
_TIFFfree(img->cielab), img->cielab = NULL;
|
_TIFFfree(img->cielab), img->cielab = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1540,11 +1556,11 @@ DECLAREContigPutFunc(putcontig8bitCIELab)
|
|||||||
fromskew *= 3;
|
fromskew *= 3;
|
||||||
while (h-- > 0) {
|
while (h-- > 0) {
|
||||||
for (x = w; x-- > 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[1],
|
||||||
(signed char)pp[2],
|
(signed char)pp[2],
|
||||||
&X, &Y, &Z,
|
&X, &Y, &Z);
|
||||||
D50_X0, D50_Y0, D50_Z0);
|
|
||||||
TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
|
TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
|
||||||
*cp++ = PACK(r, g, b);
|
*cp++ = PACK(r, g, b);
|
||||||
pp += 3;
|
pp += 3;
|
||||||
@ -2005,128 +2021,76 @@ DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
|
|||||||
#undef YCbCrSetup
|
#undef YCbCrSetup
|
||||||
#undef YCbCrtoRGB
|
#undef YCbCrtoRGB
|
||||||
|
|
||||||
#define LumaRed coeffs[0]
|
|
||||||
#define LumaGreen coeffs[1]
|
|
||||||
#define LumaBlue coeffs[2]
|
|
||||||
#define SHIFT 16
|
|
||||||
#define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5))
|
|
||||||
#define ONE_HALF ((int32)(1<<(SHIFT-1)))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize the YCbCr->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
|
static tileContigRoutine
|
||||||
initYCbCrConversion(TIFFRGBAImage* img)
|
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) {
|
if (img->ycbcr == NULL) {
|
||||||
TIFFError(TIFFFileName(img->tif),
|
img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc(
|
||||||
"No space for YCbCr->RGB conversion state");
|
TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))
|
||||||
return (NULL);
|
+ 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);
|
TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs);
|
||||||
if (_TIFFmemcmp(coeffs, img->ycbcr->coeffs, 3*sizeof (float)) != 0)
|
if (TIFFYCbCrToRGBInit(img->ycbcr,
|
||||||
TIFFYCbCrToRGBInit(img->ycbcr, img->tif);
|
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
|
* The 6.0 spec says that subsampling must be
|
||||||
* must always be <= horizontal subsampling; so
|
* one of 1, 2, or 4, and that vertical subsampling
|
||||||
* there are only a few possibilities and we just
|
* must always be <= horizontal subsampling; so
|
||||||
* enumerate the cases.
|
* there are only a few possibilities and we just
|
||||||
*/
|
* enumerate the cases.
|
||||||
TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs);
|
*/
|
||||||
switch ((hs<<4)|vs) {
|
TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs);
|
||||||
case 0x44: return (putcontig8bitYCbCr44tile);
|
switch ((hs<<4)|vs) {
|
||||||
case 0x42: return (putcontig8bitYCbCr42tile);
|
case 0x44: return (putcontig8bitYCbCr44tile);
|
||||||
case 0x41: return (putcontig8bitYCbCr41tile);
|
case 0x42: return (putcontig8bitYCbCr42tile);
|
||||||
case 0x22: return (putcontig8bitYCbCr22tile);
|
case 0x41: return (putcontig8bitYCbCr41tile);
|
||||||
case 0x21: return (putcontig8bitYCbCr21tile);
|
case 0x22: return (putcontig8bitYCbCr22tile);
|
||||||
case 0x11: return (putcontig8bitYCbCr11tile);
|
case 0x21: return (putcontig8bitYCbCr21tile);
|
||||||
}
|
case 0x11: return (putcontig8bitYCbCr11tile);
|
||||||
return (NULL);
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static tileContigRoutine
|
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;
|
return putcontig8bitCIELab;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2430,7 +2394,7 @@ pickTileContigCase(TIFFRGBAImage* img)
|
|||||||
break;
|
break;
|
||||||
case PHOTOMETRIC_CIELAB:
|
case PHOTOMETRIC_CIELAB:
|
||||||
if (img->bitspersample == 8)
|
if (img->bitspersample == 8)
|
||||||
put = initCIELabToRGBConversion(img);
|
put = initCIELabConversion(img);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
* Copyright (c) 1988-1997 Sam Leffler
|
||||||
@ -153,7 +153,8 @@ typedef struct { /* YCbCr->RGB support */
|
|||||||
int* Cb_b_tab;
|
int* Cb_b_tab;
|
||||||
int32* Cr_g_tab;
|
int32* Cr_g_tab;
|
||||||
int32* Cb_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;
|
} TIFFYCbCrToRGB;
|
||||||
|
|
||||||
typedef struct { /* CIE Lab 1976->RGB support */
|
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* Yg2g; /* Conversion of Yg to g */
|
||||||
float* Yb2b; /* Conversion of Yb to b */
|
float* Yb2b; /* Conversion of Yb to b */
|
||||||
float rstep, gstep, bstep;
|
float rstep, gstep, bstep;
|
||||||
|
float X0, Y0, Z0; /* Reference white point */
|
||||||
} TIFFCIELabToRGB;
|
} TIFFCIELabToRGB;
|
||||||
|
|
||||||
extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB**);
|
extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB*, TIFFDisplay *display,
|
||||||
extern void TIFFCIELabToXYZ(uint32, int32, int32, float *, float *, float *,
|
float X0, float Y0, float Z0);
|
||||||
float, float, float);
|
extern int TIFFCIELabToRGBEnd(TIFFCIELabToRGB*);
|
||||||
|
extern void TIFFCIELabToXYZ(TIFFCIELabToRGB *, uint32, int32, int32,
|
||||||
|
float *, float *, float *);
|
||||||
extern void TIFFXYZToRGB(TIFFCIELabToRGB *, float, float, float,
|
extern void TIFFXYZToRGB(TIFFCIELabToRGB *, float, float, float,
|
||||||
uint32 *, uint32 *, uint32 *);
|
uint32 *, uint32 *, uint32 *);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
TIFFYCbCrToRGBInit(TIFFYCbCrToRGB*, float, float, float);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RGBA-style image support.
|
* RGBA-style image support.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user