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