void _TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) { (void) tif; if (*(int32*) tw < 1) *tw = 256; if (*(int32*) th < 1) *th = 256; /* roundup to a multiple of 16 per the spec */ if (*tw & 0xf) *tw = TIFFroundup(*tw, 16); if (*th & 0xf) *th = TIFFroundup(*th, 16); }
/* * Compute the # bytes in a variable height, row-aligned strip. */ tsize_t TIFFVStripSize(TIFF* tif, uint32 nrows) { TIFFDirectory *td = &tif->tif_dir; if (nrows == (uint32) -1) nrows = td->td_imagelength; #ifdef YCBCR_SUPPORT if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_photometric == PHOTOMETRIC_YCBCR && !isUpSampled(tif)) { /* * Packed YCbCr data contain one Cb+Cr for every * HorizontalSampling*VerticalSampling Y values. * Must also roundup width and height when calculating * since images that are not a multiple of the * horizontal/vertical subsampling area include * YCbCr data for the extended image. */ tsize_t w = TIFFroundup(td->td_imagewidth, td->td_ycbcrsubsampling[0]); tsize_t scanline = TIFFhowmany(w*td->td_bitspersample, 8); tsize_t samplingarea = td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1]; nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]); /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ return ((tsize_t) (nrows*scanline + 2*(nrows*scanline / samplingarea))); } else #endif return ((tsize_t)(nrows * TIFFScanlineSize(tif))); }
/* * Compute the # bytes in a variable height, row-aligned strip. */ tsize_t TIFFVStripSize(TIFF* tif, uint32 nrows) { TIFFDirectory *td = &tif->tif_dir; if (nrows == (uint32) -1) nrows = td->td_imagelength; if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_photometric == PHOTOMETRIC_YCBCR && !isUpSampled(tif)) { /* * Packed YCbCr data contain one Cb+Cr for every * HorizontalSampling*VerticalSampling Y values. * Must also roundup width and height when calculating * since images that are not a multiple of the * horizontal/vertical subsampling area include * YCbCr data for the extended image. */ uint16 ycbcrsubsampling[2]; tsize_t w, scanline, samplingarea; ycbcrsubsampling[0] = 0; ycbcrsubsampling[1] = 0; TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, ycbcrsubsampling + 0, ycbcrsubsampling + 1 ); /* make sure we dont get division by 0 due to bad tiffs */ if (!ycbcrsubsampling[0]) ycbcrsubsampling[0] = 1; if (!ycbcrsubsampling[1]) ycbcrsubsampling[1] = 1; samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1]; if (samplingarea == 0) { _TIFFError(tif, tif->tif_name, "Invalid YCbCr subsampling"); return 0; } w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]); scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample, "TIFFVStripSize")); nrows = TIFFroundup(nrows, ycbcrsubsampling[1]); /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ scanline = multiply(tif, nrows, scanline, "TIFFVStripSize"); return ((tsize_t) summarize(tif, scanline, multiply(tif, 2, scanline / samplingarea, "TIFFVStripSize"), "TIFFVStripSize")); } else return ((tsize_t) multiply(tif, nrows, TIFFScanlineSize(tif), "TIFFVStripSize")); }
/* * Setup the raw data buffer in preparation for * reading a strip of raw data. If the buffer * is specified as zero, then a buffer of appropriate * size is allocated by the library. Otherwise, * the client must guarantee that the buffer is * large enough to hold any individual strip of * raw data. */ int TIFFReadBufferSetup(TIFF* tif, tdata_t bp, tsize_t size) { static const char module[] = "TIFFReadBufferSetup"; if (tif->tif_rawdata) { if (tif->tif_flags & TIFF_MYBUFFER) _TIFFfree(tif->tif_rawdata); tif->tif_rawdata = NULL; } if (bp) { tif->tif_rawdatasize = size; tif->tif_rawdata = (tidata_t) bp; tif->tif_flags &= ~TIFF_MYBUFFER; } else { tif->tif_rawdatasize = TIFFroundup(size, 1024); tif->tif_rawdata = (tidata_t) _TIFFmalloc(tif->tif_rawdatasize); tif->tif_flags |= TIFF_MYBUFFER; } if (tif->tif_rawdata == NULL) { TIFFError(module, "%s: No space for data buffer at scanline %ld", tif->tif_name, (long) tif->tif_row); tif->tif_rawdatasize = 0; return (0); } return (1); }
/* * Compute the # bytes in a variable length, row-aligned tile. */ tsize_t TIFFVTileSize(TIFF* tif, uint32 nrows) { TIFFDirectory *td = &tif->tif_dir; tsize_t tilesize; if (td->td_tilelength == 0 || td->td_tilewidth == 0 || td->td_tiledepth == 0) return ((tsize_t) 0); if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_photometric == PHOTOMETRIC_YCBCR && !isUpSampled(tif)) { /* * Packed YCbCr data contain one Cb+Cr for every * HorizontalSampling*VerticalSampling Y values. * Must also roundup width and height when calculating * since images that are not a multiple of the * horizontal/vertical subsampling area include * YCbCr data for the extended image. */ tsize_t w = TIFFroundup(td->td_tilewidth, td->td_ycbcrsubsampling[0]); tsize_t rowsize = TIFFhowmany8(multiply(tif, w, td->td_bitspersample, "TIFFVTileSize")); tsize_t samplingarea = td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1]; if (samplingarea == 0) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Invalid YCbCr subsampling"); return 0; } nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]); /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ tilesize = multiply(tif, nrows, rowsize, "TIFFVTileSize"); tilesize = summarize(tif, tilesize, multiply(tif, 2, tilesize / samplingarea, "TIFFVTileSize"), "TIFFVTileSize"); } else tilesize = multiply(tif, nrows, TIFFTileRowSize(tif), "TIFFVTileSize"); return ((tsize_t) multiply(tif, tilesize, td->td_tiledepth, "TIFFVTileSize")); }
/* * 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] = 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; } } }
/* * Return the number of bytes to read/write in a call to * one of the scanline-oriented i/o routines. Note that * this number may be 1/samples-per-pixel if data is * stored as separate planes. */ tsize_t TIFFScanlineSize(TIFF* tif) { TIFFDirectory *td = &tif->tif_dir; tsize_t scanline; if (td->td_planarconfig == PLANARCONFIG_CONTIG) { if (td->td_photometric == PHOTOMETRIC_YCBCR && !isUpSampled(tif)) { uint16 ycbcrsubsampling[2]; TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING, ycbcrsubsampling + 0, ycbcrsubsampling + 1); if (ycbcrsubsampling[0] == 0) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Invalid YCbCr subsampling"); return 0; } scanline = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]); scanline = TIFFhowmany8(multiply(tif, scanline, td->td_bitspersample, "TIFFScanlineSize")); return ((tsize_t) summarize(tif, scanline, multiply(tif, 2, scanline / ycbcrsubsampling[0], "TIFFVStripSize"), "TIFFVStripSize")); } else { scanline = multiply(tif, td->td_imagewidth, td->td_samplesperpixel, "TIFFScanlineSize"); } } else scanline = td->td_imagewidth; return ((tsize_t) TIFFhowmany8(multiply(tif, scanline, td->td_bitspersample, "TIFFScanlineSize"))); }
static tileContigRoutine initYCbCrConversion(TIFFRGBAImage* img) { 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); } 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); }
/* * Read the specified tile and setup for decoding. * The data buffer is expanded, as necessary, to * hold the tile's data. */ int TIFFFillTile(TIFF* tif, ttile_t tile) { static const char module[] = "TIFFFillTile"; TIFFDirectory *td = &tif->tif_dir; tsize_t bytecount; bytecount = td->td_stripbytecount[tile]; if (bytecount <= 0) { TIFFError(tif->tif_name, "%lu: Invalid tile byte count, tile %lu", (unsigned long) bytecount, (unsigned long) tile); return (0); } if (isMapped(tif) && (isFillOrder(tif, td->td_fillorder) || (tif->tif_flags & TIFF_NOBITREV))) { /* * The image is mapped into memory and we either don't * need to flip bits or the compression routine is going * to handle this operation itself. In this case, avoid * copying the raw data and instead just reference the * data from the memory mapped file image. This assumes * that the decompression routines do not modify the * contents of the raw data buffer (if they try to, * the application will get a fault since the file is * mapped read-only). */ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) _TIFFfree(tif->tif_rawdata); tif->tif_flags &= ~TIFF_MYBUFFER; if ( td->td_stripoffset[tile] + bytecount > tif->tif_size) { tif->tif_curtile = NOTILE; return (0); } tif->tif_rawdatasize = bytecount; tif->tif_rawdata = tif->tif_base + td->td_stripoffset[tile]; } else { /* * Expand raw data buffer, if needed, to * hold data tile coming from file * (perhaps should set upper bound on * the size of a buffer we'll use?). */ if (bytecount > tif->tif_rawdatasize) { tif->tif_curtile = NOTILE; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFError(module, "%s: Data buffer too small to hold tile %ld", tif->tif_name, (long) tile); return (0); } if (!TIFFReadBufferSetup(tif, 0, TIFFroundup(bytecount, 1024))) return (0); } if (TIFFReadRawTile1(tif, tile, (unsigned char *)tif->tif_rawdata, bytecount, module) != bytecount) return (0); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, bytecount); } return (TIFFStartTile(tif, tile)); }
/* * Read the specified strip and setup for decoding. * The data buffer is expanded, as necessary, to * hold the strip's data. */ int TIFFFillStrip(TIFF* tif, tstrip_t strip) { static const char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; tsize_t bytecount; bytecount = td->td_stripbytecount[strip]; if (bytecount <= 0) { TIFFError(tif->tif_name, "%lu: Invalid strip byte count, strip %lu", (u_long) bytecount, (u_long) strip); return (0); } if (isMapped(tif) && (isFillOrder(tif, td->td_fillorder) || (tif->tif_flags & TIFF_NOBITREV))) { /* * The image is mapped into memory and we either don't * need to flip bits or the compression routine is going * to handle this operation itself. In this case, avoid * copying the raw data and instead just reference the * data from the memory mapped file image. This assumes * that the decompression routines do not modify the * contents of the raw data buffer (if they try to, * the application will get a fault since the file is * mapped read-only). */ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) _TIFFfree(tif->tif_rawdata); tif->tif_flags &= ~TIFF_MYBUFFER; if ( td->td_stripoffset[strip] + bytecount > tif->tif_size) { /* * This error message might seem strange, but it's * what would happen if a read were done instead. */ TIFFError(module, "%s: Read error on strip %lu; got %lu bytes, expected %lu", tif->tif_name, (u_long) strip, (u_long) tif->tif_size - td->td_stripoffset[strip], (u_long) bytecount); tif->tif_curstrip = NOSTRIP; return (0); } tif->tif_rawdatasize = bytecount; tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip]; } else { /* * Expand raw data buffer, if needed, to * hold data strip coming from file * (perhaps should set upper bound on * the size of a buffer we'll use?). */ if (bytecount > tif->tif_rawdatasize) { tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFError(module, "%s: Data buffer too small to hold strip %lu", tif->tif_name, (u_long) strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, TIFFroundup(bytecount, 1024))) return (0); } if (TIFFReadRawStrip1(tif, strip, (u_char *)tif->tif_rawdata, bytecount, module) != bytecount) return (0); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, bytecount); } return (TIFFStartStrip(tif, strip)); }
/* * Read the specified tile and setup for decoding. The data buffer is * expanded, as necessary, to hold the tile's data. */ int TIFFFillTile(TIFF* tif, ttile_t tile) { static const char module[] = "TIFFFillTile"; TIFFDirectory *td = &tif->tif_dir; if ((tif->tif_flags&TIFF_NOREADRAW)==0) { /* * FIXME: butecount should have tsize_t type, but for now * libtiff defines tsize_t as a signed 32-bit integer and we * are losing ability to read arrays larger than 2^31 bytes. * So we are using uint32 instead of tsize_t here. */ uint32 bytecount = td->td_stripbytecount[tile]; if (bytecount <= 0) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%lu: Invalid tile byte count, tile %lu", (unsigned long) bytecount, (unsigned long) tile); return (0); } if (isMapped(tif) && (isFillOrder(tif, td->td_fillorder) || (tif->tif_flags & TIFF_NOBITREV))) { /* * The image is mapped into memory and we either don't * need to flip bits or the compression routine is * going to handle this operation itself. In this * case, avoid copying the raw data and instead just * reference the data from the memory mapped file * image. This assumes that the decompression * routines do not modify the contents of the raw data * buffer (if they try to, the application will get a * fault since the file is mapped read-only). */ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) _TIFFfree(tif->tif_rawdata); tif->tif_flags &= ~TIFF_MYBUFFER; /* * We must check for overflow, potentially causing * an OOB read. Instead of simple * * td->td_stripoffset[tile]+bytecount > tif->tif_size * * comparison (which can overflow) we do the following * two comparisons: */ if (bytecount > tif->tif_size || td->td_stripoffset[tile] > tif->tif_size - bytecount) { tif->tif_curtile = NOTILE; return (0); } tif->tif_rawdatasize = bytecount; tif->tif_rawdata = tif->tif_base + td->td_stripoffset[tile]; } else { /* * Expand raw data buffer, if needed, to hold data * tile coming from file (perhaps should set upper * bound on the size of a buffer we'll use?). */ if (bytecount > (uint32)tif->tif_rawdatasize) { tif->tif_curtile = NOTILE; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Data buffer too small to hold tile %ld", tif->tif_name, (long) tile); return (0); } if (!TIFFReadBufferSetup(tif, 0, TIFFroundup(bytecount, 1024))) return (0); } if ((uint32)TIFFReadRawTile1(tif, tile, (unsigned char *)tif->tif_rawdata, bytecount, module) != bytecount) return (0); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, bytecount); } } return (TIFFStartTile(tif, tile)); }
/* * Compute the # bytes in a variable height, row-aligned strip. */ tsize_t TIFFVStripSize(TIFF* tif, uint32 nrows) { TIFFDirectory *td = &tif->tif_dir; uint32 stripsize; if (nrows == (uint32) -1) nrows = td->td_imagelength; if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_photometric == PHOTOMETRIC_YCBCR && !isUpSampled(tif)) { /* * Packed YCbCr data contain one Cb+Cr for every * HorizontalSampling*VerticalSampling Y values. * Must also roundup width and height when calculating * since images that are not a multiple of the * horizontal/vertical subsampling area include * YCbCr data for the extended image. */ uint16 ycbcrsubsampling[2]; uint32 w, scanline, samplingarea; TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, ycbcrsubsampling + 0, ycbcrsubsampling + 1); samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1]; if (samplingarea == 0) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Invalid YCbCr subsampling"); return 0; } w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]); scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample, "TIFFVStripSize")); nrows = TIFFroundup(nrows, ycbcrsubsampling[1]); /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ scanline = multiply(tif, nrows, scanline, "TIFFVStripSize"); /* a zero anywhere in here means overflow, must return zero */ if (scanline > 0) { uint32 extra = multiply(tif, 2, scanline / samplingarea, "TIFFVStripSize"); if (extra > 0) stripsize = summarize(tif, scanline, extra, "TIFFVStripSize"); else stripsize = 0; } else stripsize = 0; } else stripsize = multiply(tif, nrows, TIFFScanlineSize(tif), "TIFFVStripSize"); /* Because tsize_t is signed, we might have conversion overflow */ if (((tsize_t) stripsize) < 0) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", "TIFFVStripSize"); stripsize = 0; } return (tsize_t) stripsize; }