]>
Commit | Line | Data |
---|---|---|
1 | /* $Id$ */ | |
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 | static uint32 | |
35 | summarize(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 | ||
51 | static uint32 | |
52 | multiply(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 | */ | |
67 | tstrip_t | |
68 | TIFFComputeStrip(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 | */ | |
89 | tstrip_t | |
90 | TIFFNumberOfStrips(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 | */ | |
106 | tsize_t | |
107 | TIFFVStripSize(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 | */ | |
157 | tsize_t | |
158 | TIFFRawStripSize(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 | */ | |
181 | tsize_t | |
182 | TIFFStripSize(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 | */ | |
197 | uint32 | |
198 | TIFFDefaultStripSize(TIFF* tif, uint32 request) | |
199 | { | |
200 | return (*tif->tif_defstripsize)(tif, request); | |
201 | } | |
202 | ||
203 | uint32 | |
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 | */ | |
226 | tsize_t | |
227 | TIFFScanlineSize(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 | * Return the number of bytes required to store a complete | |
272 | * decoded and packed raster scanline (as opposed to the | |
273 | * I/O size returned by TIFFScanlineSize which may be less | |
274 | * if data is store as separate planes). | |
275 | */ | |
276 | tsize_t | |
277 | TIFFRasterScanlineSize(TIFF* tif) | |
278 | { | |
279 | TIFFDirectory *td = &tif->tif_dir; | |
280 | tsize_t scanline; | |
281 | ||
282 | scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth, | |
283 | "TIFFRasterScanlineSize"); | |
284 | if (td->td_planarconfig == PLANARCONFIG_CONTIG) { | |
285 | scanline = multiply (tif, scanline, td->td_samplesperpixel, | |
286 | "TIFFRasterScanlineSize"); | |
287 | return ((tsize_t) TIFFhowmany8(scanline)); | |
288 | } else | |
289 | return ((tsize_t) multiply (tif, TIFFhowmany8(scanline), | |
290 | td->td_samplesperpixel, | |
291 | "TIFFRasterScanlineSize")); | |
292 | } | |
293 | ||
294 | /* vim: set ts=8 sts=8 sw=8 noet: */ |