diff options
| author | Aaron Boxer <boxerab@gmail.com> | 2014-12-09 14:33:38 -0500 |
|---|---|---|
| committer | Antonin Descampe <antonin@gmail.com> | 2015-07-03 19:19:17 +0200 |
| commit | 6b0a8e3a0fc0dd18b01a8810b6867d6da8fa79e4 (patch) | |
| tree | 4e34a268505357dad2498cf97580e72948cc4c1a /thirdparty/libtiff/tif_getimage.c | |
| parent | eadfad7a5014e0bf2a56667194af976fc9fc987c (diff) | |
upgraded to libtiff v4.0.4
Diffstat (limited to 'thirdparty/libtiff/tif_getimage.c')
| -rw-r--r-- | thirdparty/libtiff/tif_getimage.c | 325 |
1 files changed, 224 insertions, 101 deletions
diff --git a/thirdparty/libtiff/tif_getimage.c b/thirdparty/libtiff/tif_getimage.c index 6a09b4d2..f49b73fd 100644 --- a/thirdparty/libtiff/tif_getimage.c +++ b/thirdparty/libtiff/tif_getimage.c @@ -1,4 +1,4 @@ -/* $Id: tif_getimage.c,v 1.78 2011-02-23 21:46:09 fwarmerdam Exp $ */ +/* $Id: tif_getimage.c,v 1.90 2015-06-17 01:34:08 bfriesen Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler @@ -182,8 +182,23 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024]) "Planarconfiguration", td->td_planarconfig); return (0); } + if( td->td_samplesperpixel != 3 ) + { + sprintf(emsg, + "Sorry, can not handle image with %s=%d", + "Samples/pixel", td->td_samplesperpixel); + return 0; + } break; case PHOTOMETRIC_CIELAB: + if( td->td_samplesperpixel != 3 || td->td_bitspersample != 8 ) + { + sprintf(emsg, + "Sorry, can not handle image with %s=%d and %s=%d", + "Samples/pixel", td->td_samplesperpixel, + "Bits/sample", td->td_bitspersample); + return 0; + } break; default: sprintf(emsg, "Sorry, can not handle image with %s=%d", @@ -597,6 +612,10 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) int32 fromskew, toskew; uint32 nrow; int ret = 1, flip; + uint32 this_tw, tocol; + int32 this_toskew, leftmost_toskew; + int32 leftmost_fromskew; + uint32 leftmost_tw; buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif)); if (buf == 0) { @@ -617,37 +636,50 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) toskew = -(int32)(tw - w); } + /* + * Leftmost tile is clipped on left side if col_offset > 0. + */ + leftmost_fromskew = img->col_offset % tw; + leftmost_tw = tw - leftmost_fromskew; + leftmost_toskew = toskew + leftmost_fromskew; 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) + fromskew = leftmost_fromskew; + this_tw = leftmost_tw; + this_toskew = leftmost_toskew; + tocol = 0; + col = img->col_offset; + while (tocol < w) { - if (TIFFReadTile(tif, buf, col+img->col_offset, + if (TIFFReadTile(tif, buf, col, row+img->row_offset, 0, 0)==(tmsize_t)(-1) && img->stoponerr) { ret = 0; break; } - - pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); - - if (col + tw > w) - { - /* - * Tile is clipped horizontally. Calculate - * visible portion and skewing factors. - */ - uint32 npix = w - col; - fromskew = tw - npix; - (*put)(img, raster+y*w+col, col, y, - npix, nrow, fromskew, toskew + fromskew, buf + pos); - } - else - { - (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos); - } - } + pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \ + ((tmsize_t) fromskew * img->samplesperpixel); + if (tocol + this_tw > w) + { + /* + * Rightmost tile is clipped on right side. + */ + fromskew = tw - (w - tocol); + this_tw = tw - fromskew; + this_toskew = toskew + fromskew; + } + (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, buf + pos); + tocol += this_tw; + col += this_tw; + /* + * After the leftmost tile, tiles are no longer clipped on left side. + */ + fromskew = 0; + this_tw = tw; + this_toskew = toskew; + } y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); } @@ -692,19 +724,29 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) unsigned char* p2; unsigned char* pa; tmsize_t tilesize; + tmsize_t bufsize; int32 fromskew, toskew; int alpha = img->alpha; uint32 nrow; int ret = 1, flip; int colorchannels; + uint32 this_tw, tocol; + int32 this_toskew, leftmost_toskew; + int32 leftmost_fromskew; + uint32 leftmost_tw; tilesize = TIFFTileSize(tif); - buf = (unsigned char*) _TIFFmalloc((alpha?4:3)*tilesize); + 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), "%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; @@ -736,20 +778,31 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) break; } + /* + * Leftmost tile is clipped on left side if col_offset > 0. + */ + leftmost_fromskew = img->col_offset % tw; + leftmost_tw = tw - leftmost_fromskew; + leftmost_toskew = toskew + leftmost_fromskew; 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) + fromskew = leftmost_fromskew; + this_tw = leftmost_tw; + this_toskew = leftmost_toskew; + tocol = 0; + col = img->col_offset; + while (tocol < w) { - if (TIFFReadTile(tif, p0, col+img->col_offset, + if (TIFFReadTile(tif, p0, col, row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr) { ret = 0; break; } if (colorchannels > 1 - && TIFFReadTile(tif, p1, col+img->col_offset, + && TIFFReadTile(tif, p1, col, row+img->row_offset,0,1) == (tmsize_t)(-1) && img->stoponerr) { @@ -757,7 +810,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) break; } if (colorchannels > 1 - && TIFFReadTile(tif, p2, col+img->col_offset, + && TIFFReadTile(tif, p2, col, row+img->row_offset,0,2) == (tmsize_t)(-1) && img->stoponerr) { @@ -765,7 +818,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) break; } if (alpha - && TIFFReadTile(tif,pa,col+img->col_offset, + && TIFFReadTile(tif,pa,col, row+img->row_offset,0,colorchannels) == (tmsize_t)(-1) && img->stoponerr) { @@ -773,23 +826,27 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) break; } - pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); - - if (col + tw > w) + pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \ + ((tmsize_t) fromskew * img->samplesperpixel); + if (tocol + this_tw > w) { /* - * Tile is clipped horizontally. Calculate - * visible portion and skewing factors. + * Rightmost tile is clipped on right side. */ - uint32 npix = w - col; - fromskew = tw - npix; - (*put)(img, raster+y*w+col, col, y, - npix, nrow, fromskew, toskew + fromskew, - p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); - } else { - (*put)(img, raster+y*w+col, col, y, - tw, nrow, 0, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); + fromskew = tw - (w - tocol); + this_tw = tw - fromskew; + this_toskew = toskew + fromskew; } + (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, \ + p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); + tocol += this_tw; + col += this_tw; + /* + * After the leftmost tile, tiles are no longer clipped on left side. + */ + fromskew = 0; + this_tw = tw; + this_toskew = toskew; } y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow); @@ -836,6 +893,12 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) int32 fromskew, toskew; int ret = 1, flip; + TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver); + if( subsamplingver == 0 ) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Invalid vertical YCbCr subsampling"); + return (0); + } + buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif)); if (buf == 0) { TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); @@ -853,7 +916,7 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) } TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); - TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver); + scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0); for (row = 0; row < h; row += nrow) @@ -873,7 +936,8 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) break; } - pos = ((row + img->row_offset) % rowsperstrip) * scanline; + pos = ((row + img->row_offset) % rowsperstrip) * scanline + \ + ((tmsize_t) img->col_offset * img->samplesperpixel); (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos); y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); } @@ -917,17 +981,23 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) uint32 rowsperstrip, offset_row; uint32 imagewidth = img->width; tmsize_t stripsize; + tmsize_t bufsize; int32 fromskew, toskew; int alpha = img->alpha; int ret = 1, flip, colorchannels; stripsize = TIFFStripSize(tif); - p0 = buf = (unsigned char *)_TIFFmalloc((alpha?4:3)*stripsize); + 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); @@ -998,7 +1068,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) } } - pos = ((row + img->row_offset) % rowsperstrip) * scanline; + pos = ((row + img->row_offset) % rowsperstrip) * scanline + \ + ((tmsize_t) img->col_offset * img->samplesperpixel); (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); @@ -1197,6 +1268,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) @@ -1495,6 +1586,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) @@ -1800,7 +1911,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile) (void) y; fromskew = (fromskew * 10) / 4; - if ((h & 3) == 0 && (w & 1) == 0) { + if ((w & 3) == 0 && (h & 1) == 0) { for (; h >= 2; h -= 2) { x = w>>2; do { @@ -1877,7 +1988,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile) /* XXX adjust fromskew */ do { x = w>>2; - do { + while(x>0) { int32 Cb = pp[4]; int32 Cr = pp[5]; @@ -1888,7 +1999,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile) cp += 4; pp += 6; - } while (--x); + x--; + } if( (w&3) != 0 ) { @@ -1979,7 +2091,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr21tile) fromskew = (fromskew * 4) / 2; do { x = w>>1; - do { + while(x>0) { int32 Cb = pp[2]; int32 Cr = pp[3]; @@ -1988,7 +2100,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr21tile) cp += 2; pp += 4; - } while (--x); + x --; + } if( (w&1) != 0 ) { @@ -2461,7 +2574,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; @@ -2486,7 +2602,7 @@ PickContigCase(TIFFRGBAImage* img) * 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 + * Joris: added support for the [1,2] case, nonetheless, to accommodate * some OJPEG files */ uint16 SubsamplingHor; @@ -2540,58 +2656,65 @@ PickSeparateCase(TIFFRGBAImage* img) img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate; img->put.separate = NULL; switch (img->photometric) { - 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 16: - if (img->alpha == EXTRASAMPLE_ASSOCALPHA) - { - 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; + 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)); } |
