1/* $Id: tif_strip.c,v 1.19.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ 2 3/* 4 * Copyright (c) 1991-1997 Sam Leffler 5 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and 8 * its documentation for any purpose is hereby granted without fee, provided 9 * that (i) the above copyright notices and this permission notice appear in 10 * all copies of the software and related documentation, and (ii) the names of 11 * Sam Leffler and Silicon Graphics may not be used in any advertising or 12 * publicity relating to the software without the specific, prior written 13 * permission of Sam Leffler and Silicon Graphics. 14 * 15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 18 * 19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 24 * OF THIS SOFTWARE. 25 */ 26 27/* 28 * TIFF Library. 29 * 30 * Strip-organized Image Support Routines. 31 */ 32#include "tiffiop.h" 33 34static uint32 35summarize(TIFF* tif, size_t summand1, size_t summand2, const char* where) 36{ 37 /* 38 * XXX: We are using casting to uint32 here, bacause sizeof(size_t) 39 * may be larger than sizeof(uint32) on 64-bit architectures. 40 */ 41 uint32 bytes = summand1 + summand2; 42 43 if (bytes - summand1 != summand2) { 44 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where); 45 bytes = 0; 46 } 47 48 return (bytes); 49} 50 51static uint32 52multiply(TIFF* tif, size_t nmemb, size_t elem_size, const char* where) 53{ 54 uint32 bytes = nmemb * elem_size; 55 56 if (elem_size && bytes / elem_size != nmemb) { 57 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where); 58 bytes = 0; 59 } 60 61 return (bytes); 62} 63 64/* 65 * Compute which strip a (row,sample) value is in. 66 */ 67tstrip_t 68TIFFComputeStrip(TIFF* tif, uint32 row, tsample_t sample) 69{ 70 TIFFDirectory *td = &tif->tif_dir; 71 tstrip_t strip; 72 73 strip = row / td->td_rowsperstrip; 74 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { 75 if (sample >= td->td_samplesperpixel) { 76 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 77 "%lu: Sample out of range, max %lu", 78 (unsigned long) sample, (unsigned long) td->td_samplesperpixel); 79 return ((tstrip_t) 0); 80 } 81 strip += sample*td->td_stripsperimage; 82 } 83 return (strip); 84} 85 86/* 87 * Compute how many strips are in an image. 88 */ 89tstrip_t 90TIFFNumberOfStrips(TIFF* tif) 91{ 92 TIFFDirectory *td = &tif->tif_dir; 93 tstrip_t nstrips; 94 95 nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 : 96 TIFFhowmany(td->td_imagelength, td->td_rowsperstrip)); 97 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) 98 nstrips = multiply(tif, nstrips, td->td_samplesperpixel, 99 "TIFFNumberOfStrips"); 100 return (nstrips); 101} 102 103/* 104 * Compute the # bytes in a variable height, row-aligned strip. 105 */ 106tsize_t 107TIFFVStripSize(TIFF* tif, uint32 nrows) 108{ 109 TIFFDirectory *td = &tif->tif_dir; 110 111 if (nrows == (uint32) -1) 112 nrows = td->td_imagelength; 113 if (td->td_planarconfig == PLANARCONFIG_CONTIG && 114 td->td_photometric == PHOTOMETRIC_YCBCR && 115 !isUpSampled(tif)) { 116 /* 117 * Packed YCbCr data contain one Cb+Cr for every 118 * HorizontalSampling*VerticalSampling Y values. 119 * Must also roundup width and height when calculating 120 * since images that are not a multiple of the 121 * horizontal/vertical subsampling area include 122 * YCbCr data for the extended image. 123 */ 124 uint16 ycbcrsubsampling[2]; 125 tsize_t w, scanline, samplingarea; 126 127 TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, 128 ycbcrsubsampling + 0, 129 ycbcrsubsampling + 1 ); 130 131 samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1]; 132 if (samplingarea == 0) { 133 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 134 "Invalid YCbCr subsampling"); 135 return 0; 136 } 137 138 w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]); 139 scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample, 140 "TIFFVStripSize")); 141 nrows = TIFFroundup(nrows, ycbcrsubsampling[1]); 142 /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ 143 scanline = multiply(tif, nrows, scanline, "TIFFVStripSize"); 144 return ((tsize_t) 145 summarize(tif, scanline, 146 multiply(tif, 2, scanline / samplingarea, 147 "TIFFVStripSize"), "TIFFVStripSize")); 148 } else 149 return ((tsize_t) multiply(tif, nrows, TIFFScanlineSize(tif), 150 "TIFFVStripSize")); 151} 152 153 154/* 155 * Compute the # bytes in a raw strip. 156 */ 157tsize_t 158TIFFRawStripSize(TIFF* tif, tstrip_t strip) 159{ 160 TIFFDirectory* td = &tif->tif_dir; 161 tsize_t bytecount = td->td_stripbytecount[strip]; 162 163 if (bytecount <= 0) { 164 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 165 "%lu: Invalid strip byte count, strip %lu", 166 (unsigned long) bytecount, (unsigned long) strip); 167 bytecount = (tsize_t) -1; 168 } 169 170 return bytecount; 171} 172 173/* 174 * Compute the # bytes in a (row-aligned) strip. 175 * 176 * Note that if RowsPerStrip is larger than the 177 * recorded ImageLength, then the strip size is 178 * truncated to reflect the actual space required 179 * to hold the strip. 180 */ 181tsize_t 182TIFFStripSize(TIFF* tif) 183{ 184 TIFFDirectory* td = &tif->tif_dir; 185 uint32 rps = td->td_rowsperstrip; 186 if (rps > td->td_imagelength) 187 rps = td->td_imagelength; 188 return (TIFFVStripSize(tif, rps)); 189} 190 191/* 192 * Compute a default strip size based on the image 193 * characteristics and a requested value. If the 194 * request is <1 then we choose a strip size according 195 * to certain heuristics. 196 */ 197uint32 198TIFFDefaultStripSize(TIFF* tif, uint32 request) 199{ 200 return (*tif->tif_defstripsize)(tif, request); 201} 202 203uint32 204_TIFFDefaultStripSize(TIFF* tif, uint32 s) 205{ 206 if ((int32) s < 1) { 207 /* 208 * If RowsPerStrip is unspecified, try to break the 209 * image up into strips that are approximately 210 * STRIP_SIZE_DEFAULT bytes long. 211 */ 212 tsize_t scanline = TIFFScanlineSize(tif); 213 s = (uint32)STRIP_SIZE_DEFAULT / (scanline == 0 ? 1 : scanline); 214 if (s == 0) /* very wide images */ 215 s = 1; 216 } 217 return (s); 218} 219 220/* 221 * Return the number of bytes to read/write in a call to 222 * one of the scanline-oriented i/o routines. Note that 223 * this number may be 1/samples-per-pixel if data is 224 * stored as separate planes. 225 */ 226tsize_t 227TIFFScanlineSize(TIFF* tif) 228{ 229 TIFFDirectory *td = &tif->tif_dir; 230 tsize_t scanline; 231 232 if (td->td_planarconfig == PLANARCONFIG_CONTIG) { 233 if (td->td_photometric == PHOTOMETRIC_YCBCR 234 && !isUpSampled(tif)) { 235 uint16 ycbcrsubsampling[2]; 236 237 TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING, 238 ycbcrsubsampling + 0, 239 ycbcrsubsampling + 1); 240 241 if (ycbcrsubsampling[0] == 0) { 242 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 243 "Invalid YCbCr subsampling"); 244 return 0; 245 } 246 247 scanline = TIFFroundup(td->td_imagewidth, 248 ycbcrsubsampling[0]); 249 scanline = TIFFhowmany8(multiply(tif, scanline, 250 td->td_bitspersample, 251 "TIFFScanlineSize")); 252 return ((tsize_t) 253 summarize(tif, scanline, 254 multiply(tif, 2, 255 scanline / ycbcrsubsampling[0], 256 "TIFFVStripSize"), 257 "TIFFVStripSize")); 258 } else { 259 scanline = multiply(tif, td->td_imagewidth, 260 td->td_samplesperpixel, 261 "TIFFScanlineSize"); 262 } 263 } else 264 scanline = td->td_imagewidth; 265 return ((tsize_t) TIFFhowmany8(multiply(tif, scanline, 266 td->td_bitspersample, 267 "TIFFScanlineSize"))); 268} 269 270/* 271 * Some stuff depends on this older version of TIFFScanlineSize 272 * TODO: resolve this 273 */ 274tsize_t 275TIFFOldScanlineSize(TIFF* tif) 276{ 277 TIFFDirectory *td = &tif->tif_dir; 278 tsize_t scanline; 279 280 scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth, 281 "TIFFScanlineSize"); 282 if (td->td_planarconfig == PLANARCONFIG_CONTIG) 283 scanline = multiply (tif, scanline, td->td_samplesperpixel, 284 "TIFFScanlineSize"); 285 return ((tsize_t) TIFFhowmany8(scanline)); 286} 287 288/* 289 * Return the number of bytes to read/write in a call to 290 * one of the scanline-oriented i/o routines. Note that 291 * this number may be 1/samples-per-pixel if data is 292 * stored as separate planes. 293 * The ScanlineSize in case of YCbCrSubsampling is defined as the 294 * strip size divided by the strip height, i.e. the size of a pack of vertical 295 * subsampling lines divided by vertical subsampling. It should thus make 296 * sense when multiplied by a multiple of vertical subsampling. 297 * Some stuff depends on this newer version of TIFFScanlineSize 298 * TODO: resolve this 299 */ 300tsize_t 301TIFFNewScanlineSize(TIFF* tif) 302{ 303 TIFFDirectory *td = &tif->tif_dir; 304 tsize_t scanline; 305 306 if (td->td_planarconfig == PLANARCONFIG_CONTIG) { 307 if (td->td_photometric == PHOTOMETRIC_YCBCR 308 && !isUpSampled(tif)) { 309 uint16 ycbcrsubsampling[2]; 310 311 TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING, 312 ycbcrsubsampling + 0, 313 ycbcrsubsampling + 1); 314 315 if (ycbcrsubsampling[0]*ycbcrsubsampling[1] == 0) { 316 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 317 "Invalid YCbCr subsampling"); 318 return 0; 319 } 320 321 return((tsize_t) ((((td->td_imagewidth+ycbcrsubsampling[0]-1) 322 /ycbcrsubsampling[0]) 323 *(ycbcrsubsampling[0]*ycbcrsubsampling[1]+2) 324 *td->td_bitspersample+7) 325 /8)/ycbcrsubsampling[1]); 326 327 } else { 328 scanline = multiply(tif, td->td_imagewidth, 329 td->td_samplesperpixel, 330 "TIFFScanlineSize"); 331 } 332 } else 333 scanline = td->td_imagewidth; 334 return ((tsize_t) TIFFhowmany8(multiply(tif, scanline, 335 td->td_bitspersample, 336 "TIFFScanlineSize"))); 337} 338 339/* 340 * Return the number of bytes required to store a complete 341 * decoded and packed raster scanline (as opposed to the 342 * I/O size returned by TIFFScanlineSize which may be less 343 * if data is store as separate planes). 344 */ 345tsize_t 346TIFFRasterScanlineSize(TIFF* tif) 347{ 348 TIFFDirectory *td = &tif->tif_dir; 349 tsize_t scanline; 350 351 scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth, 352 "TIFFRasterScanlineSize"); 353 if (td->td_planarconfig == PLANARCONFIG_CONTIG) { 354 scanline = multiply (tif, scanline, td->td_samplesperpixel, 355 "TIFFRasterScanlineSize"); 356 return ((tsize_t) TIFFhowmany8(scanline)); 357 } else 358 return ((tsize_t) multiply (tif, TIFFhowmany8(scanline), 359 td->td_samplesperpixel, 360 "TIFFRasterScanlineSize")); 361} 362 363/* vim: set ts=8 sts=8 sw=8 noet: */ 364/* 365 * Local Variables: 366 * mode: c 367 * c-basic-offset: 8 368 * fill-column: 78 369 * End: 370 */ 371