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 
34 static uint32
summarize(TIFF * tif,size_t summand1,size_t summand2,const char * where)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
multiply(TIFF * tif,size_t nmemb,size_t elem_size,const char * where)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 
60 /*
61  * Compute which strip a (row,sample) value is in.
62  */
63 tstrip_t
TIFFComputeStrip(TIFF * tif,uint32 row,tsample_t sample)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
TIFFNumberOfStrips(TIFF * tif)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)
95 		nstrips = multiply(tif, nstrips, td->td_samplesperpixel,
96 				   "TIFFNumberOfStrips");
97 	return (nstrips);
98 }
99 
100 /*
101  * Compute the # bytes in a variable height, row-aligned strip.
102  */
103 tsize_t
TIFFVStripSize(TIFF * tif,uint32 nrows)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 		 */
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]);
134 		/* NB: don't need TIFFhowmany here 'cuz everything is rounded */
135 		scanline = multiply(tif, nrows, scanline, "TIFFVStripSize");
136 		return ((tsize_t)
137 		    summarize(tif, scanline,
138 			      multiply(tif, 2, scanline / samplingarea,
139 				       "TIFFVStripSize"), "TIFFVStripSize"));
140 	} else
141 #endif
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
TIFFRawStripSize(TIFF * tif,tstrip_t strip)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;
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
TIFFStripSize(TIFF * tif)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
TIFFDefaultStripSize(TIFF * tif,uint32 request)191 TIFFDefaultStripSize(TIFF* tif, uint32 request)
192 {
193 	return (*tif->tif_defstripsize)(tif, request);
194 }
195 
196 uint32
_TIFFDefaultStripSize(TIFF * tif,uint32 s)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
TIFFScanlineSize(TIFF * tif)219 TIFFScanlineSize(TIFF* tif)
220 {
221 	TIFFDirectory *td = &tif->tif_dir;
222 	tsize_t scanline;
223 
224 	scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth,
225 			     "TIFFScanlineSize");
226 	if (td->td_planarconfig == PLANARCONFIG_CONTIG)
227 		scanline = multiply (tif, scanline, td->td_samplesperpixel,
228 				     "TIFFScanlineSize");
229 	return ((tsize_t) TIFFhowmany8(scanline));
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
TIFFRasterScanlineSize(TIFF * tif)239 TIFFRasterScanlineSize(TIFF* tif)
240 {
241 	TIFFDirectory *td = &tif->tif_dir;
242 	tsize_t scanline;
243 
244 	scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth,
245 			     "TIFFRasterScanlineSize");
246 	if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
247 		scanline = multiply (tif, scanline, td->td_samplesperpixel,
248 				     "TIFFRasterScanlineSize");
249 		return ((tsize_t) TIFFhowmany8(scanline));
250 	} else
251 		return ((tsize_t) multiply (tif, TIFFhowmany8(scanline),
252 					    td->td_samplesperpixel,
253 					    "TIFFRasterScanlineSize"));
254 }
255