1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8 /*
9 * $Header: /src/master/dx/src/exec/dxmods/_tiff.c,v 1.13 2006/01/04 22:00:51 davidt Exp $
10 */
11
12 #include <dxconfig.h>
13
14 #if defined(HAVE_STRING_H)
15 #include <string.h>
16 #endif
17
18 #include <dx/dx.h>
19
20
21 /*
22 * This file constitutes support for writing (and some reading) TIFF (Tagged
23 * Image File Format) files as specified in the TIFF 5.0 standard available
24 * from
25 * Aldus Corp. Microsoft Corp.
26 * 411 First Ave. South 16011 NE 36th Way
27 * Suite 200 Box 97017
28 * Seattle WA 98104 Redmond WA 98073-9717
29 * 206-622-5500 206-882-8080
30 *
31 * The standard is highly recommended reading, but below is short description
32 * of TIFF...
33 *
34 * TIFF is a binary file format that consists of on 8-byte header, and
35 * a series of Image File Directories (IFD) and associated data (an image).
36 * Each IFD contains a set of fields that describe the associated data.
37 *
38 * HEADER: Found at offset 0 in the file.
39 * bytes 0-1 : 0x4949 (LSB byte ordering) or 0x4d4d (MSB)
40 * bytes 2-3 : TIFF Version, 5.0 corresponds to 0x002a (Fourty-Two).
41 * (And likely all following versions.)
42 * (Read the Aldus publication for the philosophy.)
43 * bytes 4-7 : FIle offset of first IFD.
44 *
45 * IFD: Found anywhere in a file.
46 * bytes 0-1 : the number of fields in this IFD
47 * bytes 2-n : the fields for this IFD (12 bytes each).
48 * bytes n-(n+4) : the file offset of the next IFD or 0 if none.
49 *
50 * FIELD:
51 * bytes 0-1 : The tag for this field (see the spec for tag types).
52 * bytes 2-3 : The 'type' of the value of this field.
53 * bytes 4-7 : the number of items in the field value.
54 * bytes 8-11: Either 1) the file offset for the value of this field
55 * or 2) the value itself if it can fit in 4 bytes.
56 *
57 * Needless to say, one of the fields in an IFD indicates the location of
58 * the data for the associated image.
59 *
60 * Two relatively important points follow:
61 * 1) We write the initial header, then the image data followed by
62 * an IFD for each image.
63 * 2) We always write an MSB byte ordered image. I was at a loss to
64 * try an write a correct LSB image.
65 */
66
67 #include <stdlib.h>
68
69 #if defined(HAVE_FCNTL_H)
70 #include <fcntl.h>
71 #endif
72
73 #if defined(HAVE_UNISTD_H)
74 #include <unistd.h>
75 #endif
76
77 #include "_helper_jea.h"
78 #include "_rw_image.h"
79
80 #define TIFF_ATTEMPT_STRIP_SIZE 8192 /* A number suggested in TIFF document */
81 #define TIFF_VERSION 42 /* 11/88 Version 5.0 of TIFF */
82 #define TIFF_LSB 0x4949 /* Least-significant bit first */
83 #define TIFF_MSB 0x4d4d /* Most-significant bit first */
84
85 #define TIFF_NO_COMPRESS 1
86 #define TIFF_LZW_COMPRESS 5
87
88 /*
89 * Tiff tag names and their associated numbers.
90 * They are not all here, only the ones we need to write DXRGB images.
91 * Augmented by Allain 30-Aug-1993.
92 */
93 typedef enum {
94 Artist = 315,
95 BitsPerSample = 258,
96 CellLength = 265,
97 CellWidth = 264,
98 ColorImageType_XXX = 318, /* or is it WhitePoint_XXX ? */
99 ColorResponseCurves = 301,
100 Compression = 259,
101 DateTime = 306,
102 DocumentName = 269,
103 FillOrder = 266,
104 FreeByteCounts = 289,
105 FreeOffsets = 288,
106 GrayResponseCurve = 291,
107 GrayResponseUnit = 290,
108 Group3Options = 292,
109 Group4Options = 293,
110 HostComputer = 316,
111 ImageDescription = 270,
112 ImageLength = 257,
113 ImageWidth = 256,
114 Make = 271,
115 MaxSampleValue = 281,
116 MinSampleValue = 280,
117 Model = 272,
118 NewSubfileType = 254,
119 Orientation = 274,
120 PageName = 285,
121 PageNumber = 297,
122 PhotometricInterpretation = 262,
123 PlanarConfiguration = 284,
124 Predictor = 317,
125 PrimaryChromaticities = 319,
126 ResolutionUnit = 296,
127 RowsPerStrip = 278,
128 SamplesPerPixel = 277,
129 Software = 305,
130 StripByteCounts = 279,
131 StripOffsets = 273,
132 SubfileType = 255,
133 Threshholding = 263,
134 WhitePoint_XXX = 318,
135 XPosition = 286,
136 XResolution = 282,
137 YPosition = 287,
138 YResolution = 283,
139 ColorMap = 320
140 } TiffTag;
141
142 typedef enum {
143 tiff_BYTE = 1,
144 tiff_ASCII = 2,
145 tiff_SHORT = 3,
146 tiff_LONG = 4,
147 tiff_RATIONAL = 5,
148 SHORT_LONG = 6 /* shorthand for tiff_SHORT || tiff_LONG */
149 } TiffType;
150 #define TIFF_RATIONAL_SIZE (2*4) /* two words */
151
152 static int
153 tiff_type_bytecount[] = { 0, 1, 1, 2, 4, 8 };
154
155 static char
156 *tiff_type_name[] = { NULL, "BYTE", "ASCII", "SHORT", "LONG", "RATIONAL" };
157
158
159 /*
160 * A tiff file header.
161 */
162 typedef struct tiff_header {
163 uint16 byte_order;
164 uint16 version;
165 uint32 ifd_offset;
166 } TiffHeader;
167 #define TIFF_HEADER_SIZE 8 /* bytes */
168
169 /*
170 * An field entry referenced from an IFD
171 */
172 typedef struct tiff_field {
173 uint16 tag; /* A TiffTag */
174 uint16 type; /* A TiffType */
175 uint32 length; /* Corrected: short -> long. JEA */
176 union {
177 uint32 offset;
178 uint32 value;
179 } value;
180 } TiffField;
181 #define TIFF_FIELD_SIZE 12 /* bytes */
182
183 /*
184 * An image file directory (IFD).
185 */
186 typedef struct tiff_ifd {
187 uint16 nfields;
188 TiffField *fields;
189 uint32 next_ifd_offset;
190 } TiffIFD;
191
192 /* Determine the local byte order */
193 #if defined(WORDS_BIGENDIAN)
194 # define LOCAL_MSB_ORDER
195 # define read_fwd_uint32 read_msb_uint32
196 # define read_fwd_uint16 read_msb_uint16
197 # define read_rev_uint32 read_lsb_uint32
198 # define read_rev_uint16 read_lsb_uint16
199 # define write_fwd_uint32 write_msb_uint32
200 # define write_fwd_uint16 write_msb_uint16
201 # define write_rev_uint32 write_lsb_uint32
202 # define write_rev_uint16 write_lsb_uint16
203 #else
204 # define LOCAL_LSB_ORDER
205 /* XXX - PVS testing indicated need for fixes. */
206 # define read_fwd_uint32 read_lsb_uint32
207 # define read_fwd_uint16 read_lsb_uint16
208 # define read_rev_uint32 read_msb_uint32
209 # define read_rev_uint16 read_msb_uint16
210 # define write_fwd_uint32 write_lsb_uint32
211 # define write_fwd_uint16 write_lsb_uint16
212 # define write_rev_uint32 write_msb_uint32
213 # define write_rev_uint16 write_msb_uint16
214 #endif
215
216
217 /* lseek() support.
218 JEA: Jun 30 1994: we should use SEEK_* from types.h */
219
220 #ifndef L_SET
221 # define L_SET 0
222 #endif
223 #ifndef L_INCR
224 # define L_INCR 1
225 #endif
226
227 static int rewrite_word(int fd, int offset, uint32 value);
228 static Error put_tiff_pixels(int fd, Field image, int rows, int columns,
229 int strips, int pixels_per_strip, int compress,
230 uint32 *strip_offsets, uint32 *strip_byte_counts, float gamma);
231 static Error put_tiff_header(int fd, int byte_order, int version,
232 int ifd_offset);
233 static int put_rgb_ifd(int fd, int width, int length, int strips,
234 int rows_per_strip, int compress, uint32 *strip_offsets,
235 uint32 *strip_byte_counts);
236 static int put_field(int fd, TiffTag tag, TiffType type, int n, uint32 value);
237 /*
238 * Define the maximum length of any dimension of the images.
239 * This number is only an estimate and is not expected to be used to
240 * force an image size, but may make some TIFF editors happy.
241 */
242 #define MAX_IMAGE_DIM 4 /* In inches, see the RESOLUTION tag */
243
244
245
246 static Error
write_fwd_uint32(int fd,uint32 val)247 write_fwd_uint32(int fd, uint32 val)
248 {
249 if (write(fd,(char*)&val, 4) == 4)
250 return OK;
251 else
252 {
253 DXSetError
254 ( ERROR_DATA_INVALID,
255 "#11800", /* C standard library call, %s, returns error */
256 "write()" );
257
258 return ERROR;
259 }
260 }
261
262
263 #if !defined(WORDS_BIGENDIAN)
264 static Error
write_rev_uint32(int fd,uint32 val)265 write_rev_uint32(int fd, uint32 val)
266 {
267 unsigned char c[4];
268
269 c[0] = ((unsigned char *)&val)[3];
270 c[1] = ((unsigned char *)&val)[2];
271 c[2] = ((unsigned char *)&val)[1];
272 c[3] = ((unsigned char *)&val)[0];
273
274 if (write(fd,c,4) == 4)
275 return OK;
276 else
277 {
278 DXSetError
279 ( ERROR_DATA_INVALID,
280 "#11800", /* C standard library call, %s, returns error */
281 "write()" );
282
283 return ERROR;
284 }
285 }
286 #endif
287
288
289 static Error
write_fwd_uint16(int fd,uint16 val)290 write_fwd_uint16(int fd, uint16 val)
291 {
292 if (write(fd,(char*)&val, 2) == 2)
293 return OK;
294 else
295 {
296 DXSetError
297 ( ERROR_DATA_INVALID,
298 "#11800", /* C standard library call, %s, returns error */
299 "write()" );
300
301 return ERROR;
302 }
303 }
304
305 #if !defined(WORDS_BIGENDIAN)
306 static Error
write_rev_uint16(int fd,uint16 val)307 write_rev_uint16(int fd, uint16 val)
308 {
309 unsigned char c[2];
310
311 c[0] = ((unsigned char *)&val)[1];
312 c[1] = ((unsigned char *)&val)[0];
313
314 if (write(fd,c,2) == 2)
315 return OK;
316 else
317 {
318 DXSetError
319 ( ERROR_DATA_INVALID,
320 "#11800", /* C standard library call, %s, returns error */
321 "write()" );
322
323 return ERROR;
324 }
325 }
326 #endif
327
328 static Error
read_fwd_uint32(int fd,uint32 * val)329 read_fwd_uint32 ( int fd, uint32 *val )
330 {
331 if (read(fd,(char*)val, 4) == 4)
332 return OK;
333 else
334 {
335 DXSetError
336 ( ERROR_DATA_INVALID,
337 "#11800", /* C standard library call, %s, returns error */
338 "read()" );
339
340 return ERROR;
341 }
342 }
343
344
345 static Error
read_rev_uint32(int fd,uint32 * val)346 read_rev_uint32 ( int fd, uint32 *val )
347 {
348 unsigned char c[4];
349
350 if (read(fd,c,4) != 4)
351 {
352 DXSetError
353 ( ERROR_DATA_INVALID,
354 "#11800", /* C standard library call, %s, returns error */
355 "read()" );
356
357 return ERROR;
358 }
359
360 ((unsigned char *)val)[3] = c[0];
361 ((unsigned char *)val)[2] = c[1];
362 ((unsigned char *)val)[1] = c[2];
363 ((unsigned char *)val)[0] = c[3];
364
365 return OK;
366 }
367
368
369 static Error
read_fwd_uint16(int fd,uint16 * val)370 read_fwd_uint16(int fd, uint16 *val)
371 {
372 if (read(fd,(char*)val, 2) == 2)
373 return OK;
374 else
375 {
376 DXSetError
377 ( ERROR_DATA_INVALID,
378 "#11800", /* C standard library call, %s, returns error */
379 "read()" );
380
381 return ERROR;
382 }
383 }
384
385
386 static Error
read_rev_uint16(int fd,uint16 * val)387 read_rev_uint16(int fd, uint16 *val)
388 {
389 unsigned char c[2];
390
391 if (read(fd,c,2) != 2)
392 {
393 DXSetError
394 ( ERROR_DATA_INVALID,
395 "#11800", /* C standard library call, %s, returns error */
396 "read()" );
397
398 return ERROR;
399 }
400
401 ((unsigned char *)val)[1] = c[0];
402 ((unsigned char *)val)[0] = c[1];
403
404 return OK;
405 }
406
407 /*
408 * Write out a "tiff", formatted image file from the specified field.
409 * The input field should not be composite, but may be series.
410 * By the time we get called, it has been asserted that we can write
411 * the image to the device, be it ADASD or otherwise.
412 *
413 * NOTE: The semantics here differ from those for DXRGB images in that
414 * the frame number is ignored, a new file is always created and if
415 * given a series all images in the series are written out.
416 */
417 Error
_dxf_write_tiff(RWImageArgs * iargs)418 _dxf_write_tiff(RWImageArgs *iargs)
419 {
420 uint32 last_ifd_offset_location, offset;
421 char imagefilename[MAX_IMAGE_NAMELEN];
422 uint32 *strip_offsets=NULL, *strip_byte_counts;
423 int i, fd = -1, series, rows, columns, row_size, compress;
424 int firstframe, lastframe, frames, rows_per_strip;
425 int strips, deleteable = 0;
426
427 SizeData image_sizes; /* Values as found in the image object itself */
428 Field img = NULL;
429
430 if (iargs->adasd)
431 DXErrorGoto(ERROR_NOT_IMPLEMENTED,
432 "Tiff format not supported on disk array");
433
434 if ( !_dxf_GetImageAttributes ( (Object)iargs->image, &image_sizes ) )
435 goto error;
436
437 series = iargs->imgclass == CLASS_SERIES;
438 frames = (image_sizes.endframe - image_sizes.startframe + 1);
439
440 /*
441 * Always write all frames of a series.
442 */
443 firstframe = 0;
444 lastframe = frames-1;
445
446 /*
447 * Create an appropriate file name.
448 */
449 if (!_dxf_BuildImageFileName(imagefilename,MAX_IMAGE_NAMELEN,
450 iargs->basename,
451 iargs->imgtyp,iargs->startframe,0))
452 goto error;
453
454 /*
455 * Get some nice statistics
456 */
457 rows = image_sizes.height;
458 columns = image_sizes.width;
459 row_size = columns * 3;
460 rows_per_strip = TIFF_ATTEMPT_STRIP_SIZE / row_size + 1;
461 if (rows_per_strip > rows)
462 rows_per_strip = rows;
463 strips = (rows + rows_per_strip - 1) / rows_per_strip;
464
465 if (strips < 1)
466 DXErrorGoto(ERROR_UNEXPECTED, "Tiff encountered less than 1 strip");
467
468 /*
469 * DXAllocate some space to save strip offsets and sizes.
470 */
471 strip_offsets = (uint32*)DXAllocateLocal(2 * strips * sizeof(uint32));
472 if (!strip_offsets)
473 goto error;
474 strip_byte_counts = &strip_offsets[strips];
475
476
477 /*
478 * Attempt to open image file and position to start of frame(s).
479 */
480 if ( (fd = creat (imagefilename, 0666 ) ) < 0 )
481 ErrorGotoPlus1 ( ERROR_DATA_INVALID,
482 "Can't open image file (%s)", imagefilename );
483
484
485 /*
486 * Skip the header, write it later
487 * Save the location of the IFD pointer.
488 */
489 lseek(fd,TIFF_HEADER_SIZE, L_SET);
490 last_ifd_offset_location = TIFF_HEADER_SIZE - 4;
491
492 compress = TIFF_NO_COMPRESS; /* LZW compress not implemented yet */
493 img = iargs->image;
494 for (i=firstframe ; i<=lastframe ; i++)
495 {
496 if (series) {
497 if (deleteable) DXDelete((Object)img);
498 img = _dxf_GetFlatSeriesImage((Series)iargs->image,i,
499 columns,rows,&deleteable);
500 if (!img)
501 goto error;
502 }
503
504 if (!put_tiff_pixels(fd, img, rows, columns, strips,
505 rows_per_strip*columns, compress,
506 strip_offsets, strip_byte_counts, iargs->gamma))
507 goto error;
508
509 offset = put_rgb_ifd(fd, columns, rows, strips, rows_per_strip,
510 compress, strip_offsets, strip_byte_counts);
511 if (!offset)
512 goto bad_write;
513
514 if (!rewrite_word(fd, last_ifd_offset_location, offset))
515 goto bad_write;
516
517 last_ifd_offset_location = lseek(fd, 0, L_INCR) - 4;
518 }
519
520 /* Set the last IFD next pointer to 0 */
521 if (!rewrite_word(fd, last_ifd_offset_location, 0))
522 goto bad_write;
523
524 /*
525 * Write out the header, indicating, byte ordering, version number
526 * offset of 0th IFD. NOTE: we always write an MSB tiff image.
527 */
528 if (!put_tiff_header(fd, (int)TIFF_MSB, TIFF_VERSION, 0))
529 goto bad_write;
530
531
532 if (fd >= 0) close(fd);
533 if (deleteable && img) DXDelete((Object)img);
534 if (strip_offsets) DXFree((Pointer)strip_offsets);
535
536 return OK;
537
538 bad_write:
539 DXErrorGoto( ERROR_DATA_INVALID, "Can't write TIFF file");
540 error:
541 if ( fd >= 0 ) close(fd);
542 if (deleteable && img) DXDelete((Object)img);
543 if (strip_offsets) DXFree((Pointer)strip_offsets);
544
545 return ERROR;
546 }
547
548 /*
549 * Write out an image file directory and its associated strip offsets and
550 * byte counts, the resolution and the bits per sample for our DXRGB image.
551 * Below is a diagram of what is written.
552 *
553 * . . .
554 * | 1 / 1 | x- and y- resolutions.
555 * | | Strip offsets and byte counts.
556 * . . .
557 * | |
558 * | 8 8 8 8 | bits per sample (the last 8 is filler)
559 * | IFD | Beginning of IFD.
560 * . . .
561 *
562 * The file pointer is aligned to a word boundary before we begin any
563 * writes.
564 * Returns 0 on failure, and the file offset of the IFD on success.
565 */
566
567 static int /* offset of first byte of IFD */
put_rgb_ifd(int fd,int width,int length,int strips,int rows_per_strip,int compress,uint32 * strip_offsets,uint32 * strip_byte_counts)568 put_rgb_ifd(int fd, int width, int length, int strips, int rows_per_strip,
569 int compress, uint32 *strip_offsets, uint32 *strip_byte_counts)
570 {
571 uint32 rationals[2], zero=0, i;
572 uint32 xres_offset, yres_offset, bps_offset, ifd_offset, offset;
573 uint32 sbc_offset=0, so_offset=0;
574 uint16 nentries=13;
575 uint16 uint16s[4];
576
577
578 /*
579 * Align the file pointer to a word boundary
580 */
581 xres_offset = lseek(fd,0,L_INCR);
582 if (xres_offset & 3) {
583 xres_offset = (xres_offset + 3) & ~3;
584 if (lseek(fd, xres_offset, L_SET) < 0)
585 return(0);
586 }
587
588 /*
589 * Write XResolution and YResolution values (they are equal).
590 * Create a ratio that will result in an image that has its
591 * largest dimension MAX_IMAGE_DIM inches (inches, assuming the
592 * RESOLUTION tag is set to 2).
593 */
594 yres_offset = xres_offset;
595 rationals[0] = MAX(length, width);
596 rationals[1] = MAX_IMAGE_DIM;
597 if ( !write_msb_uint32(fd, rationals[0]) ||
598 !write_msb_uint32(fd, rationals[1]) )
599 return(0);
600 offset = xres_offset + TIFF_RATIONAL_SIZE;
601
602 /*
603 * Write the StripOffsets and ByteCounts
604 */
605 if (strips > 1) {
606 so_offset = offset;
607 for (i=0 ; i<strips ; i++)
608 if (!write_msb_uint32(fd, strip_offsets[i]))
609 return(0);
610 sbc_offset = so_offset + strips*4;
611 for (i=0 ; i<strips ; i++)
612 if (!write_msb_uint32(fd, strip_byte_counts[i]))
613 return(0);
614 offset += 2*strips*4;
615 }
616
617 /*
618 * Write BitsPerSample (8,8,8) Value, write an extra uint16 to keep
619 * file pointer, word aligned.
620 */
621 bps_offset = offset;
622 uint16s[0] = uint16s[1] = uint16s[2] = uint16s[3] = 8;
623 for (i=0 ; i<4 ; i++)
624 if (!write_msb_uint16(fd, uint16s[i]))
625 return(0);
626 offset += 4*2;
627
628 /*
629 * Begin the IFD, first uint16 indicates the number of fields.
630 */
631 ifd_offset = offset;
632 if (!write_msb_uint16(fd, nentries))
633 return(0);
634
635
636 /*
637 * Write out each of the fields, the fields must be sorted
638 * in ascending tag value order, so the order of operation is important.
639 */
640 if (!put_field(fd, ImageWidth, tiff_LONG, 1, width) ||
641 !put_field(fd, ImageLength, tiff_LONG, 1, length) ||
642 !put_field(fd, BitsPerSample, tiff_SHORT, 3, bps_offset) ||
643 !put_field(fd, Compression, tiff_SHORT, 1, compress) ||
644 !put_field(fd, PhotometricInterpretation, tiff_SHORT, 1, 2))
645 return(0);
646
647 /* If only one strip, put the offset not the offset of the offset list */
648 if (((strips == 1) &&
649 !put_field(fd, StripOffsets, tiff_LONG, 1, *strip_offsets)) ||
650 !put_field(fd, StripOffsets, tiff_LONG, strips, so_offset))
651 return(0);
652
653 if (!put_field(fd, SamplesPerPixel, tiff_SHORT, 1, 3) ||
654 !put_field(fd, RowsPerStrip, tiff_LONG, 1, rows_per_strip))
655 return(0);
656
657 /* If only one strip, put the byte count not the offset of the count list */
658 if (((strips == 1) &&
659 !put_field(fd, StripByteCounts, tiff_LONG, 1, *strip_byte_counts)) ||
660 !put_field(fd, StripByteCounts, tiff_LONG, strips, sbc_offset))
661 return(0);
662
663 if (!put_field(fd, XResolution, tiff_RATIONAL, 1, xres_offset) ||
664 !put_field(fd, YResolution, tiff_RATIONAL, 1, yres_offset) ||
665 !put_field(fd, PlanarConfiguration, tiff_SHORT, 1, 1) ||
666 !put_field(fd, ResolutionUnit, tiff_SHORT, 1, 2) )
667 return(0);
668
669 /*
670 * Write out the pointer to the next IFD, we don't know it now so
671 * indicate there isn't one by writing 0.
672 */
673 if (!write_msb_uint32(fd,zero))
674 return(0);
675
676 return(ifd_offset);
677 }
678
679 /*
680 * Write an individual field of a directory entry at the current file
681 * offset for the given file descriptor.
682 * Upon entry, the value to be written is assumed to be right justified
683 * and if the size (specifed by type and n) indicates, the value(s)
684 * are left justified as per the TIFF spec.
685 *
686 * Returns 0/1 on failure/success.
687 */
688 static int
put_field(int fd,TiffTag tag,TiffType type,int n,uint32 value)689 put_field(int fd, TiffTag tag, TiffType type, int n, uint32 value)
690 {
691 uint16 s;
692 uint32 l;
693
694 s = (uint16)tag;
695 if (!write_msb_uint16(fd, s))
696 return(0);
697
698 s = (uint16)type;
699 if (!write_msb_uint16(fd, s))
700 return(0);
701
702 l = (uint32)n;
703 if (!write_msb_uint32(fd, l))
704 return(0);
705
706 /* Left justify value if indicated by the size */
707 switch (type) {
708 case tiff_ASCII:
709 case tiff_BYTE: if (n < 4) value <<= (4-n)*8;
710 break;
711 case tiff_SHORT: if (n == 1) value <<= 16;
712 break;
713 default:
714 break;
715 }
716
717 if (!write_msb_uint32(fd, value))
718 return(0);
719 return(1);
720 }
721
722 /*
723 * Overwrite the word at offset in fd with value.
724 * On return, the file pointer for fd is restored to the offset at entrance.
725 * Return 0/1 on failure/success.
726 */
727 static int
rewrite_word(int fd,int offset,uint32 value)728 rewrite_word(int fd, int offset, uint32 value)
729 {
730 int old_offset = lseek(fd, 0, L_INCR);
731
732 if ((old_offset < 0) ||
733 (lseek(fd, offset, L_SET) < 0) ||
734 !write_msb_uint32(fd, value) ||
735 (lseek(fd, old_offset, L_SET) < 0))
736 return(0);
737
738 return(old_offset);
739 }
740
741 /*
742 * Write out the DXRGB pixels of the given image which has 'rows' rows,
743 * and 'columns' columns. Pixels are to be written in 'strips' strips
744 * with 'pixels_per_strip' pixels in each strip. 'compress' indicates
745 * which type of compression to be done LZW or none. On output
746 * strip_offset[i] contains the offset of strip i and strip_byte_counts[i]
747 * contains the number of bytes in strip i.
748 *
749 * Returns ERROR/OK on failure/success and sets the error code on failure.
750 */
751 static Error
put_tiff_pixels(int fd,Field image,int rows,int columns,int strips,int pixels_per_strip,int compress,uint32 * strip_offsets,uint32 * strip_byte_counts,float gamma)752 put_tiff_pixels(int fd,
753 Field image, int rows, int columns,
754 int strips, int pixels_per_strip, int compress,
755 uint32 *strip_offsets, uint32 *strip_byte_counts, float gamma)
756 {
757 uint32 count, totpixels, npixels, i, j, offset, y,x;
758 Pointer *pixels;
759 unsigned char *rgb=NULL;
760 Array colorsArray, colorMapArray;
761 RGBColor *map = NULL;
762 #ifdef HAVE_LZW_COMPRESS
763 unsigned char *comp_rgb=NULL;
764 #endif
765 Type type;
766 int rank, shape[32];
767 ubyte gamma_table[256];
768
769 DXASSERTGOTO ( compress != TIFF_LZW_COMPRESS );
770
771 _dxf_make_gamma_table(gamma_table, gamma);
772
773 colorsArray = (Array)DXGetComponentValue(image, "colors");
774 if (! colorsArray)
775 goto error;
776
777 DXGetArrayInfo(colorsArray, NULL, &type, NULL, &rank, shape);
778
779 if (type == TYPE_UBYTE)
780 {
781 if (rank == 0 || (rank == 1 && shape[0] == 1))
782 {
783 colorMapArray = (Array)DXGetComponentValue(image, "color map");
784 if (! colorMapArray)
785 {
786 DXSetError(ERROR_DATA_INVALID,
787 "single-valued byte image requires color map");
788 goto error;
789 }
790
791 map = (RGBColor *)DXGetArrayData(colorMapArray);
792 }
793 else if (rank != 1 || shape[0] != 3)
794 {
795 DXSetError(ERROR_DATA_INVALID,
796 "images must either contain single-valued pixels with a %s",
797 "colormap or contain three-vector pixels");
798 goto error;
799 }
800 }
801 else if (type == TYPE_FLOAT)
802 {
803 if (rank != 1 || shape[0] != 3)
804 {
805 DXSetError(ERROR_DATA_INVALID,
806 "images must either contain single-valued pixels with a %s",
807 "colormap or contain three-vector pixels");
808 goto error;
809 }
810 }
811 else
812 {
813 DXSetError(ERROR_DATA_INVALID,
814 "pixel data must be either unsigned chars or floats");
815 goto error;
816 }
817
818 if (!(pixels = DXGetArrayData(colorsArray)))
819 goto error;
820
821 offset = lseek(fd, 0, L_INCR);
822
823 rgb = (unsigned char*)DXAllocateLocal(pixels_per_strip*3);
824 if (!rgb)
825 goto error;
826
827 #ifdef HAVE_LZW_COMPRESS
828 if (compress == TIFF_LZW_COMPRESS)
829 {
830 comp_rgb = (unsigned char*)DXAllocateLocal(pixels_per_strip*3);
831 if (!comp_rgb)
832 goto error;
833 }
834 #endif
835
836
837 /*
838 * This is somewhat of a mess, but seems to be required. DX images
839 * are stored from left to right and bottom to top, we need to
840 * write them out from left to right and top to bottom. Plus,
841 * we need to break (set strip_offsets[] and strip_byte_counts[],
842 * and write a strip) when we hit the end of strip or the end of the
843 * image.
844 */
845 #define CLAMP(a,b) \
846 { \
847 int f = (a) * 255.0; \
848 f = (f < 0) ? 0 : (f > 255) ? 255 : f; \
849 (b) = (unsigned char)gamma_table[f]; \
850 }
851
852 y = rows - 1;
853 totpixels = rows*columns;
854
855 if (map)
856 {
857 ubyte *from = ((ubyte *)pixels) + y*columns;
858
859 for (count=i=j=npixels=0, x=1 ; (npixels < totpixels) ; )
860 {
861 RGBColor *mapped = map + *from;
862
863 CLAMP(mapped->r, rgb[j++]);
864 CLAMP(mapped->g, rgb[j++]);
865 CLAMP(mapped->b, rgb[j++]);
866
867 if ((++count == pixels_per_strip) || (y==0 && x==columns)) {
868 /*
869 * Time to write out a strip
870 */
871 #ifdef HAVE_LZW_COMPRESS
872 if (compress == TIFF_LZW_COMPRESS)
873 tiff_lzw_compress(comp_rgb,rgb,j);
874 #endif
875 if (write(fd,(char*)rgb,j) < j)
876 DXErrorGoto(ERROR_DATA_INVALID,"Can't write output file");
877 strip_offsets[i] = offset;
878 strip_byte_counts[i] = j;
879 offset += j;
880 npixels += count;
881 j = count = 0;
882 i++;
883 }
884 if (x == columns) {
885 y--;
886 x = 1;
887 from = ((ubyte *)pixels) + y*columns;
888 } else {
889 x++;
890 from++;
891 }
892 }
893 }
894 else if (type == TYPE_FLOAT)
895 {
896 RGBColor *from = ((RGBColor *)pixels) + y*columns;
897
898 for (count=i=j=npixels=0, x=1 ; (npixels < totpixels) ; )
899 {
900 CLAMP(from->r, rgb[j++]);
901 CLAMP(from->g, rgb[j++]);
902 CLAMP(from->b, rgb[j++]);
903
904 if ((++count == pixels_per_strip) || (y==0 && x==columns)) {
905 /*
906 * Time to write out a strip
907 */
908 #ifdef HAVE_LZW_COMPRESS
909 if (compress == TIFF_LZW_COMPRESS)
910 tiff_lzw_compress(comp_rgb,rgb,j);
911 #endif
912 if (write(fd,(char*)rgb,j) < j)
913 DXErrorGoto(ERROR_DATA_INVALID,"Can't write output file");
914 strip_offsets[i] = offset;
915 strip_byte_counts[i] = j;
916 offset += j;
917 npixels += count;
918 j = count = 0;
919 i++;
920 }
921 if (x == columns) {
922 y--;
923 x = 1;
924 from = ((RGBColor *)pixels) + y*columns;
925 } else {
926 x++;
927 from++;
928 }
929 }
930 }
931 else
932 {
933 RGBByteColor *from = ((RGBByteColor *)pixels) + y*columns;
934
935 for (count=i=j=npixels=0, x=1 ; (npixels < totpixels) ; )
936 {
937 rgb[j++] = gamma_table[from->r];
938 rgb[j++] = gamma_table[from->g];
939 rgb[j++] = gamma_table[from->b];
940
941 if ((++count == pixels_per_strip) || (y==0 && x==columns)) {
942 /*
943 * Time to write out a strip
944 */
945 #ifdef HAVE_LZW_COMPRESS
946 if (compress == TIFF_LZW_COMPRESS)
947 tiff_lzw_compress(comp_rgb,rgb,j);
948 #endif
949 if (write(fd,(char*)rgb,j) < j)
950 DXErrorGoto(ERROR_DATA_INVALID,"Can't write output file");
951 strip_offsets[i] = offset;
952 strip_byte_counts[i] = j;
953 offset += j;
954 npixels += count;
955 j = count = 0;
956 i++;
957 }
958 if (x == columns) {
959 y--;
960 x = 1;
961 from = ((RGBByteColor *)pixels) + y*columns;
962 } else {
963 x++;
964 from ++;
965 }
966 }
967 }
968
969
970 DXFree((Pointer)rgb);
971 #ifdef HAVE_LZW_COMPRESS
972 DXFree((Pointer)comp_rgb);
973 #endif
974 return OK;
975 error:
976 if (rgb) DXFree((Pointer)rgb);
977 #ifdef HAVE_LZW_COMPRESS
978 if (comp_rgb) DXFree((Pointer)comp_rgb);
979 #endif
980 return ERROR;
981 }
982 /*
983 * Write the TIFF header to offset 0 of file descriptor fd.
984 * Returns 0/1 on failure/success.
985 */
986 static Error
put_tiff_header(int fd,int byte_order,int version,int ifd_offset)987 put_tiff_header(int fd, int byte_order, int version, int ifd_offset)
988 {
989 uint16 s[2];
990 uint32 l;
991
992 lseek(fd, 0, L_SET);
993
994 s[0] = (uint16)(byte_order&0xffff);
995 s[1] = (uint16)(version&0xffff);
996 if (!write_msb_uint16(fd,s[0]) || !write_msb_uint16(fd,s[1]))
997 return(0);
998
999 l = ifd_offset;
1000 if (l > 0)
1001 if (!write_msb_uint32(fd,l))
1002 return(0);
1003
1004 return(1);
1005 }
1006
1007
1008 /*----------------------------------------------------------------------------*/
1009
1010
1011 typedef struct
1012 {
1013 TiffTag tag;
1014 char *tag_name;
1015 TiffType tiff_type;
1016 uint32 size;
1017 }
1018 tag_table_entry;
1019
1020
1021 #define FUNCTION -1
1022 #define NONE -1
1023
1024 /*
1025 * The entries (plural!) 318 are not to be trusted since there is no
1026 * determining which interpretation to use.
1027 */
1028 tag_table_entry
1029 tag_entries[]
1030 =
1031 { { NewSubfileType, "NewSubfileType", tiff_LONG, 1 },
1032 { SubfileType, "SubfileType", tiff_SHORT, 1 },
1033 { ImageWidth, "ImageWidth", SHORT_LONG, 1 },
1034 { ImageLength, "ImageLength", SHORT_LONG, 1 },
1035 { BitsPerSample, "BitsPerSample", tiff_SHORT, FUNCTION },
1036 { Compression, "Compression", tiff_SHORT, 1 },
1037 { PhotometricInterpretation,
1038 "PhotometricInterpretation", tiff_SHORT, 1 },
1039 { Threshholding, "Threshholding", tiff_SHORT, 1 },
1040 { CellWidth, "CellWidth", tiff_SHORT, 1 },
1041 { CellLength, "CellLength", tiff_SHORT, 1 },
1042 { FillOrder, "FillOrder", tiff_SHORT, 1 },
1043 { DocumentName, "DocumentName", tiff_ASCII, NONE },
1044 { ImageDescription, "ImageDescription", tiff_ASCII, NONE },
1045 { Make, "Make", tiff_ASCII, NONE },
1046 { Model, "Model", tiff_ASCII, NONE },
1047 { StripOffsets, "StripOffsets", SHORT_LONG, FUNCTION },
1048 { Orientation, "Orientation", tiff_SHORT, 1 },
1049 { SamplesPerPixel, "SamplesPerPixel", tiff_SHORT, 1 },
1050 { RowsPerStrip, "RowsPerStrip", SHORT_LONG, 1 },
1051 { StripByteCounts, "StripByteCounts", SHORT_LONG, FUNCTION },
1052 { MinSampleValue, "MinSampleValue", tiff_SHORT, FUNCTION },
1053 { MaxSampleValue, "MaxSampleValue", tiff_SHORT, FUNCTION },
1054 { XResolution, "XResolution", tiff_RATIONAL, 1 },
1055 { YResolution, "YResolution", tiff_RATIONAL, 1 },
1056 { PlanarConfiguration, "PlanarConfiguration",tiff_SHORT, 1 },
1057 { PageName, "PageName", tiff_ASCII, NONE },
1058 { XPosition, "XPosition", tiff_RATIONAL, NONE },
1059 { YPosition, "YPosition", tiff_RATIONAL, NONE },
1060 { FreeOffsets, "FreeOffsets", tiff_LONG, NONE },
1061 { FreeByteCounts, "FreeByteCounts", tiff_LONG, NONE },
1062 { GrayResponseUnit, "GrayResponseUnit", tiff_SHORT, 1 },
1063 { GrayResponseCurve, "GrayResponseCurve", tiff_SHORT, FUNCTION },
1064 { Group3Options, "Group3Options", tiff_LONG, 1 },
1065 { Group4Options, "Group4Options", tiff_LONG, 1 },
1066 { ResolutionUnit, "ResolutionUnit", tiff_SHORT, 1 },
1067 { PageNumber, "PageNumber", tiff_SHORT, 2 },
1068 { ColorResponseCurves, "ColorResponseCurves",tiff_SHORT, FUNCTION },
1069 { Software, "Software", tiff_ASCII, NONE },
1070 { DateTime, "DateTime", tiff_ASCII, 20 },
1071 { Artist, "Artist", tiff_ASCII, NONE },
1072 { HostComputer, "HostComputer", tiff_ASCII, NONE },
1073 { Predictor, "Predictor", tiff_SHORT, 1 },
1074 { WhitePoint_XXX, "WhitePoint", tiff_RATIONAL, 2 },
1075 { ColorImageType_XXX, "ColorImageType", tiff_SHORT, 1 },
1076 { PrimaryChromaticities,
1077 "PrimaryChromaticities", tiff_RATIONAL, 6 },
1078 { ColorMap, "ColorMap", tiff_SHORT, FUNCTION },
1079 { ColorMap, NULL, tiff_SHORT, FUNCTION }
1080 };
1081
1082
1083
1084 static
tiff_lookup(TiffTag tag)1085 tag_table_entry * tiff_lookup ( TiffTag tag )
1086 {
1087 int i;
1088 static tag_table_entry error
1089 = { (TiffTag) -99, "** Error **", (TiffType) -99, (uint32) -99 };
1090
1091 for ( i=0; tag_entries[i].tag_name != NULL; i++ )
1092 if ( tag_entries[i].tag == tag )
1093 return &tag_entries[i];
1094
1095 return &error;
1096 }
1097
1098
1099
1100 /*
1101 * Search names, in order:
1102 * ".tiff", ".tif", ".0.tiff", ".0.tif"
1103 *
1104 * set states saying whether:
1105 * contains numeric
1106 * has which extension.
1107 */
_dxf_BuildTIFFReadFileName(char * buf,int bufl,char * basename,char * fullname,int framenum,int * numeric,int * selection)1108 char * _dxf_BuildTIFFReadFileName
1109 ( char *buf,
1110 int bufl,
1111 char *basename, /* Does not have an extension */
1112 char *fullname, /* As specified */
1113 int framenum,
1114 int *numeric, /* Numbers postfixed onto name or not? */
1115 int *selection /* file name extension ? (enumeral) */ )
1116 {
1117 int i;
1118 int fd = -1;
1119
1120 DXASSERTGOTO ( ERROR != buf );
1121 DXASSERTGOTO ( 0 < bufl );
1122 DXASSERTGOTO ( ERROR != basename );
1123 DXASSERTGOTO ( ERROR != fullname );
1124 DXASSERTGOTO ( 0 <= framenum );
1125 DXASSERTGOTO ( ERROR != numeric );
1126 DXASSERTGOTO ( ERROR != selection );
1127
1128 for ( i = 0;
1129 i < 4;
1130 i++ )
1131 {
1132 *numeric = i / 2;
1133 *selection = i % 2;
1134
1135 if ( ( *numeric == 1 ) && ( framenum == VALUE_UNSPECIFIED ) ) continue;
1136
1137 if ( !_dxf_BuildImageFileName
1138 ( buf,
1139 bufl,
1140 basename,
1141 img_typ_tiff,
1142 (*numeric==1)? framenum : -1,
1143 *selection ) )
1144 goto error;
1145
1146 if ( 0 <= ( fd = open ( buf, O_RDONLY ) ) )
1147 break;
1148 }
1149
1150 if ( 0 > fd )
1151 {
1152 *numeric = 0;
1153 *selection = 2;
1154
1155 strcpy ( buf, basename );
1156
1157 fd = open ( buf, O_RDONLY );
1158 }
1159
1160 DXDebug( "R",
1161 "_dxf_BuildTIFFReadFileName: Filen = %s, numer = %d, ext_sel = %d",
1162 buf,
1163 *numeric,
1164 *selection );
1165
1166 if (fd > -1)
1167 close ( fd );
1168
1169 return buf;
1170
1171 error:
1172 return ERROR;
1173 }
1174
1175
1176
1177 static
read_tiff_header(int fh,TiffHeader * hdr,Error (** rs)(int,uint16 *),Error (** rl)(int,uint32 *))1178 TiffHeader * read_tiff_header
1179 ( int fh,
1180 TiffHeader *hdr,
1181 Error (**rs)(int,uint16*),
1182 Error (**rl)(int,uint32*) )
1183 {
1184 int32 file_last;
1185
1186 DXASSERTGOTO ( fh > 0 );
1187 DXASSERTGOTO ( hdr != ERROR );
1188 DXASSERTGOTO ( rs != ERROR );
1189 DXASSERTGOTO ( rl != ERROR );
1190
1191 if ( 2 != read ( fh, &hdr->byte_order, 2 ) ) goto error;
1192
1193 switch ( hdr->byte_order )
1194 {
1195 default:
1196 DXErrorGoto
1197 ( ERROR_DATA_INVALID,
1198 "TIFF file header must start with 0x4949 or 0x4D4D" );
1199 break;
1200
1201 case TIFF_LSB: *rs = read_lsb_uint16; *rl = read_lsb_uint32; break;
1202 case TIFF_MSB: *rs = read_msb_uint16; *rl = read_msb_uint32; break;
1203 }
1204
1205 if ( !(*(*rs)) ( fh, &hdr->version ) ||
1206 !(*(*rl)) ( fh, &hdr->ifd_offset ) )
1207 goto error;
1208
1209 if ( hdr->version != 42 )
1210 DXWarning ( "The TIFF version number in the file is not 42." );
1211
1212 DXDebug ( "R",
1213 "ordering,version,offset = %4x,%d,%d",
1214 hdr->byte_order,
1215 hdr->version,
1216 hdr->ifd_offset );
1217
1218 if ( 0 > ( file_last = lseek ( fh, 0, 2 ) ) )
1219 DXErrorGoto2
1220 ( ERROR_DATA_INVALID,
1221 "#11800", /* C standard library call, %s, returns error */
1222 "lseek()" )
1223
1224 if ( hdr->ifd_offset > file_last )
1225 {
1226 DXDebug("R",
1227 "The TIFF initial offset (%d) is greater than file length (%d).",
1228 hdr->ifd_offset, file_last );
1229
1230 DXErrorGoto
1231 ( ERROR_DATA_INVALID,
1232 "The TIFF initial offset is greater than file length." );
1233 }
1234
1235 if ( 0 > lseek ( fh, hdr->ifd_offset, 0 ) )
1236 DXErrorGoto2
1237 ( ERROR_DATA_INVALID,
1238 "#10911", /* Seeking to offset %d in binary file failed */
1239 hdr->ifd_offset )
1240
1241 return hdr;
1242
1243 error:
1244 return ERROR;
1245 }
1246
1247
1248
1249 static
read_tiff_field(int fh,TiffField * fld,Error (* rs)(int,uint16 *),Error (* rl)(int,uint32 *))1250 TiffField * read_tiff_field
1251 ( int fh,
1252 TiffField *fld,
1253 Error (*rs)(int,uint16*),
1254 Error (*rl)(int,uint32*) )
1255 {
1256 int i;
1257 int save;
1258
1259 DXASSERTGOTO ( fh > 0 );
1260 DXASSERTGOTO ( fld != ERROR );
1261 DXASSERTGOTO ( rs != ERROR );
1262 DXASSERTGOTO ( rl != ERROR );
1263
1264 if ( !rs ( fh, &fld->tag ) ||
1265 !rs ( fh, &fld->type ) ||
1266 !rl ( fh, &fld->length ) )
1267 goto error;
1268
1269 if ( 0 > ( save = lseek ( fh, 0, 1 ) ) )
1270 DXErrorGoto2
1271 ( ERROR_DATA_INVALID,
1272 "#11800", /* C standard library call, %s, returns error */
1273 "lseek()" )
1274 else
1275 save += 4;
1276
1277 DXDebug ( "R",
1278 "tag,type,length = %d %s, %d %s, %d",
1279 fld->tag, ( tiff_lookup ( (TiffTag) fld->tag ) ) -> tag_name,
1280 fld->type, ((fld->type>=1)&&(fld->type<=5)) ?
1281 tiff_type_name [ fld->type ] :
1282 "** Error **",
1283 fld->length );
1284
1285 if ( ( tiff_type_bytecount [ fld->type ] * fld->length ) > 4 )
1286 { if ( !rl ( fh, &fld->value.offset ) ) goto error; }
1287 else
1288 switch ( fld->type )
1289 {
1290 case tiff_BYTE:
1291 case tiff_ASCII:
1292 if (read ( fh, &fld->value.value, fld->length ) != fld->length )
1293 DXErrorGoto2
1294 ( ERROR_DATA_INVALID,
1295 "#11800",
1296 /* C standard library call, %s, returns error */
1297 "read()" );
1298 break;
1299
1300 case tiff_SHORT:
1301 for ( i=0; i<fld->length; i++ )
1302 if ( !rs ( fh, &((uint16*)&fld->value.value)[i] ) )
1303 goto error;
1304 break;
1305
1306 case tiff_LONG:
1307 if ( !rl ( fh, &fld->value.value ) )
1308 goto error;
1309 break;
1310 }
1311
1312 if ( 0 > lseek ( fh, save, 0 ) )
1313 DXErrorGoto2
1314 ( ERROR_DATA_INVALID,
1315 "#10911", /* Seeking to offset %d in binary file failed */
1316 save );
1317
1318 return fld;
1319
1320 error:
1321 return ERROR;
1322 }
1323
1324
1325
1326 static
1327 /*
1328 * Read sizes from an opened TIFF file.
1329 * return read pointers for checking next entry in file IFD.
1330 *
1331 * Problem:
1332 * Image sizes may change internal to a TIFF file, yet we want only one.
1333 * Solution:
1334 * Read and use only the first image H,W.
1335 * (Alternative, not used: have restrictor parameters EG:strt,end)
1336 */
read_image_sizes_tiff(SizeData * sd,int fh,Error (* rs)(int,uint16 *),Error (* rl)(int,uint32 *))1337 SizeData * read_image_sizes_tiff
1338 ( SizeData *sd,
1339 int fh,
1340 Error (*rs)(int,uint16*),
1341 Error (*rl)(int,uint32*) )
1342 {
1343 TiffField field;
1344 uint16 tiff_entity_count;
1345 int i;
1346
1347 DXASSERTGOTO ( sd != ERROR );
1348 DXASSERTGOTO ( fh != ERROR );
1349 DXASSERTGOTO ( rs != ERROR );
1350 DXASSERTGOTO ( rl != ERROR );
1351
1352 sd->width = -1;
1353 sd->height = -1;
1354 sd->startframe = -1;
1355 sd->endframe = -1;
1356
1357 if ( !rs ( fh, &tiff_entity_count ) )
1358 goto error;
1359
1360 DXDebug ( "R",
1361 "read_image_sizes_tiff: tiff_entity_count = %d",
1362 tiff_entity_count );
1363
1364 for ( i=0;
1365 i < tiff_entity_count;
1366 i++ )
1367 if ( !read_tiff_field ( fh, &field, rs, rl ) )
1368 goto error;
1369 else
1370 switch ( field.tag )
1371 {
1372 case ImageWidth:
1373 if ( field.length != 1 )
1374 DXErrorGoto2
1375 ( ERROR_DATA_INVALID,
1376 "TIFF field `%s' has bad size setting.",
1377 "ImageWidth" );
1378
1379 if ( field.type == tiff_SHORT )
1380 sd->width = ((uint16*)&field.value.value)[0];
1381 else if ( field.type == tiff_LONG )
1382 sd->width = field.value.value;
1383 else
1384 DXErrorGoto2
1385 ( ERROR_DATA_INVALID,
1386 "TIFF field `%s' has bad type.",
1387 "ImageWidth" );
1388 break;
1389
1390 case ImageLength:
1391 if ( field.length != 1 )
1392 DXErrorGoto2
1393 ( ERROR_DATA_INVALID,
1394 "TIFF field `%s' has bad size setting.",
1395 "ImageLength" );
1396
1397 if ( field.type == tiff_SHORT )
1398 sd->height = ((uint16*)&field.value.value)[0];
1399 else if ( field.type == tiff_LONG )
1400 sd->height = field.value.value;
1401 else
1402 DXErrorGoto2
1403 ( ERROR_DATA_INVALID,
1404 "TIFF field `%s' has bad type.",
1405 "ImageLength" );
1406 break;
1407
1408 default:
1409 ;
1410 }
1411
1412 if ( sd->width == -1 )
1413 DXErrorGoto
1414 ( ERROR_DATA_INVALID, "Required TIFF field `ImageWidth' is missing" );
1415
1416 if ( sd->height == -1 )
1417 DXErrorGoto
1418 ( ERROR_DATA_INVALID, "Required TIFF field `ImageLength' is missing" );
1419
1420 DXDebug ( "R",
1421 "read_image_sizes_tiff: width,height = %d,%d",
1422 sd->width,
1423 sd->height );
1424
1425 return sd;
1426
1427 error:
1428 return ERROR;
1429 }
1430
1431
1432
1433 /*
1434 * Set a SizeData struct with values.
1435 * set state saying whether:
1436 * has multiple images in file
1437 * Careful:
1438 * if the images are stored internally,
1439 * then reset the use_numerics flag.
1440 */
_dxf_ReadImageSizesTIFF(char * name,int startframe,SizeData * data,int * use_numerics,int ext_sel,int * multiples)1441 SizeData * _dxf_ReadImageSizesTIFF
1442 ( char *name,
1443 int startframe,
1444 SizeData *data,
1445 int *use_numerics,
1446 int ext_sel,
1447 int *multiples )
1448 {
1449 TiffHeader hdr;
1450 uint16 tiff_entity_count;
1451 char copyname [ MAX_IMAGE_NAMELEN ];
1452 SizeData frame_data;
1453 int fh;
1454 Error (*rs)(int,uint16*);
1455 Error (*rl)(int,uint32*);
1456
1457 DXASSERTGOTO ( ERROR != name );
1458 DXASSERTGOTO ( ERROR != data );
1459 DXASSERTGOTO ( ERROR != use_numerics );
1460 DXASSERTGOTO ( ( ext_sel >= 0 ) && ( ext_sel <= 2 ) );
1461 DXASSERTGOTO ( ERROR != multiples );
1462
1463 /*
1464 *
1465 */
1466
1467 if ( 0 > ( fh = open ( name, O_RDONLY ) ) )
1468 DXErrorGoto2
1469 ( ERROR_BAD_PARAMETER, "#12240", /* can not open file '%s' */ name );
1470
1471 if ( !read_tiff_header ( fh, &hdr, &rs, &rl ) )
1472 goto error;
1473
1474 /*
1475 * We are now relying on the fact that the file pointer
1476 * is at the next header.
1477 */
1478 if ( !read_image_sizes_tiff ( &frame_data, fh, rs, rl ) )
1479 goto error;
1480
1481 data->height = frame_data.height;
1482 data->width = frame_data.width;
1483 data->startframe = ( startframe == VALUE_UNSPECIFIED )? 0 : startframe;
1484 data->endframe = data->startframe;
1485 *multiples = 0; /* For now. */
1486
1487 /*
1488 * Intent: See if there are multiple images in this file.
1489 */
1490 if ( !rl ( fh, &hdr.ifd_offset ) )
1491 goto error;
1492
1493 while ( hdr.ifd_offset != 0 )
1494 {
1495 data->endframe++;
1496
1497 if ( 0 > lseek ( fh, hdr.ifd_offset, 0 ) )
1498 DXErrorGoto2
1499 ( ERROR_DATA_INVALID,
1500 "#10911", /* Seeking to offset %d in binary file failed */
1501 hdr.ifd_offset );
1502
1503 if ( !rs ( fh, &tiff_entity_count ) )
1504 goto error;
1505
1506 DXDebug ( "R",
1507 "_dxf_ReadImageSizesTIFF: tiff_entity_count = %d",
1508 tiff_entity_count );
1509
1510 if ( 0 > lseek ( fh, (tiff_entity_count*TIFF_FIELD_SIZE), 1 ) )
1511 DXErrorGoto2
1512 ( ERROR_DATA_INVALID,
1513 "#10911", /* Seeking to offset %d in binary file failed */
1514 (tiff_entity_count*TIFF_FIELD_SIZE) );
1515
1516 if ( !rl ( fh, &hdr.ifd_offset ) )
1517 goto error;
1518 }
1519
1520 close ( fh );
1521
1522 if ( data->startframe != data->endframe )
1523 {
1524 *multiples = 1;
1525 *use_numerics = 0;
1526
1527 goto ok;
1528 }
1529
1530
1531 /*
1532 * Intent: See if there are multiple numbered files on disk.
1533 */
1534 if ( *use_numerics != 1 )
1535 {
1536 *multiples = 0;
1537 goto ok;
1538 }
1539
1540 if ( ERROR == strcpy ( copyname, name ) )
1541 DXSetError
1542 ( ERROR_UNEXPECTED,
1543 "#11800", /* C standard library call, %s, returns error */
1544 "strcpy()" );
1545
1546 while ( 0 <= ( fh = open ( copyname, O_RDONLY ) ) )
1547 {
1548 close ( fh );
1549
1550 DXDebug ( "R", "_dxf_ReadImageSizesTIFF: opened: %s", copyname );
1551
1552 if ( ext_sel == 2 )
1553 {
1554 if ( !_dxf_RemoveExtension ( copyname ) )
1555 goto error;
1556 }
1557 else
1558 if ( !_dxf_RemoveExtension ( copyname ) ||
1559 !_dxf_RemoveExtension ( copyname ) )
1560 goto error;
1561
1562 data->endframe++;
1563
1564 sprintf
1565 ( ©name [ strlen ( copyname ) ],
1566 (ext_sel==0)? ".%d.tiff" :
1567 (ext_sel==1)? ".%d.tif" :
1568 ".%d",
1569 data->endframe );
1570 }
1571
1572 data->endframe--;
1573
1574 ok:
1575 DXDebug ( "R",
1576 "_dxf_ReadImageSizesTIFF: h,w, s,e = %d,%d, %d,%d; "
1577 "numer = %d, multi = %d",
1578 data->height,
1579 data->width,
1580 data->startframe,
1581 data->endframe,
1582 *use_numerics,
1583 *multiples );
1584
1585 return data;
1586
1587 error:
1588 return ERROR;
1589 }
1590
1591 #define SEEK_TO_STRIP \
1592 { \
1593 uint16 ss; \
1594 uint32 ll; \
1595 \
1596 if ( 0 > lseek ( fh, seek_offset, 0 ) ) \
1597 DXErrorGoto2(ERROR_DATA_INVALID, "#10911", seek_offset); \
1598 \
1599 switch (file_data.StripOffsets.type) \
1600 { \
1601 case tiff_SHORT: \
1602 if ( !rs(fh,&ss) ) goto error; \
1603 seek_offset += 2; \
1604 ll = ss; \
1605 break; \
1606 \
1607 case tiff_LONG: \
1608 if ( !rl(fh,&ll) ) goto error; \
1609 seek_offset += 4; \
1610 break; \
1611 } \
1612 \
1613 if (0 > lseek(fh, ll, 0)) \
1614 DXErrorGoto2(ERROR_DATA_INVALID, "#10911", ll); \
1615 \
1616 striplines = file_data.rowsperstrip.val; \
1617 }
1618
1619 /*
1620 */
_dxf_InputTIFF(int width,int height,char * name,int relframe,int delayed,char * colortype)1621 Field _dxf_InputTIFF
1622 (int width, int height, char *name, int relframe, int delayed, char *colortype)
1623 {
1624 Field image = NULL;
1625 int seek_offset;
1626 int striplines;
1627 int i, x, y;
1628 TiffHeader hdr;
1629 TiffField field;
1630 uint16 tiff_entity_count;
1631 Error (*rs)(int,uint16*);
1632 Error (*rl)(int,uint32*);
1633 tag_table_entry *lookup;
1634
1635 RGBColor map[256];
1636 RGBByteColor imap[256];
1637 ubyte *buf = NULL;
1638
1639 int fh = -1;
1640 int rframe;
1641
1642 struct
1643 {
1644 int height, width;
1645 RGBColor *anchor;
1646 }
1647 image_data;
1648
1649 typedef struct
1650 {
1651 uint32 val;
1652 int set;
1653 }
1654 setval;
1655
1656 struct
1657 {
1658 setval height, width, rowsperstrip, samplesperpixel;
1659 setval planarconfiguration, photometricinterpretation, compression;
1660 TiffField StripOffsets, BitsPerSample;
1661 TiffField ColorMap, ColorResponseCurves;
1662 }
1663 file_data;
1664
1665 #define UNSET_TAG 65535
1666
1667 DXDebug ( "R", "_dxf_InputTIFF: name = %s, relframe = %d", name, relframe );
1668
1669 file_data.height.set = 0;
1670 file_data.width.set = 0;
1671 file_data.rowsperstrip.set = 0;
1672 file_data.samplesperpixel.set = 0;
1673 file_data.planarconfiguration.set = 0;
1674 file_data.compression.set = 0;
1675 file_data.photometricinterpretation.set = 0;
1676
1677 file_data.StripOffsets.tag = UNSET_TAG;
1678 file_data.BitsPerSample.tag = UNSET_TAG;
1679 file_data.ColorMap.tag = UNSET_TAG;
1680 file_data.ColorResponseCurves.tag = UNSET_TAG;
1681
1682
1683 image_data.width = width;
1684 image_data.height = height;
1685 image_data.anchor = NULL;
1686
1687 if ((image_data.width * image_data.height) == 0)
1688 DXErrorGoto2
1689 ( ERROR_BAD_PARAMETER, "#12275", 0 );
1690
1691 if ( 0 > ( fh = open ( name, O_RDONLY ) ) )
1692 DXErrorGoto2
1693 ( ERROR_BAD_PARAMETER,
1694 "#12240", /* cannot open file '%s' */
1695 name );
1696
1697 if ( !read_tiff_header ( fh, &hdr, &rs, &rl ) )
1698 goto error;
1699
1700 for ( rframe = 0; rframe <= relframe; rframe++ )
1701 {
1702 if ( !rs ( fh, &tiff_entity_count ) )
1703 goto error;
1704
1705 DXDebug ( "R",
1706 "frame:[%d] tiff entity count = %d",
1707 rframe,
1708 tiff_entity_count );
1709 /*
1710 * Seek past end of entity list and to beginning of next.
1711 * For each frame except the last.
1712 */
1713 if ( rframe < relframe )
1714 {
1715 if ( 0 > lseek ( fh, (tiff_entity_count*TIFF_FIELD_SIZE), 1 ) )
1716 DXErrorGoto2
1717 ( ERROR_DATA_INVALID,
1718 "#10911", /* Seeking to offset %d in binary file failed */
1719 (tiff_entity_count*TIFF_FIELD_SIZE) );
1720
1721 if ( !rl ( fh, &hdr.ifd_offset ) )
1722 goto error;
1723
1724 if ( hdr.ifd_offset == 0 )
1725 DXErrorGoto3
1726 ( ERROR_INTERNAL,
1727 "Ifd_offset of zero at rframe %d of %d",
1728 rframe, relframe );
1729
1730 if ( 0 > lseek ( fh, hdr.ifd_offset, 0 ) )
1731 DXErrorGoto2
1732 ( ERROR_DATA_INVALID,
1733 "#10911", /* Seeking to offset %d in binary file failed */
1734 hdr.ifd_offset );
1735 }
1736 }
1737
1738 /*
1739 * Read in all significant field data.
1740 */
1741 for ( i=0; i<tiff_entity_count; i++ )
1742 if ( !read_tiff_field ( fh, &field, rs, rl ) )
1743 goto error;
1744 else
1745 {
1746 setval tmp_integer = {0, 0};
1747 int remote_data = -1;
1748
1749 /*
1750 * Pre-screening for fields that we have to look at.
1751 */
1752 switch ( field.tag )
1753 {
1754 case ImageWidth:
1755 case ImageLength:
1756 case BitsPerSample:
1757 case StripOffsets:
1758 case SamplesPerPixel:
1759 case RowsPerStrip:
1760 case PlanarConfiguration:
1761 case PhotometricInterpretation:
1762 case Compression:
1763 case ColorResponseCurves:
1764 case ColorMap:
1765
1766 if ( ERROR == ( lookup =
1767 tiff_lookup ( (TiffTag)field.tag ) ) )
1768 goto error;
1769
1770 if ( ( ( field.type < tiff_BYTE ) ||
1771 ( field.type > tiff_RATIONAL ) )
1772 ||
1773 ( ( lookup->tiff_type == SHORT_LONG ) &&
1774 ( ( field.type != tiff_SHORT ) &&
1775 ( field.type != tiff_LONG ) ) )
1776 ||
1777 ( ( lookup->tiff_type != SHORT_LONG ) &&
1778 ( lookup->tiff_type != field.type ) ) )
1779 DXErrorGoto2
1780 ( ERROR_DATA_INVALID,
1781 "TIFF field `%s' has bad type.",
1782 lookup->tag_name );
1783
1784 if ( ( lookup->size != FUNCTION ) &&
1785 ( field.length != lookup->size ) )
1786 DXErrorGoto2
1787 ( ERROR_DATA_INVALID,
1788 "TIFF field `%s' has bad size setting.",
1789 lookup->tag_name );
1790
1791 if ( field.length != 1 )
1792 tmp_integer.set = 0;
1793 else
1794 switch ( field.type )
1795 {
1796 case tiff_SHORT:
1797 tmp_integer.val
1798 = ((uint16*)&field.value.value)[0];
1799 tmp_integer.set = 1;
1800 break;
1801
1802 case tiff_LONG:
1803 tmp_integer.val = field.value.value;
1804 tmp_integer.set = 1;
1805 break;
1806
1807 default:
1808 tmp_integer.set = 0;
1809 }
1810
1811 remote_data =
1812 (4 < ( tiff_type_bytecount[field.type] * field.length));
1813
1814 break;
1815
1816 default:
1817 remote_data = -1;
1818 }
1819
1820 /*
1821 * Store the setting.
1822 */
1823 switch ( field.tag )
1824 {
1825 case ImageWidth:
1826 if ( !tmp_integer.set || ( remote_data != 0 ) )
1827 DXErrorGoto
1828 ( ERROR_UNEXPECTED,
1829 "Getting TIFF integer, field `ImageWidth'" );
1830
1831 file_data.width = tmp_integer;
1832 break;
1833
1834 case ImageLength:
1835 if ( !tmp_integer.set || ( remote_data != 0 ) )
1836 DXErrorGoto
1837 ( ERROR_UNEXPECTED,
1838 "Getting TIFF integer, field `ImageLength'" );
1839
1840 file_data.height = tmp_integer;
1841 break;
1842
1843 case SamplesPerPixel:
1844 if ( !tmp_integer.set || ( remote_data != 0 ) )
1845 DXErrorGoto
1846 ( ERROR_UNEXPECTED,
1847 "Getting TIFF integer, field `SamplesPerPixel'" );
1848
1849 file_data.samplesperpixel = tmp_integer;
1850 break;
1851
1852 case RowsPerStrip:
1853 if ( !tmp_integer.set || ( remote_data != 0 ) )
1854 DXErrorGoto
1855 ( ERROR_UNEXPECTED,
1856 "Getting TIFF integer, field `RowsPerStrip'" );
1857
1858 file_data.rowsperstrip = tmp_integer;
1859 break;
1860
1861 case PhotometricInterpretation:
1862 if ( !tmp_integer.set || ( remote_data != 0 ) )
1863 DXErrorGoto
1864 ( ERROR_UNEXPECTED,
1865 "Getting TIFF integer,"
1866 " field `PhotometricInterpretation'" );
1867
1868 file_data.photometricinterpretation = tmp_integer;
1869 break;
1870
1871 case PlanarConfiguration:
1872 if ( !tmp_integer.set || ( remote_data != 0 ) )
1873 DXErrorGoto
1874 ( ERROR_UNEXPECTED,
1875 "Getting TIFF integer, field `PlanarConfiguration'" );
1876
1877 file_data.planarconfiguration = tmp_integer;
1878 break;
1879
1880 case Compression:
1881 if ( !tmp_integer.set || ( remote_data != 0 ) )
1882 DXErrorGoto
1883 ( ERROR_UNEXPECTED,
1884 "Getting TIFF integer, field `Compression'" );
1885
1886 file_data.compression = tmp_integer;
1887 break;
1888
1889 case BitsPerSample:
1890 file_data.BitsPerSample = field;
1891 break;
1892
1893 case StripOffsets:
1894 file_data.StripOffsets = field;
1895 break;
1896
1897 case ColorResponseCurves:
1898 file_data.ColorResponseCurves = field;
1899 break;
1900
1901 case ColorMap:
1902 file_data.ColorMap = field;
1903 break;
1904
1905 default:
1906 ;
1907 }
1908 }
1909
1910
1911 /*
1912 * Check what was found, default what can be, Error on what can't.
1913 * Mandatory settings
1914 */
1915 /* 256 ImageWidth */
1916 if ( !file_data.width.set )
1917 DXErrorGoto
1918 ( ERROR_DATA_INVALID,
1919 "Required TIFF field `ImageWidth' is missing" )
1920 else
1921 if ( file_data.width.val != image_data.width )
1922 DXErrorGoto
1923 ( ERROR_INTERNAL, "TIFF Image width disagreement" );
1924
1925 /* 257 ImageLength */
1926 if ( !file_data.height.set )
1927 DXErrorGoto
1928 ( ERROR_DATA_INVALID,
1929 "Required TIFF field `ImageLength' is missing" )
1930 else
1931 if ( file_data.height.val != image_data.height )
1932 DXErrorGoto
1933 ( ERROR_INTERNAL, "TIFF Image length disagreement" );
1934
1935 /* 273 StripOffsets */
1936 if ( file_data.StripOffsets.tag == UNSET_TAG )
1937 DXErrorGoto
1938 ( ERROR_DATA_INVALID,
1939 "Required TIFF field `StripOffsets' is missing" );
1940
1941
1942 /*
1943 * Defaultable settings.
1944 * Since TIFF settings are supposed to be in numeric sorted order,
1945 * construct defaulting (using backward cross references) this way.
1946 * exceptions:
1947 * SamplesPerPixel is defined after BitsPerSample (size depends on)
1948 */
1949
1950 /* 258 BitsPerSample */
1951 if ( file_data.BitsPerSample.tag == UNSET_TAG )
1952 {
1953 file_data.BitsPerSample.tag = BitsPerSample;
1954 file_data.BitsPerSample.value.value = 8; /* XXX 3 */ /* XXX uint16 */
1955 DXMessage
1956 ( "Defaulting TIFF `BitsPerSample' to 8,8,8" );
1957 }
1958 else
1959 {
1960 if ( 1 == file_data.BitsPerSample.length )
1961 {
1962 if ( ((uint16*)&file_data.BitsPerSample.value.value)[0] != 8 )
1963 DXErrorGoto
1964 ( ERROR_DATA_INVALID,
1965 "TIFF field `BitsPerSample' must be 8" );
1966 }
1967 else if ( 3 == file_data.BitsPerSample.length )
1968 {
1969 uint16 bps[3];
1970
1971 if ( 0 > lseek ( fh, file_data.BitsPerSample.value.offset, 0 ) )
1972 DXErrorGoto2
1973 ( ERROR_DATA_INVALID,
1974 "#10911", /* Seeking to offset %d in binary file failed */
1975 file_data.BitsPerSample.value.offset );
1976
1977 if ( !rs(fh, &bps[0]) || !rs(fh, &bps[1]) || !rs(fh, &bps[2]) )
1978 goto error;
1979
1980 if ( ( bps[0] != 8 ) || ( bps[1] != 8 ) || ( bps[2] != 8 ) )
1981 DXErrorGoto
1982 ( ERROR_DATA_INVALID,
1983 "TIFF field `BitsPerSample' must be 8,8,8" );
1984 }
1985 }
1986
1987
1988 /* 259 Compression */
1989 if ( !file_data.compression.set )
1990 {
1991 file_data.compression.val = 1;
1992 file_data.compression.set = 1;
1993 DXMessage
1994 ( "Defaulting TIFF `Compression' to 1 (None)" );
1995 }
1996 else if ( file_data.compression.val != 1 )
1997 DXErrorGoto
1998 ( ERROR_DATA_INVALID,
1999 "TIFF field `Compression' must be 1 (None)" );
2000
2001 /* 262 PhotometricInterpretation */
2002 if ( !file_data.photometricinterpretation.set )
2003 {
2004 file_data.photometricinterpretation.val = 2;
2005 file_data.photometricinterpretation.set = 1;
2006 DXMessage
2007 ( "Defaulting TIFF `PhotometricInterpretation' to 2 (RGB)" );
2008 }
2009 else if (
2010 ( file_data.photometricinterpretation.val != 0 ) &&
2011 ( file_data.photometricinterpretation.val != 1 ) &&
2012 ( file_data.photometricinterpretation.val != 2 ) &&
2013 ( file_data.photometricinterpretation.val != 3 ) )
2014 DXErrorGoto
2015 ( ERROR_DATA_INVALID,
2016 "TIFF field `PhotometricInterpretation'"
2017 " must be 0 (Min-Is-White) 1 (Min-Is-Black) 2 (RGB) or 3 (Palette)" );
2018
2019 DXDebug ( "R", "PhotometricInterpretation is %s",
2020 (file_data.photometricinterpretation.val == 0)? "Min_Is_White" :
2021 (file_data.photometricinterpretation.val == 1)? "Min_Is_Black" :
2022 (file_data.photometricinterpretation.val == 2)? "RGB" :
2023 (file_data.photometricinterpretation.val == 3)? "Palette" :
2024 "Bad!" );
2025
2026
2027 /* 277 SamplesPerPixel */
2028 if ( !file_data.samplesperpixel.set )
2029 {
2030 if ( file_data.photometricinterpretation.val == 2 )
2031 file_data.samplesperpixel.val = 3;
2032
2033 else if ( file_data.photometricinterpretation.val == 0 ||
2034 file_data.photometricinterpretation.val == 1 ||
2035 file_data.photometricinterpretation.val == 3 )
2036 file_data.samplesperpixel.val = 1;
2037
2038 file_data.samplesperpixel.set = 1;
2039 DXMessage
2040 ( "Defaulting TIFF `SamplesPerPixel' to %d",
2041 file_data.samplesperpixel.val );
2042 }
2043 else if (
2044 ( file_data.samplesperpixel.val != 1 ) &&
2045 ( file_data.samplesperpixel.val != 3 ) )
2046 DXErrorGoto
2047 ( ERROR_DATA_INVALID,
2048 "TIFF field `SamplesPerPixel' must be 1 or 3" );
2049
2050 if ( file_data.samplesperpixel.val != file_data.BitsPerSample.length )
2051 {
2052 DXWarning
2053 ( "TIFF fields `BitsPerSample'(length) and `SamplesPerPixel'"
2054 " conflict. (L%d != %d)",
2055 file_data.BitsPerSample.length,
2056 file_data.samplesperpixel.val );
2057
2058 DXWarning
2059 ( "Proceeding, though errors may result..." );
2060 }
2061
2062 if ( ( ( file_data.photometricinterpretation.val == 2 ) &&
2063 ( file_data.samplesperpixel.val != 3 ) )
2064 ||
2065 ( (( file_data.photometricinterpretation.val == 0 ) ||
2066 ( file_data.photometricinterpretation.val == 1 ) ||
2067 ( file_data.photometricinterpretation.val == 3 )) &&
2068 ( file_data.samplesperpixel.val != 1 ) ) )
2069 {
2070 DXWarning
2071 ( "TIFF fields `PhotometricInterpretation' and `SamplesPerPixel'"
2072 " conflict. (pmi=%d, spp=%d)",
2073 file_data.photometricinterpretation.val,
2074 file_data.samplesperpixel.val );
2075
2076 DXWarning
2077 ( "Proceeding, though errors may result..." );
2078 }
2079
2080
2081 /* 278 RowsPerStrip */
2082 if ( !file_data.rowsperstrip.set )
2083 {
2084 file_data.rowsperstrip.val = 2000000000; /* Signed integer infinity */
2085 file_data.rowsperstrip.set = 1;
2086 }
2087 /* When rowsperstrip not arbitrarily large... */
2088 else if ( ( file_data.rowsperstrip.val
2089 < ( file_data.height.val * file_data.width.val ) )
2090 &&
2091 /* perform number of strips consistency check */
2092 ( file_data.StripOffsets.length
2093 < ( ( file_data.height.val + file_data.rowsperstrip.val - 1 )
2094 / file_data.rowsperstrip.val ) ) )
2095 {
2096 DXWarning
2097 ( "TIFF fields `StripOffsets(length),ImageLength,RowsPerStrip'"
2098 " conflict. (L(so)=%d,il=%d,rps=%d)",
2099 file_data.StripOffsets.length,
2100 file_data.height.val,
2101 file_data.rowsperstrip.val );
2102
2103 DXWarning
2104 ( "Proceeding, though errors may result..." );
2105 }
2106
2107
2108 /* 284 PlanarConfiguration */
2109 if ( !file_data.planarconfiguration.set )
2110 {
2111 file_data.planarconfiguration.val = 1;
2112 file_data.planarconfiguration.set = 1;
2113 DXMessage
2114 ( "Defaulting TIFF `PlanarConfiguration' to 1 (contiguous pixels)" );
2115 }
2116 else if ( file_data.planarconfiguration.val != 1 )
2117 DXErrorGoto
2118 ( ERROR_DATA_INVALID,
2119 "TIFF field `PlanarConfiguration' must be 1 (contiguous)" );
2120
2121
2122 /* 301 ColorResponseCurves */
2123 if ( file_data.ColorResponseCurves.tag != UNSET_TAG )
2124 DXWarning
2125 ( "TIFF Field `ColorResponseCurves' ignored." );
2126
2127
2128 /* 320 ColorMap */
2129 if ( file_data.ColorMap.tag != UNSET_TAG )
2130 {
2131 if ( file_data.photometricinterpretation.val == 0 ||
2132 file_data.photometricinterpretation.val == 1 ||
2133 file_data.photometricinterpretation.val == 2 )
2134 DXWarning
2135 ( "This is not a PaletteColor image."
2136 " TIFF Field `ColorMap' ignored." );
2137 else
2138 {
2139 int ii;
2140 uint16 ss;
2141
2142 if ( file_data.ColorMap.length != 768 )
2143 {
2144 DXWarning
2145 ( "TIFF field `ColorMap' has bad size setting. (%d)",
2146 file_data.ColorMap.length );
2147
2148 DXWarning
2149 ( "Proceeding, though errors may result..." );
2150 }
2151
2152 if ( 0 > lseek ( fh, file_data.ColorMap.value.offset, 0 ) )
2153 DXErrorGoto2
2154 ( ERROR_DATA_INVALID,
2155 "#10911", /* Seeking to offset %d in binary file failed */
2156 file_data.ColorMap.value.offset );
2157
2158 /* XXX speed concerns */
2159 for ( ii=0; ii<256; ii++ )
2160 if ( rs ( fh, (uint16 *)&ss ) ) map[ii].r = ss / 65535.0;
2161 else goto error;
2162
2163 for ( ii=0; ii<256; ii++ )
2164 if ( rs ( fh, (uint16 *)&ss ) ) map[ii].g = ss / 65535.0;
2165 else goto error;
2166
2167 for ( ii=0; ii<256; ii++ )
2168 if ( rs ( fh, (uint16 *)&ss ) ) map[ii].b = ss / 65535.0;
2169 else goto error;
2170 }
2171 }
2172 else
2173 {
2174 if ( file_data.photometricinterpretation.val == 0 )
2175 {
2176 int ii;
2177
2178 for ( ii=0; ii<256; ii++ )
2179 map[ii].r = map[ii].g = map[ii].b = (255-ii) / 256.0;
2180
2181 }
2182 else if ( file_data.photometricinterpretation.val == 1 )
2183 {
2184 int ii;
2185
2186 for ( ii=0; ii<256; ii++ )
2187 map[ii].r = map[ii].g = map[ii].b = ii / 256.0;
2188
2189 }
2190 else if ( file_data.photometricinterpretation.val == 3 )
2191 {
2192 int ii;
2193
2194 DXWarning
2195 ( "TIFF field `ColorMap' is not present."
2196 " Installing a simple linear one." );
2197
2198 for ( ii=0; ii<256; ii++ )
2199 map[ii].r = map[ii].g = map[ii].b = ii / 256.0;
2200
2201 DXWarning
2202 ( "Proceeding, though errors may result..." );
2203 }
2204 }
2205
2206
2207 /*
2208 * End TIFF internal file parameter analysis.
2209 */
2210 if ( file_data.StripOffsets.length == 1 )
2211 {
2212 if (0 > lseek(fh, file_data.StripOffsets.value.offset, 0))
2213 DXErrorGoto2(ERROR_DATA_INVALID, "#10911",
2214 file_data.StripOffsets.value.offset );
2215
2216 seek_offset = 0;
2217 striplines = file_data.rowsperstrip.val;
2218 }
2219 else
2220 {
2221 seek_offset = file_data.StripOffsets.value.offset;
2222 striplines = 0;
2223 }
2224
2225 /*
2226 * Set the image pixels. Finally!
2227 */
2228 if ( ( file_data.samplesperpixel.val == 3 ) &&
2229 ( file_data.photometricinterpretation.val == 2 ) )
2230 {
2231 Type type;
2232 int rank, shape[32];
2233 Array colorsArray;
2234 Pointer pixels;
2235
2236 image = DXMakeImageFormat(width, height, colortype);
2237 if (! image)
2238 goto error;
2239
2240 colorsArray = (Array)DXGetComponentValue(image, "colors");
2241
2242 DXGetArrayInfo(colorsArray, NULL, &type, NULL, &rank, shape);
2243
2244 if (rank != 1 || shape[0] != 3 ||
2245 (type != TYPE_UBYTE && type != TYPE_FLOAT))
2246 {
2247 DXSetError(ERROR_INTERNAL,
2248 "3-vector float or byte image templates required %s",
2249 "to import non-mapped tiff");
2250 goto error;
2251 }
2252
2253 /*
2254 * If the output is type float then we'll be needing an input
2255 * buffer in any case
2256 */
2257 if (type == TYPE_FLOAT)
2258 {
2259 buf = DXAllocate(width * file_data.samplesperpixel.val);
2260 if (! buf)
2261 goto error;
2262 }
2263
2264 pixels = DXGetArrayData(colorsArray);
2265
2266 for (y=(image_data.height-1); y>=0; y--, striplines--)
2267 {
2268
2269 if (striplines == 0)
2270 SEEK_TO_STRIP;
2271
2272 if (type == TYPE_FLOAT)
2273 {
2274 int n = read(fh, buf, width*file_data.samplesperpixel.val);
2275 float *fptr = ((float *)pixels) + 3*y*width;
2276 ubyte *cptr = (ubyte *)buf;
2277
2278 if (n != width*file_data.samplesperpixel.val)
2279 {
2280 DXSetError(ERROR_INTERNAL,
2281 "error reading in a scan-line from tiff file");
2282 goto error;
2283 }
2284
2285 for (x = 0; x < image_data.width*3; x++)
2286 *fptr++ = *cptr++ / 255.0;
2287 }
2288 else
2289 {
2290 ubyte *fptr = ((ubyte *)pixels) + 3*y*width;
2291
2292 if (read(fh, fptr, width*file_data.samplesperpixel.val)
2293 != width*file_data.samplesperpixel.val)
2294 {
2295 DXSetError(ERROR_INTERNAL,
2296 "error reading in a scan-line from tiff file");
2297 goto error;
2298 }
2299 }
2300 }
2301 }
2302 else if ( ( file_data.samplesperpixel.val == 1 ) &&
2303 ((file_data.photometricinterpretation.val == 0 ) ||
2304 (file_data.photometricinterpretation.val == 1 ) ||
2305 (file_data.photometricinterpretation.val == 3 )) )
2306 {
2307 Type type;
2308 int rank, shape[32];
2309 Array colorsArray = NULL;
2310 Array colorMap = NULL;
2311 Pointer pixels;
2312
2313 if (delayed == DELAYED_YES)
2314 colortype = COLORTYPE_DELAYED;
2315 image = DXMakeImageFormat(width, height, colortype);
2316 if (! image)
2317 goto error;
2318
2319 colorsArray = (Array)DXGetComponentValue(image, "colors");
2320
2321 DXGetArrayInfo(colorsArray, NULL, &type, NULL, &rank, shape);
2322
2323 pixels = DXGetArrayData(colorsArray);
2324
2325 /*
2326 * we'll be needing an input buffer
2327 */
2328 buf = DXAllocate(width * file_data.samplesperpixel.val);
2329 if (! buf)
2330 goto error;
2331
2332 if (rank == 0 || (rank == 1 && shape[0] == 1))
2333 {
2334 Type mType;
2335 int mRank, mShape[32], mLen;
2336
2337 colorMap = (Array)DXGetComponentValue(image, "color map");
2338 if (! colorMap)
2339 {
2340 DXSetError(ERROR_INTERNAL,
2341 "single-valued image requires a color map");
2342 goto error;
2343 }
2344
2345 DXGetArrayInfo(colorMap, &mLen, &mType, NULL, &mRank, mShape);
2346
2347 if (mLen != 256 || mType != TYPE_FLOAT ||
2348 mRank != 1 || mShape[0] != 3)
2349 {
2350 DXSetError(ERROR_INTERNAL,
2351 "DXMakeImage returned invalid delayed-color image");
2352 goto error;
2353 }
2354
2355 memcpy(DXGetArrayData(colorMap), map, 256*3*sizeof(float));
2356
2357 for (y=(image_data.height-1); y>=0; y--, striplines--)
2358 {
2359 ubyte *fptr = ((ubyte *)pixels) + y*width;
2360
2361 if (striplines == 0)
2362 SEEK_TO_STRIP;
2363
2364 if (read(fh, fptr, width) != width)
2365 {
2366 DXSetError(ERROR_INTERNAL,
2367 "error reading in a scan-line from tiff file");
2368 goto error;
2369 }
2370 }
2371 }
2372 else if (rank == 1 && shape[0] == 3)
2373 {
2374 if (type == TYPE_UBYTE)
2375 {
2376 int i;
2377 for (i = 0; i < 256; i++)
2378 {
2379 imap[i].r = 255*map[i].r;
2380 imap[i].g = 255*map[i].g;
2381 imap[i].b = 255*map[i].b;
2382 }
2383 }
2384
2385 for (y=(image_data.height-1); y>=0; y--, striplines--)
2386 {
2387 if (striplines == 0)
2388 SEEK_TO_STRIP;
2389
2390 if (read(fh, buf, width*file_data.samplesperpixel.val)
2391 != width*file_data.samplesperpixel.val)
2392 {
2393 DXSetError(ERROR_INTERNAL,
2394 "error reading in a scan-line from tiff file");
2395 goto error;
2396 }
2397
2398 if (type == TYPE_FLOAT)
2399 {
2400 float *fptr = ((float *)pixels) + 3*y*width;
2401 ubyte *cptr = (ubyte *)buf;
2402
2403 for (x = 0; x < image_data.width; x++)
2404 {
2405 *fptr++ = map[*cptr].r;
2406 *fptr++ = map[*cptr].g;
2407 *fptr++ = map[*cptr].b;
2408 cptr ++;
2409 }
2410 }
2411 else if (type == TYPE_UBYTE)
2412 {
2413 ubyte *fptr = ((ubyte *)pixels) + 3*y*width;
2414 ubyte *cptr = (ubyte *)buf;
2415
2416 for (x = 0; x < image_data.width; x++)
2417 {
2418 *fptr++ = imap[*cptr].r;
2419 *fptr++ = imap[*cptr].g;
2420 *fptr++ = imap[*cptr].b;
2421 cptr ++;
2422 }
2423 }
2424 }
2425 }
2426 }
2427 else
2428 DXErrorGoto ( ERROR_INTERNAL, "TIFF incompatible modes" );
2429
2430 close ( fh );
2431
2432 DXFree((Pointer)buf);
2433 return image;
2434
2435 error:
2436 if ( fh >= 0 ) close ( fh );
2437 DXFree((Pointer)buf);
2438 return ERROR;
2439 }
2440