summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libtiff/libtiff/tif_getimage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libtiff/libtiff/tif_getimage.c')
-rw-r--r--src/3rdparty/libtiff/libtiff/tif_getimage.c474
1 files changed, 336 insertions, 138 deletions
diff --git a/src/3rdparty/libtiff/libtiff/tif_getimage.c b/src/3rdparty/libtiff/libtiff/tif_getimage.c
index 667f323..a85273c 100644
--- a/src/3rdparty/libtiff/libtiff/tif_getimage.c
+++ b/src/3rdparty/libtiff/libtiff/tif_getimage.c
@@ -1,4 +1,4 @@
-/* $Id: tif_getimage.c,v 1.63.2.3 2009-08-30 16:21:46 bfriesen Exp $ */
+/* $Id: tif_getimage.c,v 1.82 2012-06-06 00:17:49 fwarmerdam Exp $ */
/*
* Copyright (c) 1991-1997 Sam Leffler
@@ -38,6 +38,10 @@ static int gtStripContig(TIFFRGBAImage*, uint32*, uint32, uint32);
static int gtStripSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
static int PickContigCase(TIFFRGBAImage*);
static int PickSeparateCase(TIFFRGBAImage*);
+
+static int BuildMapUaToAa(TIFFRGBAImage* img);
+static int BuildMapBitdepth16To8(TIFFRGBAImage* img);
+
static const char photoTag[] = "PhotometricInterpretation";
/*
@@ -50,7 +54,7 @@ static const char photoTag[] = "PhotometricInterpretation";
* Color conversion constants. We will define display types here.
*/
-TIFFDisplay display_sRGB = {
+static const TIFFDisplay display_sRGB = {
{ /* XYZ -> luminance matrix */
{ 3.2410F, -1.5374F, -0.4986F },
{ -0.9692F, 1.8760F, 0.0416F },
@@ -202,10 +206,16 @@ TIFFRGBAImageEnd(TIFFRGBAImage* img)
_TIFFfree(img->ycbcr), img->ycbcr = NULL;
if (img->cielab)
_TIFFfree(img->cielab), img->cielab = NULL;
+ if (img->UaToAa)
+ _TIFFfree(img->UaToAa), img->UaToAa = NULL;
+ if (img->Bitdepth16To8)
+ _TIFFfree(img->Bitdepth16To8), img->Bitdepth16To8 = NULL;
+
if( img->redcmap ) {
_TIFFfree( img->redcmap );
_TIFFfree( img->greencmap );
_TIFFfree( img->bluecmap );
+ img->redcmap = img->greencmap = img->bluecmap = NULL;
}
}
@@ -252,7 +262,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
default:
sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
img->bitspersample);
- return (0);
+ goto fail_return;
}
img->alpha = 0;
TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
@@ -301,7 +311,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
break;
default:
sprintf(emsg, "Missing needed %s tag", photoTag);
- return (0);
+ goto fail_return;
}
}
switch (img->photometric) {
@@ -309,7 +319,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
&red_orig, &green_orig, &blue_orig)) {
sprintf(emsg, "Missing required \"Colormap\" tag");
- return (0);
+ goto fail_return;
}
/* copy the colormaps so we can modify them */
@@ -319,7 +329,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
if( !img->redcmap || !img->greencmap || !img->bluecmap ) {
sprintf(emsg, "Out of memory for colormap copy");
- return (0);
+ goto fail_return;
}
_TIFFmemcpy( img->redcmap, red_orig, n_color * 2 );
@@ -338,7 +348,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
photoTag, img->photometric,
"Samples/pixel", img->samplesperpixel,
img->bitspersample);
- return (0);
+ goto fail_return;
}
break;
case PHOTOMETRIC_YCBCR:
@@ -371,7 +381,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
if (colorchannels < 3) {
sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
"Color channels", colorchannels);
- return (0);
+ goto fail_return;
}
break;
case PHOTOMETRIC_SEPARATED:
@@ -381,12 +391,12 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
if (inkset != INKSET_CMYK) {
sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
"InkSet", inkset);
- return (0);
+ goto fail_return;
}
if (img->samplesperpixel < 4) {
sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
"Samples/pixel", img->samplesperpixel);
- return (0);
+ goto fail_return;
}
}
break;
@@ -394,7 +404,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
if (compress != COMPRESSION_SGILOG) {
sprintf(emsg, "Sorry, LogL data must have %s=%d",
"Compression", COMPRESSION_SGILOG);
- return (0);
+ goto fail_return;
}
TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */
@@ -404,7 +414,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) {
sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
"Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
- return (0);
+ goto fail_return;
}
if (planarconfig != PLANARCONFIG_CONTIG) {
sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
@@ -420,30 +430,39 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
default:
sprintf(emsg, "Sorry, can not handle image with %s=%d",
photoTag, img->photometric);
- return (0);
+ goto fail_return;
}
img->Map = NULL;
img->BWmap = NULL;
img->PALmap = NULL;
img->ycbcr = NULL;
img->cielab = NULL;
+ img->UaToAa = NULL;
+ img->Bitdepth16To8 = NULL;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
img->isContig =
- !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1);
+ !(planarconfig == PLANARCONFIG_SEPARATE && img->samplesperpixel > 1);
if (img->isContig) {
if (!PickContigCase(img)) {
sprintf(emsg, "Sorry, can not handle image");
- return 0;
+ goto fail_return;
}
} else {
if (!PickSeparateCase(img)) {
sprintf(emsg, "Sorry, can not handle image");
- return 0;
+ goto fail_return;
}
}
return 1;
+
+ fail_return:
+ _TIFFfree( img->redcmap );
+ _TIFFfree( img->greencmap );
+ _TIFFfree( img->bluecmap );
+ img->redcmap = img->greencmap = img->bluecmap = NULL;
+ return 0;
}
int
@@ -572,7 +591,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
TIFF* tif = img->tif;
tileContigRoutine put = img->put.contig;
uint32 col, row, y, rowstoread;
- uint32 pos;
+ tmsize_t pos;
uint32 tw, th;
unsigned char* buf;
int32 fromskew, toskew;
@@ -581,7 +600,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif));
if (buf == 0) {
- TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer");
return (0);
}
_TIFFmemset(buf, 0, TIFFTileSize(tif));
@@ -604,14 +623,14 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
nrow = (row + rowstoread > h ? h - row : rowstoread);
for (col = 0; col < w; col += tw)
{
- if (TIFFReadTile(tif, buf, col+img->col_offset,
- row+img->row_offset, 0, 0) < 0 && img->stoponerr)
+ if (TIFFReadTile(tif, buf, col+img->col_offset,
+ row+img->row_offset, 0, 0)==(tmsize_t)(-1) && img->stoponerr)
{
ret = 0;
break;
}
- pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
+ pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
if (col + tw > w)
{
@@ -665,26 +684,33 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
TIFF* tif = img->tif;
tileSeparateRoutine put = img->put.separate;
uint32 col, row, y, rowstoread;
- uint32 pos;
+ tmsize_t pos;
uint32 tw, th;
unsigned char* buf;
unsigned char* p0;
unsigned char* p1;
unsigned char* p2;
unsigned char* pa;
- tsize_t tilesize;
+ tmsize_t tilesize;
+ tmsize_t bufsize;
int32 fromskew, toskew;
int alpha = img->alpha;
uint32 nrow;
int ret = 1, flip;
+ int colorchannels;
- tilesize = TIFFTileSize(tif);
- buf = (unsigned char*) _TIFFmalloc((alpha?4:3)*tilesize);
+ tilesize = TIFFTileSize(tif);
+ bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,tilesize);
+ if (bufsize == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate");
+ return (0);
+ }
+ buf = (unsigned char*) _TIFFmalloc(bufsize);
if (buf == 0) {
- TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer");
return (0);
}
- _TIFFmemset(buf, 0, (alpha?4:3)*tilesize);
+ _TIFFmemset(buf, 0, bufsize);
p0 = buf;
p1 = p0 + tilesize;
p2 = p1 + tilesize;
@@ -702,41 +728,58 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
toskew = -(int32)(tw - w);
}
+ switch( img->photometric )
+ {
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ case PHOTOMETRIC_PALETTE:
+ colorchannels = 1;
+ p2 = p1 = p0;
+ break;
+
+ default:
+ colorchannels = 3;
+ break;
+ }
+
for (row = 0; row < h; row += nrow)
{
rowstoread = th - (row + img->row_offset) % th;
nrow = (row + rowstoread > h ? h - row : rowstoread);
for (col = 0; col < w; col += tw)
{
- if (TIFFReadTile(tif, p0, col+img->col_offset,
- row+img->row_offset,0,0) < 0 && img->stoponerr)
+ if (TIFFReadTile(tif, p0, col+img->col_offset,
+ row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr)
{
ret = 0;
break;
}
- if (TIFFReadTile(tif, p1, col+img->col_offset,
- row+img->row_offset,0,1) < 0 && img->stoponerr)
+ if (colorchannels > 1
+ && TIFFReadTile(tif, p1, col+img->col_offset,
+ row+img->row_offset,0,1) == (tmsize_t)(-1)
+ && img->stoponerr)
{
ret = 0;
break;
}
- if (TIFFReadTile(tif, p2, col+img->col_offset,
- row+img->row_offset,0,2) < 0 && img->stoponerr)
+ if (colorchannels > 1
+ && TIFFReadTile(tif, p2, col+img->col_offset,
+ row+img->row_offset,0,2) == (tmsize_t)(-1)
+ && img->stoponerr)
{
ret = 0;
break;
}
- if (alpha)
- {
- if (TIFFReadTile(tif,pa,col+img->col_offset,
- row+img->row_offset,0,3) < 0 && img->stoponerr)
- {
- ret = 0;
- break;
- }
+ if (alpha
+ && TIFFReadTile(tif,pa,col+img->col_offset,
+ row+img->row_offset,0,colorchannels) == (tmsize_t)(-1)
+ && img->stoponerr)
+ {
+ ret = 0;
+ break;
}
- pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
+ pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
if (col + tw > w)
{
@@ -790,12 +833,12 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
TIFF* tif = img->tif;
tileContigRoutine put = img->put.contig;
uint32 row, y, nrow, nrowsub, rowstoread;
- uint32 pos;
+ tmsize_t pos;
unsigned char* buf;
uint32 rowsperstrip;
uint16 subsamplinghor,subsamplingver;
uint32 imagewidth = img->width;
- tsize_t scanline;
+ tmsize_t scanline;
int32 fromskew, toskew;
int ret = 1, flip;
@@ -817,7 +860,7 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver);
- scanline = TIFFNewScanlineSize(tif);
+ scanline = TIFFScanlineSize(tif);
fromskew = (w < imagewidth ? imagewidth - w : 0);
for (row = 0; row < h; row += nrow)
{
@@ -829,7 +872,7 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
if (TIFFReadEncodedStrip(tif,
TIFFComputeStrip(tif,row+img->row_offset, 0),
buf,
- ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline) < 0
+ ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline)==(tmsize_t)(-1)
&& img->stoponerr)
{
ret = 0;
@@ -875,22 +918,28 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
unsigned char *buf;
unsigned char *p0, *p1, *p2, *pa;
uint32 row, y, nrow, rowstoread;
- uint32 pos;
- tsize_t scanline;
+ tmsize_t pos;
+ tmsize_t scanline;
uint32 rowsperstrip, offset_row;
uint32 imagewidth = img->width;
- tsize_t stripsize;
+ tmsize_t stripsize;
+ tmsize_t bufsize;
int32 fromskew, toskew;
int alpha = img->alpha;
- int ret = 1, flip;
+ int ret = 1, flip, colorchannels;
- stripsize = TIFFStripSize(tif);
- p0 = buf = (unsigned char *)_TIFFmalloc((alpha?4:3)*stripsize);
+ stripsize = TIFFStripSize(tif);
+ bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,stripsize);
+ if (bufsize == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate");
+ return (0);
+ }
+ p0 = buf = (unsigned char *)_TIFFmalloc(bufsize);
if (buf == 0) {
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
return (0);
}
- _TIFFmemset(buf, 0, (alpha?4:3)*stripsize);
+ _TIFFmemset(buf, 0, bufsize);
p1 = p0 + stripsize;
p2 = p1 + stripsize;
pa = (alpha?(p2+stripsize):NULL);
@@ -905,8 +954,22 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
toskew = -(int32)(w - w);
}
+ switch( img->photometric )
+ {
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ case PHOTOMETRIC_PALETTE:
+ colorchannels = 1;
+ p2 = p1 = p0;
+ break;
+
+ default:
+ colorchannels = 3;
+ break;
+ }
+
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
- scanline = TIFFScanlineSize(tif);
+ scanline = TIFFScanlineSize(tif);
fromskew = (w < imagewidth ? imagewidth - w : 0);
for (row = 0; row < h; row += nrow)
{
@@ -914,21 +977,23 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
nrow = (row + rowstoread > h ? h - row : rowstoread);
offset_row = row + img->row_offset;
if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
- p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
+ p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1)
&& img->stoponerr)
{
ret = 0;
break;
}
- if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
- p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
+ if (colorchannels > 1
+ && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
+ p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1)
&& img->stoponerr)
{
ret = 0;
break;
}
- if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
- p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
+ if (colorchannels > 1
+ && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
+ p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1)
&& img->stoponerr)
{
ret = 0;
@@ -936,8 +1001,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
}
if (alpha)
{
- if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 3),
- pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, colorchannels),
+ pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1)
&& img->stoponerr)
{
ret = 0;
@@ -1036,6 +1101,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 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) \
@@ -1143,6 +1209,26 @@ DECLAREContigPutFunc(putgreytile)
}
/*
+ * 8-bit greyscale with associated alpha => colormap/RGBA
+ */
+DECLAREContigPutFunc(putagreytile)
+{
+ int samplesperpixel = img->samplesperpixel;
+ uint32** BWmap = img->BWmap;
+
+ (void) y;
+ while (h-- > 0) {
+ for (x = w; x-- > 0;)
+ {
+ *cp++ = BWmap[*pp][0] & (*(pp+1) << 24 | ~A1);
+ pp += samplesperpixel;
+ }
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
* 16-bit greyscale => colormap/RGB
*/
DECLAREContigPutFunc(put16bitbwtile)
@@ -1266,11 +1352,13 @@ DECLAREContigPutFunc(putRGBUAcontig8bittile)
fromskew *= samplesperpixel;
while (h-- > 0) {
uint32 r, g, b, a;
+ uint8* m;
for (x = w; x-- > 0;) {
a = pp[3];
- r = (a*pp[0] + 127) / 255;
- g = (a*pp[1] + 127) / 255;
- b = (a*pp[2] + 127) / 255;
+ m = img->UaToAa+(a<<8);
+ r = m[pp[0]];
+ g = m[pp[1]];
+ b = m[pp[2]];
*cp++ = PACK4(r,g,b,a);
pp += samplesperpixel;
}
@@ -1290,8 +1378,10 @@ DECLAREContigPutFunc(putRGBcontig16bittile)
fromskew *= samplesperpixel;
while (h-- > 0) {
for (x = w; x-- > 0;) {
- *cp++ = PACKW(wp[0],wp[1],wp[2]);
- wp += samplesperpixel;
+ *cp++ = PACK(img->Bitdepth16To8[wp[0]],
+ img->Bitdepth16To8[wp[1]],
+ img->Bitdepth16To8[wp[2]]);
+ wp += samplesperpixel;
}
cp += toskew;
wp += fromskew;
@@ -1310,8 +1400,11 @@ DECLAREContigPutFunc(putRGBAAcontig16bittile)
fromskew *= samplesperpixel;
while (h-- > 0) {
for (x = w; x-- > 0;) {
- *cp++ = PACKW4(wp[0],wp[1],wp[2],wp[3]);
- wp += samplesperpixel;
+ *cp++ = PACK4(img->Bitdepth16To8[wp[0]],
+ img->Bitdepth16To8[wp[1]],
+ img->Bitdepth16To8[wp[2]],
+ img->Bitdepth16To8[wp[3]]);
+ wp += samplesperpixel;
}
cp += toskew;
wp += fromskew;
@@ -1330,13 +1423,15 @@ DECLAREContigPutFunc(putRGBUAcontig16bittile)
fromskew *= samplesperpixel;
while (h-- > 0) {
uint32 r,g,b,a;
+ uint8* m;
for (x = w; x-- > 0;) {
- a = W2B(wp[3]);
- r = (a*W2B(wp[0]) + 127) / 255;
- g = (a*W2B(wp[1]) + 127) / 255;
- b = (a*W2B(wp[2]) + 127) / 255;
- *cp++ = PACK4(r,g,b,a);
- wp += samplesperpixel;
+ a = img->Bitdepth16To8[wp[3]];
+ m = img->UaToAa+(a<<8);
+ r = m[img->Bitdepth16To8[wp[0]]];
+ g = m[img->Bitdepth16To8[wp[1]]];
+ b = m[img->Bitdepth16To8[wp[2]]];
+ *cp++ = PACK4(r,g,b,a);
+ wp += samplesperpixel;
}
cp += toskew;
wp += fromskew;
@@ -1423,7 +1518,7 @@ DECLARESepPutFunc(putRGBseparate8bittile)
*/
DECLARESepPutFunc(putRGBAAseparate8bittile)
{
- (void) img; (void) x; (void) y;
+ (void) img; (void) x; (void) y;
while (h-- > 0) {
UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
SKEW4(r, g, b, a, fromskew);
@@ -1432,6 +1527,26 @@ DECLARESepPutFunc(putRGBAAseparate8bittile)
}
/*
+ * 8-bit unpacked CMYK samples => RGBA
+ */
+DECLARESepPutFunc(putCMYKseparate8bittile)
+{
+ (void) img; (void) y;
+ while (h-- > 0) {
+ uint32 rv, gv, bv, kv;
+ for (x = w; x-- > 0;) {
+ kv = 255 - *a++;
+ rv = (kv*(255-*r++))/255;
+ gv = (kv*(255-*g++))/255;
+ bv = (kv*(255-*b++))/255;
+ *cp++ = PACK4(rv,gv,bv,255);
+ }
+ SKEW4(r, g, b, a, fromskew);
+ cp += toskew;
+ }
+}
+
+/*
* 8-bit unpacked samples => RGBA w/ unassociated alpha
*/
DECLARESepPutFunc(putRGBUAseparate8bittile)
@@ -1439,11 +1554,13 @@ DECLARESepPutFunc(putRGBUAseparate8bittile)
(void) img; (void) y;
while (h-- > 0) {
uint32 rv, gv, bv, av;
+ uint8* m;
for (x = w; x-- > 0;) {
av = *a++;
- rv = (av* *r++ + 127) / 255;
- gv = (av* *g++ + 127) / 255;
- bv = (av* *b++ + 127) / 255;
+ m = img->UaToAa+(av<<8);
+ rv = m[*r++];
+ gv = m[*g++];
+ bv = m[*b++];
*cp++ = PACK4(rv,gv,bv,av);
}
SKEW4(r, g, b, a, fromskew);
@@ -1462,7 +1579,9 @@ DECLARESepPutFunc(putRGBseparate16bittile)
(void) img; (void) y; (void) a;
while (h-- > 0) {
for (x = 0; x < w; x++)
- *cp++ = PACKW(*wr++,*wg++,*wb++);
+ *cp++ = PACK(img->Bitdepth16To8[*wr++],
+ img->Bitdepth16To8[*wg++],
+ img->Bitdepth16To8[*wb++]);
SKEW(wr, wg, wb, fromskew);
cp += toskew;
}
@@ -1480,7 +1599,10 @@ DECLARESepPutFunc(putRGBAAseparate16bittile)
(void) img; (void) y;
while (h-- > 0) {
for (x = 0; x < w; x++)
- *cp++ = PACKW4(*wr++,*wg++,*wb++,*wa++);
+ *cp++ = PACK4(img->Bitdepth16To8[*wr++],
+ img->Bitdepth16To8[*wg++],
+ img->Bitdepth16To8[*wb++],
+ img->Bitdepth16To8[*wa++]);
SKEW4(wr, wg, wb, wa, fromskew);
cp += toskew;
}
@@ -1498,12 +1620,14 @@ DECLARESepPutFunc(putRGBUAseparate16bittile)
(void) img; (void) y;
while (h-- > 0) {
uint32 r,g,b,a;
+ uint8* m;
for (x = w; x-- > 0;) {
- a = W2B(*wa++);
- r = (a*W2B(*wr++) + 127) / 255;
- g = (a*W2B(*wg++) + 127) / 255;
- b = (a*W2B(*wb++) + 127) / 255;
- *cp++ = PACK4(r,g,b,a);
+ a = img->Bitdepth16To8[*wa++];
+ m = img->UaToAa+(a<<8);
+ r = m[img->Bitdepth16To8[*wr++]];
+ g = m[img->Bitdepth16To8[*wg++]];
+ b = m[img->Bitdepth16To8[*wb++]];
+ *cp++ = PACK4(r,g,b,a);
}
SKEW4(wr, wg, wb, wa, fromskew);
cp += toskew;
@@ -1846,6 +1970,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
{
uint32* cp2;
+ int32 incr = 2*toskew+w;
(void) y;
fromskew = (fromskew / 2) * 6;
cp2 = cp+w+toskew;
@@ -1872,8 +1997,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
cp2 ++ ;
pp += 6;
}
- cp += toskew*2+w;
- cp2 += toskew*2+w;
+ cp += incr;
+ cp2 += incr;
pp += fromskew;
h-=2;
}
@@ -1939,6 +2064,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
{
uint32* cp2;
+ int32 incr = 2*toskew+w;
(void) y;
fromskew = (fromskew / 2) * 4;
cp2 = cp+w+toskew;
@@ -1953,8 +2079,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
cp2 ++;
pp += 4;
} while (--x);
- cp += toskew*2+w;
- cp2 += toskew*2+w;
+ cp += incr;
+ cp2 += incr;
pp += fromskew;
h-=2;
}
@@ -2016,13 +2142,13 @@ DECLARESepPutFunc(putseparate8bitYCbCr11tile)
static int
initYCbCrConversion(TIFFRGBAImage* img)
{
- static char module[] = "initYCbCrConversion";
+ static const char module[] = "initYCbCrConversion";
float *luma, *refBlackWhite;
if (img->ycbcr == NULL) {
img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc(
- TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))
+ TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long))
+ 4*256*sizeof (TIFFRGBValue)
+ 2*256*sizeof (int)
+ 3*256*sizeof (int32)
@@ -2045,7 +2171,7 @@ initYCbCrConversion(TIFFRGBAImage* img)
static tileContigRoutine
initCIELabConversion(TIFFRGBAImage* img)
{
- static char module[] = "initCIELabConversion";
+ static const char module[] = "initCIELabConversion";
float *whitePoint;
float refWhite[3];
@@ -2325,23 +2451,28 @@ PickContigCase(TIFFRGBAImage* img)
img->put.contig = putRGBAAcontig8bittile;
else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
{
- img->put.contig = putRGBUAcontig8bittile;
+ if (BuildMapUaToAa(img))
+ img->put.contig = putRGBUAcontig8bittile;
}
else
- img->put.contig = putRGBcontig8bittile;
+ img->put.contig = putRGBcontig8bittile;
break;
case 16:
if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
{
- img->put.contig = putRGBAAcontig16bittile;
+ if (BuildMapBitdepth16To8(img))
+ img->put.contig = putRGBAAcontig16bittile;
}
else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
{
- img->put.contig = putRGBUAcontig16bittile;
+ if (BuildMapBitdepth16To8(img) &&
+ BuildMapUaToAa(img))
+ img->put.contig = putRGBUAcontig16bittile;
}
else
{
- img->put.contig = putRGBcontig16bittile;
+ if (BuildMapBitdepth16To8(img))
+ img->put.contig = putRGBcontig16bittile;
}
break;
}
@@ -2382,7 +2513,10 @@ PickContigCase(TIFFRGBAImage* img)
img->put.contig = put16bitbwtile;
break;
case 8:
- img->put.contig = putgreytile;
+ if (img->alpha && img->samplesperpixel == 2)
+ img->put.contig = putagreytile;
+ else
+ img->put.contig = putgreytile;
break;
case 4:
img->put.contig = put4bitbwtile;
@@ -2397,7 +2531,7 @@ PickContigCase(TIFFRGBAImage* img)
}
break;
case PHOTOMETRIC_YCBCR:
- if (img->bitspersample == 8)
+ if ((img->bitspersample==8) && (img->samplesperpixel==3))
{
if (initYCbCrConversion(img)!=0)
{
@@ -2461,54 +2595,111 @@ PickSeparateCase(TIFFRGBAImage* img)
img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
img->put.separate = NULL;
switch (img->photometric) {
- case PHOTOMETRIC_RGB:
- switch (img->bitspersample) {
- case 8:
- if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
- img->put.separate = putRGBAAseparate8bittile;
- else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
- {
- img->put.separate = putRGBUAseparate8bittile;
- }
- else
- img->put.separate = putRGBseparate8bittile;
- break;
- case 16:
- if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
- {
- img->put.separate = putRGBAAseparate16bittile;
- }
- else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
- {
- img->put.separate = putRGBUAseparate16bittile;
- }
- else
- {
- img->put.separate = putRGBseparate16bittile;
- }
- break;
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ /* greyscale images processed pretty much as RGB by gtTileSeparate */
+ case PHOTOMETRIC_RGB:
+ switch (img->bitspersample) {
+ case 8:
+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+ img->put.separate = putRGBAAseparate8bittile;
+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+ {
+ if (BuildMapUaToAa(img))
+ img->put.separate = putRGBUAseparate8bittile;
}
+ else
+ img->put.separate = putRGBseparate8bittile;
break;
- case PHOTOMETRIC_YCBCR:
- if ((img->bitspersample==8) && (img->samplesperpixel==3))
+ case 16:
+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
{
- 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 */
- }
- }
+ if (BuildMapBitdepth16To8(img))
+ img->put.separate = putRGBAAseparate16bittile;
+ }
+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+ {
+ if (BuildMapBitdepth16To8(img) &&
+ BuildMapUaToAa(img))
+ img->put.separate = putRGBUAseparate16bittile;
+ }
+ else
+ {
+ if (BuildMapBitdepth16To8(img))
+ img->put.separate = putRGBseparate16bittile;
}
break;
+ }
+ break;
+ case PHOTOMETRIC_SEPARATED:
+ if (img->bitspersample == 8 && img->samplesperpixel == 4)
+ {
+ img->alpha = 1; // Not alpha, but seems like the only way to get 4th band
+ img->put.separate = putCMYKseparate8bittile;
+ }
+ 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));
}
+static int
+BuildMapUaToAa(TIFFRGBAImage* img)
+{
+ static const char module[]="BuildMapUaToAa";
+ uint8* m;
+ uint16 na,nv;
+ assert(img->UaToAa==NULL);
+ img->UaToAa=_TIFFmalloc(65536);
+ if (img->UaToAa==NULL)
+ {
+ TIFFErrorExt(img->tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ m=img->UaToAa;
+ for (na=0; na<256; na++)
+ {
+ for (nv=0; nv<256; nv++)
+ *m++=(nv*na+127)/255;
+ }
+ return(1);
+}
+
+static int
+BuildMapBitdepth16To8(TIFFRGBAImage* img)
+{
+ static const char module[]="BuildMapBitdepth16To8";
+ uint8* m;
+ uint32 n;
+ assert(img->Bitdepth16To8==NULL);
+ img->Bitdepth16To8=_TIFFmalloc(65536);
+ if (img->Bitdepth16To8==NULL)
+ {
+ TIFFErrorExt(img->tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ m=img->Bitdepth16To8;
+ for (n=0; n<65536; n++)
+ *m++=(n+128)/257;
+ return(1);
+}
+
+
/*
* Read a whole strip off data from the file, and convert to RGBA form.
* If this is the last strip, then it will only contain the portion of
@@ -2667,3 +2858,10 @@ TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster)
}
/* vim: set ts=8 sts=8 sw=8 noet: */
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * fill-column: 78
+ * End:
+ */