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