]>
Commit | Line | Data |
---|---|---|
1 | /* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_pdsdirwrite.c,v 1.3 2005/12/21 12:23:13 joris Exp $ */ | |
2 | ||
3 | /* When writing data to TIFF files, it is often useful to store application- | |
4 | specific data in a private TIFF directory so that the tags don't need to | |
5 | be registered and won't conflict with other people's user-defined tags. | |
6 | One needs to have a registered public tag which contains some amount of | |
7 | raw data. That raw data, however, is interpreted at an independent, | |
8 | separate, private tiff directory. This file provides some routines which | |
9 | will be useful for converting that data from its raw binary form into | |
10 | the proper form for your application. | |
11 | */ | |
12 | ||
13 | /* | |
14 | * Copyright (c) 1988-1996 Sam Leffler | |
15 | * Copyright (c) 1991-1996 Silicon Graphics, Inc. | |
16 | * Copyright (c( 1996 USAF Phillips Laboratory | |
17 | * | |
18 | * Permission to use, copy, modify, distribute, and sell this software and | |
19 | * its documentation for any purpose is hereby granted without fee, provided | |
20 | * that (i) the above copyright notices and this permission notice appear in | |
21 | * all copies of the software and related documentation, and (ii) the names of | |
22 | * Sam Leffler and Silicon Graphics may not be used in any advertising or | |
23 | * publicity relating to the software without the specific, prior written | |
24 | * permission of Sam Leffler and Silicon Graphics. | |
25 | * | |
26 | * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, | |
27 | * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY | |
28 | * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | |
29 | * | |
30 | * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR | |
31 | * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, | |
32 | * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
33 | * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF | |
34 | * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
35 | * OF THIS SOFTWARE. | |
36 | */ | |
37 | ||
38 | /* | |
39 | * TIFF Library. | |
40 | * | |
41 | * These routines written by Conrad J. Poelman on a single late-night of | |
42 | * March 20-21, 1996. | |
43 | * | |
44 | * The entire purpose of this file is to provide a single external function, | |
45 | * TIFFWritePrivateDataSubDirectory(). This function is intended for use | |
46 | * in writing a private subdirectory structure into a TIFF file. The | |
47 | * actual reading of data from the structure is handled by the getFieldFn(), | |
48 | * which is passed to TIFFWritePrivateDataSubDirectory() as a parameter. The | |
49 | * idea is to enable any application wishing to read private subdirectories to | |
50 | * do so easily using this function, without modifying the TIFF library. | |
51 | * | |
52 | * The astute observer will notice that only two functions are at all different | |
53 | * from the original tif_dirwrite.c file: TIFFWritePrivateDataSubDirectory()and | |
54 | * TIFFWriteNormalSubTag(). All the other stuff that makes this file so huge | |
55 | * is only necessary because all of those functions are declared static in | |
56 | * tif_dirwrite.c, so we have to totally duplicate them in order to use them. | |
57 | * | |
58 | * Oh, also please note the bug-fix in the routine TIFFWriteNormalSubTag(), | |
59 | * which equally should be applied to TIFFWriteNormalTag(). | |
60 | * | |
61 | */ | |
62 | #include "tiffiop.h" | |
63 | ||
64 | #if HAVE_IEEEFP | |
65 | #define TIFFCvtNativeToIEEEFloat(tif, n, fp) | |
66 | #define TIFFCvtNativeToIEEEDouble(tif, n, dp) | |
67 | #else | |
68 | extern void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*); | |
69 | extern void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*); | |
70 | #endif | |
71 | ||
72 | static int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*); | |
73 | static int TIFFWriteNormalSubTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*, | |
74 | int (*getFieldFn)(TIFF *tif,ttag_t tag,...)); | |
75 | static void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32); | |
76 | static int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*); | |
77 | static int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*); | |
78 | static int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*); | |
79 | static int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**); | |
80 | static int TIFFWriteShortArray(TIFF*, | |
81 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint16*); | |
82 | static int TIFFWriteLongArray(TIFF *, | |
83 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint32*); | |
84 | static int TIFFWriteRationalArray(TIFF *, | |
85 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*); | |
86 | static int TIFFWriteFloatArray(TIFF *, | |
87 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*); | |
88 | static int TIFFWriteDoubleArray(TIFF *, | |
89 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*); | |
90 | static int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*); | |
91 | static int TIFFWriteAnyArray(TIFF*, | |
92 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*); | |
93 | #ifdef COLORIMETRY_SUPPORT | |
94 | static int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*); | |
95 | #endif | |
96 | static int TIFFWriteData(TIFF*, TIFFDirEntry*, char*); | |
97 | static int TIFFLinkDirectory(TIFF*); | |
98 | ||
99 | #define WriteRationalPair(type, tag1, v1, tag2, v2) { \ | |
100 | if (!TIFFWriteRational(tif, type, tag1, dir, v1)) \ | |
101 | goto bad; \ | |
102 | if (!TIFFWriteRational(tif, type, tag2, dir+1, v2)) \ | |
103 | goto bad; \ | |
104 | dir++; \ | |
105 | } | |
106 | #define TIFFWriteRational(tif, type, tag, dir, v) \ | |
107 | TIFFWriteRationalArray((tif), (type), (tag), (dir), 1, &(v)) | |
108 | #ifndef TIFFWriteRational | |
109 | static int TIFFWriteRational(TIFF*, | |
110 | TIFFDataType, ttag_t, TIFFDirEntry*, float); | |
111 | #endif | |
112 | ||
113 | /* This function will write an entire directory to the disk, and return the | |
114 | offset value indicating where in the file it wrote the beginning of the | |
115 | directory structure. This is NOT the same as the offset value before | |
116 | calling this function, because some of the fields may have caused various | |
117 | data items to be written out BEFORE writing the directory structure. | |
118 | ||
119 | This code was basically written by ripping of the TIFFWriteDirectory() | |
120 | code and generalizing it, using RPS's TIFFWritePliIfd() code for | |
121 | inspiration. My original goal was to make this code general enough that | |
122 | the original TIFFWriteDirectory() could be rewritten to just call this | |
123 | function with the appropriate field and field-accessing arguments. | |
124 | ||
125 | However, now I realize that there's a lot of code that gets executed for | |
126 | the main, standard TIFF directories that does not apply to special | |
127 | private subdirectories, so such a reimplementation for the sake of | |
128 | eliminating redundant or duplicate code is probably not possible, | |
129 | unless we also pass in a Main flag to indiciate which type of handling | |
130 | to do, which would be kind of a hack. I've marked those places where I | |
131 | changed or ripped out code which would have to be re-inserted to | |
132 | generalize this function. If it can be done in a clean and graceful way, | |
133 | it would be a great way to generalize the TIFF library. Otherwise, I'll | |
134 | just leave this code here where it duplicates but remains on top of and | |
135 | hopefully mostly independent of the main TIFF library. | |
136 | ||
137 | The caller will probably want to free the sub directory structure after | |
138 | returning from this call, since otherwise once written out, the user | |
139 | is likely to forget about it and leave data lying around. | |
140 | */ | |
141 | toff_t | |
142 | TIFFWritePrivateDataSubDirectory(TIFF* tif, | |
143 | uint32 pdir_fieldsset[], int pdir_fields_last, | |
144 | TIFFFieldInfo *field_info, | |
145 | int (*getFieldFn)(TIFF *tif, ttag_t tag, ...)) | |
146 | { | |
147 | uint16 dircount; | |
148 | uint32 diroff, nextdiroff; | |
149 | ttag_t tag; | |
150 | uint32 nfields; | |
151 | tsize_t dirsize; | |
152 | char* data; | |
153 | TIFFDirEntry* dir; | |
154 | u_long b, *fields, fields_size; | |
155 | toff_t directory_offset; | |
156 | TIFFFieldInfo* fip; | |
157 | ||
158 | /* | |
159 | * Deleted out all of the encoder flushing and such code from here - | |
160 | * not necessary for subdirectories. | |
161 | */ | |
162 | ||
163 | /* Finish writing out any image data. */ | |
164 | TIFFFlushData(tif); | |
165 | ||
166 | /* | |
167 | * Size the directory so that we can calculate | |
168 | * offsets for the data items that aren't kept | |
169 | * in-place in each field. | |
170 | */ | |
171 | nfields = 0; | |
172 | for (b = 0; b <= pdir_fields_last; b++) | |
173 | if (FieldSet(pdir_fieldsset, b)) | |
174 | /* Deleted code to make size of first 4 tags 2 | |
175 | instead of 1. */ | |
176 | nfields += 1; | |
177 | dirsize = nfields * sizeof (TIFFDirEntry); | |
178 | data = (char*) _TIFFmalloc(dirsize); | |
179 | if (data == NULL) { | |
180 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
181 | "Cannot write private subdirectory, out of space"); | |
182 | return (0); | |
183 | } | |
184 | /* | |
185 | * Place directory in data section of the file. If there isn't one | |
186 | * yet, place it at the end of the file. The directory is treated as | |
187 | * data, so we don't link it into the directory structure at all. | |
188 | */ | |
189 | if (tif->tif_dataoff == 0) | |
190 | tif->tif_dataoff =(TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; | |
191 | diroff = tif->tif_dataoff; | |
192 | tif->tif_dataoff = (toff_t)( | |
193 | diroff + sizeof (uint16) + dirsize + sizeof (toff_t)); | |
194 | if (tif->tif_dataoff & 1) | |
195 | tif->tif_dataoff++; | |
196 | (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); | |
197 | /*tif->tif_curdir++;*/ | |
198 | dir = (TIFFDirEntry*) data; | |
199 | /* | |
200 | * Setup external form of directory | |
201 | * entries and write data items. | |
202 | */ | |
203 | /* | |
204 | * We make a local copy of the fieldsset here so that we don't mess | |
205 | * up the original one when we call ResetFieldBit(). But I'm not sure | |
206 | * why the original code calls ResetFieldBit(), since we're already | |
207 | * going through the fields in order... | |
208 | * | |
209 | * fields_size is the number of uint32's we will need to hold the | |
210 | * bit-mask for all of the fields. If our highest field number is | |
211 | * 100, then we'll need 100 / (8*4)+1 == 4 uint32's to hold the | |
212 | * fieldset. | |
213 | * | |
214 | * Unlike the original code, we allocate fields dynamically based | |
215 | * on the requested pdir_fields_last value, allowing private | |
216 | * data subdirectories to contain more than the built-in code's limit | |
217 | * of 95 tags in a directory. | |
218 | */ | |
219 | fields_size = pdir_fields_last / (8*sizeof(uint32)) + 1; | |
220 | fields = _TIFFmalloc(fields_size*sizeof(uint32)); | |
221 | _TIFFmemcpy(fields, pdir_fieldsset, fields_size * sizeof(uint32)); | |
222 | ||
223 | /* Deleted "write out extra samples tag" code here. */ | |
224 | ||
225 | /* Deleted code for checking a billion little special cases for the | |
226 | * standard TIFF tags. Should add a general mechanism for overloading | |
227 | * write function for each field, just like Brian kept telling me!!! | |
228 | */ | |
229 | for (fip = field_info; fip->field_tag; fip++) { | |
230 | /* Deleted code to check for FIELD_IGNORE!! */ | |
231 | if (/* fip->field_bit == FIELD_IGNORE || */ | |
232 | !FieldSet(fields, fip->field_bit)) | |
233 | continue; | |
234 | if (!TIFFWriteNormalSubTag(tif, dir, fip, getFieldFn)) | |
235 | goto bad; | |
236 | dir++; | |
237 | ResetFieldBit(fields, fip->field_bit); | |
238 | } | |
239 | ||
240 | /* Now we've written all of the referenced data, and are about to | |
241 | write the main directory structure, so grab the tif_dataoff value | |
242 | now so we can remember where we wrote the directory. */ | |
243 | directory_offset = tif->tif_dataoff; | |
244 | ||
245 | /* | |
246 | * Write directory. | |
247 | */ | |
248 | dircount = (uint16) nfields; | |
249 | /* Deleted code to link to the next directory - we set it to zero! */ | |
250 | nextdiroff = 0; | |
251 | if (tif->tif_flags & TIFF_SWAB) { | |
252 | /* | |
253 | * The file's byte order is opposite to the | |
254 | * native machine architecture. We overwrite | |
255 | * the directory information with impunity | |
256 | * because it'll be released below after we | |
257 | * write it to the file. Note that all the | |
258 | * other tag construction routines assume that | |
259 | * we do this byte-swapping; i.e. they only | |
260 | * byte-swap indirect data. | |
261 | */ | |
262 | for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) { | |
263 | TIFFSwabArrayOfShort(&dir->tdir_tag, 2); | |
264 | TIFFSwabArrayOfLong(&dir->tdir_count, 2); | |
265 | } | |
266 | dircount = (uint16) nfields; | |
267 | TIFFSwabShort(&dircount); | |
268 | TIFFSwabLong(&nextdiroff); | |
269 | } | |
270 | ||
271 | (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); | |
272 | if (!WriteOK(tif, &dircount, sizeof (dircount))) { | |
273 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing private subdirectory count"); | |
274 | goto bad; | |
275 | } | |
276 | if (!WriteOK(tif, data, dirsize)) { | |
277 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing private subdirectory contents"); | |
278 | goto bad; | |
279 | } | |
280 | if (!WriteOK(tif, &nextdiroff, sizeof (nextdiroff))) { | |
281 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing private subdirectory link"); | |
282 | goto bad; | |
283 | } | |
284 | tif->tif_dataoff += sizeof(dircount) + dirsize + sizeof(nextdiroff); | |
285 | ||
286 | _TIFFfree(data); | |
287 | _TIFFfree(fields); | |
288 | tif->tif_flags &= ~TIFF_DIRTYDIRECT; | |
289 | ||
290 | #if (0) | |
291 | /* This stuff commented out because I don't think we want it for | |
292 | subdirectories, but I could be wrong. */ | |
293 | (*tif->tif_cleanup)(tif); | |
294 | ||
295 | /* | |
296 | * Reset directory-related state for subsequent | |
297 | * directories. | |
298 | */ | |
299 | TIFFDefaultDirectory(tif); | |
300 | tif->tif_curoff = 0; | |
301 | tif->tif_row = (uint32) -1; | |
302 | tif->tif_curstrip = (tstrip_t) -1; | |
303 | #endif | |
304 | ||
305 | return (directory_offset); | |
306 | bad: | |
307 | _TIFFfree(data); | |
308 | _TIFFfree(fields); | |
309 | return (0); | |
310 | } | |
311 | #undef WriteRationalPair | |
312 | ||
313 | /* | |
314 | * Process tags that are not special cased. | |
315 | */ | |
316 | /* The standard function TIFFWriteNormalTag() could definitely be replaced | |
317 | with a simple call to this function, just adding TIFFGetField() as the | |
318 | last argument. */ | |
319 | static int | |
320 | TIFFWriteNormalSubTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip, | |
321 | int (*getFieldFn)(TIFF *tif, ttag_t tag, ...)) | |
322 | { | |
323 | u_short wc = (u_short) fip->field_writecount; | |
324 | ||
325 | dir->tdir_tag = fip->field_tag; | |
326 | dir->tdir_type = (u_short) fip->field_type; | |
327 | dir->tdir_count = wc; | |
328 | #define WRITEF(x,y) x(tif, fip->field_type, fip->field_tag, dir, wc, y) | |
329 | switch (fip->field_type) { | |
330 | case TIFF_SHORT: | |
331 | case TIFF_SSHORT: | |
332 | if (wc > 1) { | |
333 | uint16* wp; | |
334 | if (wc == (u_short) TIFF_VARIABLE) { | |
335 | (*getFieldFn)(tif, fip->field_tag, &wc, &wp); | |
336 | dir->tdir_count = wc; | |
337 | } else | |
338 | (*getFieldFn)(tif, fip->field_tag, &wp); | |
339 | if (!WRITEF(TIFFWriteShortArray, wp)) | |
340 | return (0); | |
341 | } else { | |
342 | uint16 sv; | |
343 | (*getFieldFn)(tif, fip->field_tag, &sv); | |
344 | dir->tdir_offset = | |
345 | TIFFInsertData(tif, dir->tdir_type, sv); | |
346 | } | |
347 | break; | |
348 | case TIFF_LONG: | |
349 | case TIFF_SLONG: | |
350 | if (wc > 1) { | |
351 | uint32* lp; | |
352 | if (wc == (u_short) TIFF_VARIABLE) { | |
353 | (*getFieldFn)(tif, fip->field_tag, &wc, &lp); | |
354 | dir->tdir_count = wc; | |
355 | } else | |
356 | (*getFieldFn)(tif, fip->field_tag, &lp); | |
357 | if (!WRITEF(TIFFWriteLongArray, lp)) | |
358 | return (0); | |
359 | } else { | |
360 | /* XXX handle LONG->SHORT conversion */ | |
361 | (*getFieldFn)(tif, fip->field_tag, &dir->tdir_offset); | |
362 | } | |
363 | break; | |
364 | case TIFF_RATIONAL: | |
365 | case TIFF_SRATIONAL: | |
366 | if (wc > 1) { | |
367 | float* fp; | |
368 | if (wc == (u_short) TIFF_VARIABLE) { | |
369 | (*getFieldFn)(tif, fip->field_tag, &wc, &fp); | |
370 | dir->tdir_count = wc; | |
371 | } else | |
372 | (*getFieldFn)(tif, fip->field_tag, &fp); | |
373 | if (!WRITEF(TIFFWriteRationalArray, fp)) | |
374 | return (0); | |
375 | } else { | |
376 | float fv; | |
377 | (*getFieldFn)(tif, fip->field_tag, &fv); | |
378 | if (!WRITEF(TIFFWriteRationalArray, &fv)) | |
379 | return (0); | |
380 | } | |
381 | break; | |
382 | case TIFF_FLOAT: | |
383 | if (wc > 1) { | |
384 | float* fp; | |
385 | if (wc == (u_short) TIFF_VARIABLE) { | |
386 | (*getFieldFn)(tif, fip->field_tag, &wc, &fp); | |
387 | dir->tdir_count = wc; | |
388 | } else | |
389 | (*getFieldFn)(tif, fip->field_tag, &fp); | |
390 | if (!WRITEF(TIFFWriteFloatArray, fp)) | |
391 | return (0); | |
392 | } else { | |
393 | float fv; | |
394 | (*getFieldFn)(tif, fip->field_tag, &fv); | |
395 | if (!WRITEF(TIFFWriteFloatArray, &fv)) | |
396 | return (0); | |
397 | } | |
398 | break; | |
399 | case TIFF_DOUBLE: | |
400 | /* Hey - I think this is a bug, or at least a "gross | |
401 | inconsistency", in the TIFF library. Look at the original | |
402 | TIFF library code below within the "#if (0) ... #else". | |
403 | Just from the type of *dp, you can see that this code | |
404 | expects TIFFGetField() to be handed a double ** for | |
405 | any TIFF_DOUBLE tag, even for the constant wc==1 case. | |
406 | This is totally inconsistent with other fields (like | |
407 | TIFF_FLOAT, above) and is also inconsistent with the | |
408 | TIFFSetField() function for TIFF_DOUBLEs, which expects | |
409 | to be passed a single double by value for the wc==1 case. | |
410 | (See the handling of TIFFFetchNormalTag() in tif_dirread.c | |
411 | for an example.) Maybe this function was written before | |
412 | TIFFWriteDoubleArray() was written, not that that's an | |
413 | excuse. Anyway, the new code below is a trivial modification | |
414 | of the TIFF_FLOAT code above. The fact that even single | |
415 | doubles get written out in the data segment and get an | |
416 | offset value stored is irrelevant here - that is all | |
417 | handled by TIFFWriteDoubleArray(). */ | |
418 | #if (0) | |
419 | { double* dp; | |
420 | if (wc == (u_short) TIFF_VARIABLE) { | |
421 | (*getFieldFn)(tif, fip->field_tag, &wc, &dp); | |
422 | dir->tdir_count = wc; | |
423 | } else | |
424 | (*getFieldFn)(tif, fip->field_tag, &dp); | |
425 | TIFFCvtNativeToIEEEDouble(tif, wc, dp); | |
426 | if (!TIFFWriteData(tif, dir, (char*) dp)) | |
427 | return (0); | |
428 | } | |
429 | #else | |
430 | if (wc > 1) { | |
431 | double* dp; | |
432 | if (wc == (u_short) TIFF_VARIABLE) { | |
433 | (*getFieldFn)(tif, fip->field_tag, &wc, &dp); | |
434 | dir->tdir_count = wc; | |
435 | } else | |
436 | (*getFieldFn)(tif, fip->field_tag, &dp); | |
437 | if (!WRITEF(TIFFWriteDoubleArray, dp)) | |
438 | return (0); | |
439 | } else { | |
440 | double dv; | |
441 | (*getFieldFn)(tif, fip->field_tag, &dv); | |
442 | if (!WRITEF(TIFFWriteDoubleArray, &dv)) | |
443 | return (0); | |
444 | } | |
445 | #endif | |
446 | break; | |
447 | case TIFF_ASCII: | |
448 | { char* cp; | |
449 | (*getFieldFn)(tif, fip->field_tag, &cp); | |
450 | dir->tdir_count = (uint32) (strlen(cp) + 1); | |
451 | if (!TIFFWriteByteArray(tif, dir, cp)) | |
452 | return (0); | |
453 | } | |
454 | break; | |
455 | case TIFF_UNDEFINED: | |
456 | { char* cp; | |
457 | if (wc == (u_short) TIFF_VARIABLE) { | |
458 | (*getFieldFn)(tif, fip->field_tag, &wc, &cp); | |
459 | dir->tdir_count = wc; | |
460 | } else | |
461 | (*getFieldFn)(tif, fip->field_tag, &cp); | |
462 | if (!TIFFWriteByteArray(tif, dir, cp)) | |
463 | return (0); | |
464 | } | |
465 | break; | |
466 | } | |
467 | return (1); | |
468 | } | |
469 | #undef WRITEF | |
470 | ||
471 | /* Everything after this is exactly duplicated from the standard tif_dirwrite.c | |
472 | file, necessitated by the fact that they are declared static there so | |
473 | we can't call them! | |
474 | */ | |
475 | /* | |
476 | * Setup a directory entry with either a SHORT | |
477 | * or LONG type according to the value. | |
478 | */ | |
479 | static void | |
480 | TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v) | |
481 | { | |
482 | dir->tdir_tag = tag; | |
483 | dir->tdir_count = 1; | |
484 | if (v > 0xffffL) { | |
485 | dir->tdir_type = (short) TIFF_LONG; | |
486 | dir->tdir_offset = v; | |
487 | } else { | |
488 | dir->tdir_type = (short) TIFF_SHORT; | |
489 | dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v); | |
490 | } | |
491 | } | |
492 | #undef MakeShortDirent | |
493 | ||
494 | #ifndef TIFFWriteRational | |
495 | /* | |
496 | * Setup a RATIONAL directory entry and | |
497 | * write the associated indirect value. | |
498 | */ | |
499 | static int | |
500 | TIFFWriteRational(TIFF* tif, | |
501 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, float v) | |
502 | { | |
503 | return (TIFFWriteRationalArray(tif, type, tag, dir, 1, &v)); | |
504 | } | |
505 | #endif | |
506 | ||
507 | #define NITEMS(x) (sizeof (x) / sizeof (x[0])) | |
508 | /* | |
509 | * Setup a directory entry that references a | |
510 | * samples/pixel array of SHORT values and | |
511 | * (potentially) write the associated indirect | |
512 | * values. | |
513 | */ | |
514 | static int | |
515 | TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) | |
516 | { | |
517 | uint16 buf[10], v; | |
518 | uint16* w = buf; | |
519 | int i, status, samples = tif->tif_dir.td_samplesperpixel; | |
520 | ||
521 | if (samples > NITEMS(buf)) | |
522 | w = (uint16*) _TIFFmalloc(samples * sizeof (uint16)); | |
523 | TIFFGetField(tif, tag, &v); | |
524 | for (i = 0; i < samples; i++) | |
525 | w[i] = v; | |
526 | status = TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, samples, w); | |
527 | if (w != buf) | |
528 | _TIFFfree((char*) w); | |
529 | return (status); | |
530 | } | |
531 | ||
532 | /* | |
533 | * Setup a directory entry that references a samples/pixel array of ``type'' | |
534 | * values and (potentially) write the associated indirect values. The source | |
535 | * data from TIFFGetField() for the specified tag must be returned as double. | |
536 | */ | |
537 | static int | |
538 | TIFFWritePerSampleAnys(TIFF* tif, | |
539 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir) | |
540 | { | |
541 | double buf[10], v; | |
542 | double* w = buf; | |
543 | int i, status; | |
544 | int samples = (int) tif->tif_dir.td_samplesperpixel; | |
545 | ||
546 | if (samples > NITEMS(buf)) | |
547 | w = (double*) _TIFFmalloc(samples * sizeof (double)); | |
548 | TIFFGetField(tif, tag, &v); | |
549 | for (i = 0; i < samples; i++) | |
550 | w[i] = v; | |
551 | status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w); | |
552 | if (w != buf) | |
553 | _TIFFfree(w); | |
554 | return (status); | |
555 | } | |
556 | #undef NITEMS | |
557 | ||
558 | /* | |
559 | * Setup a pair of shorts that are returned by | |
560 | * value, rather than as a reference to an array. | |
561 | */ | |
562 | static int | |
563 | TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) | |
564 | { | |
565 | uint16 v[2]; | |
566 | ||
567 | TIFFGetField(tif, tag, &v[0], &v[1]); | |
568 | return (TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, 2, v)); | |
569 | } | |
570 | ||
571 | /* | |
572 | * Setup a directory entry for an NxM table of shorts, | |
573 | * where M is known to be 2**bitspersample, and write | |
574 | * the associated indirect data. | |
575 | */ | |
576 | static int | |
577 | TIFFWriteShortTable(TIFF* tif, | |
578 | ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table) | |
579 | { | |
580 | uint32 i, off; | |
581 | ||
582 | dir->tdir_tag = tag; | |
583 | dir->tdir_type = (short) TIFF_SHORT; | |
584 | /* XXX -- yech, fool TIFFWriteData */ | |
585 | dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample); | |
586 | off = tif->tif_dataoff; | |
587 | for (i = 0; i < n; i++) | |
588 | if (!TIFFWriteData(tif, dir, (char *)table[i])) | |
589 | return (0); | |
590 | dir->tdir_count *= n; | |
591 | dir->tdir_offset = off; | |
592 | return (1); | |
593 | } | |
594 | ||
595 | /* | |
596 | * Write/copy data associated with an ASCII or opaque tag value. | |
597 | */ | |
598 | static int | |
599 | TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp) | |
600 | { | |
601 | if (dir->tdir_count > 4) { | |
602 | if (!TIFFWriteData(tif, dir, cp)) | |
603 | return (0); | |
604 | } else | |
605 | _TIFFmemcpy(&dir->tdir_offset, cp, dir->tdir_count); | |
606 | return (1); | |
607 | } | |
608 | ||
609 | /* | |
610 | * Setup a directory entry of an array of SHORT | |
611 | * or SSHORT and write the associated indirect values. | |
612 | */ | |
613 | static int | |
614 | TIFFWriteShortArray(TIFF* tif, | |
615 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16* v) | |
616 | { | |
617 | dir->tdir_tag = tag; | |
618 | dir->tdir_type = (short) type; | |
619 | dir->tdir_count = n; | |
620 | if (n <= 2) { | |
621 | if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { | |
622 | dir->tdir_offset = (uint32) ((long) v[0] << 16); | |
623 | if (n == 2) | |
624 | dir->tdir_offset |= v[1] & 0xffff; | |
625 | } else { | |
626 | dir->tdir_offset = v[0] & 0xffff; | |
627 | if (n == 2) | |
628 | dir->tdir_offset |= (long) v[1] << 16; | |
629 | } | |
630 | return (1); | |
631 | } else | |
632 | return (TIFFWriteData(tif, dir, (char*) v)); | |
633 | } | |
634 | ||
635 | /* | |
636 | * Setup a directory entry of an array of LONG | |
637 | * or SLONG and write the associated indirect values. | |
638 | */ | |
639 | static int | |
640 | TIFFWriteLongArray(TIFF* tif, | |
641 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint32* v) | |
642 | { | |
643 | dir->tdir_tag = tag; | |
644 | dir->tdir_type = (short) type; | |
645 | dir->tdir_count = n; | |
646 | if (n == 1) { | |
647 | dir->tdir_offset = v[0]; | |
648 | return (1); | |
649 | } else | |
650 | return (TIFFWriteData(tif, dir, (char*) v)); | |
651 | } | |
652 | ||
653 | /* | |
654 | * Setup a directory entry of an array of RATIONAL | |
655 | * or SRATIONAL and write the associated indirect values. | |
656 | */ | |
657 | static int | |
658 | TIFFWriteRationalArray(TIFF* tif, | |
659 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v) | |
660 | { | |
661 | uint32 i; | |
662 | uint32* t; | |
663 | int status; | |
664 | ||
665 | dir->tdir_tag = tag; | |
666 | dir->tdir_type = (short) type; | |
667 | dir->tdir_count = n; | |
668 | t = (uint32*) _TIFFmalloc(2*n * sizeof (uint32)); | |
669 | for (i = 0; i < n; i++) { | |
670 | float fv = v[i]; | |
671 | int sign = 1; | |
672 | uint32 den; | |
673 | ||
674 | if (fv < 0) { | |
675 | if (type == TIFF_RATIONAL) { | |
676 | TIFFWarning(tif->tif_name, | |
677 | "\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL", | |
678 | _TIFFFieldWithTag(tif,tag)->field_name, v); | |
679 | fv = 0; | |
680 | } else | |
681 | fv = -fv, sign = -1; | |
682 | } | |
683 | den = 1L; | |
684 | if (fv > 0) { | |
685 | while (fv < 1L<<(31-3) && den < 1L<<(31-3)) | |
686 | fv *= 1<<3, den *= 1L<<3; | |
687 | } | |
688 | t[2*i+0] = sign * (fv + 0.5); | |
689 | t[2*i+1] = den; | |
690 | } | |
691 | status = TIFFWriteData(tif, dir, (char *)t); | |
692 | _TIFFfree((char*) t); | |
693 | return (status); | |
694 | } | |
695 | ||
696 | static int | |
697 | TIFFWriteFloatArray(TIFF* tif, | |
698 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v) | |
699 | { | |
700 | dir->tdir_tag = tag; | |
701 | dir->tdir_type = (short) type; | |
702 | dir->tdir_count = n; | |
703 | TIFFCvtNativeToIEEEFloat(tif, n, v); | |
704 | if (n == 1) { | |
705 | dir->tdir_offset = *(uint32*) &v[0]; | |
706 | return (1); | |
707 | } else | |
708 | return (TIFFWriteData(tif, dir, (char*) v)); | |
709 | } | |
710 | ||
711 | static int | |
712 | TIFFWriteDoubleArray(TIFF* tif, | |
713 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v) | |
714 | { | |
715 | dir->tdir_tag = tag; | |
716 | dir->tdir_type = (short) type; | |
717 | dir->tdir_count = n; | |
718 | TIFFCvtNativeToIEEEDouble(tif, n, v); | |
719 | return (TIFFWriteData(tif, dir, (char*) v)); | |
720 | } | |
721 | ||
722 | /* | |
723 | * Write an array of ``type'' values for a specified tag (i.e. this is a tag | |
724 | * which is allowed to have different types, e.g. SMaxSampleType). | |
725 | * Internally the data values are represented as double since a double can | |
726 | * hold any of the TIFF tag types (yes, this should really be an abstract | |
727 | * type tany_t for portability). The data is converted into the specified | |
728 | * type in a temporary buffer and then handed off to the appropriate array | |
729 | * writer. | |
730 | */ | |
731 | static int | |
732 | TIFFWriteAnyArray(TIFF* tif, | |
733 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v) | |
734 | { | |
735 | char buf[10 * sizeof(double)]; | |
736 | char* w = buf; | |
737 | int i, status = 0; | |
738 | ||
739 | if (n * TIFFDataWidth(type) > sizeof buf) | |
740 | w = (char*) _TIFFmalloc(n * TIFFDataWidth(type)); | |
741 | switch (type) { | |
742 | case TIFF_BYTE: | |
743 | { unsigned char* bp = (unsigned char*) w; | |
744 | for (i = 0; i < n; i++) | |
745 | bp[i] = (unsigned char) v[i]; | |
746 | dir->tdir_tag = tag; | |
747 | dir->tdir_type = (short) type; | |
748 | dir->tdir_count = n; | |
749 | if (!TIFFWriteByteArray(tif, dir, (char*) bp)) | |
750 | goto out; | |
751 | } | |
752 | break; | |
753 | case TIFF_SBYTE: | |
754 | { signed char* bp = (signed char*) w; | |
755 | for (i = 0; i < n; i++) | |
756 | bp[i] = (signed char) v[i]; | |
757 | dir->tdir_tag = tag; | |
758 | dir->tdir_type = (short) type; | |
759 | dir->tdir_count = n; | |
760 | if (!TIFFWriteByteArray(tif, dir, (char*) bp)) | |
761 | goto out; | |
762 | } | |
763 | break; | |
764 | case TIFF_SHORT: | |
765 | { uint16* bp = (uint16*) w; | |
766 | for (i = 0; i < n; i++) | |
767 | bp[i] = (uint16) v[i]; | |
768 | if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp)) | |
769 | goto out; | |
770 | } | |
771 | break; | |
772 | case TIFF_SSHORT: | |
773 | { int16* bp = (int16*) w; | |
774 | for (i = 0; i < n; i++) | |
775 | bp[i] = (int16) v[i]; | |
776 | if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp)) | |
777 | goto out; | |
778 | } | |
779 | break; | |
780 | case TIFF_LONG: | |
781 | { uint32* bp = (uint32*) w; | |
782 | for (i = 0; i < n; i++) | |
783 | bp[i] = (uint32) v[i]; | |
784 | if (!TIFFWriteLongArray(tif, type, tag, dir, n, bp)) | |
785 | goto out; | |
786 | } | |
787 | break; | |
788 | case TIFF_SLONG: | |
789 | { int32* bp = (int32*) w; | |
790 | for (i = 0; i < n; i++) | |
791 | bp[i] = (int32) v[i]; | |
792 | if (!TIFFWriteLongArray(tif, type, tag, dir, n, (uint32*) bp)) | |
793 | goto out; | |
794 | } | |
795 | break; | |
796 | case TIFF_FLOAT: | |
797 | { float* bp = (float*) w; | |
798 | for (i = 0; i < n; i++) | |
799 | bp[i] = (float) v[i]; | |
800 | if (!TIFFWriteFloatArray(tif, type, tag, dir, n, bp)) | |
801 | goto out; | |
802 | } | |
803 | break; | |
804 | case TIFF_DOUBLE: | |
805 | return (TIFFWriteDoubleArray(tif, type, tag, dir, n, v)); | |
806 | default: | |
807 | /* TIFF_NOTYPE */ | |
808 | /* TIFF_ASCII */ | |
809 | /* TIFF_UNDEFINED */ | |
810 | /* TIFF_RATIONAL */ | |
811 | /* TIFF_SRATIONAL */ | |
812 | goto out; | |
813 | } | |
814 | status = 1; | |
815 | out: | |
816 | if (w != buf) | |
817 | _TIFFfree(w); | |
818 | return (status); | |
819 | } | |
820 | ||
821 | #ifdef COLORIMETRY_SUPPORT | |
822 | static int | |
823 | TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir) | |
824 | { | |
825 | TIFFDirectory* td = &tif->tif_dir; | |
826 | tsize_t n = (1L<<td->td_bitspersample) * sizeof (uint16); | |
827 | uint16** tf = td->td_transferfunction; | |
828 | int ncols; | |
829 | ||
830 | /* | |
831 | * Check if the table can be written as a single column, | |
832 | * or if it must be written as 3 columns. Note that we | |
833 | * write a 3-column tag if there are 2 samples/pixel and | |
834 | * a single column of data won't suffice--hmm. | |
835 | */ | |
836 | switch (td->td_samplesperpixel - td->td_extrasamples) { | |
837 | default: if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; } | |
838 | case 2: if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; } | |
839 | case 1: case 0: ncols = 1; | |
840 | } | |
841 | return (TIFFWriteShortTable(tif, | |
842 | TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf)); | |
843 | } | |
844 | #endif | |
845 | ||
846 | /* | |
847 | * Write a contiguous directory item. | |
848 | */ | |
849 | static int | |
850 | TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp) | |
851 | { | |
852 | tsize_t cc; | |
853 | ||
854 | if (tif->tif_flags & TIFF_SWAB) { | |
855 | switch (dir->tdir_type) { | |
856 | case TIFF_SHORT: | |
857 | case TIFF_SSHORT: | |
858 | TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); | |
859 | break; | |
860 | case TIFF_LONG: | |
861 | case TIFF_SLONG: | |
862 | case TIFF_FLOAT: | |
863 | TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); | |
864 | break; | |
865 | case TIFF_RATIONAL: | |
866 | case TIFF_SRATIONAL: | |
867 | TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); | |
868 | break; | |
869 | case TIFF_DOUBLE: | |
870 | TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); | |
871 | break; | |
872 | } | |
873 | } | |
874 | dir->tdir_offset = tif->tif_dataoff; | |
875 | cc = dir->tdir_count * TIFFDataWidth(dir->tdir_type); | |
876 | if (SeekOK(tif, dir->tdir_offset) && | |
877 | WriteOK(tif, cp, cc)) { | |
878 | tif->tif_dataoff += (cc + 1) & ~1; | |
879 | return (1); | |
880 | } | |
881 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing data for field \"%s\"", | |
882 | _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); | |
883 | return (0); | |
884 | } | |
885 | ||
886 | /* | |
887 | * Link the current directory into the | |
888 | * directory chain for the file. | |
889 | */ | |
890 | static int | |
891 | TIFFLinkDirectory(TIFF* tif) | |
892 | { | |
893 | static const char module[] = "TIFFLinkDirectory"; | |
894 | uint32 nextdir; | |
895 | uint32 diroff; | |
896 | ||
897 | tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; | |
898 | diroff = (uint32) tif->tif_diroff; | |
899 | if (tif->tif_flags & TIFF_SWAB) | |
900 | TIFFSwabLong(&diroff); | |
901 | #if SUBIFD_SUPPORT | |
902 | if (tif->tif_flags & TIFF_INSUBIFD) { | |
903 | (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); | |
904 | if (!WriteOK(tif, &diroff, sizeof (diroff))) { | |
905 | TIFFErrorExt(tif->tif_clientdata, module, | |
906 | "%s: Error writing SubIFD directory link", | |
907 | tif->tif_name); | |
908 | return (0); | |
909 | } | |
910 | /* | |
911 | * Advance to the next SubIFD or, if this is | |
912 | * the last one configured, revert back to the | |
913 | * normal directory linkage. | |
914 | */ | |
915 | if (--tif->tif_nsubifd) | |
916 | tif->tif_subifdoff += sizeof (diroff); | |
917 | else | |
918 | tif->tif_flags &= ~TIFF_INSUBIFD; | |
919 | return (1); | |
920 | } | |
921 | #endif | |
922 | if (tif->tif_header.tiff_diroff == 0) { | |
923 | /* | |
924 | * First directory, overwrite offset in header. | |
925 | */ | |
926 | tif->tif_header.tiff_diroff = (uint32) tif->tif_diroff; | |
927 | #define HDROFF(f) ((toff_t) &(((TIFFHeader*) 0)->f)) | |
928 | (void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET); | |
929 | if (!WriteOK(tif, &diroff, sizeof (diroff))) { | |
930 | TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing TIFF header"); | |
931 | return (0); | |
932 | } | |
933 | return (1); | |
934 | } | |
935 | /* | |
936 | * Not the first directory, search to the last and append. | |
937 | */ | |
938 | nextdir = tif->tif_header.tiff_diroff; | |
939 | do { | |
940 | uint16 dircount; | |
941 | ||
942 | if (!SeekOK(tif, nextdir) || | |
943 | !ReadOK(tif, &dircount, sizeof (dircount))) { | |
944 | TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count"); | |
945 | return (0); | |
946 | } | |
947 | if (tif->tif_flags & TIFF_SWAB) | |
948 | TIFFSwabShort(&dircount); | |
949 | (void) TIFFSeekFile(tif, | |
950 | dircount * sizeof (TIFFDirEntry), SEEK_CUR); | |
951 | if (!ReadOK(tif, &nextdir, sizeof (nextdir))) { | |
952 | TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link"); | |
953 | return (0); | |
954 | } | |
955 | if (tif->tif_flags & TIFF_SWAB) | |
956 | TIFFSwabLong(&nextdir); | |
957 | } while (nextdir != 0); | |
958 | (void) TIFFSeekFile(tif, -(toff_t) sizeof (nextdir), SEEK_CUR); | |
959 | if (!WriteOK(tif, &diroff, sizeof (diroff))) { | |
960 | TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); | |
961 | return (0); | |
962 | } | |
963 | return (1); | |
964 | } |