]>
Commit | Line | Data |
---|---|---|
b47c832e RR |
1 | /* $Header$ */ |
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 | ||
00cb87b4 VZ |
34 | static uint32 |
35 | summarize(TIFF* tif, size_t summand1, size_t summand2, const char* where) | |
36 | { | |
37 | uint32 bytes = summand1 + summand2; | |
38 | ||
39 | if (bytes - summand1 != summand2) { | |
40 | TIFFError(tif->tif_name, "Integer overflow in %s", where); | |
41 | bytes = 0; | |
42 | } | |
43 | ||
44 | return (bytes); | |
45 | } | |
46 | ||
47 | static uint32 | |
48 | multiply(TIFF* tif, size_t nmemb, size_t elem_size, const char* where) | |
49 | { | |
50 | uint32 bytes = nmemb * elem_size; | |
51 | ||
52 | if (elem_size && bytes / elem_size != nmemb) { | |
53 | TIFFError(tif->tif_name, "Integer overflow in %s", where); | |
54 | bytes = 0; | |
55 | } | |
56 | ||
57 | return (bytes); | |
58 | } | |
59 | ||
b47c832e RR |
60 | /* |
61 | * Compute which strip a (row,sample) value is in. | |
62 | */ | |
63 | tstrip_t | |
64 | TIFFComputeStrip(TIFF* tif, uint32 row, tsample_t sample) | |
65 | { | |
66 | TIFFDirectory *td = &tif->tif_dir; | |
67 | tstrip_t strip; | |
68 | ||
69 | strip = row / td->td_rowsperstrip; | |
70 | if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { | |
71 | if (sample >= td->td_samplesperpixel) { | |
72 | TIFFError(tif->tif_name, | |
73 | "%u: Sample out of range, max %u", | |
74 | sample, td->td_samplesperpixel); | |
75 | return ((tstrip_t) 0); | |
76 | } | |
77 | strip += sample*td->td_stripsperimage; | |
78 | } | |
79 | return (strip); | |
80 | } | |
81 | ||
82 | /* | |
83 | * Compute how many strips are in an image. | |
84 | */ | |
85 | tstrip_t | |
86 | TIFFNumberOfStrips(TIFF* tif) | |
87 | { | |
88 | TIFFDirectory *td = &tif->tif_dir; | |
89 | tstrip_t nstrips; | |
90 | ||
91 | nstrips = (td->td_rowsperstrip == (uint32) -1 ? | |
92 | (td->td_imagelength != 0 ? 1 : 0) : | |
93 | TIFFhowmany(td->td_imagelength, td->td_rowsperstrip)); | |
94 | if (td->td_planarconfig == PLANARCONFIG_SEPARATE) | |
00cb87b4 VZ |
95 | nstrips = multiply(tif, nstrips, td->td_samplesperpixel, |
96 | "TIFFNumberOfStrips"); | |
b47c832e RR |
97 | return (nstrips); |
98 | } | |
99 | ||
100 | /* | |
101 | * Compute the # bytes in a variable height, row-aligned strip. | |
102 | */ | |
103 | tsize_t | |
104 | TIFFVStripSize(TIFF* tif, uint32 nrows) | |
105 | { | |
106 | TIFFDirectory *td = &tif->tif_dir; | |
107 | ||
108 | if (nrows == (uint32) -1) | |
109 | nrows = td->td_imagelength; | |
110 | #ifdef YCBCR_SUPPORT | |
111 | if (td->td_planarconfig == PLANARCONFIG_CONTIG && | |
112 | td->td_photometric == PHOTOMETRIC_YCBCR && | |
113 | !isUpSampled(tif)) { | |
114 | /* | |
115 | * Packed YCbCr data contain one Cb+Cr for every | |
116 | * HorizontalSampling*VerticalSampling Y values. | |
117 | * Must also roundup width and height when calculating | |
118 | * since images that are not a multiple of the | |
119 | * horizontal/vertical subsampling area include | |
120 | * YCbCr data for the extended image. | |
121 | */ | |
00cb87b4 VZ |
122 | uint16 ycbcrsubsampling[2]; |
123 | tsize_t w, scanline, samplingarea; | |
124 | ||
125 | TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, | |
126 | ycbcrsubsampling + 0, | |
127 | ycbcrsubsampling + 1 ); | |
128 | ||
129 | w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]); | |
130 | scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample, | |
131 | "TIFFVStripSize")); | |
132 | samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1]; | |
133 | nrows = TIFFroundup(nrows, ycbcrsubsampling[1]); | |
b47c832e | 134 | /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ |
00cb87b4 | 135 | scanline = multiply(tif, nrows, scanline, "TIFFVStripSize"); |
b47c832e | 136 | return ((tsize_t) |
00cb87b4 VZ |
137 | summarize(tif, scanline, |
138 | multiply(tif, 2, scanline / samplingarea, | |
139 | "TIFFVStripSize"), "TIFFVStripSize")); | |
b47c832e RR |
140 | } else |
141 | #endif | |
00cb87b4 VZ |
142 | return ((tsize_t) multiply(tif, nrows, TIFFScanlineSize(tif), |
143 | "TIFFVStripSize")); | |
144 | } | |
145 | ||
146 | ||
147 | /* | |
148 | * Compute the # bytes in a raw strip. | |
149 | */ | |
150 | tsize_t | |
151 | TIFFRawStripSize(TIFF* tif, tstrip_t strip) | |
152 | { | |
153 | TIFFDirectory* td = &tif->tif_dir; | |
154 | tsize_t bytecount = td->td_stripbytecount[strip]; | |
155 | ||
156 | if (bytecount <= 0) { | |
157 | TIFFError(tif->tif_name, | |
158 | "%lu: Invalid strip byte count, strip %lu", | |
159 | (u_long) bytecount, (u_long) strip); | |
160 | bytecount = (tsize_t) -1; | |
161 | } | |
162 | ||
163 | return bytecount; | |
b47c832e RR |
164 | } |
165 | ||
166 | /* | |
167 | * Compute the # bytes in a (row-aligned) strip. | |
168 | * | |
169 | * Note that if RowsPerStrip is larger than the | |
170 | * recorded ImageLength, then the strip size is | |
171 | * truncated to reflect the actual space required | |
172 | * to hold the strip. | |
173 | */ | |
174 | tsize_t | |
175 | TIFFStripSize(TIFF* tif) | |
176 | { | |
177 | TIFFDirectory* td = &tif->tif_dir; | |
178 | uint32 rps = td->td_rowsperstrip; | |
179 | if (rps > td->td_imagelength) | |
180 | rps = td->td_imagelength; | |
181 | return (TIFFVStripSize(tif, rps)); | |
182 | } | |
183 | ||
184 | /* | |
185 | * Compute a default strip size based on the image | |
186 | * characteristics and a requested value. If the | |
187 | * request is <1 then we choose a strip size according | |
188 | * to certain heuristics. | |
189 | */ | |
190 | uint32 | |
191 | TIFFDefaultStripSize(TIFF* tif, uint32 request) | |
192 | { | |
193 | return (*tif->tif_defstripsize)(tif, request); | |
194 | } | |
195 | ||
196 | uint32 | |
197 | _TIFFDefaultStripSize(TIFF* tif, uint32 s) | |
198 | { | |
199 | if ((int32) s < 1) { | |
200 | /* | |
201 | * If RowsPerStrip is unspecified, try to break the | |
202 | * image up into strips that are approximately 8Kbytes. | |
203 | */ | |
204 | tsize_t scanline = TIFFScanlineSize(tif); | |
205 | s = (uint32)(8*1024) / (scanline == 0 ? 1 : scanline); | |
206 | if (s == 0) /* very wide images */ | |
207 | s = 1; | |
208 | } | |
209 | return (s); | |
210 | } | |
211 | ||
212 | /* | |
213 | * Return the number of bytes to read/write in a call to | |
214 | * one of the scanline-oriented i/o routines. Note that | |
215 | * this number may be 1/samples-per-pixel if data is | |
216 | * stored as separate planes. | |
217 | */ | |
218 | tsize_t | |
219 | TIFFScanlineSize(TIFF* tif) | |
220 | { | |
221 | TIFFDirectory *td = &tif->tif_dir; | |
222 | tsize_t scanline; | |
223 | ||
00cb87b4 VZ |
224 | scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth, |
225 | "TIFFScanlineSize"); | |
b47c832e | 226 | if (td->td_planarconfig == PLANARCONFIG_CONTIG) |
00cb87b4 VZ |
227 | scanline = multiply (tif, scanline, td->td_samplesperpixel, |
228 | "TIFFScanlineSize"); | |
229 | return ((tsize_t) TIFFhowmany8(scanline)); | |
b47c832e RR |
230 | } |
231 | ||
232 | /* | |
233 | * Return the number of bytes required to store a complete | |
234 | * decoded and packed raster scanline (as opposed to the | |
235 | * I/O size returned by TIFFScanlineSize which may be less | |
236 | * if data is store as separate planes). | |
237 | */ | |
238 | tsize_t | |
239 | TIFFRasterScanlineSize(TIFF* tif) | |
240 | { | |
241 | TIFFDirectory *td = &tif->tif_dir; | |
242 | tsize_t scanline; | |
243 | ||
00cb87b4 VZ |
244 | scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth, |
245 | "TIFFRasterScanlineSize"); | |
b47c832e | 246 | if (td->td_planarconfig == PLANARCONFIG_CONTIG) { |
00cb87b4 VZ |
247 | scanline = multiply (tif, scanline, td->td_samplesperpixel, |
248 | "TIFFRasterScanlineSize"); | |
249 | return ((tsize_t) TIFFhowmany8(scanline)); | |
b47c832e | 250 | } else |
00cb87b4 VZ |
251 | return ((tsize_t) multiply (tif, TIFFhowmany8(scanline), |
252 | td->td_samplesperpixel, | |
253 | "TIFFRasterScanlineSize")); | |
b47c832e | 254 | } |