Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtHelp / il / iltiff.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: iltiff.c /main/6 1996/10/04 11:29:48 rcs $ */
24 /**---------------------------------------------------------------------
25 ***     
26 ***    (c)Copyright 1991 Hewlett-Packard Co.
27 ***    
28 ***                             RESTRICTED RIGHTS LEGEND
29 ***    Use, duplication, or disclosure by the U.S. Government is subject to
30 ***    restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
31 ***    Technical Data and Computer Software clause in DFARS 252.227-7013.
32 ***                             Hewlett-Packard Company
33 ***                             3000 Hanover Street
34 ***                             Palo Alto, CA 94304 U.S.A.
35 ***    Rights for non-DOD U.S. Government Departments and Agencies are as set
36 ***    forth in FAR 52.227-19(c)(1,2).
37 ***
38 ***-------------------------------------------------------------------*/
39
40     /*  /ilc/iltiff.c : General TIFF file access functions, including
41         those exposed in /ilc/iltiffint.h to other /ilc/iltiff*.c code.
42     */
43
44 #include "iltiffint.h"
45 #include "ilerrors.h"
46
47 #ifdef DTLIB
48 /* Used when this module is compiled by the DtHelp library build */
49 #include "GraphicsP.h"
50 #endif /* DTLIB */
51
52     /*  Size in bytes of one item (# items = TIFF "length"), for each TIFF tag type.
53         Also, # of entries of that type which fit in one long.
54         Indexed by tag type = 1..IL_MAX_TAG_TYPE (0 entry unused).
55     */
56 IL_PRIVATE int _ilTagTypeItemSizes [IL_MAX_TAG_TYPE+1] = {
57     0,                          /* 0th entry unused; invalid tag type */
58     1,                          /* IL_TAG_BYTE */
59     1,                          /* IL_TAG_ASCII */
60     2,                          /* IL_TAG_SHORT */
61     4,                          /* IL_TAG_LONG */
62     8 };                        /* IL_TAG_RATIONAL */
63
64 IL_PRIVATE int _ilTagTypeItemsThatFit [IL_MAX_TAG_TYPE+1] = {
65     0,                          /* 0th entry unused; invalid tag type */
66     4,                          /* IL_TAG_BYTE */
67     4,                          /* IL_TAG_ASCII */
68     2,                          /* IL_TAG_SHORT */
69     1,                          /* IL_TAG_LONG */
70     0 };                        /* IL_TAG_RATIONAL */
71
72     /*  Structure of the first 8 bytes of a TIFF file: see ilConnectFile() */
73 typedef struct {
74     ilByte              byteOrder[2];
75     ilByte              version[2];
76     ilByte              IFDHeadOffset[4];
77     } ilTIFFHeader;
78
79
80         /*  ------------------------- ilFreeFileList -------------------------------- */
81         /*  Free the file list in the given file "*pFile".
82             Note: ilFreeFileList() is also the Destroy() function for ilFile object.
83         */
84
85 static void ilFreeFileList (
86     ilFilePtr           pFile
87     )
88 {
89 register ilFileImagePtr pFileImage, pAltFileImage, pFileImageTemp;
90
91         /*  Run thru the list of file images; for each: if a mask image destroy it
92             (only one); if child images, destroy them - they are linked by pChild.
93         */
94     pFileImage = pFile->pFileImageHead;
95     while (pFileImage) {
96
97             /*  Destroy the mask image if present */
98         pAltFileImage = (ilFileImagePtr)pFileImage->p.pMask;
99         if (pAltFileImage)
100             IL_FREE (pAltFileImage);
101
102             /*  Destroy the child images if present.  They are linked
103                 by pNext, and each one can have a mask image.
104             */
105         pAltFileImage = (ilFileImagePtr)pFileImage->p.pChild;
106         while (pAltFileImage) {
107             if (pAltFileImage->p.pMask)
108                 IL_FREE (pAltFileImage->p.pMask);
109             pFileImageTemp = pAltFileImage;
110             pAltFileImage = (ilFileImagePtr)pAltFileImage->p.pNext;
111             IL_FREE (pFileImageTemp);
112             }
113
114             /*  Destroy the main image */
115         pFileImageTemp = pFileImage;
116         pFileImage = (ilFileImagePtr)pFileImage->p.pNext;
117         IL_FREE (pFileImageTemp);
118         }
119
120         /*  Make the list empty and declare it invalid.
121         */
122     pFile->pFileImageHead = pFile->pFileImageTail = (ilFileImagePtr)NULL;
123     pFile->haveImageList = FALSE;
124 }
125
126
127         /*  ----------------------- ilReadFileTags --------------------------------- */
128         /*  Public function: see spec.
129         */
130 ilPtr ilReadFileTags (
131     ilFileImage         fileImage,
132     int                 nTagsInit,
133     unsigned short     *pTagNumbers,
134     ilFileTag         **ppTags,
135     unsigned long       mustBeZero
136     )
137 {
138 #define RFT_FATAL_ERROR(_error) {error = (_error);  goto RFTFatalError; }
139 ilFileImagePtr          pFileImage;
140 ilTIFFTagPtr            pFileTag, pFileTags;
141 ilError                 error;
142 ilBool                  tagFound;
143 unsigned long           readSize, mallocSize;
144 CARD32                  offset;
145 ilPtr                   pTagData, pTagAlloc;
146 ilFilePtr               pFile;
147 ilFileTag              *pTag, **ppTag;
148 int                     tagNumber, nFileTags, nItems, nTags, tagType, i;
149 register ilBool         bigEndian;
150
151     pFileImage = (ilFileImagePtr)fileImage;
152     if (mustBeZero != 0) {
153         pFileImage->context->error = IL_ERROR_PAR_NOT_ZERO;
154         return (ilPtr)NULL;                                     /* EXIT */
155         }
156     if (nTagsInit <= 0) {
157         pFileImage->context->error = IL_OK;
158         return (ilPtr)NULL;                                     /* no tags; EXIT */
159         }
160
161     pFile = (ilFilePtr)pFileImage->p.file;
162     bigEndian = pFile->bigEndian;
163
164         /*  Allocate space and read in all the file tags to "*pFileTags".
165             Flip the bytes of number, type and length, but not the data/offset.
166         */
167     pTagAlloc = (ilPtr)NULL;                    /* in case of fatal error */
168     readSize = pFileImage->tagCount * IL_TAG_SIZE;
169     pFileTags = (ilTIFFTagPtr)IL_MALLOC (readSize);
170     if (!pFileTags)
171         RFT_FATAL_ERROR (IL_ERROR_MALLOC)
172     if (!IL_SEEK (pFile, pFileImage->tagOffset)
173      || !IL_READ (pFile, readSize, pFileTags))
174         RFT_FATAL_ERROR (IL_ERROR_FILE_IO)
175
176     pFileTag = pFileTags;
177     pTagData = (ilPtr)pFileTag;
178     nFileTags = pFileImage->tagCount;
179     while (nFileTags-- > 0) {
180         IL_FLIP_SHORT (bigEndian, pTagData, pFileTag->number)
181         pTagData += 2;
182         IL_FLIP_SHORT (bigEndian, pTagData, tagType)
183
184             /*  NOTE: declare fatal error if tag type out of range, BUT TIFF 6.0 says 
185                 we should ignore these tags; ALSO, there are new tag types for 6.0.
186             */
187         if ((tagType == 0) || (tagType > IL_MAX_TAG_TYPE))
188             RFT_FATAL_ERROR (IL_ERROR_FILE_TAG_TYPE)
189         pFileTag->type = tagType;
190         pTagData += 2;
191         IL_FLIP_LONG (bigEndian, pTagData, pFileTag->length)
192         pTagData += 8;                      /* skip length and data */
193         pFileTag++;
194         }
195
196         /*  For each of caller's tags: find *pTagNumber in the pFileTags list.
197             If not found, set corresponding "ppTags" entry to null, else point it
198             at the found entry in pFileTags list, add its data size (rounded up to 
199             multiple of 4 - long-align), and the size of one ilFileTag, to "mallocSize".
200         */
201     mallocSize = 0;
202     ppTag = ppTags;
203     nTags = nTagsInit;
204     while (nTags-- > 0) {
205         tagNumber = *pTagNumbers++;
206         tagFound = FALSE;
207         pFileTag = pFileTags;
208         nFileTags = pFileImage->tagCount;
209         while (nFileTags-- > 0) {
210             if (pFileTag->number == tagNumber) {
211                 tagFound = TRUE;
212                 break;
213                 }
214             else pFileTag++;
215             }
216         if (tagFound) {
217             mallocSize += sizeof (ilFileTag) + 
218                 (pFileTag->length * _ilTagTypeItemSizes [pFileTag->type] + 3) & ~3;
219             *ppTag++ = (ilFileTag *)pFileTag;
220             }
221         else *ppTag++ = (ilFileTag *)NULL;
222         }
223
224         /*  If no tags found; exit, else allocate "mallocSize" bytes, and for each found
225             tag, point corresponding "ppTags" to spot in pTagAlloc that has the ilFileTag
226             data, followed by the data itself, then long aligned.
227                 What is returned will look like:
228                     ppTags [0] == null if tag not present, else ->:  
229                                     tag data:                               byte offset
230                                       number (same value as corresponding       0
231                                               entry in pTagsNumbers)
232                                       type                                      2
233                                       nItems                                    4
234                                       pItems (points to <items>, i.e. one       8
235                                         long past this spot, or null if 
236                                         "nItems" is zero (0).
237                                       <items> - "nItems" occurrences of data   12
238                                         depending on "type".
239                     ppTags [1]->      <next tag, at offset 12 + ppTag[0]->nItems
240                                         * size in bytes of one ppTag[0] item,
241                                       as determined by "type".
242         */
243     if (mallocSize == 0) {
244         IL_FREE (pFileTags);
245         pFileImage->context->error = IL_OK;
246         return (ilPtr)NULL;                                     /* EXIT */
247         }
248     pTagAlloc = (ilPtr)malloc (mallocSize);     /* caller uses free() to free this */
249     if (!pTagAlloc)
250         RFT_FATAL_ERROR (IL_ERROR_MALLOC)
251
252     pTag = (ilFileTag *)pTagAlloc;
253     nTags = nTagsInit;
254     ppTag = ppTags;
255     while (nTags-- > 0) {
256         if (!*ppTag)
257             ppTag++;                            /* tag not found, already null, next */
258         else {                                  /* tag found */
259             pFileTag = (ilTIFFTagPtr)*ppTag;    /* points to internal tag data */
260             *ppTag++ = pTag;                    /* point to converted data, next tag */
261             pTag->number = pFileTag->number;    /* copy from pFileTags to pTagAlloc */
262             tagType = pTag->type = pFileTag->type;
263             nItems = pTag->nItems = pFileTag->length;
264             pTagData = (ilPtr)pTag + sizeof(ilFileTag);
265
266             if (nItems == 0) {
267                 pTag->pItems = (ilPtr)NULL;
268                 pTag = (ilFileTag *)pTagData;   /* point pTag to spot for next tag */
269                 }
270             else {
271                 pTag->pItems = pTagData;        /* data follows the tag */
272                 pTag = (ilFileTag *)(pTagData + /* next spot = past data, long-aligned */
273                     ((nItems * _ilTagTypeItemSizes [tagType] + 3) & ~3));
274
275                     /*  Byte flip the tag data to the spot pointed to by "pTagData",
276                         i.e. right after the 12 bytes for the tag.  In TIFF, the data
277                         is in the "offset" field tag if it fits in 4 bytes, else offset
278                         points to the data in the file - seek and read it in that case.
279                     */
280                 switch (tagType) {
281                   case IL_TAG_BYTE:
282                   case IL_TAG_ASCII:
283                     if (nItems <= 4)
284                         bcopy (pFileTag->data.chars, (char *)pTagData, nItems);
285                     else {
286                         IL_FLIP_LONG (bigEndian, pFileTag->data.chars, offset)
287                         if (!IL_SEEK (pFile, offset) 
288                          || !IL_READ (pFile, nItems, pTagData))
289                             RFT_FATAL_ERROR (IL_ERROR_FILE_IO)
290                         }
291                     break;
292
293                   case IL_TAG_SHORT:
294                     if (nItems <= 2) {
295                         for (i = 0; nItems > 0; nItems--, i += 2, pTagData += 2)
296                             IL_FLIP_SHORT (bigEndian, pFileTag->data.chars + i,
297                                            *((unsigned short *)pTagData))
298                         }
299                     else {
300                         IL_FLIP_LONG (bigEndian, pFileTag->data.chars, offset)
301                         if (!IL_SEEK (pFile, offset)
302                          || !IL_READ (pFile, nItems<<1, pTagData))
303                             RFT_FATAL_ERROR (IL_ERROR_FILE_IO)
304                         for (; nItems > 0; nItems--, pTagData += 2)
305                             IL_FLIP_SHORT (bigEndian, pTagData, *((unsigned short *)pTagData))
306                         }
307                     break;
308
309                   case IL_TAG_LONG:
310                     if (nItems == 1)
311                         IL_FLIP_LONG (bigEndian, pFileTag->data.chars, *((INT32 *)pTagData))
312                     else {
313                         IL_FLIP_LONG (bigEndian, pFileTag->data.chars, offset)
314                         if (!IL_SEEK (pFile, offset)
315                          || !IL_READ (pFile, nItems<<2, pTagData))
316                             RFT_FATAL_ERROR (IL_ERROR_FILE_IO)
317                         for (; nItems > 0; nItems--, pTagData += 4)
318                             IL_FLIP_LONG (bigEndian, pTagData, *((INT32 *)pTagData))
319                         }
320                     break;
321
322                   case IL_TAG_RATIONAL:
323                     IL_FLIP_LONG (bigEndian, pFileTag->data.chars, offset)
324                     if (!IL_SEEK (pFile, offset) || !IL_READ (pFile, nItems<<3, pTagData))
325                         RFT_FATAL_ERROR (IL_ERROR_FILE_IO)
326                     while (nItems-- > 0) {
327                         IL_FLIP_LONG (bigEndian, pTagData, *((INT32 *)pTagData))
328                         pTagData += 4;
329                         IL_FLIP_LONG (bigEndian, pTagData, *((INT32 *)pTagData))
330                         pTagData += 4;
331                         }
332                     break;
333                     }
334                 }   /* END nItems > 0 */
335             }       /* END tag found */
336         }           /* END each caller's tag */
337
338         /*  Tags read succesfully: free pFileTags (local buffer); return pTagAlloc.
339         */
340     IL_FREE (pFileTags);
341     pFileImage->context->error = IL_OK;
342     return pTagAlloc;                                           /* EXIT */
343
344         /*  Fatal error: free pFileTags, pTagAlloc if not null, return error code, null.
345         */
346 RFTFatalError:
347     if (pFileTags)
348         IL_FREE (pFileTags);
349     if (pTagAlloc)
350         free (pTagAlloc);
351     pFileImage->context->error = error;
352     return (ilPtr)NULL;                                         /* EXIT */
353 }
354
355
356         /*  --------------------- ilAddImageToList --------------------------------- */
357         /*  Called when forming file image list.  "pPrevFileImage" is a pointer to the
358             previous non-mask image in the file; null if pFileImage first non-mask read.
359             pFileImage->imageType indicates whether image being added is 
360             child/mask/mainImage; if child or mask, pPrevFileImage must be non-null.
361         */
362 static void ilAddImageToList (
363     ilFilePtr                   pFile,
364     register ilFileImagePtr     pFileImage,
365     ilFileImagePtr              pPrevFileImage
366     )
367 {
368     pFileImage->p.pNext = pFileImage->p.pPrev = 
369         pFileImage->p.pChild = pFileImage->p.pMask = (ilFileImage)NULL;
370
371     switch (pFileImage->imageType) {
372       case childImage:
373         if (pPrevFileImage->imageType == childImage)
374              pPrevFileImage->p.pNext = (ilFileImage)pFileImage;
375         else pPrevFileImage->p.pChild = (ilFileImage)pFileImage;
376         break;
377
378       case maskImage:
379         pPrevFileImage->p.pMask = (ilFileImage)pFileImage;
380         break;
381
382         /*  Main image: if page # present, add to list in page order, else add to end */
383       case mainImage:
384         if (pFileImage->p.nPages < 0) {     /* no page #; add to end of list */
385             if (pFileImage->p.pPrev = (ilFileImage)pFile->pFileImageTail)
386                 pFileImage->p.pPrev->pNext = (ilFileImage)pFileImage;
387             else pFile->pFileImageHead = pFileImage;
388             }
389         else {
390                 /*  Have page #.  If list is empty or page # <= that of first element in
391                     list, add pFileImage to front of list; otherwise find place in list
392                     based on page # and insert image in that place.
393                 */
394             pPrevFileImage = pFile->pFileImageHead;
395             if (!pPrevFileImage || (pFileImage->p.page <= pPrevFileImage->p.page)) {
396                 pFileImage->p.pNext = (ilFileImage)pPrevFileImage;  /* add to front */
397                 pFileImage->p.pPrev = (ilFileImage)NULL;
398                 pFile->pFileImageHead = pFileImage;
399                 }
400             else {      /* Add after pPrevFileImage w/ highest page # <= image's page # */
401                 while (pPrevFileImage->p.pNext
402                  && (pPrevFileImage->p.pNext->page <= pFileImage->p.page)) {
403                     pPrevFileImage = (ilFileImagePtr)pPrevFileImage->p.pNext;
404                     }
405                 pFileImage->p.pNext = pPrevFileImage->p.pNext;
406                 pFileImage->p.pPrev = (ilFileImage)pPrevFileImage;
407                 pPrevFileImage->p.pNext = (ilFileImage)pFileImage;
408                 }
409             }
410
411             /*  Point next in list, or tail if this image is last, back to this image */
412         if (pFileImage->p.pNext)
413             pFileImage->p.pNext->pPrev = (ilFileImage)pFileImage;
414         else pFile->pFileImageTail = pFileImage;
415         break;
416         }
417 }
418
419
420         /*  --------------------- ilReadTagsAndAddImageToList ------------------------ */
421         /*  Look at the tag values in the given file image "*pFileImage", and if the tags
422             indicate a supported image, add it to the list of file images in "*pFile".
423             If image is not supported (e.g unknown compression type) the image is freed.
424                 ppPrevFileImage must point to the ptr to the previous image read from the 
425             file, or null if this is the first image; used for child and mask images.
426                 Return IL_OK if image valid, even if not supported; an error means
427             the image is malformed (e.g. missing required tag).
428         */
429 static ilError ilReadTagsAndAddImageToList (
430     ilFilePtr                   pFile,
431     ilFileImagePtr             *ppPrevFileImage,
432     register ilFileImagePtr     pFileImage
433     )
434 {
435     /*  Indexes into "tagNumbers" below. NOTE: order is important, as tags are checked
436         in the below order, and some tags default to values which must be before them.
437             Also NOTE: check for type other than short/long and # items done  below!
438     */
439 #define NEW_SUBFILE_TYPE     0
440 #define IMAGE_WIDTH          1
441 #define IMAGE_LENGTH         2
442 #define RESOLUTION_UNIT      3
443 #define X_RESOLUTION         4          /* follow RESOLUTION_UNIT */
444 #define Y_RESOLUTION         5          /* follow RESOLUTION_UNIT */
445 #define ROWS_PER_STRIP       6          /* follow IMAGE_WIDTH */
446 #define SAMPLES_PER_PIXEL    7
447 #define PLANAR_CONFIGURATION 8          /* follow SAMPLES_PER_PIXEL */
448 #define BITS_PER_SAMPLE      9          /* follow SAMPLES_PER_PIXEL */
449 #define FILL_ORDER           10
450 #define GROUP_3_OPTIONS      11         /* follow FILL_ORDER */
451 #define GROUP_4_OPTIONS      12         /* follow FILL_ORDER */
452 #define COMPRESSION          13         /* follow GROUP_3/4_OPTIONS, FILL_ORDER */
453 #define PREDICTOR            14         /* follow COMPRESSION */
454 #define PHOTOMETRIC_INTERPRETATION 15   /* follow COMP, BITS_PS, SAMPLES_PP, NEW_SFT */
455 #define PAGE_NUMBER          16         /* follow NEW_SFT */
456 #define JPEG_PROC            17         /* follow COMPRESSION */
457 #define YCBCR_COEFFICIENTS   18         /* follow PHOTO_INT */
458 #define YCBCR_SUBSAMPLING    19         /* follow PHOTO_INT */
459 #define YCBCR_POSITIONING    20         /* follow PHOTO_INT */
460 #define REFERENCE_BLACK_WHITE 21        /* follow PHOTO_INT */
461 #define PRIVATE_0            22         /* follow PHOTO_INT */
462
463 static unsigned short tagNumbers [] = {
464     IL_TAG_NEW_SUBFILE_TYPE,
465     IL_TAG_IMAGE_WIDTH,
466     IL_TAG_IMAGE_LENGTH,
467     IL_TAG_RESOLUTION_UNIT,
468     IL_TAG_X_RESOLUTION,
469     IL_TAG_Y_RESOLUTION,
470     IL_TAG_ROWS_PER_STRIP,
471     IL_TAG_SAMPLES_PER_PIXEL,
472     IL_TAG_PLANAR_CONFIGURATION,
473     IL_TAG_BITS_PER_SAMPLE,
474     IL_TAG_FILL_ORDER,
475     IL_TAG_GROUP_3_OPTIONS,
476     IL_TAG_GROUP_4_OPTIONS,
477     IL_TAG_COMPRESSION,
478     IL_TAG_PREDICTOR,
479     IL_TAG_PHOTOMETRIC_INTERPRETATION,
480     IL_TAG_PAGE_NUMBER,
481     IL_TAG_JPEG_PROC,
482     IL_TAG_YCBCR_COEFFICIENTS,
483     IL_TAG_YCBCR_SUBSAMPLING,
484     IL_TAG_YCBCR_POSITIONING,
485     IL_TAG_REFERENCE_BLACK_WHITE,
486     IL_TAG_PRIVATE_0 };
487
488 #define AI_NTAGS            (sizeof(tagNumbers) / sizeof (unsigned short))
489 #define AIL_FATAL_ERROR(_error) {error = (_error);  goto AILFatalError; }
490
491 ilFileImageRelation        imageType;
492 ilFileTag                  *tag [AI_NTAGS];
493 ilBool                      present;
494 ilError                     error;
495 ilPtr                       pTagAlloc;
496 register unsigned long      value;
497 int                         i, tagIndex, nBits, resolutionUnit, fillOrder;
498 unsigned long               group3CompData;
499 unsigned long               group4CompData;
500 register ilFileTag         *pTag;
501 ilYCbCrInfo                *pYCbCr;     /* null if not YCbCr ; else -> des...YCbCr */
502
503         /*  Init/zero des and format in *pFileImage.
504         */
505     IL_INIT_IMAGE_DES (&pFileImage->p.des)
506     IL_INIT_IMAGE_FORMAT (&pFileImage->p.format)
507
508         /*  Read the above file tags; fatal error if error returned.
509         */
510     pTagAlloc = ilReadFileTags ((ilFileImage)pFileImage, AI_NTAGS, tagNumbers, tag, 0);
511     if (!pTagAlloc)
512         return (pFileImage->context->error) ? 
513             pFileImage->context->error : IL_ERROR_FILE_MISSING_TAG;
514
515         /*  Loop thru the tags; set "present" true if tag found, set "value" to integer
516             value of tag (long or short allowed - exceptions checked explicitly - else
517             fatal error).
518                 Fix bug #0169: ignore tags with # items <= 0.
519         */
520     for (tagIndex = 0; tagIndex < AI_NTAGS; tagIndex++) {
521         if ((pTag = tag [tagIndex]) && (pTag->nItems > 0)) {
522             if (pTag->type == IL_TAG_SHORT)
523                 value = *((unsigned short *)pTag->pItems);
524             else if (pTag->type == IL_TAG_LONG)
525 /* compatibility problem with long and unsigned long data fields */
526                 value = *((CARD32 *)pTag->pItems);
527             else if ((tagIndex != X_RESOLUTION) 
528                   && (tagIndex != Y_RESOLUTION)
529                   && (tagIndex != YCBCR_COEFFICIENTS)
530                   && (tagIndex != REFERENCE_BLACK_WHITE))
531                     AIL_FATAL_ERROR (IL_ERROR_FILE_MALFORMED_TAG);
532             if (pTag->nItems != 1) {
533                 if ((tagIndex != BITS_PER_SAMPLE) 
534                  && (tagIndex != PAGE_NUMBER)
535                  && (tagIndex != YCBCR_COEFFICIENTS)
536                  && (tagIndex != YCBCR_SUBSAMPLING)
537                  && (tagIndex != REFERENCE_BLACK_WHITE)
538                  && (tagIndex != PRIVATE_0))
539                     AIL_FATAL_ERROR (IL_ERROR_FILE_MALFORMED_TAG);
540                 }
541             present = TRUE;
542             }
543         else present = FALSE;
544
545             /*  Parse the tags and fill in pFileImage->format, des.  Init des first.
546                 See page 8 in the TIFF v5.0 spec for info on each tag type.
547             */
548         switch (tagIndex) {
549           case NEW_SUBFILE_TYPE:
550             if (present && (value & 4)) imageType = maskImage;
551             else if (present && (value & 1)) imageType = childImage;
552             else imageType = mainImage;
553             break;
554
555           case IMAGE_WIDTH:
556             if (!present) AIL_FATAL_ERROR (IL_ERROR_FILE_MISSING_TAG);
557             pFileImage->p.width = value;
558             break;
559
560           case IMAGE_LENGTH:
561             if (!present) AIL_FATAL_ERROR (IL_ERROR_FILE_MISSING_TAG);
562             pFileImage->p.height = value;
563             break;
564
565                 /*  Resolution returned as dpi * 2, or "0" if not present.  The TIFF
566                     spec says should default to 300 dpi if not present, but we let
567                     the caller make that assumption.
568                 */
569           case RESOLUTION_UNIT:
570             if (!present) 
571                 resolutionUnit = 2;             /* default to inches */
572             else resolutionUnit = value;
573             break;
574
575           case X_RESOLUTION:
576           case Y_RESOLUTION:
577             { long      denom;
578             if (!present)
579                 value = 0;
580             else {
581                 if (pTag->type != IL_TAG_RATIONAL)
582                     AIL_FATAL_ERROR (IL_ERROR_FILE_MALFORMED_TAG);
583 /* compatibility problem with long and unsigned long data fields */
584                 value = *((INT32 *)pTag->pItems);
585                 denom = *((INT32 *)pTag->pItems + 1);
586                 if (resolutionUnit == 3)            /* centimeters */
587                     value = (denom == 0) ? 0 : (double)value / 2.54 / (double)denom + 0.5;
588                 else                                /* not centimeters: assume inches */
589                     value = (denom == 0) ? 0 : (double)value / (double)denom + 0.5;
590                 }
591             if (tagIndex == X_RESOLUTION)
592                  pFileImage->p.xRes = value;
593             else pFileImage->p.yRes = value;
594             }
595             break;
596
597           case ROWS_PER_STRIP:
598             if (!present || (((long)value) < 0) || (value > pFileImage->p.height))
599                  pFileImage->p.stripHeight = pFileImage->p.height;
600             else pFileImage->p.stripHeight = value;
601             break;
602
603           case SAMPLES_PER_PIXEL:
604             if (!present) value = 1;
605             if (value <= 0) 
606                 AIL_FATAL_ERROR (IL_ERROR_FILE_TAG_VALUE);
607             if (value > IL_MAX_SAMPLES)
608                 goto UnsupportedImage;
609             pFileImage->p.des.nSamplesPerPixel = value;
610             break;
611
612                 /*  Planar configuration: default to pixels unless more than one
613                     sample, and value is present and is 2.
614                 */
615           case PLANAR_CONFIGURATION:
616             pFileImage->p.format.sampleOrder = ((pFileImage->p.des.nSamplesPerPixel != 1) 
617                 && present && (value == 2)) ? IL_SAMPLE_PLANES : IL_SAMPLE_PIXELS;
618             break;
619
620                 /*  bits per sample: default to 1, or to first item (in "value") if
621                     fewer items than samples per pixel.
622                 */
623           case BITS_PER_SAMPLE:
624             for (i = 0; i < pFileImage->p.des.nSamplesPerPixel; i++)
625                 pFileImage->p.format.nBitsPerSample [i] = (!present || (pTag->nItems < 1)) ?
626                     1 : ((i > pTag->nItems - 1) ? value : *((unsigned short *)pTag->pItems + i));
627             break;
628
629                 /*  FillOrder: used for class F only (TIFF compression "3")
630                 */
631           case FILL_ORDER:
632             fillOrder = (present && (value == 2)) ? IL_LSB_FIRST : IL_MSB_FIRST;
633             break;
634
635                 /*  Parse group 3 TIFF options, assumed to be 0 if not present.
636                     As per TIFF spec, dont support if any unrecognized bits are not 0.
637                     Note that "group3CompData" is set to 0 below if comp = 2 (TIFF G3).
638                 */
639           case GROUP_3_OPTIONS:
640             group3CompData = IL_G3M_EOL_MARKERS;    /* EOL present if not "TIFF" G3 */
641             if (fillOrder == IL_LSB_FIRST)
642                 group3CompData |= IL_G3M_LSB_FIRST;
643             if (present) {
644                 if (value & ~0x7)
645                     goto UnsupportedImage;      /* non-zero unhandled bits; unsupported */
646                 if (value & 1)
647                     group3CompData |= IL_G3M_2D;
648                 if (value & 2)
649                     group3CompData |= IL_G3M_UNCOMPRESSED;
650                 if (!(value & 4))
651                     group3CompData |= IL_G3M_EOL_UNALIGNED;
652                 }
653             break;
654
655                 /*  Group 4: set LSB first if FillOrder tag specifies it.  If 
656                     Group4Options tag defined and any bit other than zero set (bit 0
657                     is undefined) than consider image unsupported.  Bit one (1) specifies
658                     "uncompressed" mode which is not supported.
659                 */
660           case GROUP_4_OPTIONS:
661             group4CompData = 0;
662             if (fillOrder == IL_LSB_FIRST)
663                 group4CompData |= IL_G4M_LSB_FIRST;
664             if (present) {
665                 if (value & ~1)
666                     goto UnsupportedImage;      /* non-zero unhandled bits; unsupported */
667                 }
668             break;
669
670           case COMPRESSION:
671             if (!present) value = 1;
672             switch (value) {
673               case 1: pFileImage->p.des.compression = IL_UNCOMPRESSED; break;
674
675                 /*  Comp codes 2 and 3 are both Group 3 - the difference is only in
676                     what *pCompData describes.  For code 2 ("TIFF" group 3), the comp
677                     data is 0 - the bits were defined that way.  For code 3, use what
678                     was deciphered/defaulted by the group 3 options tag.
679                 */
680               case 2: 
681                 group3CompData = 0;     /* "TIFF" G3 - default options, set to 0 */
682               case 3:                   /* "true" G3 */
683                 pFileImage->p.des.compression = IL_G3;
684                 pFileImage->p.des.compInfo.g3.flags = group3CompData;
685                 break;
686
687               case 4: pFileImage->p.des.compression = IL_G4;         
688                 pFileImage->p.des.compInfo.g4.flags = group4CompData;
689                 break;
690               case 5: pFileImage->p.des.compression = IL_LZW; break;
691               case 6: 
692                 pFileImage->p.des.compression = IL_JPEG;
693                 pFileImage->p.des.compInfo.JPEG.reserved = IL_JPEGM_RAW;
694                 pFileImage->p.des.compInfo.JPEG.process = 0;
695                 break;
696               case 32773: pFileImage->p.des.compression = IL_PACKBITS; break;
697               default: goto UnsupportedImage;
698                 }
699             break;
700
701                 /*  NOTE: predictive LZW not supported yet !!!!
702                 */
703           case PREDICTOR:
704             if (present && (value != 1) && (pFileImage->p.des.compression == IL_LZW))
705                 goto UnsupportedImage;
706             break;
707
708                 /*  If no photometric interpration, default based on (assumed) image
709                     type: 1 sample: 1 bit/pixel: bitonal, white=0 if fax comp, else 1;
710                                   > 1 bit/pixel: gray, black=0.
711                           3 samples: RGB; else error.
712                 */
713           case PHOTOMETRIC_INTERPRETATION:
714             pYCbCr = (ilYCbCrInfo *)NULL;       /* unless a YCbCr image */
715             if (!present) {
716                 if (pFileImage->p.des.nSamplesPerPixel == 1) {
717                     if (pFileImage->p.format.nBitsPerSample[0] == 1) {
718                         pFileImage->p.des.type = IL_BITONAL;
719                         switch (pFileImage->p.des.compression) {
720                           case IL_G3: case IL_G4:
721                             pFileImage->p.des.blackIsZero = FALSE;
722                             break;
723                           default:
724                             pFileImage->p.des.blackIsZero = TRUE;
725                             break;
726                             }
727                         }
728                     else {
729                         pFileImage->p.des.type = IL_GRAY;
730                         pFileImage->p.des.blackIsZero = TRUE;
731                         }
732                     }
733                 else if (pFileImage->p.des.nSamplesPerPixel == 3)
734                     pFileImage->p.des.type = IL_RGB;
735                 else AIL_FATAL_ERROR (IL_ERROR_FILE_MISSING_TAG);
736                 }
737             else switch (value) {   /* photo interpretation present; handle it */
738
739                     /*  Bitonal or gray; 0 = white is 0, else black is zero. */
740               case 0:
741               case 1: 
742                 if (pFileImage->p.des.nSamplesPerPixel != 1)
743                     AIL_FATAL_ERROR (IL_ERROR_FILE_TAG_VALUE);
744                 pFileImage->p.des.blackIsZero = (value == 1);
745                 pFileImage->p.des.type = (pFileImage->p.format.nBitsPerSample[0] == 1) ?
746                     IL_BITONAL : IL_GRAY;
747                 break;
748
749                     /*  RGB. */
750               case 2:
751                 if (pFileImage->p.des.nSamplesPerPixel != 3)
752                     AIL_FATAL_ERROR (IL_ERROR_FILE_TAG_VALUE);
753                 pFileImage->p.des.type = IL_RGB;
754                 break;
755
756                     /*  Palette images: max of 8 bits */
757               case 3:
758                 if (pFileImage->p.des.nSamplesPerPixel != 1)
759                     AIL_FATAL_ERROR (IL_ERROR_FILE_TAG_VALUE);
760                 if (pFileImage->p.format.nBitsPerSample[0] > 8)
761                     goto UnsupportedImage;
762                 pFileImage->p.des.type = IL_PALETTE;
763                 break;
764
765                     /*  Mask image: is bitonal */
766               case 4:
767                 if (pFileImage->p.des.nSamplesPerPixel != 1)
768                     AIL_FATAL_ERROR (IL_ERROR_FILE_TAG_VALUE);
769                 pFileImage->p.des.type = IL_BITONAL;
770                 pFileImage->p.des.blackIsZero = FALSE;
771                 imageType = maskImage;
772                 break;
773
774                     /*  YCbCr: set pYCbCr to non-null */
775               case 6:
776                 if (pFileImage->p.des.nSamplesPerPixel != 3)
777                     AIL_FATAL_ERROR (IL_ERROR_FILE_TAG_VALUE);
778                 pFileImage->p.des.type = IL_YCBCR;
779                 pYCbCr = &pFileImage->p.des.typeInfo.YCbCr;     /* point to YCbCr data */
780                 break;
781
782                     /*  Others not supported */
783               default: goto UnsupportedImage;
784                 }
785             break;
786
787           case PAGE_NUMBER:
788             if (present) {
789                 if ((pTag->nItems != 2) || (pTag->type != IL_TAG_SHORT))
790                     AIL_FATAL_ERROR (IL_ERROR_FILE_MALFORMED_TAG);
791                 pFileImage->p.page = value;
792                 pFileImage->p.nPages = *((unsigned short *)pTag->pItems + 1);
793                 }
794             else pFileImage->p.page = pFileImage->p.nPages = -1;
795             break;
796
797                 /*  JPEG tags: ignore if not JPEG compression */
798           case JPEG_PROC:
799             if (pFileImage->p.des.compression == IL_JPEG) {
800                 if (!present) AIL_FATAL_ERROR (IL_ERROR_FILE_MISSING_TAG);
801                 if (value != 1)         /* only baseline sequential supported! */
802                     goto UnsupportedImage;
803                 }
804             break;
805
806                 /*  YCbCr tags: ignored if not YCbCr image */
807           case YCBCR_COEFFICIENTS:
808             if (pYCbCr) {
809                 if (!present) {
810                     pYCbCr->lumaRed = 2990;
811                     pYCbCr->lumaGreen = 5870;
812                     pYCbCr->lumaBlue = 1140;
813                     }
814                 else {
815 /* compatibility problem with long or unsigned long data fields */
816                     register INT32 *pLong = (INT32 *)pTag->pItems;
817                     double          num, denom;
818                     if ((pTag->nItems != 3) || (pTag->type != IL_TAG_RATIONAL))
819                         AIL_FATAL_ERROR (IL_ERROR_FILE_MALFORMED_TAG);
820                     num = *pLong++;  denom = *pLong++;
821                     pYCbCr->lumaRed = num/denom * 10000;
822                     num = *pLong++;  denom = *pLong++;
823                     pYCbCr->lumaGreen = num/denom * 10000;
824                     num = *pLong++;  denom = *pLong++;
825                     pYCbCr->lumaBlue = num/denom * 10000;
826                     }
827                 }
828             break;
829
830           case YCBCR_SUBSAMPLING:
831             if (pYCbCr) {
832                 if (!present)
833                     pYCbCr->sample[1].subsampleHoriz = pYCbCr->sample[1].subsampleVert = 2;
834                 else {
835                     if ((pTag->nItems != 2) || (pTag->type != IL_TAG_SHORT))
836                         AIL_FATAL_ERROR (IL_ERROR_FILE_MALFORMED_TAG);
837                     pYCbCr->sample[1].subsampleHoriz = *((short *)pTag->pItems);
838                     pYCbCr->sample[1].subsampleVert = *((short *)pTag->pItems + 1);
839                     }
840                         /* Set Y subsampling to (1,1); copy Cr to Cb: defined by TIFF */
841                 pYCbCr->sample[0].subsampleHoriz = pYCbCr->sample[0].subsampleVert = 1;
842                 pYCbCr->sample[2].subsampleHoriz = pYCbCr->sample[1].subsampleHoriz;
843                 pYCbCr->sample[2].subsampleVert = pYCbCr->sample[1].subsampleVert;
844                 }
845             break;
846
847                 /*  Ignore positioning for now; set to zero (0) */
848           case YCBCR_POSITIONING:
849             if (pYCbCr)
850                 pYCbCr->positioning = 0;
851             break;
852
853             /*  ReferenceBlackWhite: if present, allow tag type to be "long" or "rational".
854                 "rational" is the correct tag type; "long" was written by Image 1 (the
855                 first Developer's Kit that supported JPEG), so support the old files.
856             */
857           case REFERENCE_BLACK_WHITE:
858             if (pYCbCr) {
859                 register ilYCbCrSampleInfo  *pSample = pYCbCr->sample;
860                 int                         i;
861                 if (!present) {
862                     pSample->refBlack = 0; pSample->refWhite = 255; pSample++;
863                     pSample->refBlack = 0; pSample->refWhite = 255; pSample++;
864                     pSample->refBlack = 0; pSample->refWhite = 255; pSample++;
865                     }
866                 else {
867 /* compatibility problem with long and unsigned long data fields */
868                     register INT32 *pLong = (INT32 *)pTag->pItems;
869                     if (pTag->nItems != 6)
870                         AIL_FATAL_ERROR (IL_ERROR_FILE_MALFORMED_TAG);
871                     if (pTag->type == IL_TAG_LONG) {            /* old type */
872                         for (i = 0; i < 3; i++, pSample++) {
873                             pSample->refBlack = *pLong++; 
874                             pSample->refWhite = *pLong++;
875                             }
876                         }
877                     else if (pTag->type == IL_TAG_RATIONAL) {   /* correct TIFF 6.0 type */
878                         long    num, denom;
879                         for (i = 0; i < 3; i++, pSample++) {
880                             num = *pLong++;
881                             denom = *pLong++;
882                             pSample->refBlack = (denom == 1) ? num :
883                                 (double)num / (double)denom + 0.5;
884                             num = *pLong++;
885                             denom = *pLong++;
886                             pSample->refWhite = (denom == 1) ? num :
887                                 (double)num / (double)denom + 0.5;
888                             }
889                         }
890                     else AIL_FATAL_ERROR (IL_ERROR_FILE_MALFORMED_TAG); /* bad tag type */
891                     }
892                 }
893             break;
894
895                 /*  HP IL private tag.  See /ilc/iltiffint.h for definition.
896                     If "dithered palette" mask on, set levels and bit in flags in des.
897                 */
898           case PRIVATE_0:
899             if (present) {
900                 if (value & IL_TAG_P0_FLAG_DITHER_LEVELS) {
901                     if (pFileImage->p.des.type == IL_PALETTE) {
902                         register short *pLevel = ((short *)pTag->pItems + 1);
903                         if ((pTag->nItems < 4) || (pTag->type != IL_TAG_SHORT))
904                             AIL_FATAL_ERROR (IL_ERROR_FILE_MALFORMED_TAG);
905                         pFileImage->p.des.flags |= IL_DITHERED_PALETTE;
906                         pFileImage->p.des.typeInfo.palette.levels[0] = *pLevel++;
907                         pFileImage->p.des.typeInfo.palette.levels[1] = *pLevel++;
908                         pFileImage->p.des.typeInfo.palette.levels[2] = *pLevel++;
909                         }
910                     }
911                 }
912             break;
913
914             }   /* END switch tag index */
915         }       /* END each tag */
916
917         /*  All the tags are parsed and valid so far.  Finish filling in *pFileImage;
918             # levels is inferred from # bits; only supporting byte/sample for now.
919         */
920     for (i = 0; i < pFileImage->p.des.nSamplesPerPixel; i++) {
921         nBits = pFileImage->p.format.nBitsPerSample [i];
922         if (nBits <= 0)
923             AIL_FATAL_ERROR (IL_ERROR_FILE_TAG_VALUE);      /* error; invalid # bits */
924         if (nBits > 8)
925             goto UnsupportedImage;                          /* not error, not supported */
926         pFileImage->p.des.nLevelsPerSample [i] = 1 << nBits;
927         }
928     pFileImage->p.format.byteOrder = IL_MSB_FIRST;          /* arbitrary! */
929     pFileImage->p.format.rowBitAlign = 8;                   /* by TIFF definition */
930
931         /*  If mask image: must be bitonal or discard it. */
932     if (imageType == maskImage) {
933         register ilFileImagePtr pPrevFileImage = *ppPrevFileImage;
934         if (!pPrevFileImage                                     /* no image before it */
935          || pPrevFileImage->p.pMask                             /* already has mask */
936          || (pFileImage->p.des.nSamplesPerPixel != 1)
937          || (pFileImage->p.format.nBitsPerSample[0] != 1))
938             goto UnsupportedImage;                              /* reject image */
939         }
940
941         /*  If a child image and no previous image, make a main image and add it. */
942     if ((imageType == childImage) && !*ppPrevFileImage)
943         imageType = mainImage;
944
945         /*  Add image to list, make previous image unless a mask image */
946     pFileImage->imageType = imageType;                      /* child/mask/mainImage */
947     ilAddImageToList (pFile, pFileImage, *ppPrevFileImage);
948     if (imageType != maskImage)
949         *ppPrevFileImage = pFileImage;
950
951     free (pTagAlloc);                                       /* free() as client would */
952     return IL_OK;                                           /* success; EXIT */
953
954         /*  Error: free pTagAlloc, but not pFileImage - caller does that. Return error.
955             Use free(), not IL_FREE(), to free pTagAlloc, just like caller should.
956         */
957 AILFatalError:
958     if (pTagAlloc)
959         free (pTagAlloc);
960     return error;
961
962         /*  Image is not supported; not an error, but don't add to list - free image.
963         */
964 UnsupportedImage:
965     IL_FREE (pFileImage);
966     return IL_OK;
967 }
968
969
970         /*  ------------------------ ilListFileImages ------------------------------- */
971         /*  Public function: see spec.
972         */
973 ilFileImage ilListFileImages (
974     ilFile              file,
975     unsigned long       mustBeZero
976     )
977 {
978 ilError                 error;
979 long                    imageSequenceNumber;
980 ilByte                  fourBytes [4];
981 ilFileOffset            IFDOffset;
982 ilFileImagePtr          pFileImage, pFileImageHead, pPrevFileImage;
983 ilTIFFHeader            header;
984 register ilFilePtr      pFile;
985 register ilBool         bigEndian;
986
987         /*  Check if image list already built - if so, return ptr to it.
988         */
989     pFile = (ilFilePtr)file;
990     if (mustBeZero != 0) {
991         pFile->o.p.context->error = IL_ERROR_PAR_NOT_ZERO;
992         return (ilFileImage)NULL;                               /* EXIT */
993         }
994     if (pFile->haveImageList) {
995         pFile->o.p.context->error = IL_OK;
996         return (ilFileImage)pFile->pFileImageHead;              /* EXIT */
997         }
998
999     ilFreeFileList (pFile);                 /* remove potential invalid image list */
1000
1001         /*  Dont have image list - read file and build the list.  When done, 
1002             pFile->IFDTailPtrOffset points to the "next IFD" ptr which is null, i.e.
1003             the next IFD ptr for the last image in the file.  For a file with no images
1004             that would be the ptr in the file header.
1005                 First read header to get ptr to first image in file.
1006         */
1007 #ifdef DTLIB
1008     /* Used when this module is compiled by the DtHelp library build */
1009     if (_DtGrSeek (pFile->stream, pFile->offset, 0)) {
1010 #else
1011     if (fseek (pFile->stream, pFile->offset, 0)) {
1012 #endif /* DTLIB */
1013         pFile->o.p.context->error = IL_ERROR_FILE_IO;
1014         return (ilFileImage)NULL;
1015         }
1016 #ifdef DTLIB
1017     /* Used when this module is compiled by the DtHelp library build */
1018     if (!_DtGrRead ((char *)&header, sizeof (header), 1, pFile->stream)) {
1019 #else
1020     if (!fread ((char *)&header, sizeof (header), 1, pFile->stream)) {
1021 #endif /* DTLIB */
1022         pFile->o.p.context->error = IL_ERROR_FILE_IO;
1023         return (ilFileImage)NULL;
1024         }
1025     IL_FLIP_LONG (pFile->bigEndian, header.IFDHeadOffset, IFDOffset);
1026
1027     pFile->haveImageList = TRUE;
1028     pFile->IFDTailPtrOffset = 4;            /* point to first IFD ptr in header */
1029     imageSequenceNumber = 0;
1030     bigEndian = pFile->bigEndian;
1031     pPrevFileImage = (ilFileImagePtr)NULL;
1032
1033         /*  Overview: read the tag count, allocate room for tags (pBeginTagBuffer) and
1034             read the unflipped tags into it.  Allocate space for converted tags 
1035             (pFile->pTags) and copy/flip unflipped tags into it.
1036             After the tags comes the offset to next IFD; read and flip it.
1037         */
1038     while (IFDOffset) {
1039         imageSequenceNumber++;
1040         pFileImage = (ilFileImagePtr)IL_MALLOC_ZERO (sizeof (ilFileImageRec));
1041         if (!pFileImage) {
1042             error = IL_ERROR_MALLOC;
1043             goto LFIFatalError;
1044             }
1045
1046         pFileImage->p.file = (ilFile)pFile;
1047         pFileImage->context = pFile->o.p.context;
1048
1049             /*  Read and flip the tagCount, @IFDOffset.  Point tagOffset at next location.
1050             */
1051         if (!IL_SEEK (pFile, IFDOffset)
1052          || !IL_READ (pFile, 2, fourBytes)) {
1053             error = IL_ERROR_FILE_IO;
1054             goto LFIFatalError;
1055             }
1056         IL_FLIP_SHORT (bigEndian, fourBytes, pFileImage->tagCount);
1057         pFileImage->tagOffset = IFDOffset + 2;
1058
1059             /*  Add file image to list, if supported.  An error is returned only if
1060                 the file image is malformed; not if it is just unsupported.
1061             */
1062         if (error = ilReadTagsAndAddImageToList (pFile, &pPrevFileImage, pFileImage))
1063             goto LFIFatalError;             /* fatal error returned; EXIT */
1064
1065             /*  Read and flip offset to next IFD, at end of tags; save in pFile. */
1066         IFDOffset += pFileImage->tagCount * IL_TAG_SIZE + 2;
1067         pFile->IFDTailPtrOffset = IFDOffset;
1068         if (!IL_SEEK (pFile, IFDOffset)
1069          || !IL_READ (pFile, 4, fourBytes)) {
1070             error = IL_ERROR_FILE_IO;
1071             goto LFIFatalError;
1072             }
1073         IL_FLIP_LONG (bigEndian, fourBytes, IFDOffset);
1074         }   /* END one IFD */
1075
1076         /*  Images accessed successfully; return ok; */
1077     pFile->o.p.context->error = IL_OK;
1078     return (ilFileImage)pFile->pFileImageHead;                      /* EXIT */
1079
1080         /*  Fatal error: dispose file list and pFileImage if non-null, return "error",
1081             and sequence # of image in file that provoked the error.
1082         */
1083 LFIFatalError:
1084     if (pFileImage)
1085         IL_FREE (pFileImage);
1086     ilFreeFileList (pFile);
1087     pFile->o.p.context->error = error;
1088     pFile->o.p.context->errorInfo = imageSequenceNumber;
1089     return (ilFileImage)NULL;
1090 }
1091
1092
1093         /*  ------------------------ ilConnectFile -------------------------------- */
1094         /*  Public function: see spec.
1095             Locate a TIFF file at "offset" within "file", and return a handle used
1096             to access this file, or return null and an error code.
1097         */
1098 ilFile ilConnectFile (
1099     ilContext           context,
1100 #ifdef DTLIB
1101     /* Used when this module is compiled by the DtHelp library build */
1102     _DtGrStream         *stream,
1103 #else
1104     FILE                *stream,
1105 #endif /* DTLIB */
1106     long                offset,
1107     unsigned long       mustBeZero
1108     )
1109 {
1110 ilBool                  bigEndian;
1111 ilFilePtr               pFile;
1112 ilTIFFHeader            header;
1113
1114     if (mustBeZero != 0) {
1115         context->error = IL_ERROR_PAR_NOT_ZERO;
1116         return (ilPipe)NULL;
1117         }
1118
1119         /*  Read what should be a TIFF file header at "offset" within "file".
1120             Verify that byte order is "MM" (bigEndian) or "II" (!bigEndian) or error.
1121             Verify the answer to life, the universe, and everything ...
1122         */
1123 #ifdef DTLIB
1124     /* Used when this module is compiled by the DtHelp library build */
1125     if (_DtGrSeek (stream, offset, 0)) {   /* nonzero means error for fseek */
1126 #else
1127     if (fseek (stream, offset, 0)) {       /* nonzero means error for fseek */
1128 #endif /* DTLIB */
1129         context->error = IL_ERROR_FILE_IO;
1130         return (ilFile)NULL;
1131         }
1132 #ifdef DTLIB
1133     /* Used when this module is compiled by the DtHelp library build */
1134     if (!_DtGrRead ((char *)&header, sizeof (header), 1, stream)) {
1135 #else
1136     if (!fread ((char *)&header, sizeof (header), 1, stream)) {
1137 #endif /* DTLIB */
1138         context->error = IL_ERROR_FILE_IO;
1139         return (ilFile)NULL;
1140         }
1141     if ((header.byteOrder[0] == 'M') && (header.byteOrder[1] == 'M'))
1142         bigEndian = TRUE;
1143     else if ((header.byteOrder[0] == 'I') && (header.byteOrder[1] == 'I'))
1144         bigEndian = FALSE;
1145     else {
1146         context->error = IL_ERROR_FILE_NOT_TIFF;
1147         return (ilFile)NULL;
1148         }
1149     if (!(bigEndian && (header.version[0] == 0) && (header.version[1] == 42))
1150      && !(!bigEndian && (header.version[0] == 42) && (header.version[1] == 0))) {
1151         context->error = IL_ERROR_FILE_NOT_TIFF;
1152         return (ilFile)NULL;
1153         }
1154
1155         /*  File seems to be a valid TIFF file.  Create an ilFileRec object, init it
1156             and return ptr to it.
1157         */
1158     pFile = (ilFilePtr)_ilCreateObject (context, IL_FILE, ilFreeFileList, sizeof(ilFileRec));
1159     if (!pFile)
1160         return (ilFile)NULL;                        /* context->error already set */
1161
1162     pFile->stream = stream;
1163     pFile->offset = offset;
1164     pFile->bigEndian = bigEndian;
1165     pFile->pFileImageHead = pFile->pFileImageTail = (ilFileImagePtr)NULL;
1166     pFile->haveImageList = FALSE;
1167
1168     context->error = IL_OK;
1169     return (ilFile)pFile;
1170 }
1171