From b1c2b3ed272fbc27f3801c9407d1b3b60b483096 Mon Sep 17 00:00:00 2001 From: Joris Van Damme Date: Wed, 12 Apr 2006 07:29:51 +0000 Subject: [PATCH] Added support for planarconfig separate non-subsampled YCbCr to tif_getimage.c --- ChangeLog | 9 ++- libtiff/tif_getimage.c | 149 ++++++++++++++++++++++++++++------------- 2 files changed, 109 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index 359616a0..68b2c858 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ +2006-04-12 Joris Van Damme + + * libtiff/tif_getimage.c: Added support for planarconfig separate + non-subsampled YCbCr (i.e. separate YCbCr with subsampling [1,1]) + 2006-04-11 Joris Van Damme - * libtiff/tiff_getimage.c: Revision of all RGB(A) put routines + * libtiff/tif_getimage.c: Revision of all RGB(A) put routines - Conversion of unassociated alpha to associated alpha now done with more performant LUT, and calculation more correct - Conversion of 16bit data to 8bit data now done with @@ -9,7 +14,7 @@ 2006-04-11 Joris Van Damme - * libtiff/tiff_getimage.c: + * libtiff/tif_getimage.c: - When there is no alpha, gtTileSeparate and gtStripSeparate allocated buffer for alpha strile and filled it, only to never read it back. Removed allocation and fill. diff --git a/libtiff/tif_getimage.c b/libtiff/tif_getimage.c index ade51f76..b021c52c 100644 --- a/libtiff/tif_getimage.c +++ b/libtiff/tif_getimage.c @@ -1,4 +1,4 @@ -/* $Id: tif_getimage.c,v 1.59 2006-04-11 13:33:19 joris Exp $ */ +/* $Id: tif_getimage.c,v 1.60 2006-04-12 07:29:51 joris Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler @@ -131,11 +131,12 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024]) */ break; case PHOTOMETRIC_YCBCR: - if (td->td_planarconfig != PLANARCONFIG_CONTIG) { - sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d", - "Planarconfiguration", td->td_planarconfig); - return (0); - } + /* + * TODO: if at all meaningful and useful, make more complete + * support check here, or better still, refactor to let supporting + * code decide whether there is support and what meaningfull + * error to return + */ break; case PHOTOMETRIC_RGB: if (colorchannels < 3) { @@ -350,17 +351,17 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) } break; case PHOTOMETRIC_YCBCR: - if (planarconfig != PLANARCONFIG_CONTIG) { - sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d", - "Planarconfiguration", planarconfig); - return (0); - } /* It would probably be nice to have a reality check here. */ if (planarconfig == PLANARCONFIG_CONTIG) /* can rely on libjpeg to convert to RGB */ /* XXX should restore current state on exit */ switch (compress) { case COMPRESSION_JPEG: + /* + * TODO: when complete tests verify complete desubsampling + * and YCbCr handling, remove use of TIFFTAG_JPEGCOLORMODE in + * favor of tif_getimage.c native handling + */ TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); img->photometric = PHOTOMETRIC_RGB; break; @@ -368,6 +369,12 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) /* do nothing */; break; } + /* + * TODO: if at all meaningful and useful, make more complete + * support check here, or better still, refactor to let supporting + * code decide whether there is support and what meaningfull + * error to return + */ break; case PHOTOMETRIC_RGB: if (colorchannels < 3) { @@ -1035,7 +1042,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) #define PACK4(r,g,b,a) \ ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24)) #define W2B(v) (((v)>>8)&0xff) -/* TODO: PACKW should have been made redundant in favor of Bitdepth16To8 LUT */ +/* TODO: PACKW should have be made redundant in favor of Bitdepth16To8 LUT */ #define PACKW(r,g,b) \ ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1) #define PACKW4(r,g,b,a) \ @@ -2007,57 +2014,53 @@ DECLAREContigPutFunc(putcontig8bitYCbCr11tile) pp += fromskew; } while (--h); } + +/* + * 8-bit packed YCbCr samples w/ no subsampling => RGB + */ +DECLARESepPutFunc(putseparate8bitYCbCr11tile) +{ + /* TODO: naming of input vars is still off, change obfuscating declaration inside define, or resolve obfuscation */ + while (h-- > 0) { + x = w; + do { + uint32 dr, dg, db; + TIFFYCbCrtoRGB(img->ycbcr,*r++,*g++,*b++,&dr,&dg,&db); + *cp++ = PACK(dr,dg,db); + } while (--x); + SKEW(r, g, b, fromskew); + cp += toskew; + } +} #undef YCbCrtoRGB -static tileContigRoutine +static int initYCbCrConversion(TIFFRGBAImage* img) { static char module[] = "initYCbCrConversion"; float *luma, *refBlackWhite; - uint16 hs, vs; if (img->ycbcr == NULL) { - img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( + img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)) + 4*256*sizeof (TIFFRGBValue) + 2*256*sizeof (int) + 3*256*sizeof (int32) - ); - if (img->ycbcr == NULL) { + ); + if (img->ycbcr == NULL) { TIFFErrorExt(img->tif->tif_clientdata, module, - "No space for YCbCr->RGB conversion state"); - return (NULL); - } + "No space for YCbCr->RGB conversion state"); + return (0); + } } TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma); TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE, - &refBlackWhite); + &refBlackWhite); if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 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. - * Joris: added support for the [1,2] case, nonetheless, to accomodate - * some OJPEG files - */ - 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 0x12: return (putcontig8bitYCbCr12tile); - case 0x11: return (putcontig8bitYCbCr11tile); - } - - return (NULL); + return(0); + return (1); } static tileContigRoutine @@ -2420,9 +2423,45 @@ PickContigCase(TIFFRGBAImage* img) } break; case PHOTOMETRIC_YCBCR: - if (buildMap(img)) { - if (img->bitspersample == 8) - img->put.contig = initYCbCrConversion(img); + if (img->bitspersample == 8) + { + if (initYCbCrConversion(img)!=0) + { + uint16 hs, vs; + /* + * 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. + * Joris: added support for the [1,2] case, nonetheless, to accomodate + * some OJPEG files + */ + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); + switch ((hs<<4)|vs) { + case 0x44: + img->put.contig = putcontig8bitYCbCr44tile; + break; + case 0x42: + img->put.contig = putcontig8bitYCbCr42tile; + break; + case 0x41: + img->put.contig = putcontig8bitYCbCr41tile; + break; + case 0x22: + img->put.contig = putcontig8bitYCbCr22tile; + break; + case 0x21: + img->put.contig = putcontig8bitYCbCr21tile; + break; + case 0x12: + img->put.contig = putcontig8bitYCbCr12tile; + break; + case 0x11: + img->put.contig = putcontig8bitYCbCr11tile; + break; + } + } } break; case PHOTOMETRIC_CIELAB: @@ -2480,6 +2519,22 @@ PickSeparateCase(TIFFRGBAImage* img) break; } break; + case PHOTOMETRIC_YCBCR: + if ((img->bitspersample==8) && (img->samplesperpixel==3)) + { + if (initYCbCrConversion(img)!=0) + { + uint16 hs, vs; + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); + switch ((hs<<4)|vs) { + case 0x11: + img->put.separate = putseparate8bitYCbCr11tile; + break; + /* TODO: add other cases here */ + } + } + } + break; } return ((img->get!=NULL) && (img->put.separate!=NULL)); }