OLD | NEW |
| (Empty) |
1 /* $Id: tif_strip.c,v 1.35 2012-06-06 05:33:55 fwarmerdam 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 | |
34 /* | |
35 * Compute which strip a (row,sample) value is in. | |
36 */ | |
37 uint32 | |
38 TIFFComputeStrip(TIFF* tif, uint32 row, uint16 sample) | |
39 { | |
40 static const char module[] = "TIFFComputeStrip"; | |
41 TIFFDirectory *td = &tif->tif_dir; | |
42 uint32 strip; | |
43 | |
44 strip = row / td->td_rowsperstrip; | |
45 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { | |
46 if (sample >= td->td_samplesperpixel) { | |
47 TIFFErrorExt(tif->tif_clientdata, module, | |
48 "%lu: Sample out of range, max %lu", | |
49 (unsigned long) sample, (unsigned long) td->td_sampl
esperpixel); | |
50 return (0); | |
51 } | |
52 strip += (uint32)sample*td->td_stripsperimage; | |
53 } | |
54 return (strip); | |
55 } | |
56 | |
57 /* | |
58 * Compute how many strips are in an image. | |
59 */ | |
60 uint32 | |
61 TIFFNumberOfStrips(TIFF* tif) | |
62 { | |
63 TIFFDirectory *td = &tif->tif_dir; | |
64 uint32 nstrips; | |
65 | |
66 nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 : | |
67 TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip)); | |
68 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) | |
69 nstrips = _TIFFMultiply32(tif, nstrips, (uint32)td->td_samplespe
rpixel, | |
70 "TIFFNumberOfStrips"); | |
71 return (nstrips); | |
72 } | |
73 | |
74 /* | |
75 * Compute the # bytes in a variable height, row-aligned strip. | |
76 */ | |
77 uint64 | |
78 TIFFVStripSize64(TIFF* tif, uint32 nrows) | |
79 { | |
80 static const char module[] = "TIFFVStripSize64"; | |
81 TIFFDirectory *td = &tif->tif_dir; | |
82 if (nrows==(uint32)(-1)) | |
83 nrows=td->td_imagelength; | |
84 if ((td->td_planarconfig==PLANARCONFIG_CONTIG)&& | |
85 (td->td_photometric == PHOTOMETRIC_YCBCR)&& | |
86 (!isUpSampled(tif))) | |
87 { | |
88 /* | |
89 * Packed YCbCr data contain one Cb+Cr for every | |
90 * HorizontalSampling*VerticalSampling Y values. | |
91 * Must also roundup width and height when calculating | |
92 * since images that are not a multiple of the | |
93 * horizontal/vertical subsampling area include | |
94 * YCbCr data for the extended image. | |
95 */ | |
96 uint16 ycbcrsubsampling[2]; | |
97 uint16 samplingblock_samples; | |
98 uint32 samplingblocks_hor; | |
99 uint32 samplingblocks_ver; | |
100 uint64 samplingrow_samples; | |
101 uint64 samplingrow_size; | |
102 if(td->td_samplesperpixel!=3) | |
103 { | |
104 TIFFErrorExt(tif->tif_clientdata,module, | |
105 "Invalid td_samplesperpixel value"); | |
106 return 0; | |
107 } | |
108 TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING,ycbcrsubsampl
ing+0, | |
109 ycbcrsubsampling+1); | |
110 if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 && ycb
crsubsampling[0] != 4) | |
111 ||(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 && y
cbcrsubsampling[1] != 4)) | |
112 { | |
113 TIFFErrorExt(tif->tif_clientdata,module, | |
114 "Invalid YCbCr subsampling (%dx%d)", | |
115 ycbcrsubsampling[0], | |
116 ycbcrsubsampling[1] ); | |
117 return 0; | |
118 } | |
119 samplingblock_samples=ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; | |
120 samplingblocks_hor=TIFFhowmany_32(td->td_imagewidth,ycbcrsubsamp
ling[0]); | |
121 samplingblocks_ver=TIFFhowmany_32(nrows,ycbcrsubsampling[1]); | |
122 samplingrow_samples=_TIFFMultiply64(tif,samplingblocks_hor,sampl
ingblock_samples,module); | |
123 samplingrow_size=TIFFhowmany8_64(_TIFFMultiply64(tif,samplingrow
_samples,td->td_bitspersample,module)); | |
124 return(_TIFFMultiply64(tif,samplingrow_size,samplingblocks_ver,m
odule)); | |
125 } | |
126 else | |
127 return(_TIFFMultiply64(tif,nrows,TIFFScanlineSize64(tif),module)
); | |
128 } | |
129 tmsize_t | |
130 TIFFVStripSize(TIFF* tif, uint32 nrows) | |
131 { | |
132 static const char module[] = "TIFFVStripSize"; | |
133 uint64 m; | |
134 tmsize_t n; | |
135 m=TIFFVStripSize64(tif,nrows); | |
136 n=(tmsize_t)m; | |
137 if ((uint64)n!=m) | |
138 { | |
139 TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); | |
140 n=0; | |
141 } | |
142 return(n); | |
143 } | |
144 | |
145 /* | |
146 * Compute the # bytes in a raw strip. | |
147 */ | |
148 uint64 | |
149 TIFFRawStripSize64(TIFF* tif, uint32 strip) | |
150 { | |
151 static const char module[] = "TIFFRawStripSize64"; | |
152 TIFFDirectory* td = &tif->tif_dir; | |
153 uint64 bytecount = td->td_stripbytecount[strip]; | |
154 | |
155 if (bytecount == 0) | |
156 { | |
157 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) | |
158 TIFFErrorExt(tif->tif_clientdata, module, | |
159 "%I64u: Invalid strip byte count, strip %lu", | |
160 (unsigned __int64) bytecount, | |
161 (unsigned long) strip); | |
162 #else | |
163 TIFFErrorExt(tif->tif_clientdata, module, | |
164 "%llu: Invalid strip byte count, strip %lu", | |
165 (unsigned long long) bytecount, | |
166 (unsigned long) strip); | |
167 #endif | |
168 bytecount = (uint64) -1; | |
169 } | |
170 | |
171 return bytecount; | |
172 } | |
173 tmsize_t | |
174 TIFFRawStripSize(TIFF* tif, uint32 strip) | |
175 { | |
176 static const char module[] = "TIFFRawStripSize"; | |
177 uint64 m; | |
178 tmsize_t n; | |
179 m=TIFFRawStripSize64(tif,strip); | |
180 if (m==(uint64)(-1)) | |
181 n=(tmsize_t)(-1); | |
182 else | |
183 { | |
184 n=(tmsize_t)m; | |
185 if ((uint64)n!=m) | |
186 { | |
187 TIFFErrorExt(tif->tif_clientdata,module,"Integer overflo
w"); | |
188 n=0; | |
189 } | |
190 } | |
191 return(n); | |
192 } | |
193 | |
194 /* | |
195 * Compute the # bytes in a (row-aligned) strip. | |
196 * | |
197 * Note that if RowsPerStrip is larger than the | |
198 * recorded ImageLength, then the strip size is | |
199 * truncated to reflect the actual space required | |
200 * to hold the strip. | |
201 */ | |
202 uint64 | |
203 TIFFStripSize64(TIFF* tif) | |
204 { | |
205 TIFFDirectory* td = &tif->tif_dir; | |
206 uint32 rps = td->td_rowsperstrip; | |
207 if (rps > td->td_imagelength) | |
208 rps = td->td_imagelength; | |
209 return (TIFFVStripSize64(tif, rps)); | |
210 } | |
211 tmsize_t | |
212 TIFFStripSize(TIFF* tif) | |
213 { | |
214 static const char module[] = "TIFFStripSize"; | |
215 uint64 m; | |
216 tmsize_t n; | |
217 m=TIFFStripSize64(tif); | |
218 n=(tmsize_t)m; | |
219 if ((uint64)n!=m) | |
220 { | |
221 TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); | |
222 n=0; | |
223 } | |
224 return(n); | |
225 } | |
226 | |
227 /* | |
228 * Compute a default strip size based on the image | |
229 * characteristics and a requested value. If the | |
230 * request is <1 then we choose a strip size according | |
231 * to certain heuristics. | |
232 */ | |
233 uint32 | |
234 TIFFDefaultStripSize(TIFF* tif, uint32 request) | |
235 { | |
236 return (*tif->tif_defstripsize)(tif, request); | |
237 } | |
238 | |
239 uint32 | |
240 _TIFFDefaultStripSize(TIFF* tif, uint32 s) | |
241 { | |
242 if ((int32) s < 1) { | |
243 /* | |
244 * If RowsPerStrip is unspecified, try to break the | |
245 * image up into strips that are approximately | |
246 * STRIP_SIZE_DEFAULT bytes long. | |
247 */ | |
248 uint64 scanlinesize; | |
249 uint64 rows; | |
250 scanlinesize=TIFFScanlineSize64(tif); | |
251 if (scanlinesize==0) | |
252 scanlinesize=1; | |
253 rows=(uint64)STRIP_SIZE_DEFAULT/scanlinesize; | |
254 if (rows==0) | |
255 rows=1; | |
256 else if (rows>0xFFFFFFFF) | |
257 rows=0xFFFFFFFF; | |
258 s=(uint32)rows; | |
259 } | |
260 return (s); | |
261 } | |
262 | |
263 /* | |
264 * Return the number of bytes to read/write in a call to | |
265 * one of the scanline-oriented i/o routines. Note that | |
266 * this number may be 1/samples-per-pixel if data is | |
267 * stored as separate planes. | |
268 * The ScanlineSize in case of YCbCrSubsampling is defined as the | |
269 * strip size divided by the strip height, i.e. the size of a pack of vertical | |
270 * subsampling lines divided by vertical subsampling. It should thus make | |
271 * sense when multiplied by a multiple of vertical subsampling. | |
272 */ | |
273 uint64 | |
274 TIFFScanlineSize64(TIFF* tif) | |
275 { | |
276 static const char module[] = "TIFFScanlineSize64"; | |
277 TIFFDirectory *td = &tif->tif_dir; | |
278 uint64 scanline_size; | |
279 if (td->td_planarconfig==PLANARCONFIG_CONTIG) | |
280 { | |
281 if ((td->td_photometric==PHOTOMETRIC_YCBCR)&& | |
282 (td->td_samplesperpixel==3)&& | |
283 (!isUpSampled(tif))) | |
284 { | |
285 uint16 ycbcrsubsampling[2]; | |
286 uint16 samplingblock_samples; | |
287 uint32 samplingblocks_hor; | |
288 uint64 samplingrow_samples; | |
289 uint64 samplingrow_size; | |
290 if(td->td_samplesperpixel!=3) | |
291 { | |
292 TIFFErrorExt(tif->tif_clientdata,module, | |
293 "Invalid td_samplesperpixel value"); | |
294 return 0; | |
295 } | |
296 TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING, | |
297 ycbcrsubsampling+0, | |
298 ycbcrsubsampling+1); | |
299 if (((ycbcrsubsampling[0]!=1)&&(ycbcrsubsampling[0]!=2)&
&(ycbcrsubsampling[0]!=4)) || | |
300 ((ycbcrsubsampling[1]!=1)&&(ycbcrsubsampling[1]!=2)&
&(ycbcrsubsampling[1]!=4))) | |
301 { | |
302 TIFFErrorExt(tif->tif_clientdata,module, | |
303 "Invalid YCbCr subsampling"); | |
304 return 0; | |
305 } | |
306 samplingblock_samples = ycbcrsubsampling[0]*ycbcrsubsamp
ling[1]+2; | |
307 samplingblocks_hor = TIFFhowmany_32(td->td_imagewidth,yc
bcrsubsampling[0]); | |
308 samplingrow_samples = _TIFFMultiply64(tif,samplingblocks
_hor,samplingblock_samples,module); | |
309 samplingrow_size = TIFFhowmany_64(_TIFFMultiply64(tif,sa
mplingrow_samples,td->td_bitspersample,module),8); | |
310 scanline_size = (samplingrow_size/ycbcrsubsampling[1]); | |
311 } | |
312 else | |
313 { | |
314 uint64 scanline_samples; | |
315 scanline_samples=_TIFFMultiply64(tif,td->td_imagewidth,t
d->td_samplesperpixel,module); | |
316 scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,scanlin
e_samples,td->td_bitspersample,module),8); | |
317 } | |
318 } | |
319 else | |
320 scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,td->td_imagewid
th,td->td_bitspersample,module),8); | |
321 return(scanline_size); | |
322 } | |
323 tmsize_t | |
324 TIFFScanlineSize(TIFF* tif) | |
325 { | |
326 static const char module[] = "TIFFScanlineSize"; | |
327 uint64 m; | |
328 tmsize_t n; | |
329 m=TIFFScanlineSize64(tif); | |
330 n=(tmsize_t)m; | |
331 if ((uint64)n!=m) | |
332 { | |
333 TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic over
flow"); | |
334 n=0; | |
335 } | |
336 return(n); | |
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 */ | |
345 uint64 | |
346 TIFFRasterScanlineSize64(TIFF* tif) | |
347 { | |
348 static const char module[] = "TIFFRasterScanlineSize64"; | |
349 TIFFDirectory *td = &tif->tif_dir; | |
350 uint64 scanline; | |
351 | |
352 scanline = _TIFFMultiply64(tif, td->td_bitspersample, td->td_imagewidth,
module); | |
353 if (td->td_planarconfig == PLANARCONFIG_CONTIG) { | |
354 scanline = _TIFFMultiply64(tif, scanline, td->td_samplesperpixel
, module); | |
355 return (TIFFhowmany8_64(scanline)); | |
356 } else | |
357 return (_TIFFMultiply64(tif, TIFFhowmany8_64(scanline), | |
358 td->td_samplesperpixel, module)); | |
359 } | |
360 tmsize_t | |
361 TIFFRasterScanlineSize(TIFF* tif) | |
362 { | |
363 static const char module[] = "TIFFRasterScanlineSize"; | |
364 uint64 m; | |
365 tmsize_t n; | |
366 m=TIFFRasterScanlineSize64(tif); | |
367 n=(tmsize_t)m; | |
368 if ((uint64)n!=m) | |
369 { | |
370 TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic over
flow"); | |
371 n=0; | |
372 } | |
373 return(n); | |
374 } | |
375 | |
376 /* vim: set ts=8 sts=8 sw=8 noet: */ | |
377 /* | |
378 * Local Variables: | |
379 * mode: c | |
380 * c-basic-offset: 8 | |
381 * fill-column: 78 | |
382 * End: | |
383 */ | |
384 | |
OLD | NEW |