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