]>
Commit | Line | Data |
---|---|---|
1 | /* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_pdsdirread.c,v 1.3 2005/12/21 12:23:13 joris Exp $ */ | |
2 | ||
3 | /* | |
4 | * Copyright (c) 1988-1996 Sam Leffler | |
5 | * Copyright (c) 1991-1996 Silicon Graphics, Inc. | |
6 | * Copyright (c( 1996 USAF Phillips Laboratory | |
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 | * These routines written by Conrad J. Poelman on a single late-night of | |
32 | * March 20-21, 1996. | |
33 | * | |
34 | * The entire purpose of this file is to provide a single external function, | |
35 | * TIFFReadPrivateDataSubDirectory(). This function is intended for use in reading a | |
36 | * private subdirectory from a TIFF file into a private structure. The | |
37 | * actual writing of data into the structure is handled by the setFieldFn(), | |
38 | * which is passed to TIFFReadPrivateDataSubDirectory() as a parameter. The idea is to | |
39 | * enable any application wishing to store private subdirectories to do so | |
40 | * easily using this function, without modifying the TIFF library. | |
41 | * | |
42 | * The astute observer will notice that only two functions are at all different | |
43 | * from the original tif_dirread.c file: TIFFReadPrivateDataSubDirectory() and | |
44 | * TIFFFetchNormalSubTag(). All the other stuff that makes this file so huge | |
45 | * is only necessary because all of those functions are declared static in | |
46 | * tif_dirread.c, so we have to totally duplicate them in order to use them. | |
47 | * | |
48 | * Oh, also note the bug fix in TIFFFetchFloat(). | |
49 | * | |
50 | */ | |
51 | ||
52 | #include "tiffiop.h" | |
53 | ||
54 | #define IGNORE 0 /* tag placeholder used below */ | |
55 | ||
56 | #if HAVE_IEEEFP | |
57 | #define TIFFCvtIEEEFloatToNative(tif, n, fp) | |
58 | #define TIFFCvtIEEEDoubleToNative(tif, n, dp) | |
59 | #else | |
60 | extern void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*); | |
61 | extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*); | |
62 | #endif | |
63 | ||
64 | static void EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16); | |
65 | static void MissingRequired(TIFF*, const char*); | |
66 | static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32); | |
67 | static tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*); | |
68 | static tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*); | |
69 | static float TIFFFetchRational(TIFF*, TIFFDirEntry*); | |
70 | static int TIFFFetchNormalSubTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*, | |
71 | int (*getFieldFn)(TIFF *tif,ttag_t tag,...)); | |
72 | static int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntry*, int*); | |
73 | static int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntry*, double*); | |
74 | static int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*); | |
75 | static int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**); | |
76 | static int TIFFFetchExtraSamples(TIFF*, TIFFDirEntry*); | |
77 | static int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*); | |
78 | static float TIFFFetchFloat(TIFF*, TIFFDirEntry*); | |
79 | static int TIFFFetchFloatArray(TIFF*, TIFFDirEntry*, float*); | |
80 | static int TIFFFetchDoubleArray(TIFF*, TIFFDirEntry*, double*); | |
81 | static int TIFFFetchAnyArray(TIFF*, TIFFDirEntry*, double*); | |
82 | static int TIFFFetchShortPair(TIFF*, TIFFDirEntry*); | |
83 | #if STRIPCHOP_SUPPORT | |
84 | static void ChopUpSingleUncompressedStrip(TIFF*); | |
85 | #endif | |
86 | ||
87 | static char * | |
88 | CheckMalloc(TIFF* tif, tsize_t n, const char* what) | |
89 | { | |
90 | char *cp = (char*)_TIFFmalloc(n); | |
91 | if (cp == NULL) | |
92 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "No space %s", what); | |
93 | return (cp); | |
94 | } | |
95 | ||
96 | /* Just as was done with TIFFWritePrivateDataSubDirectory(), here we implement | |
97 | TIFFReadPrivateDataSubDirectory() which takes an offset into the TIFF file, | |
98 | a TIFFFieldInfo structure specifying the types of the various tags, | |
99 | and a function to use to set individual tags when they are encountered. | |
100 | The data is read from the file, translated using the TIFF library's | |
101 | built-in machine-independent conversion functions, and filled into | |
102 | private subdirectory structure. | |
103 | ||
104 | This code was written by copying the original TIFFReadDirectory() function | |
105 | from tif_dirread.c and paring it down to what is needed for this. | |
106 | ||
107 | It is the caller's responsibility to allocate and initialize the internal | |
108 | structure that setFieldFn() will be writing into. If this function is being | |
109 | called more than once before closing the file, the caller also must be | |
110 | careful to free data in the structure before re-initializing. | |
111 | ||
112 | It is also the caller's responsibility to verify the presence of | |
113 | any required fields after reading the directory in. | |
114 | */ | |
115 | ||
116 | ||
117 | int | |
118 | TIFFReadPrivateDataSubDirectory(TIFF* tif, toff_t pdir_offset, | |
119 | TIFFFieldInfo *field_info, | |
120 | int (*setFieldFn)(TIFF *tif, ttag_t tag, ...)) | |
121 | { | |
122 | register TIFFDirEntry* dp; | |
123 | register int n; | |
124 | register TIFFDirectory* td; | |
125 | TIFFDirEntry* dir; | |
126 | int iv; | |
127 | long v; | |
128 | double dv; | |
129 | const TIFFFieldInfo* fip; | |
130 | int fix; | |
131 | uint16 dircount; | |
132 | uint32 nextdiroff; | |
133 | char* cp; | |
134 | int diroutoforderwarning = 0; | |
135 | ||
136 | /* Skipped part about checking for directories or compression data. */ | |
137 | ||
138 | if (!isMapped(tif)) { | |
139 | if (!SeekOK(tif, pdir_offset)) { | |
140 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
141 | "Seek error accessing TIFF private subdirectory"); | |
142 | return (0); | |
143 | } | |
144 | if (!ReadOK(tif, &dircount, sizeof (uint16))) { | |
145 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
146 | "Can not read TIFF private subdirectory count"); | |
147 | return (0); | |
148 | } | |
149 | if (tif->tif_flags & TIFF_SWAB) | |
150 | TIFFSwabShort(&dircount); | |
151 | dir = (TIFFDirEntry *)CheckMalloc(tif, | |
152 | dircount * sizeof (TIFFDirEntry), "to read TIFF private subdirectory"); | |
153 | if (dir == NULL) | |
154 | return (0); | |
155 | if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) { | |
156 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Can not read TIFF private subdirectory"); | |
157 | goto bad; | |
158 | } | |
159 | /* | |
160 | * Read offset to next directory for sequential scans. | |
161 | */ | |
162 | (void) ReadOK(tif, &nextdiroff, sizeof (uint32)); | |
163 | } else { | |
164 | toff_t off = pdir_offset; | |
165 | ||
166 | if (off + sizeof (short) > tif->tif_size) { | |
167 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
168 | "Can not read TIFF private subdirectory count"); | |
169 | return (0); | |
170 | } else | |
171 | _TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16)); | |
172 | off += sizeof (uint16); | |
173 | if (tif->tif_flags & TIFF_SWAB) | |
174 | TIFFSwabShort(&dircount); | |
175 | dir = (TIFFDirEntry *)CheckMalloc(tif, | |
176 | dircount * sizeof (TIFFDirEntry), "to read TIFF private subdirectory"); | |
177 | if (dir == NULL) | |
178 | return (0); | |
179 | if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) { | |
180 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Can not read TIFF private subdirectory"); | |
181 | goto bad; | |
182 | } else | |
183 | _TIFFmemcpy(dir, tif->tif_base + off, | |
184 | dircount*sizeof (TIFFDirEntry)); | |
185 | off += dircount* sizeof (TIFFDirEntry); | |
186 | if (off + sizeof (uint32) < tif->tif_size) | |
187 | _TIFFmemcpy(&nextdiroff, tif->tif_base+off, sizeof (uint32)); | |
188 | } | |
189 | if (tif->tif_flags & TIFF_SWAB) | |
190 | TIFFSwabLong(&nextdiroff); | |
191 | ||
192 | /* | |
193 | * Setup default value and then make a pass over | |
194 | * the fields to check type and tag information, | |
195 | * and to extract info required to size data | |
196 | * structures. A second pass is made afterwards | |
197 | * to read in everthing not taken in the first pass. | |
198 | */ | |
199 | td = &tif->tif_dir; | |
200 | ||
201 | for (fip = field_info, dp = dir, n = dircount; | |
202 | n > 0; n--, dp++) { | |
203 | if (tif->tif_flags & TIFF_SWAB) { | |
204 | TIFFSwabArrayOfShort(&dp->tdir_tag, 2); | |
205 | TIFFSwabArrayOfLong(&dp->tdir_count, 2); | |
206 | } | |
207 | /* | |
208 | * Find the field information entry for this tag. | |
209 | */ | |
210 | /* | |
211 | * Silicon Beach (at least) writes unordered | |
212 | * directory tags (violating the spec). Handle | |
213 | * it here, but be obnoxious (maybe they'll fix it?). | |
214 | */ | |
215 | if (dp->tdir_tag < fip->field_tag) { | |
216 | if (!diroutoforderwarning) { | |
217 | TIFFWarning(tif->tif_name, | |
218 | "invalid TIFF private subdirectory; tags are not sorted in ascending order"); | |
219 | diroutoforderwarning = 1; | |
220 | } | |
221 | fip = field_info; /* O(n^2) */ | |
222 | } | |
223 | ||
224 | while (fip->field_tag && fip->field_tag < dp->tdir_tag) | |
225 | fip++; | |
226 | if (!fip->field_tag || fip->field_tag != dp->tdir_tag) { | |
227 | TIFFWarning(tif->tif_name, | |
228 | "unknown field with tag %d (0x%x) in private subdirectory ignored", | |
229 | dp->tdir_tag, dp->tdir_tag); | |
230 | dp->tdir_tag = IGNORE; | |
231 | fip = field_info;/* restart search */ | |
232 | continue; | |
233 | } | |
234 | /* | |
235 | * Null out old tags that we ignore. | |
236 | */ | |
237 | ||
238 | /* Not implemented yet, since FIELD_IGNORE is specific to | |
239 | the main directories. Could pass this in too... */ | |
240 | if (0 /* && fip->field_bit == FIELD_IGNORE */) { | |
241 | ignore: | |
242 | dp->tdir_tag = IGNORE; | |
243 | continue; | |
244 | } | |
245 | ||
246 | /* | |
247 | * Check data type. | |
248 | */ | |
249 | ||
250 | while (dp->tdir_type != (u_short)fip->field_type) { | |
251 | if (fip->field_type == TIFF_ANY) /* wildcard */ | |
252 | break; | |
253 | fip++; | |
254 | if (!fip->field_tag || fip->field_tag != dp->tdir_tag) { | |
255 | TIFFWarning(tif->tif_name, | |
256 | "wrong data type %d for \"%s\"; tag ignored", | |
257 | dp->tdir_type, fip[-1].field_name); | |
258 | goto ignore; | |
259 | } | |
260 | } | |
261 | /* | |
262 | * Check count if known in advance. | |
263 | */ | |
264 | if (fip->field_readcount != TIFF_VARIABLE) { | |
265 | uint32 expected = (fip->field_readcount == TIFF_SPP) ? | |
266 | (uint32) td->td_samplesperpixel : | |
267 | (uint32) fip->field_readcount; | |
268 | if (!CheckDirCount(tif, dp, expected)) | |
269 | goto ignore; | |
270 | } | |
271 | ||
272 | /* Now read in and process data from field. */ | |
273 | if (!TIFFFetchNormalSubTag(tif, dp, fip, setFieldFn)) | |
274 | goto bad; | |
275 | ||
276 | } | |
277 | ||
278 | if (dir) | |
279 | _TIFFfree(dir); | |
280 | return (1); | |
281 | bad: | |
282 | if (dir) | |
283 | _TIFFfree(dir); | |
284 | return (0); | |
285 | } | |
286 | ||
287 | static void | |
288 | EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) | |
289 | { | |
290 | register TIFFDirEntry *dp; | |
291 | register TIFFDirectory *td = &tif->tif_dir; | |
292 | uint16 i; | |
293 | ||
294 | if (td->td_stripbytecount) | |
295 | _TIFFfree(td->td_stripbytecount); | |
296 | td->td_stripbytecount = (uint32*) | |
297 | CheckMalloc(tif, td->td_nstrips * sizeof (uint32), | |
298 | "for \"StripByteCounts\" array"); | |
299 | if (td->td_compression != COMPRESSION_NONE) { | |
300 | uint32 space = (uint32)(sizeof (TIFFHeader) | |
301 | + sizeof (uint16) | |
302 | + (dircount * sizeof (TIFFDirEntry)) | |
303 | + sizeof (uint32)); | |
304 | toff_t filesize = TIFFGetFileSize(tif); | |
305 | uint16 n; | |
306 | ||
307 | /* calculate amount of space used by indirect values */ | |
308 | for (dp = dir, n = dircount; n > 0; n--, dp++) { | |
309 | uint32 cc = dp->tdir_count*TIFFDataWidth(dp->tdir_type); | |
310 | if (cc > sizeof (uint32)) | |
311 | space += cc; | |
312 | } | |
313 | space = (filesize - space) / td->td_samplesperpixel; | |
314 | for (i = 0; i < td->td_nstrips; i++) | |
315 | td->td_stripbytecount[i] = space; | |
316 | /* | |
317 | * This gross hack handles the case were the offset to | |
318 | * the last strip is past the place where we think the strip | |
319 | * should begin. Since a strip of data must be contiguous, | |
320 | * it's safe to assume that we've overestimated the amount | |
321 | * of data in the strip and trim this number back accordingly. | |
322 | */ | |
323 | i--; | |
324 | if (td->td_stripoffset[i] + td->td_stripbytecount[i] > filesize) | |
325 | td->td_stripbytecount[i] = | |
326 | filesize - td->td_stripoffset[i]; | |
327 | } else { | |
328 | uint32 rowbytes = TIFFScanlineSize(tif); | |
329 | uint32 rowsperstrip = td->td_imagelength / td->td_nstrips; | |
330 | for (i = 0; i < td->td_nstrips; i++) | |
331 | td->td_stripbytecount[i] = rowbytes*rowsperstrip; | |
332 | } | |
333 | TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); | |
334 | if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) | |
335 | td->td_rowsperstrip = td->td_imagelength; | |
336 | } | |
337 | ||
338 | static void | |
339 | MissingRequired(TIFF* tif, const char* tagname) | |
340 | { | |
341 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
342 | "TIFF directory is missing required \"%s\" field", tagname); | |
343 | } | |
344 | ||
345 | /* | |
346 | * Check the count field of a directory | |
347 | * entry against a known value. The caller | |
348 | * is expected to skip/ignore the tag if | |
349 | * there is a mismatch. | |
350 | */ | |
351 | static int | |
352 | CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count) | |
353 | { | |
354 | if (count != dir->tdir_count) { | |
355 | TIFFWarning(tif->tif_name, | |
356 | "incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored", | |
357 | _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, | |
358 | dir->tdir_count, count); | |
359 | return (0); | |
360 | } | |
361 | return (1); | |
362 | } | |
363 | ||
364 | /* | |
365 | * Fetch a contiguous directory item. | |
366 | */ | |
367 | static tsize_t | |
368 | TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp) | |
369 | { | |
370 | int w = TIFFDataWidth(dir->tdir_type); | |
371 | tsize_t cc = dir->tdir_count * w; | |
372 | ||
373 | if (!isMapped(tif)) { | |
374 | if (!SeekOK(tif, dir->tdir_offset)) | |
375 | goto bad; | |
376 | if (!ReadOK(tif, cp, cc)) | |
377 | goto bad; | |
378 | } else { | |
379 | if (dir->tdir_offset + cc > tif->tif_size) | |
380 | goto bad; | |
381 | _TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc); | |
382 | } | |
383 | if (tif->tif_flags & TIFF_SWAB) { | |
384 | switch (dir->tdir_type) { | |
385 | case TIFF_SHORT: | |
386 | case TIFF_SSHORT: | |
387 | TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); | |
388 | break; | |
389 | case TIFF_LONG: | |
390 | case TIFF_SLONG: | |
391 | case TIFF_FLOAT: | |
392 | TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); | |
393 | break; | |
394 | case TIFF_RATIONAL: | |
395 | case TIFF_SRATIONAL: | |
396 | TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); | |
397 | break; | |
398 | case TIFF_DOUBLE: | |
399 | TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); | |
400 | break; | |
401 | } | |
402 | } | |
403 | return (cc); | |
404 | bad: | |
405 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error fetching data for field \"%s\"", | |
406 | _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); | |
407 | return ((tsize_t) 0); | |
408 | } | |
409 | ||
410 | /* | |
411 | * Fetch an ASCII item from the file. | |
412 | */ | |
413 | static tsize_t | |
414 | TIFFFetchString(TIFF* tif, TIFFDirEntry* dir, char* cp) | |
415 | { | |
416 | if (dir->tdir_count <= 4) { | |
417 | uint32 l = dir->tdir_offset; | |
418 | if (tif->tif_flags & TIFF_SWAB) | |
419 | TIFFSwabLong(&l); | |
420 | _TIFFmemcpy(cp, &l, dir->tdir_count); | |
421 | return (1); | |
422 | } | |
423 | return (TIFFFetchData(tif, dir, cp)); | |
424 | } | |
425 | ||
426 | /* | |
427 | * Convert numerator+denominator to float. | |
428 | */ | |
429 | static int | |
430 | cvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv) | |
431 | { | |
432 | if (denom == 0) { | |
433 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
434 | "%s: Rational with zero denominator (num = %lu)", | |
435 | _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num); | |
436 | return (0); | |
437 | } else { | |
438 | if (dir->tdir_type == TIFF_RATIONAL) | |
439 | *rv = ((float)num / (float)denom); | |
440 | else | |
441 | *rv = ((float)(int32)num / (float)(int32)denom); | |
442 | return (1); | |
443 | } | |
444 | } | |
445 | ||
446 | /* | |
447 | * Fetch a rational item from the file | |
448 | * at offset off and return the value | |
449 | * as a floating point number. | |
450 | */ | |
451 | static float | |
452 | TIFFFetchRational(TIFF* tif, TIFFDirEntry* dir) | |
453 | { | |
454 | uint32 l[2]; | |
455 | float v; | |
456 | ||
457 | return (!TIFFFetchData(tif, dir, (char *)l) || | |
458 | !cvtRational(tif, dir, l[0], l[1], &v) ? 1.0f : v); | |
459 | } | |
460 | ||
461 | /* | |
462 | * Fetch a single floating point value | |
463 | * from the offset field and return it | |
464 | * as a native float. | |
465 | */ | |
466 | static float | |
467 | TIFFFetchFloat(TIFF* tif, TIFFDirEntry* dir) | |
468 | { | |
469 | /* This appears to be a flagrant bug in the TIFF library, yet I | |
470 | actually don't understand how it could have ever worked the old | |
471 | way. Look at the comments in my new code and you'll understand. */ | |
472 | #if (0) | |
473 | float v = (float) | |
474 | TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset); | |
475 | TIFFCvtIEEEFloatToNative(tif, 1, &v); | |
476 | #else | |
477 | float v; | |
478 | /* This is a little bit tricky - if we just cast the uint32 to a float, | |
479 | C will perform a numerical conversion, which is not what we want. | |
480 | We want to take the actual bit pattern in the uint32 and interpret | |
481 | it as a float. Thus we cast a uint32 * into a float * and then | |
482 | dereference to get v. */ | |
483 | uint32 l = (uint32) | |
484 | TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset); | |
485 | v = * (float *) &l; | |
486 | TIFFCvtIEEEFloatToNative(tif, 1, &v); | |
487 | #endif | |
488 | return (v); | |
489 | ||
490 | } | |
491 | ||
492 | /* | |
493 | * Fetch an array of BYTE or SBYTE values. | |
494 | */ | |
495 | static int | |
496 | TIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint16* v) | |
497 | { | |
498 | if (dir->tdir_count <= 4) { | |
499 | /* | |
500 | * Extract data from offset field. | |
501 | */ | |
502 | if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { | |
503 | switch (dir->tdir_count) { | |
504 | case 4: v[3] = dir->tdir_offset & 0xff; | |
505 | case 3: v[2] = (dir->tdir_offset >> 8) & 0xff; | |
506 | case 2: v[1] = (dir->tdir_offset >> 16) & 0xff; | |
507 | case 1: v[0] = dir->tdir_offset >> 24; | |
508 | } | |
509 | } else { | |
510 | switch (dir->tdir_count) { | |
511 | case 4: v[3] = dir->tdir_offset >> 24; | |
512 | case 3: v[2] = (dir->tdir_offset >> 16) & 0xff; | |
513 | case 2: v[1] = (dir->tdir_offset >> 8) & 0xff; | |
514 | case 1: v[0] = dir->tdir_offset & 0xff; | |
515 | } | |
516 | } | |
517 | return (1); | |
518 | } else | |
519 | return (TIFFFetchData(tif, dir, (char*) v) != 0); /* XXX */ | |
520 | } | |
521 | ||
522 | /* | |
523 | * Fetch an array of SHORT or SSHORT values. | |
524 | */ | |
525 | static int | |
526 | TIFFFetchShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v) | |
527 | { | |
528 | if (dir->tdir_count <= 2) { | |
529 | if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { | |
530 | switch (dir->tdir_count) { | |
531 | case 2: v[1] = dir->tdir_offset & 0xffff; | |
532 | case 1: v[0] = dir->tdir_offset >> 16; | |
533 | } | |
534 | } else { | |
535 | switch (dir->tdir_count) { | |
536 | case 2: v[1] = dir->tdir_offset >> 16; | |
537 | case 1: v[0] = dir->tdir_offset & 0xffff; | |
538 | } | |
539 | } | |
540 | return (1); | |
541 | } else | |
542 | return (TIFFFetchData(tif, dir, (char *)v) != 0); | |
543 | } | |
544 | ||
545 | /* | |
546 | * Fetch a pair of SHORT or BYTE values. | |
547 | */ | |
548 | static int | |
549 | TIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir) | |
550 | { | |
551 | uint16 v[2]; | |
552 | int ok = 0; | |
553 | ||
554 | switch (dir->tdir_type) { | |
555 | case TIFF_SHORT: | |
556 | case TIFF_SSHORT: | |
557 | ok = TIFFFetchShortArray(tif, dir, v); | |
558 | break; | |
559 | case TIFF_BYTE: | |
560 | case TIFF_SBYTE: | |
561 | ok = TIFFFetchByteArray(tif, dir, v); | |
562 | break; | |
563 | } | |
564 | if (ok) | |
565 | TIFFSetField(tif, dir->tdir_tag, v[0], v[1]); | |
566 | return (ok); | |
567 | } | |
568 | ||
569 | /* | |
570 | * Fetch an array of LONG or SLONG values. | |
571 | */ | |
572 | static int | |
573 | TIFFFetchLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v) | |
574 | { | |
575 | if (dir->tdir_count == 1) { | |
576 | v[0] = dir->tdir_offset; | |
577 | return (1); | |
578 | } else | |
579 | return (TIFFFetchData(tif, dir, (char*) v) != 0); | |
580 | } | |
581 | ||
582 | /* | |
583 | * Fetch an array of RATIONAL or SRATIONAL values. | |
584 | */ | |
585 | static int | |
586 | TIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v) | |
587 | { | |
588 | int ok = 0; | |
589 | uint32* l; | |
590 | ||
591 | l = (uint32*)CheckMalloc(tif, | |
592 | dir->tdir_count*TIFFDataWidth(dir->tdir_type), | |
593 | "to fetch array of rationals"); | |
594 | if (l) { | |
595 | if (TIFFFetchData(tif, dir, (char *)l)) { | |
596 | uint32 i; | |
597 | for (i = 0; i < dir->tdir_count; i++) { | |
598 | ok = cvtRational(tif, dir, | |
599 | l[2*i+0], l[2*i+1], &v[i]); | |
600 | if (!ok) | |
601 | break; | |
602 | } | |
603 | } | |
604 | _TIFFfree((char *)l); | |
605 | } | |
606 | return (ok); | |
607 | } | |
608 | ||
609 | /* | |
610 | * Fetch an array of FLOAT values. | |
611 | */ | |
612 | static int | |
613 | TIFFFetchFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v) | |
614 | { | |
615 | ||
616 | if (dir->tdir_count == 1) { | |
617 | v[0] = *(float*) &dir->tdir_offset; | |
618 | TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); | |
619 | return (1); | |
620 | } else if (TIFFFetchData(tif, dir, (char*) v)) { | |
621 | TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); | |
622 | return (1); | |
623 | } else | |
624 | return (0); | |
625 | } | |
626 | ||
627 | /* | |
628 | * Fetch an array of DOUBLE values. | |
629 | */ | |
630 | static int | |
631 | TIFFFetchDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v) | |
632 | { | |
633 | if (TIFFFetchData(tif, dir, (char*) v)) { | |
634 | TIFFCvtIEEEDoubleToNative(tif, dir->tdir_count, v); | |
635 | return (1); | |
636 | } else | |
637 | return (0); | |
638 | } | |
639 | ||
640 | /* | |
641 | * Fetch an array of ANY values. The actual values are | |
642 | * returned as doubles which should be able hold all the | |
643 | * types. Yes, there really should be an tany_t to avoid | |
644 | * this potential non-portability ... Note in particular | |
645 | * that we assume that the double return value vector is | |
646 | * large enough to read in any fundamental type. We use | |
647 | * that vector as a buffer to read in the base type vector | |
648 | * and then convert it in place to double (from end | |
649 | * to front of course). | |
650 | */ | |
651 | static int | |
652 | TIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v) | |
653 | { | |
654 | int i; | |
655 | ||
656 | switch (dir->tdir_type) { | |
657 | case TIFF_BYTE: | |
658 | case TIFF_SBYTE: | |
659 | if (!TIFFFetchByteArray(tif, dir, (uint16*) v)) | |
660 | return (0); | |
661 | if (dir->tdir_type == TIFF_BYTE) { | |
662 | uint16* vp = (uint16*) v; | |
663 | for (i = dir->tdir_count-1; i >= 0; i--) | |
664 | v[i] = vp[i]; | |
665 | } else { | |
666 | int16* vp = (int16*) v; | |
667 | for (i = dir->tdir_count-1; i >= 0; i--) | |
668 | v[i] = vp[i]; | |
669 | } | |
670 | break; | |
671 | case TIFF_SHORT: | |
672 | case TIFF_SSHORT: | |
673 | if (!TIFFFetchShortArray(tif, dir, (uint16*) v)) | |
674 | return (0); | |
675 | if (dir->tdir_type == TIFF_SHORT) { | |
676 | uint16* vp = (uint16*) v; | |
677 | for (i = dir->tdir_count-1; i >= 0; i--) | |
678 | v[i] = vp[i]; | |
679 | } else { | |
680 | int16* vp = (int16*) v; | |
681 | for (i = dir->tdir_count-1; i >= 0; i--) | |
682 | v[i] = vp[i]; | |
683 | } | |
684 | break; | |
685 | case TIFF_LONG: | |
686 | case TIFF_SLONG: | |
687 | if (!TIFFFetchLongArray(tif, dir, (uint32*) v)) | |
688 | return (0); | |
689 | if (dir->tdir_type == TIFF_LONG) { | |
690 | uint32* vp = (uint32*) v; | |
691 | for (i = dir->tdir_count-1; i >= 0; i--) | |
692 | v[i] = vp[i]; | |
693 | } else { | |
694 | int32* vp = (int32*) v; | |
695 | for (i = dir->tdir_count-1; i >= 0; i--) | |
696 | v[i] = vp[i]; | |
697 | } | |
698 | break; | |
699 | case TIFF_RATIONAL: | |
700 | case TIFF_SRATIONAL: | |
701 | if (!TIFFFetchRationalArray(tif, dir, (float*) v)) | |
702 | return (0); | |
703 | { float* vp = (float*) v; | |
704 | for (i = dir->tdir_count-1; i >= 0; i--) | |
705 | v[i] = vp[i]; | |
706 | } | |
707 | break; | |
708 | case TIFF_FLOAT: | |
709 | if (!TIFFFetchFloatArray(tif, dir, (float*) v)) | |
710 | return (0); | |
711 | { float* vp = (float*) v; | |
712 | for (i = dir->tdir_count-1; i >= 0; i--) | |
713 | v[i] = vp[i]; | |
714 | } | |
715 | break; | |
716 | case TIFF_DOUBLE: | |
717 | return (TIFFFetchDoubleArray(tif, dir, (double*) v)); | |
718 | default: | |
719 | /* TIFF_NOTYPE */ | |
720 | /* TIFF_ASCII */ | |
721 | /* TIFF_UNDEFINED */ | |
722 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
723 | "Cannot read TIFF_ANY type %d for field \"%s\"", | |
724 | _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); | |
725 | return (0); | |
726 | } | |
727 | return (1); | |
728 | } | |
729 | ||
730 | ||
731 | /* | |
732 | * Fetch a tag that is not handled by special case code. | |
733 | */ | |
734 | /* The standard function TIFFFetchNormalTag() could definitely be replaced | |
735 | with a simple call to this function, just adding TIFFSetField() as the | |
736 | last argument. */ | |
737 | static int | |
738 | TIFFFetchNormalSubTag(TIFF* tif, TIFFDirEntry* dp, const TIFFFieldInfo* fip, | |
739 | int (*setFieldFn)(TIFF *tif, ttag_t tag, ...)) | |
740 | { | |
741 | static char mesg[] = "to fetch tag value"; | |
742 | int ok = 0; | |
743 | ||
744 | if (dp->tdir_count > 1) { /* array of values */ | |
745 | char* cp = NULL; | |
746 | ||
747 | switch (dp->tdir_type) { | |
748 | case TIFF_BYTE: | |
749 | case TIFF_SBYTE: | |
750 | /* NB: always expand BYTE values to shorts */ | |
751 | cp = CheckMalloc(tif, | |
752 | dp->tdir_count * sizeof (uint16), mesg); | |
753 | ok = cp && TIFFFetchByteArray(tif, dp, (uint16*) cp); | |
754 | break; | |
755 | case TIFF_SHORT: | |
756 | case TIFF_SSHORT: | |
757 | cp = CheckMalloc(tif, | |
758 | dp->tdir_count * sizeof (uint16), mesg); | |
759 | ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp); | |
760 | break; | |
761 | case TIFF_LONG: | |
762 | case TIFF_SLONG: | |
763 | cp = CheckMalloc(tif, | |
764 | dp->tdir_count * sizeof (uint32), mesg); | |
765 | ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp); | |
766 | break; | |
767 | case TIFF_RATIONAL: | |
768 | case TIFF_SRATIONAL: | |
769 | cp = CheckMalloc(tif, | |
770 | dp->tdir_count * sizeof (float), mesg); | |
771 | ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp); | |
772 | break; | |
773 | case TIFF_FLOAT: | |
774 | cp = CheckMalloc(tif, | |
775 | dp->tdir_count * sizeof (float), mesg); | |
776 | ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp); | |
777 | break; | |
778 | case TIFF_DOUBLE: | |
779 | cp = CheckMalloc(tif, | |
780 | dp->tdir_count * sizeof (double), mesg); | |
781 | ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp); | |
782 | break; | |
783 | case TIFF_ASCII: | |
784 | case TIFF_UNDEFINED: /* bit of a cheat... */ | |
785 | /* | |
786 | * Some vendors write strings w/o the trailing | |
787 | * NULL byte, so always append one just in case. | |
788 | */ | |
789 | cp = CheckMalloc(tif, dp->tdir_count+1, mesg); | |
790 | if (ok = (cp && TIFFFetchString(tif, dp, cp))) | |
791 | cp[dp->tdir_count] = '\0'; /* XXX */ | |
792 | break; | |
793 | } | |
794 | if (ok) { | |
795 | ok = (fip->field_passcount ? | |
796 | (*setFieldFn)(tif, dp->tdir_tag, dp->tdir_count, cp) | |
797 | : (*setFieldFn)(tif, dp->tdir_tag, cp)); | |
798 | } | |
799 | if (cp != NULL) | |
800 | _TIFFfree(cp); | |
801 | } else if (CheckDirCount(tif, dp, 1)) { /* singleton value */ | |
802 | switch (dp->tdir_type) { | |
803 | case TIFF_BYTE: | |
804 | case TIFF_SBYTE: | |
805 | case TIFF_SHORT: | |
806 | case TIFF_SSHORT: | |
807 | /* | |
808 | * If the tag is also acceptable as a LONG or SLONG | |
809 | * then (*setFieldFn) will expect an uint32 parameter | |
810 | * passed to it (through varargs). Thus, for machines | |
811 | * where sizeof (int) != sizeof (uint32) we must do | |
812 | * a careful check here. It's hard to say if this | |
813 | * is worth optimizing. | |
814 | * | |
815 | * NB: We use TIFFFieldWithTag here knowing that | |
816 | * it returns us the first entry in the table | |
817 | * for the tag and that that entry is for the | |
818 | * widest potential data type the tag may have. | |
819 | */ | |
820 | { TIFFDataType type = fip->field_type; | |
821 | if (type != TIFF_LONG && type != TIFF_SLONG) { | |
822 | uint16 v = (uint16) | |
823 | TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); | |
824 | ok = (fip->field_passcount ? | |
825 | (*setFieldFn)(tif, dp->tdir_tag, 1, &v) | |
826 | : (*setFieldFn)(tif, dp->tdir_tag, v)); | |
827 | break; | |
828 | } | |
829 | } | |
830 | /* fall thru... */ | |
831 | case TIFF_LONG: | |
832 | case TIFF_SLONG: | |
833 | { uint32 v32 = | |
834 | TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); | |
835 | ok = (fip->field_passcount ? | |
836 | (*setFieldFn)(tif, dp->tdir_tag, 1, &v32) | |
837 | : (*setFieldFn)(tif, dp->tdir_tag, v32)); | |
838 | } | |
839 | break; | |
840 | case TIFF_RATIONAL: | |
841 | case TIFF_SRATIONAL: | |
842 | case TIFF_FLOAT: | |
843 | { float v = (dp->tdir_type == TIFF_FLOAT ? | |
844 | TIFFFetchFloat(tif, dp) | |
845 | : TIFFFetchRational(tif, dp)); | |
846 | ok = (fip->field_passcount ? | |
847 | (*setFieldFn)(tif, dp->tdir_tag, 1, &v) | |
848 | : (*setFieldFn)(tif, dp->tdir_tag, v)); | |
849 | } | |
850 | break; | |
851 | case TIFF_DOUBLE: | |
852 | { double v; | |
853 | ok = (TIFFFetchDoubleArray(tif, dp, &v) && | |
854 | (fip->field_passcount ? | |
855 | (*setFieldFn)(tif, dp->tdir_tag, 1, &v) | |
856 | : (*setFieldFn)(tif, dp->tdir_tag, v)) | |
857 | ); | |
858 | } | |
859 | break; | |
860 | case TIFF_ASCII: | |
861 | case TIFF_UNDEFINED: /* bit of a cheat... */ | |
862 | { char c[2]; | |
863 | if (ok = (TIFFFetchString(tif, dp, c) != 0)) { | |
864 | c[1] = '\0'; /* XXX paranoid */ | |
865 | ok = (*setFieldFn)(tif, dp->tdir_tag, c); | |
866 | } | |
867 | } | |
868 | break; | |
869 | } | |
870 | } | |
871 | return (ok); | |
872 | } | |
873 | ||
874 | /* Everything after this is exactly duplicated from the standard tif_dirread.c | |
875 | file, necessitated by the fact that they are declared static there so | |
876 | we can't call them! | |
877 | */ | |
878 | #define NITEMS(x) (sizeof (x) / sizeof (x[0])) | |
879 | /* | |
880 | * Fetch samples/pixel short values for | |
881 | * the specified tag and verify that | |
882 | * all values are the same. | |
883 | */ | |
884 | static int | |
885 | TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, int* pl) | |
886 | { | |
887 | int samples = tif->tif_dir.td_samplesperpixel; | |
888 | int status = 0; | |
889 | ||
890 | if (CheckDirCount(tif, dir, (uint32) samples)) { | |
891 | uint16 buf[10]; | |
892 | uint16* v = buf; | |
893 | ||
894 | if (samples > NITEMS(buf)) | |
895 | v = (uint16*) _TIFFmalloc(samples * sizeof (uint16)); | |
896 | if (TIFFFetchShortArray(tif, dir, v)) { | |
897 | int i; | |
898 | for (i = 1; i < samples; i++) | |
899 | if (v[i] != v[0]) { | |
900 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
901 | "Cannot handle different per-sample values for field \"%s\"", | |
902 | _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); | |
903 | goto bad; | |
904 | } | |
905 | *pl = v[0]; | |
906 | status = 1; | |
907 | } | |
908 | bad: | |
909 | if (v != buf) | |
910 | _TIFFfree((char*) v); | |
911 | } | |
912 | return (status); | |
913 | } | |
914 | ||
915 | /* | |
916 | * Fetch samples/pixel ANY values for | |
917 | * the specified tag and verify that | |
918 | * all values are the same. | |
919 | */ | |
920 | static int | |
921 | TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl) | |
922 | { | |
923 | int samples = (int) tif->tif_dir.td_samplesperpixel; | |
924 | int status = 0; | |
925 | ||
926 | if (CheckDirCount(tif, dir, (uint32) samples)) { | |
927 | double buf[10]; | |
928 | double* v = buf; | |
929 | ||
930 | if (samples > NITEMS(buf)) | |
931 | v = (double*) _TIFFmalloc(samples * sizeof (double)); | |
932 | if (TIFFFetchAnyArray(tif, dir, v)) { | |
933 | int i; | |
934 | for (i = 1; i < samples; i++) | |
935 | if (v[i] != v[0]) { | |
936 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
937 | "Cannot handle different per-sample values for field \"%s\"", | |
938 | _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); | |
939 | goto bad; | |
940 | } | |
941 | *pl = v[0]; | |
942 | status = 1; | |
943 | } | |
944 | bad: | |
945 | if (v != buf) | |
946 | _TIFFfree(v); | |
947 | } | |
948 | return (status); | |
949 | } | |
950 | #undef NITEMS | |
951 | ||
952 | /* | |
953 | * Fetch a set of offsets or lengths. | |
954 | * While this routine says "strips", | |
955 | * in fact it's also used for tiles. | |
956 | */ | |
957 | static int | |
958 | TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, long nstrips, uint32** lpp) | |
959 | { | |
960 | register uint32* lp; | |
961 | int status; | |
962 | ||
963 | if (!CheckDirCount(tif, dir, (uint32) nstrips)) | |
964 | return (0); | |
965 | /* | |
966 | * Allocate space for strip information. | |
967 | */ | |
968 | if (*lpp == NULL && | |
969 | (*lpp = (uint32 *)CheckMalloc(tif, | |
970 | nstrips * sizeof (uint32), "for strip array")) == NULL) | |
971 | return (0); | |
972 | lp = *lpp; | |
973 | if (dir->tdir_type == (int)TIFF_SHORT) { | |
974 | /* | |
975 | * Handle uint16->uint32 expansion. | |
976 | */ | |
977 | uint16* dp = (uint16*) CheckMalloc(tif, | |
978 | dir->tdir_count* sizeof (uint16), "to fetch strip tag"); | |
979 | if (dp == NULL) | |
980 | return (0); | |
981 | if (status = TIFFFetchShortArray(tif, dir, dp)) { | |
982 | register uint16* wp = dp; | |
983 | while (nstrips-- > 0) | |
984 | *lp++ = *wp++; | |
985 | } | |
986 | _TIFFfree((char*) dp); | |
987 | } else | |
988 | status = TIFFFetchLongArray(tif, dir, lp); | |
989 | return (status); | |
990 | } | |
991 | ||
992 | #define NITEMS(x) (sizeof (x) / sizeof (x[0])) | |
993 | /* | |
994 | * Fetch and set the ExtraSamples tag. | |
995 | */ | |
996 | static int | |
997 | TIFFFetchExtraSamples(TIFF* tif, TIFFDirEntry* dir) | |
998 | { | |
999 | uint16 buf[10]; | |
1000 | uint16* v = buf; | |
1001 | int status; | |
1002 | ||
1003 | if (dir->tdir_count > NITEMS(buf)) | |
1004 | v = (uint16*) _TIFFmalloc(dir->tdir_count * sizeof (uint16)); | |
1005 | if (dir->tdir_type == TIFF_BYTE) | |
1006 | status = TIFFFetchByteArray(tif, dir, v); | |
1007 | else | |
1008 | status = TIFFFetchShortArray(tif, dir, v); | |
1009 | if (status) | |
1010 | status = TIFFSetField(tif, dir->tdir_tag, dir->tdir_count, v); | |
1011 | if (v != buf) | |
1012 | _TIFFfree((char*) v); | |
1013 | return (status); | |
1014 | } | |
1015 | #undef NITEMS | |
1016 | ||
1017 | #ifdef COLORIMETRY_SUPPORT | |
1018 | /* | |
1019 | * Fetch and set the RefBlackWhite tag. | |
1020 | */ | |
1021 | static int | |
1022 | TIFFFetchRefBlackWhite(TIFF* tif, TIFFDirEntry* dir) | |
1023 | { | |
1024 | static char mesg[] = "for \"ReferenceBlackWhite\" array"; | |
1025 | char* cp; | |
1026 | int ok; | |
1027 | ||
1028 | if (dir->tdir_type == TIFF_RATIONAL) | |
1029 | return (1/*TIFFFetchNormalTag(tif, dir) just so linker won't complain - this part of the code is never used anyway */); | |
1030 | /* | |
1031 | * Handle LONG's for backward compatibility. | |
1032 | */ | |
1033 | cp = CheckMalloc(tif, dir->tdir_count * sizeof (uint32), mesg); | |
1034 | if (ok = (cp && TIFFFetchLongArray(tif, dir, (uint32*) cp))) { | |
1035 | float* fp = (float*) | |
1036 | CheckMalloc(tif, dir->tdir_count * sizeof (float), mesg); | |
1037 | if (ok = (fp != NULL)) { | |
1038 | uint32 i; | |
1039 | for (i = 0; i < dir->tdir_count; i++) | |
1040 | fp[i] = (float)((uint32*) cp)[i]; | |
1041 | ok = TIFFSetField(tif, dir->tdir_tag, fp); | |
1042 | _TIFFfree((char*) fp); | |
1043 | } | |
1044 | } | |
1045 | if (cp) | |
1046 | _TIFFfree(cp); | |
1047 | return (ok); | |
1048 | } | |
1049 | #endif | |
1050 | ||
1051 | #if STRIPCHOP_SUPPORT | |
1052 | /* | |
1053 | * Replace a single strip (tile) of uncompressed data by | |
1054 | * multiple strips (tiles), each approximately 8Kbytes. | |
1055 | * This is useful for dealing with large images or | |
1056 | * for dealing with machines with a limited amount | |
1057 | * memory. | |
1058 | */ | |
1059 | static void | |
1060 | ChopUpSingleUncompressedStrip(TIFF* tif) | |
1061 | { | |
1062 | register TIFFDirectory *td = &tif->tif_dir; | |
1063 | uint32 bytecount = td->td_stripbytecount[0]; | |
1064 | uint32 offset = td->td_stripoffset[0]; | |
1065 | tsize_t rowbytes = TIFFVTileSize(tif, 1), stripbytes; | |
1066 | tstrip_t strip, nstrips, rowsperstrip; | |
1067 | uint32* newcounts; | |
1068 | uint32* newoffsets; | |
1069 | ||
1070 | /* | |
1071 | * Make the rows hold at least one | |
1072 | * scanline, but fill 8k if possible. | |
1073 | */ | |
1074 | if (rowbytes > 8192) { | |
1075 | stripbytes = rowbytes; | |
1076 | rowsperstrip = 1; | |
1077 | } else { | |
1078 | rowsperstrip = 8192 / rowbytes; | |
1079 | stripbytes = rowbytes * rowsperstrip; | |
1080 | } | |
1081 | /* never increase the number of strips in an image */ | |
1082 | if (rowsperstrip >= td->td_rowsperstrip) | |
1083 | return; | |
1084 | nstrips = (tstrip_t) TIFFhowmany(bytecount, stripbytes); | |
1085 | newcounts = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32), | |
1086 | "for chopped \"StripByteCounts\" array"); | |
1087 | newoffsets = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32), | |
1088 | "for chopped \"StripOffsets\" array"); | |
1089 | if (newcounts == NULL || newoffsets == NULL) { | |
1090 | /* | |
1091 | * Unable to allocate new strip information, give | |
1092 | * up and use the original one strip information. | |
1093 | */ | |
1094 | if (newcounts != NULL) | |
1095 | _TIFFfree(newcounts); | |
1096 | if (newoffsets != NULL) | |
1097 | _TIFFfree(newoffsets); | |
1098 | return; | |
1099 | } | |
1100 | /* | |
1101 | * Fill the strip information arrays with | |
1102 | * new bytecounts and offsets that reflect | |
1103 | * the broken-up format. | |
1104 | */ | |
1105 | for (strip = 0; strip < nstrips; strip++) { | |
1106 | if (stripbytes > bytecount) | |
1107 | stripbytes = bytecount; | |
1108 | newcounts[strip] = stripbytes; | |
1109 | newoffsets[strip] = offset; | |
1110 | offset += stripbytes; | |
1111 | bytecount -= stripbytes; | |
1112 | } | |
1113 | /* | |
1114 | * Replace old single strip info with multi-strip info. | |
1115 | */ | |
1116 | td->td_stripsperimage = td->td_nstrips = nstrips; | |
1117 | TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); | |
1118 | ||
1119 | _TIFFfree(td->td_stripbytecount); | |
1120 | _TIFFfree(td->td_stripoffset); | |
1121 | td->td_stripbytecount = newcounts; | |
1122 | td->td_stripoffset = newoffsets; | |
1123 | } | |
1124 | #endif /* STRIPCHOP_SUPPORT */ |