/* * 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))); }
/* * 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. * The ScanlineSize in case of YCbCrSubsampling is defined as the * strip size divided by the strip height, i.e. the size of a pack of vertical * subsampling lines divided by vertical subsampling. It should thus make * sense when multiplied by a multiple of vertical subsampling. */ uint64 TIFFScanlineSize64(TIFF* tif) { static const char module[] = "TIFFScanlineSize64"; TIFFDirectory *td = &tif->tif_dir; uint64 scanline_size; if (td->td_planarconfig==PLANARCONFIG_CONTIG) { if ((td->td_photometric==PHOTOMETRIC_YCBCR)&& (td->td_samplesperpixel==3)&& (!isUpSampled(tif))) { uint16 ycbcrsubsampling[2]; uint16 samplingblock_samples; uint32 samplingblocks_hor; uint64 samplingrow_samples; uint64 samplingrow_size; if(td->td_samplesperpixel!=3) { TIFFErrorExt(tif->tif_clientdata,module, "Invalid td_samplesperpixel value"); return 0; } TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING, ycbcrsubsampling+0, ycbcrsubsampling+1); if (((ycbcrsubsampling[0]!=1)&&(ycbcrsubsampling[0]!=2)&&(ycbcrsubsampling[0]!=4)) || ((ycbcrsubsampling[1]!=1)&&(ycbcrsubsampling[1]!=2)&&(ycbcrsubsampling[1]!=4))) { TIFFErrorExt(tif->tif_clientdata,module, "Invalid YCbCr subsampling"); return 0; } samplingblock_samples = ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; samplingblocks_hor = TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]); samplingrow_samples = _TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); samplingrow_size = TIFFhowmany_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module),8); /* IMLIB scanline_size = (samplingrow_size/ycbcrsubsampling[1]); See tif_jpeg.c */ scanline_size = samplingrow_size; } else { uint64 scanline_samples; scanline_samples=_TIFFMultiply64(tif,td->td_imagewidth,td->td_samplesperpixel,module); scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,scanline_samples,td->td_bitspersample,module),8); } } else { scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,td->td_imagewidth,td->td_bitspersample,module),8); } if (scanline_size == 0) { TIFFErrorExt(tif->tif_clientdata,module,"Computed scanline size is zero"); return 0; } return(scanline_size); }
/* * Compute the # bytes in a variable height, row-aligned strip. */ uint64 TIFFVStripSize64(TIFF* tif, uint32 nrows) { static const char module[] = "TIFFVStripSize64"; 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]; uint16 samplingblock_samples; uint32 samplingblocks_hor; uint32 samplingblocks_ver; uint64 samplingrow_samples; uint64 samplingrow_size; if(td->td_samplesperpixel!=3) { TIFFErrorExt(tif->tif_clientdata,module, "Invalid td_samplesperpixel value"); return 0; } TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING,ycbcrsubsampling+0, ycbcrsubsampling+1); if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 && ycbcrsubsampling[0] != 4) ||(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 && ycbcrsubsampling[1] != 4)) { TIFFErrorExt(tif->tif_clientdata,module, "Invalid YCbCr subsampling (%dx%d)", ycbcrsubsampling[0], ycbcrsubsampling[1] ); return 0; } samplingblock_samples=ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; samplingblocks_hor=TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]); samplingblocks_ver=TIFFhowmany_32(nrows,ycbcrsubsampling[1]); samplingrow_samples=_TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); samplingrow_size=TIFFhowmany8_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module)); return(_TIFFMultiply64(tif,samplingrow_size,samplingblocks_ver,module)); } else return(_TIFFMultiply64(tif,nrows,TIFFScanlineSize64(tif),module)); }
/* * 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")); }
/* * 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")); }
/* * 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"))); }
/* * Return nonzero if the data is returned up-sampled. */ int TIFFIsUpSampled(TIFF* tif) { return (isUpSampled(tif)); }
/* * 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; }