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             ( &copyname [ 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