]>
Commit | Line | Data |
---|---|---|
b47c832e RR |
1 | /* $Header$ */ |
2 | ||
3 | /* | |
4 | * Copyright (c) 1988-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 | * Directory Write Support Routines. | |
31 | */ | |
32 | #include "tiffiop.h" | |
33 | ||
34 | #if HAVE_IEEEFP | |
35 | #define TIFFCvtNativeToIEEEFloat(tif, n, fp) | |
36 | #define TIFFCvtNativeToIEEEDouble(tif, n, dp) | |
37 | #else | |
38 | extern void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*); | |
39 | extern void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*); | |
40 | #endif | |
41 | ||
42 | static int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*); | |
43 | static void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32); | |
44 | static int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*); | |
45 | static int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*); | |
46 | static int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*); | |
47 | static int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**); | |
48 | static int TIFFWriteShortArray(TIFF*, | |
49 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint16*); | |
50 | static int TIFFWriteLongArray(TIFF *, | |
51 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint32*); | |
52 | static int TIFFWriteRationalArray(TIFF *, | |
53 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*); | |
54 | static int TIFFWriteFloatArray(TIFF *, | |
55 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*); | |
56 | static int TIFFWriteDoubleArray(TIFF *, | |
57 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*); | |
58 | static int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*); | |
59 | static int TIFFWriteAnyArray(TIFF*, | |
60 | TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*); | |
61 | #ifdef COLORIMETRY_SUPPORT | |
62 | static int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*); | |
63 | #endif | |
64 | #ifdef CMYK_SUPPORT | |
65 | static int TIFFWriteInkNames(TIFF*, TIFFDirEntry*); | |
66 | #endif | |
67 | static int TIFFWriteData(TIFF*, TIFFDirEntry*, char*); | |
68 | static int TIFFLinkDirectory(TIFF*); | |
69 | ||
70 | #define WriteRationalPair(type, tag1, v1, tag2, v2) { \ | |
71 | if (!TIFFWriteRational(tif, type, tag1, dir, v1)) \ | |
72 | goto bad; \ | |
73 | if (!TIFFWriteRational(tif, type, tag2, dir+1, v2)) \ | |
74 | goto bad; \ | |
75 | dir++; \ | |
76 | } | |
77 | #define TIFFWriteRational(tif, type, tag, dir, v) \ | |
78 | TIFFWriteRationalArray((tif), (type), (tag), (dir), 1, &(v)) | |
79 | #ifndef TIFFWriteRational | |
80 | static int TIFFWriteRational(TIFF*, | |
81 | TIFFDataType, ttag_t, TIFFDirEntry*, float); | |
82 | #endif | |
83 | ||
84 | /* | |
85 | * Write the contents of the current directory | |
86 | * to the specified file. This routine doesn't | |
87 | * handle overwriting a directory with auxiliary | |
88 | * storage that's been changed. | |
89 | */ | |
90 | int | |
91 | TIFFWriteDirectory(TIFF* tif) | |
92 | { | |
93 | uint16 dircount; | |
94 | uint32 diroff; | |
95 | ttag_t tag; | |
96 | uint32 nfields; | |
97 | tsize_t dirsize; | |
98 | char* data; | |
99 | TIFFDirEntry* dir; | |
100 | TIFFDirectory* td; | |
101 | u_long b, fields[FIELD_SETLONGS]; | |
102 | int fi, nfi; | |
103 | ||
104 | if (tif->tif_mode == O_RDONLY) | |
105 | return (1); | |
106 | /* | |
107 | * Clear write state so that subsequent images with | |
108 | * different characteristics get the right buffers | |
109 | * setup for them. | |
110 | */ | |
111 | if (tif->tif_flags & TIFF_POSTENCODE) { | |
112 | tif->tif_flags &= ~TIFF_POSTENCODE; | |
113 | if (!(*tif->tif_postencode)(tif)) { | |
114 | TIFFError(tif->tif_name, | |
115 | "Error post-encoding before directory write"); | |
116 | return (0); | |
117 | } | |
118 | } | |
119 | (*tif->tif_close)(tif); /* shutdown encoder */ | |
120 | /* | |
121 | * Flush any data that might have been written | |
122 | * by the compression close+cleanup routines. | |
123 | */ | |
124 | if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) { | |
125 | TIFFError(tif->tif_name, | |
126 | "Error flushing data before directory write"); | |
127 | return (0); | |
128 | } | |
129 | if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { | |
130 | _TIFFfree(tif->tif_rawdata); | |
131 | tif->tif_rawdata = NULL; | |
132 | tif->tif_rawcc = 0; | |
133 | } | |
134 | tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); | |
135 | ||
136 | td = &tif->tif_dir; | |
137 | /* | |
138 | * Size the directory so that we can calculate | |
139 | * offsets for the data items that aren't kept | |
140 | * in-place in each field. | |
141 | */ | |
142 | nfields = 0; | |
143 | for (b = 0; b <= FIELD_LAST; b++) | |
144 | if (TIFFFieldSet(tif, b)) | |
145 | nfields += (b < FIELD_SUBFILETYPE ? 2 : 1); | |
146 | dirsize = nfields * sizeof (TIFFDirEntry); | |
147 | data = (char*) _TIFFmalloc(dirsize); | |
148 | if (data == NULL) { | |
149 | TIFFError(tif->tif_name, | |
150 | "Cannot write directory, out of space"); | |
151 | return (0); | |
152 | } | |
153 | /* | |
154 | * Directory hasn't been placed yet, put | |
155 | * it at the end of the file and link it | |
156 | * into the existing directory structure. | |
157 | */ | |
158 | if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif)) | |
159 | goto bad; | |
160 | tif->tif_dataoff = (toff_t)( | |
161 | tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t)); | |
162 | if (tif->tif_dataoff & 1) | |
163 | tif->tif_dataoff++; | |
164 | (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); | |
165 | tif->tif_curdir++; | |
166 | dir = (TIFFDirEntry*) data; | |
167 | /* | |
168 | * Setup external form of directory | |
169 | * entries and write data items. | |
170 | */ | |
171 | _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields)); | |
172 | /* | |
173 | * Write out ExtraSamples tag only if | |
174 | * extra samples are present in the data. | |
175 | */ | |
176 | if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) { | |
177 | ResetFieldBit(fields, FIELD_EXTRASAMPLES); | |
178 | nfields--; | |
179 | dirsize -= sizeof (TIFFDirEntry); | |
180 | } /*XXX*/ | |
181 | for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) { | |
182 | const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi]; | |
183 | if (!FieldSet(fields, fip->field_bit)) | |
184 | continue; | |
185 | switch (fip->field_bit) { | |
186 | case FIELD_STRIPOFFSETS: | |
187 | /* | |
188 | * We use one field bit for both strip and tile | |
189 | * offsets, and so must be careful in selecting | |
190 | * the appropriate field descriptor (so that tags | |
191 | * are written in sorted order). | |
192 | */ | |
193 | tag = isTiled(tif) ? | |
194 | TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS; | |
195 | if (tag != fip->field_tag) | |
196 | continue; | |
197 | if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir, | |
198 | (uint32) td->td_nstrips, td->td_stripoffset)) | |
199 | goto bad; | |
200 | break; | |
201 | case FIELD_STRIPBYTECOUNTS: | |
202 | /* | |
203 | * We use one field bit for both strip and tile | |
204 | * byte counts, and so must be careful in selecting | |
205 | * the appropriate field descriptor (so that tags | |
206 | * are written in sorted order). | |
207 | */ | |
208 | tag = isTiled(tif) ? | |
209 | TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS; | |
210 | if (tag != fip->field_tag) | |
211 | continue; | |
212 | if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir, | |
213 | (uint32) td->td_nstrips, td->td_stripbytecount)) | |
214 | goto bad; | |
215 | break; | |
216 | case FIELD_ROWSPERSTRIP: | |
217 | TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP, | |
218 | dir, td->td_rowsperstrip); | |
219 | break; | |
220 | case FIELD_COLORMAP: | |
221 | if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir, | |
222 | 3, td->td_colormap)) | |
223 | goto bad; | |
224 | break; | |
225 | case FIELD_IMAGEDIMENSIONS: | |
226 | TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH, | |
227 | dir++, td->td_imagewidth); | |
228 | TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH, | |
229 | dir, td->td_imagelength); | |
230 | break; | |
231 | case FIELD_TILEDIMENSIONS: | |
232 | TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH, | |
233 | dir++, td->td_tilewidth); | |
234 | TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH, | |
235 | dir, td->td_tilelength); | |
236 | break; | |
237 | case FIELD_POSITION: | |
238 | WriteRationalPair(TIFF_RATIONAL, | |
239 | TIFFTAG_XPOSITION, td->td_xposition, | |
240 | TIFFTAG_YPOSITION, td->td_yposition); | |
241 | break; | |
242 | case FIELD_RESOLUTION: | |
243 | WriteRationalPair(TIFF_RATIONAL, | |
244 | TIFFTAG_XRESOLUTION, td->td_xresolution, | |
245 | TIFFTAG_YRESOLUTION, td->td_yresolution); | |
246 | break; | |
247 | case FIELD_BITSPERSAMPLE: | |
248 | case FIELD_MINSAMPLEVALUE: | |
249 | case FIELD_MAXSAMPLEVALUE: | |
250 | case FIELD_SAMPLEFORMAT: | |
251 | if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir)) | |
252 | goto bad; | |
253 | break; | |
254 | case FIELD_SMINSAMPLEVALUE: | |
255 | case FIELD_SMAXSAMPLEVALUE: | |
256 | if (!TIFFWritePerSampleAnys(tif, | |
257 | _TIFFSampleToTagType(tif), fip->field_tag, dir)) | |
258 | goto bad; | |
259 | break; | |
260 | case FIELD_PAGENUMBER: | |
261 | case FIELD_HALFTONEHINTS: | |
262 | #ifdef YCBCR_SUPPORT | |
263 | case FIELD_YCBCRSUBSAMPLING: | |
264 | #endif | |
265 | #ifdef CMYK_SUPPORT | |
266 | case FIELD_DOTRANGE: | |
267 | #endif | |
268 | if (!TIFFSetupShortPair(tif, fip->field_tag, dir)) | |
269 | goto bad; | |
270 | break; | |
271 | #ifdef CMYK_SUPPORT | |
272 | case FIELD_INKNAMES: | |
273 | if (!TIFFWriteInkNames(tif, dir)) | |
274 | goto bad; | |
275 | break; | |
276 | #endif | |
277 | #ifdef COLORIMETRY_SUPPORT | |
278 | case FIELD_TRANSFERFUNCTION: | |
279 | if (!TIFFWriteTransferFunction(tif, dir)) | |
280 | goto bad; | |
281 | break; | |
282 | #endif | |
283 | #if SUBIFD_SUPPORT | |
284 | case FIELD_SUBIFD: | |
285 | if (!TIFFWriteNormalTag(tif, dir, fip)) | |
286 | goto bad; | |
287 | /* | |
288 | * Total hack: if this directory includes a SubIFD | |
289 | * tag then force the next <n> directories to be | |
290 | * written as ``sub directories'' of this one. This | |
291 | * is used to write things like thumbnails and | |
292 | * image masks that one wants to keep out of the | |
293 | * normal directory linkage access mechanism. | |
294 | */ | |
295 | if (dir->tdir_count > 0) { | |
296 | tif->tif_flags |= TIFF_INSUBIFD; | |
297 | tif->tif_nsubifd = dir->tdir_count; | |
298 | if (dir->tdir_count > 1) | |
299 | tif->tif_subifdoff = dir->tdir_offset; | |
300 | else | |
301 | tif->tif_subifdoff = (uint32)( | |
302 | tif->tif_diroff | |
303 | + sizeof (uint16) | |
304 | + ((char*)&dir->tdir_offset-data)); | |
305 | } | |
306 | break; | |
307 | #endif | |
308 | default: | |
309 | if (!TIFFWriteNormalTag(tif, dir, fip)) | |
310 | goto bad; | |
311 | break; | |
312 | } | |
313 | dir++; | |
314 | ResetFieldBit(fields, fip->field_bit); | |
315 | } | |
316 | /* | |
317 | * Write directory. | |
318 | */ | |
319 | dircount = (uint16) nfields; | |
320 | diroff = (uint32) tif->tif_nextdiroff; | |
321 | if (tif->tif_flags & TIFF_SWAB) { | |
322 | /* | |
323 | * The file's byte order is opposite to the | |
324 | * native machine architecture. We overwrite | |
325 | * the directory information with impunity | |
326 | * because it'll be released below after we | |
327 | * write it to the file. Note that all the | |
328 | * other tag construction routines assume that | |
329 | * we do this byte-swapping; i.e. they only | |
330 | * byte-swap indirect data. | |
331 | */ | |
332 | for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) { | |
333 | TIFFSwabArrayOfShort(&dir->tdir_tag, 2); | |
334 | TIFFSwabArrayOfLong(&dir->tdir_count, 2); | |
335 | } | |
336 | dircount = (uint16) nfields; | |
337 | TIFFSwabShort(&dircount); | |
338 | TIFFSwabLong(&diroff); | |
339 | } | |
340 | (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET); | |
341 | if (!WriteOK(tif, &dircount, sizeof (dircount))) { | |
342 | TIFFError(tif->tif_name, "Error writing directory count"); | |
343 | goto bad; | |
344 | } | |
345 | if (!WriteOK(tif, data, dirsize)) { | |
346 | TIFFError(tif->tif_name, "Error writing directory contents"); | |
347 | goto bad; | |
348 | } | |
349 | if (!WriteOK(tif, &diroff, sizeof (diroff))) { | |
350 | TIFFError(tif->tif_name, "Error writing directory link"); | |
351 | goto bad; | |
352 | } | |
353 | TIFFFreeDirectory(tif); | |
354 | _TIFFfree(data); | |
355 | tif->tif_flags &= ~TIFF_DIRTYDIRECT; | |
356 | (*tif->tif_cleanup)(tif); | |
357 | ||
358 | /* | |
359 | * Reset directory-related state for subsequent | |
360 | * directories. | |
361 | */ | |
362 | TIFFDefaultDirectory(tif); | |
363 | tif->tif_diroff = 0; | |
364 | tif->tif_curoff = 0; | |
365 | tif->tif_row = (uint32) -1; | |
366 | tif->tif_curstrip = (tstrip_t) -1; | |
367 | return (1); | |
368 | bad: | |
369 | _TIFFfree(data); | |
370 | return (0); | |
371 | } | |
372 | #undef WriteRationalPair | |
373 | ||
374 | /* | |
375 | * Process tags that are not special cased. | |
376 | */ | |
377 | static int | |
378 | TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip) | |
379 | { | |
380 | u_short wc = (u_short) fip->field_writecount; | |
381 | uint32 wc2; | |
382 | ||
383 | dir->tdir_tag = fip->field_tag; | |
384 | dir->tdir_type = (u_short) fip->field_type; | |
385 | dir->tdir_count = wc; | |
386 | #define WRITEF(x,y) x(tif, fip->field_type, fip->field_tag, dir, wc, y) | |
387 | switch (fip->field_type) { | |
388 | case TIFF_SHORT: | |
389 | case TIFF_SSHORT: | |
390 | if (wc > 1) { | |
391 | uint16* wp; | |
392 | if (wc == (u_short) TIFF_VARIABLE) | |
393 | TIFFGetField(tif, fip->field_tag, &wc, &wp); | |
394 | else | |
395 | TIFFGetField(tif, fip->field_tag, &wp); | |
396 | if (!WRITEF(TIFFWriteShortArray, wp)) | |
397 | return (0); | |
398 | } else { | |
399 | uint16 sv; | |
400 | TIFFGetField(tif, fip->field_tag, &sv); | |
401 | dir->tdir_offset = | |
402 | TIFFInsertData(tif, dir->tdir_type, sv); | |
403 | } | |
404 | break; | |
405 | case TIFF_LONG: | |
406 | case TIFF_SLONG: | |
407 | if (wc > 1) { | |
408 | uint32* lp; | |
409 | if (wc == (u_short) TIFF_VARIABLE) | |
410 | TIFFGetField(tif, fip->field_tag, &wc, &lp); | |
411 | else | |
412 | TIFFGetField(tif, fip->field_tag, &lp); | |
413 | if (!WRITEF(TIFFWriteLongArray, lp)) | |
414 | return (0); | |
415 | } else { | |
416 | /* XXX handle LONG->SHORT conversion */ | |
417 | TIFFGetField(tif, fip->field_tag, &dir->tdir_offset); | |
418 | } | |
419 | break; | |
420 | case TIFF_RATIONAL: | |
421 | case TIFF_SRATIONAL: | |
422 | if (wc > 1) { | |
423 | float* fp; | |
424 | if (wc == (u_short) TIFF_VARIABLE) | |
425 | TIFFGetField(tif, fip->field_tag, &wc, &fp); | |
426 | else | |
427 | TIFFGetField(tif, fip->field_tag, &fp); | |
428 | if (!WRITEF(TIFFWriteRationalArray, fp)) | |
429 | return (0); | |
430 | } else { | |
431 | float fv; | |
432 | TIFFGetField(tif, fip->field_tag, &fv); | |
433 | if (!WRITEF(TIFFWriteRationalArray, &fv)) | |
434 | return (0); | |
435 | } | |
436 | break; | |
437 | case TIFF_FLOAT: | |
438 | if (wc > 1) { | |
439 | float* fp; | |
440 | if (wc == (u_short) TIFF_VARIABLE) | |
441 | TIFFGetField(tif, fip->field_tag, &wc, &fp); | |
442 | else | |
443 | TIFFGetField(tif, fip->field_tag, &fp); | |
444 | if (!WRITEF(TIFFWriteFloatArray, fp)) | |
445 | return (0); | |
446 | } else { | |
447 | float fv; | |
448 | TIFFGetField(tif, fip->field_tag, &fv); | |
449 | if (!WRITEF(TIFFWriteFloatArray, &fv)) | |
450 | return (0); | |
451 | } | |
452 | break; | |
453 | case TIFF_DOUBLE: | |
454 | if (wc > 1) { | |
455 | double* dp; | |
456 | if (wc == (u_short) TIFF_VARIABLE) | |
457 | TIFFGetField(tif, fip->field_tag, &wc, &dp); | |
458 | else | |
459 | TIFFGetField(tif, fip->field_tag, &dp); | |
460 | if (!WRITEF(TIFFWriteDoubleArray, dp)) | |
461 | return (0); | |
462 | } else { | |
463 | double dv; | |
464 | TIFFGetField(tif, fip->field_tag, &dv); | |
465 | if (!WRITEF(TIFFWriteDoubleArray, &dv)) | |
466 | return (0); | |
467 | } | |
468 | break; | |
469 | case TIFF_ASCII: | |
470 | { char* cp; | |
471 | TIFFGetField(tif, fip->field_tag, &cp); | |
472 | dir->tdir_count = (uint32) (strlen(cp) + 1); | |
473 | if (!TIFFWriteByteArray(tif, dir, cp)) | |
474 | return (0); | |
475 | } | |
476 | break; | |
477 | ||
478 | /* added based on patch request from MARTIN.MCBRIDE.MM@agfa.co.uk, | |
479 | correctness not verified (FW, 99/08) */ | |
480 | case TIFF_BYTE: | |
481 | case TIFF_SBYTE: | |
482 | if (wc > 1) { | |
483 | char* cp; | |
484 | if (wc == (u_short) TIFF_VARIABLE) { | |
485 | TIFFGetField(tif, fip->field_tag, &wc, &cp); | |
486 | dir->tdir_count = wc; | |
487 | } else | |
488 | TIFFGetField(tif, fip->field_tag, &cp); | |
489 | if (!TIFFWriteByteArray(tif, dir, cp)) | |
490 | return (0); | |
491 | } else { | |
492 | char cv; | |
493 | TIFFGetField(tif, fip->field_tag, &cv); | |
494 | if (!TIFFWriteByteArray(tif, dir, &cv)) | |
495 | return (0); | |
496 | } | |
497 | break; | |
498 | ||
499 | case TIFF_UNDEFINED: | |
500 | { char* cp; | |
501 | if (wc == (u_short) TIFF_VARIABLE) { | |
502 | TIFFGetField(tif, fip->field_tag, &wc, &cp); | |
503 | dir->tdir_count = wc; | |
504 | } else if (wc == (u_short) TIFF_VARIABLE2) { | |
505 | TIFFGetField(tif, fip->field_tag, &wc2, &cp); | |
506 | dir->tdir_count = wc2; | |
507 | } else | |
508 | TIFFGetField(tif, fip->field_tag, &cp); | |
509 | if (!TIFFWriteByteArray(tif, dir, cp)) | |
510 | return (0); | |
511 | } | |
512 | break; | |
513 | ||
514 | case TIFF_NOTYPE: | |
515 | break; | |
516 | } | |
517 | return (1); | |
518 | } | |
519 | #undef WRITEF | |
520 | ||
521 | /* | |
522 | * Setup a directory entry with either a SHORT | |
523 | * or LONG type according to the value. | |
524 | */ | |
525 | static void | |
526 | TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v) | |
527 | { | |
528 | dir->tdir_tag = tag; | |
529 | dir->tdir_count = 1; | |
530 | if (v > 0xffffL) { | |
531 | dir->tdir_type = (short) TIFF_LONG; | |
532 | dir->tdir_offset = v; | |
533 | } else { | |
534 | dir->tdir_type = (short) TIFF_SHORT; | |
535 | dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v); | |
536 | } | |
537 | } | |
538 | #undef MakeShortDirent | |
539 | ||
540 | #ifndef TIFFWriteRational | |
541 | /* | |
542 | * Setup a RATIONAL directory entry and | |
543 | * write the associated indirect value. | |
544 | */ | |
545 | static int | |
546 | TIFFWriteRational(TIFF* tif, | |
547 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, float v) | |
548 | { | |
549 | return (TIFFWriteRationalArray(tif, type, tag, dir, 1, &v)); | |
550 | } | |
551 | #endif | |
552 | ||
553 | #define NITEMS(x) (sizeof (x) / sizeof (x[0])) | |
554 | /* | |
555 | * Setup a directory entry that references a | |
556 | * samples/pixel array of SHORT values and | |
557 | * (potentially) write the associated indirect | |
558 | * values. | |
559 | */ | |
560 | static int | |
561 | TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) | |
562 | { | |
563 | uint16 buf[10], v; | |
564 | uint16* w = buf; | |
565 | int i, status, samples = tif->tif_dir.td_samplesperpixel; | |
566 | ||
567 | if (samples > NITEMS(buf)) | |
568 | w = (uint16*) _TIFFmalloc(samples * sizeof (uint16)); | |
569 | TIFFGetField(tif, tag, &v); | |
570 | for (i = 0; i < samples; i++) | |
571 | w[i] = v; | |
572 | status = TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, samples, w); | |
573 | if (w != buf) | |
574 | _TIFFfree((char*) w); | |
575 | return (status); | |
576 | } | |
577 | ||
578 | /* | |
579 | * Setup a directory entry that references a samples/pixel array of ``type'' | |
580 | * values and (potentially) write the associated indirect values. The source | |
581 | * data from TIFFGetField() for the specified tag must be returned as double. | |
582 | */ | |
583 | static int | |
584 | TIFFWritePerSampleAnys(TIFF* tif, | |
585 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir) | |
586 | { | |
587 | double buf[10], v; | |
588 | double* w = buf; | |
589 | int i, status; | |
590 | int samples = (int) tif->tif_dir.td_samplesperpixel; | |
591 | ||
592 | if (samples > NITEMS(buf)) | |
593 | w = (double*) _TIFFmalloc(samples * sizeof (double)); | |
594 | TIFFGetField(tif, tag, &v); | |
595 | for (i = 0; i < samples; i++) | |
596 | w[i] = v; | |
597 | status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w); | |
598 | if (w != buf) | |
599 | _TIFFfree(w); | |
600 | return (status); | |
601 | } | |
602 | #undef NITEMS | |
603 | ||
604 | /* | |
605 | * Setup a pair of shorts that are returned by | |
606 | * value, rather than as a reference to an array. | |
607 | */ | |
608 | static int | |
609 | TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) | |
610 | { | |
611 | uint16 v[2]; | |
612 | ||
613 | TIFFGetField(tif, tag, &v[0], &v[1]); | |
614 | return (TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, 2, v)); | |
615 | } | |
616 | ||
617 | /* | |
618 | * Setup a directory entry for an NxM table of shorts, | |
619 | * where M is known to be 2**bitspersample, and write | |
620 | * the associated indirect data. | |
621 | */ | |
622 | static int | |
623 | TIFFWriteShortTable(TIFF* tif, | |
624 | ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table) | |
625 | { | |
626 | uint32 i, off; | |
627 | ||
628 | dir->tdir_tag = tag; | |
629 | dir->tdir_type = (short) TIFF_SHORT; | |
630 | /* XXX -- yech, fool TIFFWriteData */ | |
631 | dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample); | |
632 | off = tif->tif_dataoff; | |
633 | for (i = 0; i < n; i++) | |
634 | if (!TIFFWriteData(tif, dir, (char *)table[i])) | |
635 | return (0); | |
636 | dir->tdir_count *= n; | |
637 | dir->tdir_offset = off; | |
638 | return (1); | |
639 | } | |
640 | ||
641 | /* | |
642 | * Write/copy data associated with an ASCII or opaque tag value. | |
643 | */ | |
644 | static int | |
645 | TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp) | |
646 | { | |
647 | if (dir->tdir_count > 4) { | |
648 | if (!TIFFWriteData(tif, dir, cp)) | |
649 | return (0); | |
650 | } else | |
651 | _TIFFmemcpy(&dir->tdir_offset, cp, dir->tdir_count); | |
652 | return (1); | |
653 | } | |
654 | ||
655 | /* | |
656 | * Setup a directory entry of an array of SHORT | |
657 | * or SSHORT and write the associated indirect values. | |
658 | */ | |
659 | static int | |
660 | TIFFWriteShortArray(TIFF* tif, | |
661 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16* v) | |
662 | { | |
663 | dir->tdir_tag = tag; | |
664 | dir->tdir_type = (short) type; | |
665 | dir->tdir_count = n; | |
666 | if (n <= 2) { | |
667 | if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { | |
668 | dir->tdir_offset = (uint32) ((long) v[0] << 16); | |
669 | if (n == 2) | |
670 | dir->tdir_offset |= v[1] & 0xffff; | |
671 | } else { | |
672 | dir->tdir_offset = v[0] & 0xffff; | |
673 | if (n == 2) | |
674 | dir->tdir_offset |= (long) v[1] << 16; | |
675 | } | |
676 | return (1); | |
677 | } else | |
678 | return (TIFFWriteData(tif, dir, (char*) v)); | |
679 | } | |
680 | ||
681 | /* | |
682 | * Setup a directory entry of an array of LONG | |
683 | * or SLONG and write the associated indirect values. | |
684 | */ | |
685 | static int | |
686 | TIFFWriteLongArray(TIFF* tif, | |
687 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint32* v) | |
688 | { | |
689 | dir->tdir_tag = tag; | |
690 | dir->tdir_type = (short) type; | |
691 | dir->tdir_count = n; | |
692 | if (n == 1) { | |
693 | dir->tdir_offset = v[0]; | |
694 | return (1); | |
695 | } else | |
696 | return (TIFFWriteData(tif, dir, (char*) v)); | |
697 | } | |
698 | ||
699 | /* | |
700 | * Setup a directory entry of an array of RATIONAL | |
701 | * or SRATIONAL and write the associated indirect values. | |
702 | */ | |
703 | static int | |
704 | TIFFWriteRationalArray(TIFF* tif, | |
705 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v) | |
706 | { | |
707 | uint32 i; | |
708 | uint32* t; | |
709 | int status; | |
710 | ||
711 | dir->tdir_tag = tag; | |
712 | dir->tdir_type = (short) type; | |
713 | dir->tdir_count = n; | |
714 | t = (uint32*) _TIFFmalloc(2*n * sizeof (uint32)); | |
715 | for (i = 0; i < n; i++) { | |
716 | float fv = v[i]; | |
717 | int sign = 1; | |
718 | uint32 den; | |
719 | ||
720 | if (fv < 0) { | |
721 | if (type == TIFF_RATIONAL) { | |
722 | TIFFWarning(tif->tif_name, | |
723 | "\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL", | |
724 | _TIFFFieldWithTag(tif,tag)->field_name, fv); | |
725 | fv = 0; | |
726 | } else | |
727 | fv = -fv, sign = -1; | |
728 | } | |
729 | den = 1L; | |
730 | if (fv > 0) { | |
731 | while (fv < 1L<<(31-3) && den < 1L<<(31-3)) | |
732 | fv *= 1<<3, den *= 1L<<3; | |
733 | } | |
734 | t[2*i+0] = sign * (fv + 0.5); | |
735 | t[2*i+1] = den; | |
736 | } | |
737 | status = TIFFWriteData(tif, dir, (char *)t); | |
738 | _TIFFfree((char*) t); | |
739 | return (status); | |
740 | } | |
741 | ||
742 | static int | |
743 | TIFFWriteFloatArray(TIFF* tif, | |
744 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v) | |
745 | { | |
746 | dir->tdir_tag = tag; | |
747 | dir->tdir_type = (short) type; | |
748 | dir->tdir_count = n; | |
749 | TIFFCvtNativeToIEEEFloat(tif, n, v); | |
750 | if (n == 1) { | |
751 | dir->tdir_offset = *(uint32*) &v[0]; | |
752 | return (1); | |
753 | } else | |
754 | return (TIFFWriteData(tif, dir, (char*) v)); | |
755 | } | |
756 | ||
757 | static int | |
758 | TIFFWriteDoubleArray(TIFF* tif, | |
759 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v) | |
760 | { | |
761 | dir->tdir_tag = tag; | |
762 | dir->tdir_type = (short) type; | |
763 | dir->tdir_count = n; | |
764 | TIFFCvtNativeToIEEEDouble(tif, n, v); | |
765 | return (TIFFWriteData(tif, dir, (char*) v)); | |
766 | } | |
767 | ||
768 | /* | |
769 | * Write an array of ``type'' values for a specified tag (i.e. this is a tag | |
770 | * which is allowed to have different types, e.g. SMaxSampleType). | |
771 | * Internally the data values are represented as double since a double can | |
772 | * hold any of the TIFF tag types (yes, this should really be an abstract | |
773 | * type tany_t for portability). The data is converted into the specified | |
774 | * type in a temporary buffer and then handed off to the appropriate array | |
775 | * writer. | |
776 | */ | |
777 | static int | |
778 | TIFFWriteAnyArray(TIFF* tif, | |
779 | TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v) | |
780 | { | |
781 | char buf[10 * sizeof(double)]; | |
782 | char* w = buf; | |
783 | int i, status = 0; | |
784 | ||
785 | if (n * tiffDataWidth[type] > sizeof buf) | |
786 | w = (char*) _TIFFmalloc(n * tiffDataWidth[type]); | |
787 | switch (type) { | |
788 | case TIFF_BYTE: | |
789 | { uint8* bp = (uint8*) w; | |
790 | for (i = 0; i < n; i++) | |
791 | bp[i] = (uint8) v[i]; | |
792 | dir->tdir_tag = tag; | |
793 | dir->tdir_type = (short) type; | |
794 | dir->tdir_count = n; | |
795 | if (!TIFFWriteByteArray(tif, dir, (char*) bp)) | |
796 | goto out; | |
797 | } | |
798 | break; | |
799 | case TIFF_SBYTE: | |
800 | { int8* bp = (int8*) w; | |
801 | for (i = 0; i < n; i++) | |
802 | bp[i] = (int8) v[i]; | |
803 | dir->tdir_tag = tag; | |
804 | dir->tdir_type = (short) type; | |
805 | dir->tdir_count = n; | |
806 | if (!TIFFWriteByteArray(tif, dir, (char*) bp)) | |
807 | goto out; | |
808 | } | |
809 | break; | |
810 | case TIFF_SHORT: | |
811 | { uint16* bp = (uint16*) w; | |
812 | for (i = 0; i < n; i++) | |
813 | bp[i] = (uint16) v[i]; | |
814 | if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp)) | |
815 | goto out; | |
816 | } | |
817 | break; | |
818 | case TIFF_SSHORT: | |
819 | { int16* bp = (int16*) w; | |
820 | for (i = 0; i < n; i++) | |
821 | bp[i] = (int16) v[i]; | |
822 | if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp)) | |
823 | goto out; | |
824 | } | |
825 | break; | |
826 | case TIFF_LONG: | |
827 | { uint32* bp = (uint32*) w; | |
828 | for (i = 0; i < n; i++) | |
829 | bp[i] = (uint32) v[i]; | |
830 | if (!TIFFWriteLongArray(tif, type, tag, dir, n, bp)) | |
831 | goto out; | |
832 | } | |
833 | break; | |
834 | case TIFF_SLONG: | |
835 | { int32* bp = (int32*) w; | |
836 | for (i = 0; i < n; i++) | |
837 | bp[i] = (int32) v[i]; | |
838 | if (!TIFFWriteLongArray(tif, type, tag, dir, n, (uint32*) bp)) | |
839 | goto out; | |
840 | } | |
841 | break; | |
842 | case TIFF_FLOAT: | |
843 | { float* bp = (float*) w; | |
844 | for (i = 0; i < n; i++) | |
845 | bp[i] = (float) v[i]; | |
846 | if (!TIFFWriteFloatArray(tif, type, tag, dir, n, bp)) | |
847 | goto out; | |
848 | } | |
849 | break; | |
850 | case TIFF_DOUBLE: | |
851 | return (TIFFWriteDoubleArray(tif, type, tag, dir, n, v)); | |
852 | default: | |
853 | /* TIFF_NOTYPE */ | |
854 | /* TIFF_ASCII */ | |
855 | /* TIFF_UNDEFINED */ | |
856 | /* TIFF_RATIONAL */ | |
857 | /* TIFF_SRATIONAL */ | |
858 | goto out; | |
859 | } | |
860 | status = 1; | |
861 | out: | |
862 | if (w != buf) | |
863 | _TIFFfree(w); | |
864 | return (status); | |
865 | } | |
866 | ||
867 | #ifdef COLORIMETRY_SUPPORT | |
868 | static int | |
869 | TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir) | |
870 | { | |
871 | TIFFDirectory* td = &tif->tif_dir; | |
872 | tsize_t n = (1L<<td->td_bitspersample) * sizeof (uint16); | |
873 | uint16** tf = td->td_transferfunction; | |
874 | int ncols; | |
875 | ||
876 | /* | |
877 | * Check if the table can be written as a single column, | |
878 | * or if it must be written as 3 columns. Note that we | |
879 | * write a 3-column tag if there are 2 samples/pixel and | |
880 | * a single column of data won't suffice--hmm. | |
881 | */ | |
882 | switch (td->td_samplesperpixel - td->td_extrasamples) { | |
883 | default: if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; } | |
884 | case 2: if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; } | |
885 | case 1: case 0: ncols = 1; | |
886 | } | |
887 | return (TIFFWriteShortTable(tif, | |
888 | TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf)); | |
889 | } | |
890 | #endif | |
891 | ||
892 | #ifdef CMYK_SUPPORT | |
893 | static int | |
894 | TIFFWriteInkNames(TIFF* tif, TIFFDirEntry* dir) | |
895 | { | |
896 | TIFFDirectory* td = &tif->tif_dir; | |
897 | ||
898 | dir->tdir_tag = TIFFTAG_INKNAMES; | |
899 | dir->tdir_type = (short) TIFF_ASCII; | |
900 | dir->tdir_count = td->td_inknameslen; | |
901 | return (TIFFWriteByteArray(tif, dir, td->td_inknames)); | |
902 | } | |
903 | #endif | |
904 | ||
905 | /* | |
906 | * Write a contiguous directory item. | |
907 | */ | |
908 | static int | |
909 | TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp) | |
910 | { | |
911 | tsize_t cc; | |
912 | ||
913 | if (tif->tif_flags & TIFF_SWAB) { | |
914 | switch (dir->tdir_type) { | |
915 | case TIFF_SHORT: | |
916 | case TIFF_SSHORT: | |
917 | TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); | |
918 | break; | |
919 | case TIFF_LONG: | |
920 | case TIFF_SLONG: | |
921 | case TIFF_FLOAT: | |
922 | TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); | |
923 | break; | |
924 | case TIFF_RATIONAL: | |
925 | case TIFF_SRATIONAL: | |
926 | TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); | |
927 | break; | |
928 | case TIFF_DOUBLE: | |
929 | TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); | |
930 | break; | |
931 | } | |
932 | } | |
933 | dir->tdir_offset = tif->tif_dataoff; | |
934 | cc = dir->tdir_count * tiffDataWidth[dir->tdir_type]; | |
935 | if (SeekOK(tif, dir->tdir_offset) && | |
936 | WriteOK(tif, cp, cc)) { | |
937 | tif->tif_dataoff += (cc + 1) & ~1; | |
938 | return (1); | |
939 | } | |
940 | TIFFError(tif->tif_name, "Error writing data for field \"%s\"", | |
941 | _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); | |
942 | return (0); | |
943 | } | |
944 | ||
945 | /* | |
946 | * Link the current directory into the | |
947 | * directory chain for the file. | |
948 | */ | |
949 | static int | |
950 | TIFFLinkDirectory(TIFF* tif) | |
951 | { | |
952 | static const char module[] = "TIFFLinkDirectory"; | |
953 | uint32 nextdir; | |
954 | uint32 diroff; | |
955 | ||
956 | tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; | |
957 | diroff = (uint32) tif->tif_diroff; | |
958 | if (tif->tif_flags & TIFF_SWAB) | |
959 | TIFFSwabLong(&diroff); | |
960 | #if SUBIFD_SUPPORT | |
961 | if (tif->tif_flags & TIFF_INSUBIFD) { | |
962 | (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); | |
963 | if (!WriteOK(tif, &diroff, sizeof (diroff))) { | |
964 | TIFFError(module, | |
965 | "%s: Error writing SubIFD directory link", | |
966 | tif->tif_name); | |
967 | return (0); | |
968 | } | |
969 | /* | |
970 | * Advance to the next SubIFD or, if this is | |
971 | * the last one configured, revert back to the | |
972 | * normal directory linkage. | |
973 | */ | |
974 | if (--tif->tif_nsubifd) | |
975 | tif->tif_subifdoff += sizeof (diroff); | |
976 | else | |
977 | tif->tif_flags &= ~TIFF_INSUBIFD; | |
978 | return (1); | |
979 | } | |
980 | #endif | |
981 | if (tif->tif_header.tiff_diroff == 0) { | |
982 | /* | |
983 | * First directory, overwrite offset in header. | |
984 | */ | |
985 | tif->tif_header.tiff_diroff = (uint32) tif->tif_diroff; | |
986 | #define HDROFF(f) ((toff_t) &(((TIFFHeader*) 0)->f)) | |
987 | (void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET); | |
988 | if (!WriteOK(tif, &diroff, sizeof (diroff))) { | |
989 | TIFFError(tif->tif_name, "Error writing TIFF header"); | |
990 | return (0); | |
991 | } | |
992 | return (1); | |
993 | } | |
994 | /* | |
995 | * Not the first directory, search to the last and append. | |
996 | */ | |
997 | nextdir = tif->tif_header.tiff_diroff; | |
998 | do { | |
999 | uint16 dircount; | |
1000 | ||
1001 | if (!SeekOK(tif, nextdir) || | |
1002 | !ReadOK(tif, &dircount, sizeof (dircount))) { | |
1003 | TIFFError(module, "Error fetching directory count"); | |
1004 | return (0); | |
1005 | } | |
1006 | if (tif->tif_flags & TIFF_SWAB) | |
1007 | TIFFSwabShort(&dircount); | |
1008 | (void) TIFFSeekFile(tif, | |
1009 | dircount * sizeof (TIFFDirEntry), SEEK_CUR); | |
1010 | if (!ReadOK(tif, &nextdir, sizeof (nextdir))) { | |
1011 | TIFFError(module, "Error fetching directory link"); | |
1012 | return (0); | |
1013 | } | |
1014 | if (tif->tif_flags & TIFF_SWAB) | |
1015 | TIFFSwabLong(&nextdir); | |
1016 | } while (nextdir != 0); | |
1017 | (void) TIFFSeekFile(tif, -(toff_t) sizeof (nextdir), SEEK_CUR); | |
1018 | if (!WriteOK(tif, &diroff, sizeof (diroff))) { | |
1019 | TIFFError(module, "Error writing directory link"); | |
1020 | return (0); | |
1021 | } | |
1022 | return (1); | |
1023 | } |