lib/DtHelp/il: remove register keyword
[oweals/cde.git] / cde / lib / DtHelp / il / iltiffread.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: iltiffread.c /main/5 1996/06/19 12:20:39 ageorge $ */
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/iltiffread.c : Code for ilReadFileImage(); add a producer to the pipe
41         to read from a TIFF file.  See also /ilc/iltiff.c and /ilc/iltiffwrite.c .
42     */
43
44 #include <stdlib.h>
45
46 #include "iltiffint.h"
47 #include "ilpipelem.h"
48 #include "ilcodec.h"
49 #include "ilerrors.h"
50 #include "ilutiljpeg.h"
51
52 typedef struct {
53             /*  Data set into private when element added */
54     ilFilePtr           pFile;              /* ptr to IL file being read */
55     ilFileImagePtr      pFileImage;         /* ptr to file image being read */
56     unsigned int        compression;        /* compression type of data being read */
57     long                stripHeight;        /* # lines per strip except for last strip */
58     unsigned short     *pPalette;           /* ptr to palette; filled in by Init() */
59     ilPtr               pCompData;          /* ptr to comp data; filled in by Init() */
60     ilBool              initDone;           /* if true, Init() has been called */
61
62             /*  Data set into private by ilReadFileInit(). */
63     ilPtr               pTagAlloc;          /* ptr to allocate file tags */
64     ilImagePlaneInfo   *pDstImagePlane;     /* ptr to plane 0 of dst image */
65     long                nStrips;            /* total # of strips to read */
66     long                nStripsLeft;        /* # of strips left to read */
67     long                lastStripHeight;    /* # lines in last strip */
68     CARD32             *pOffsetsInit;       /* ptr to strip offsets */
69     CARD32             *pOffsets;           /* ptr to next strip offset to read */
70     ilBool              shortOffsets;       /* offsets are short (else long) */
71     CARD32             *pByteCountsInit;    /* ptr to strip byte counts or null */
72     CARD32             *pByteCounts;        /* ptr to next count to read or null */
73     ilBool              shortByteCounts;    /* byte counts short (else long) */
74     unsigned long       nStripBytes;        /* if !pByteCounts: # bytes per strip */
75     unsigned long       nLastStripBytes;    /* if !pByteCounts: # bytes in last strip */
76     } ilReadFilePrivRec, *ilReadFilePrivPtr;
77
78
79
80         /*  --------------------- ilReadJPEGTags -------------------------- */
81         /*  Called by ilReadFileInit() to read JPEG tag data, for JPEG-compressed file.
82         */
83 static ilError ilReadJPEGTags (
84     ilFilePtr           pFile,              /* file to read */
85     int                 nComps,             /* # of samples/components in this image */
86     long               *pQOffsets,          /* array of nComps file offsets to tables */
87     long               *pDCOffsets,
88     long               *pACOffsets,
89     ilJPEGData *pCompData          /* ptr to structure to fill in */
90     )
91 {
92     int        i, c, nBytes;
93     ilJPEGSampleData *pSample;
94     ilPtr      pTable;
95     ilByte              buffer[16];         /* buffer for DC/AC table prefix (# codes) */
96
97         /*  Use sample/component index as table index; load tables based on sample */
98     for (c = 0, pSample = pCompData->sample; c < IL_MAX_SAMPLES; c++, pSample++) {
99         pSample->QTableIndex = c;
100         pSample->DCTableIndex = c;
101         pSample->ACTableIndex = c;
102         pSample->reserved = 0;
103         }
104
105         /*  Load "nComps" of each type of table into slot indexed by sample #. */
106     for (c = 0; c < nComps; c++, pQOffsets++, pDCOffsets++, pACOffsets++) {
107
108             /*  Read Q table into 64 byte malloc'd block and point to it */
109         if (!(pTable = (ilPtr)IL_MALLOC (64)))
110             return IL_ERROR_MALLOC;
111         pCompData->QTables[c] = pTable;
112         if (!IL_SEEK (pFile, *pQOffsets) || !IL_READ (pFile, 64, pTable))
113             return IL_ERROR_FILE_IO;
114
115             /*  Read DC table: first 16 bytes are # of codes for each length (1..16);
116                 the codes follow in bytes, "size" = sum of values of first 16 bytes.
117                 Malloc space and read in "size" + 16 bytes.
118             */
119         if (!IL_SEEK (pFile, *pDCOffsets) || !IL_READ (pFile, 16, buffer))
120             return IL_ERROR_FILE_IO;
121         for (i = 0, nBytes = 16; i < 16; i++)
122             nBytes += buffer[i];
123         if (!(pTable = (ilPtr)IL_MALLOC (nBytes)))
124             return IL_ERROR_MALLOC;
125         pCompData->DCTables[c] = pTable;
126         if (!IL_SEEK (pFile, *pDCOffsets) || !IL_READ (pFile, nBytes, pTable))
127             return IL_ERROR_FILE_IO;
128
129             /*  Read AC table: same as DC table */
130         if (!IL_SEEK (pFile, *pACOffsets) || !IL_READ (pFile, 16, buffer))
131             return IL_ERROR_FILE_IO;
132         for (i = 0, nBytes = 16; i < 16; i++)
133             nBytes += buffer[i];
134         if (!(pTable = (ilPtr)IL_MALLOC (nBytes)))
135             return IL_ERROR_MALLOC;
136         pCompData->ACTables[c] = pTable;
137         if (!IL_SEEK (pFile, *pACOffsets) || !IL_READ (pFile, nBytes, pTable))
138             return IL_ERROR_FILE_IO;
139         }
140
141     return IL_OK;
142 }
143
144
145         /*  --------------------- ilReadFileInit -------------------------- */
146         /*  Init() function for ilReadFileImage().  Read the strip offsets (required)
147             and strip byte counts (required if compressed) tags.
148         */
149 static ilError ilReadFileInit (
150     ilPtr              pPrivate,
151     ilImageInfo        *pSrcImage,
152     ilImageInfo        *pDstImage
153     )
154 {
155 ilReadFilePrivPtr pPriv = (ilReadFilePrivPtr)pPrivate;
156 ilFileImagePtr          pFileImage;
157 ilError                 error;
158 ilFileTag     *pTag;
159
160     /*  Data for tags to read: "numbers" is the array of tag ids, "nTags" in length.
161         "?Index" vars are indices into "numbers" and returned data "tags".
162     */
163 #define                 MAX_NTAGS 10        /* max # of tags read at once (plus slop) */
164 int                     nTags;              /* # of tags to read */
165 unsigned short          numbers[MAX_NTAGS]; /* tag ids to read */
166 ilFileTag              *tags [MAX_NTAGS];   /* ptr to returned data */
167 int                     stripOffsetsIndex, stripByteCountsIndex, colorMapIndex,
168                         QTablesIndex, DCTablesIndex, ACTablesIndex, softwareIndex,
169                         restartIndex;
170 #define ADD_TAG(_index, _tagid) { \
171     _index = nTags++;             \
172     numbers[_index] = _tagid;     \
173     }
174
175
176         /*  If this function has already been called, exit.  All of the tag data is
177             read in here and kept around, so if pipe is being re-executed there is no
178             need to read it again - merely reset current strip ptrs to start of data.
179         */
180     if (pPriv->initDone) {
181         pPriv->pOffsets = pPriv->pOffsetsInit;
182         pPriv->pByteCounts = pPriv->pByteCountsInit;
183         pPriv->nStripsLeft = pPriv->nStrips;
184         return IL_OK;
185         }
186
187         /*  Read the strip tags, which reads in the actual strips.  Offsets (file offsets
188             to strips) are required; read the byte counts only if the image is compressed.
189             Read ColorMap tag if a palette image; read JPEG tags if JPEG compressed.
190         */
191     pFileImage = pPriv->pFileImage;
192     nTags = 0;
193     ADD_TAG (stripOffsetsIndex, IL_TAG_STRIP_OFFSETS)
194
195     if (pPriv->pPalette)
196         ADD_TAG (colorMapIndex, IL_TAG_COLOR_MAP)
197
198     if (pPriv->compression != IL_UNCOMPRESSED)
199         ADD_TAG (stripByteCountsIndex, IL_TAG_STRIP_BYTE_COUNTS)
200
201     if (pPriv->compression == IL_JPEG) {
202         ADD_TAG (stripByteCountsIndex, IL_TAG_STRIP_BYTE_COUNTS)
203         ADD_TAG (QTablesIndex, IL_TAG_JPEG_Q_TABLES)
204         ADD_TAG (DCTablesIndex, IL_TAG_JPEG_DC_TABLES)
205         ADD_TAG (ACTablesIndex, IL_TAG_JPEG_AC_TABLES)
206         ADD_TAG (softwareIndex, IL_TAG_SOFTWARE)            /* for bug; see below */
207         ADD_TAG (restartIndex, IL_TAG_JPEG_RESTART_INTERVAL)
208         }
209
210     pPriv->pTagAlloc = ilReadFileTags ((ilFileImage)pFileImage, nTags, numbers, tags, 0);
211     if (pFileImage->context->error)
212         return pFileImage->context->error;
213
214     pPriv->pDstImagePlane = pDstImage->plane;
215
216         /*  Set pOffsets, ptr to strip offsets (required); determine if short/long. */
217     if (!(pTag = tags [stripOffsetsIndex]))
218         return IL_ERROR_FILE_STRIP_TAGS;
219     pPriv->nStripsLeft = pPriv->nStrips = pTag->nItems;
220     pPriv->pOffsets = pPriv->pOffsetsInit = (CARD32 *)pTag->pItems;
221     if (pTag->type == IL_TAG_SHORT)
222         pPriv->shortOffsets = TRUE;
223     else if (pTag->type == IL_TAG_LONG)
224         pPriv->shortOffsets = FALSE;
225     else return IL_ERROR_FILE_STRIP_TAGS;
226
227         /*  Validate nStrips with stripHeight and height of image. */
228     if (pPriv->nStrips <= 0)
229         return IL_ERROR_FILE_STRIP_TAGS;
230     pPriv->lastStripHeight = pFileImage->p.height - 
231                                 (pPriv->nStrips-1) * pFileImage->p.stripHeight;
232     if ((pPriv->lastStripHeight <= 0) 
233      || (pPriv->lastStripHeight > pFileImage->p.stripHeight))
234         return IL_ERROR_FILE_STRIP_TAGS;
235
236         /*  If image is uncompressed, ignore strip byte counts - can calculate them,
237             and it is safer (have seen uncompressed files with bad strip byte counts, 
238             and perhaps they should be rejected, but we can read them, so why not?):
239             set nStripBytes based on dst row bytes, nLastStripBytes for last strip.
240             If compress: Strip byte counts must exist and have same # items as offsets.
241         */
242     if (pPriv->compression == IL_UNCOMPRESSED) {
243         unsigned long dstRowBytes = pPriv->pDstImagePlane->nBytesPerRow;
244         pPriv->pByteCounts = pPriv->pByteCountsInit = (CARD32 *)NULL;
245         pPriv->nStripBytes = pPriv->stripHeight * dstRowBytes;
246         pPriv->nLastStripBytes = pPriv->lastStripHeight * dstRowBytes;
247         }
248     else {
249         pTag = tags [stripByteCountsIndex];
250         if (!pTag)
251             return IL_ERROR_FILE_STRIP_TAGS;
252         pPriv->pByteCounts = pPriv->pByteCountsInit = (CARD32 *)pTag->pItems;
253         if (pTag->nItems != pPriv->nStrips)
254             return IL_ERROR_FILE_STRIP_TAGS;
255         if (pTag->type == IL_TAG_SHORT)
256             pPriv->shortByteCounts = TRUE;
257         else if (pTag->type == IL_TAG_LONG)
258             pPriv->shortByteCounts = FALSE;
259         else return IL_ERROR_FILE_STRIP_TAGS;
260         }
261
262         /*  ColorMap (palette) must be present if a palette image (pPriv->pPalette).
263             Copy TIFF palette (size = 2 ** nBits)  to pPriv->pPalette (size = 3 * 256).
264         */
265     if (pPriv->pPalette) {
266         unsigned short *pPalette, *pFilePalette;
267         int             nPaletteEntries, i;
268
269         pTag = tags [colorMapIndex];
270         if (!pTag)
271             return IL_ERROR_FILE_MISSING_TAG;
272         nPaletteEntries = 1 << pPriv->pFileImage->p.format.nBitsPerSample[0];
273         if (pTag->nItems != (3 * nPaletteEntries))
274             return IL_ERROR_FILE_MALFORMED_TAG;
275         pPalette = pPriv->pPalette;
276         pFilePalette = (unsigned short *)pTag->pItems;
277         for (i = 0; i < nPaletteEntries; i++, pPalette++, pFilePalette++) {
278             pPalette[0]   = pFilePalette [0];
279             pPalette[256] = pFilePalette [nPaletteEntries];
280             pPalette[512] = pFilePalette [nPaletteEntries << 1];
281             }
282         }
283
284         /*  If a JPEG file read JPEG tags and load Q/DC/AC tables into pCompData.
285             JPEG table tags must be present and # items = # components/samples.
286         */
287     if (pPriv->compression == IL_JPEG) {
288         int             nSamples = pFileImage->p.des.nSamplesPerPixel;
289         ilFileTag      *pQTag, *pDCTag, *pACTag, *pTag;
290
291         pQTag  = tags[QTablesIndex];
292         pDCTag = tags[DCTablesIndex];
293         pACTag = tags[ACTablesIndex];
294         if (!pQTag || !pDCTag || !pACTag)
295             return IL_ERROR_FILE_MISSING_TAG;
296         if ((pQTag->nItems != nSamples)  || (pQTag->type != IL_TAG_LONG)
297          || (pDCTag->nItems != nSamples) || (pDCTag->type != IL_TAG_LONG)
298          || (pACTag->nItems != nSamples) || (pACTag->type != IL_TAG_LONG))
299             return IL_ERROR_FILE_MALFORMED_TAG;
300
301         if ((error = ilReadJPEGTags (pPriv->pFile, nSamples, (long *)pQTag->pItems,
302                                     (long *)pDCTag->pItems, (long *)pACTag->pItems, 
303                                     (ilJPEGData *)pPriv->pCompData)))
304             return error;
305
306             /*  If restartInterval tag present, store value else default to 0 */
307         if ((pTag = tags[restartIndex]) && (pTag->type == IL_TAG_SHORT))
308             ((ilJPEGData *)pPriv->pCompData)->restartInterval = *((short *)pTag->pItems);
309         else ((ilJPEGData *)pPriv->pCompData)->restartInterval = 0;
310
311             /*  Handle 2 bugs in older versions of IL (v2.0 and earlier).  These versions
312                 always wrote in "JIF mode", as a single strip.  The read code always
313                 read using the JIF tag instead of the strip offsets/byte counts, because
314                 the decompression code could only handle JIF data.  
315                     "count" bug: in versions 2.0 and earlier. The (single) strip byte 
316                 count was too small; usually by 8 for a single sample image (gray) or 14 
317                 for multi-sample (RGB or YCbCr); larger for some baselevels.
318                 Then work around the count bug by reading until the EOI marker is found.
319                 The data length is then all bytes up but not including the EOI marker.
320                     "offset" bug: the strip offset is 3 bytes too small.  Fix by adding
321                 3 to the strip offset.
322                     The bugs are in files written by IL versions 1.1 (Image Developer's
323                 Kit release; first to support JPEG) or 2.0 (Image 2).
324                 So if the first "n" chars of the software tag are:
325                     "HP IL v1.1"  (n = 10)  count and offset bugs
326                     "HP IL v2.0"  (n = 10)  count bug
327                     "HP IL v 2.0" (n = 11)  count bug
328             */
329         {   ilBool          hasCountBug, hasOffsetBug;
330             ilFileTag      *pSoftwareTag;
331             char           *pName;
332
333             hasCountBug = FALSE;
334             hasOffsetBug = FALSE;
335             if ((pSoftwareTag = tags[softwareIndex])) {
336                 pName = (char *)pSoftwareTag->pItems;
337                 if ((pSoftwareTag->nItems >= 7) && (pName[0] == 'H') && (pName[1] == 'P') 
338                  && (pName[2] == ' ') && (pName[3] == 'I') && (pName[4] == 'L') 
339                  && (pName[5] == ' ') && (pName[6] == 'v')) {
340                     if ((pSoftwareTag->nItems >= 10) && (pName[7] == '1') 
341                      && (pName[8] == '.') && (pName[9] == '1'))
342                         hasCountBug = hasOffsetBug = TRUE;
343                     else if ((pSoftwareTag->nItems >= 10)
344                      && (pName[7] == '2') && (pName[8] == '.') && (pName[9] == '0'))
345                         hasCountBug = TRUE;
346                     else if ((pSoftwareTag->nItems >= 11) && (pName[7] == ' ') 
347                      && (pName[8] == '2') && (pName[9] == '.') && (pName[10] == '0'))
348                         hasCountBug = TRUE;
349                     }
350                 }
351
352             if (hasOffsetBug)
353                 *pPriv->pOffsets += 3;
354
355             if (hasCountBug) {
356 #               define JPEGM_FIRST_BYTE 0xFF    /* first byte of all JPEG markers */
357 #               define JPEGM_EOI        0xD9    /* End Of Image */
358                 ilByte                  value;
359                 long                    nStripBytes;
360
361                 nStripBytes = *pPriv->pByteCounts;
362                 if (!IL_SEEK (pPriv->pFile, *pPriv->pOffsets + nStripBytes))
363                     return (IL_ERROR_COMPRESSED_DATA);
364                 do {                        /* get a marker */
365                     do {
366                         if (!IL_READ (pPriv->pFile, 1, &value))
367                             return IL_ERROR_COMPRESSED_DATA;
368                         nStripBytes++;
369                         } while (value != JPEGM_FIRST_BYTE);
370                     do {
371                         if (!IL_READ (pPriv->pFile, 1, &value))
372                             return IL_ERROR_COMPRESSED_DATA;
373                         nStripBytes++;
374                         } while (value == JPEGM_FIRST_BYTE);
375                     } while (!value);          /* skip "0" after ff */
376
377                 if (value != JPEGM_EOI)
378                     return IL_ERROR_COMPRESSED_DATA;
379
380                     /*  nStripBytes now includes marker; subtract 2 to remove marker */
381                 nStripBytes -= 2;
382                 *pPriv->pByteCounts = nStripBytes;
383                 }
384         }
385
386         }   /* END JPEG */
387
388     pPriv->initDone = TRUE;             /* avoid re-reading; e.g. palette data */
389     return IL_OK;
390 }
391
392
393         /*  ------------------------ ilReadFileDestroy -------------------------------- */
394         /*  Destroy() function for ilReadFileImage().  Calls ilDestroyObject() on the
395             file, whose refCount was inc'd when element added.  This prevents the file
396             from being destroyed until the pipe element is destroyed.
397                 Free the palette space, compression data and tag malloc space if present.
398         */
399 static ilError ilReadFileDestroy (
400     ilPtr  pPrivate
401     )
402 {
403     ilReadFilePrivPtr pPriv = (ilReadFilePrivPtr)pPrivate;
404     ilDestroyObject ((ilObject)pPriv->pFile);
405
406     if (pPriv->pPalette)
407         IL_FREE (pPriv->pPalette);
408
409     if (pPriv->pCompData && (pPriv->compression == IL_JPEG)) {
410         _ilJPEGFreeTables ((ilJPEGData *)pPriv->pCompData);
411         IL_FREE (pPriv->pCompData);
412         }
413
414     if (pPriv->pTagAlloc && pPriv->initDone)
415         free (pPriv->pTagAlloc);        /* not IL_FREE(); act like client */
416
417     return IL_OK;
418 }
419
420
421
422         /*  --------------------- ilReadFileExecute -------------------------- */
423         /*  Execute() for ilReadFileImage().  Read one strip (or whole image if no 
424             strips) out to the dst image.  If compressed, special care required.
425             This is a producer; signal last strip if no more strips to read.
426         */
427 static ilError ilReadFileExecute (
428     ilExecuteData          *pData,
429     long                    dstLine,
430     long                   *pNLines
431     )
432 {
433 ilReadFilePrivPtr  pPriv;
434 unsigned long               nBytes, offset;
435 ilPtr                       pDst;
436 ilImagePlaneInfo           *pDstImagePlane;
437
438
439         /*  Get "offset", position of strip in file, and "nBytes" to read: from strip
440             byte counts if present (must be if compressed), else use calculated values.
441         */
442     pPriv = (ilReadFilePrivPtr)pData->pPrivate;
443     pPriv->nStripsLeft--;
444     if (pPriv->shortOffsets) {
445         offset = *((unsigned short *)pPriv->pOffsets);
446         pPriv->pOffsets = (CARD32 *)((ilPtr)pPriv->pOffsets + 2);
447         }
448     else offset = *pPriv->pOffsets++;
449     if (pPriv->pByteCounts) {
450         if (pPriv->shortByteCounts) {
451             nBytes = *((unsigned short *)pPriv->pByteCounts);
452             pPriv->pByteCounts = (CARD32 *)((ilPtr)pPriv->pByteCounts + 2);
453             }
454         else nBytes = *pPriv->pByteCounts++;
455         }
456     else nBytes = (pPriv->nStripsLeft <= 0) ? pPriv->nLastStripBytes : pPriv->nStripBytes;
457
458         /*  If reading a compressed image, read into "pPixels + srcOffset" (ignore
459             dstLine); make sure room for "nBytes"; (re)alloc buffer if not room.
460                 Pass "nBytes" written on to next pipe element.
461         */
462     pDstImagePlane = pPriv->pDstImagePlane;
463     if (pPriv->compression != IL_UNCOMPRESSED) {
464         long         dstOffset;
465         dstOffset = *pData->compressed.pDstOffset;
466         if ((dstOffset + nBytes) > pDstImagePlane->bufferSize)
467             if (!_ilReallocCompressedBuffer (pData->pDstImage, 0, dstOffset + nBytes))
468                 return IL_ERROR_MALLOC;                 /* error, EXIT */
469         pDst = pDstImagePlane->pPixels + dstOffset;
470         *pData->compressed.pNBytesWritten = nBytes;
471         }
472     else pDst = pDstImagePlane->pPixels + dstLine * pDstImagePlane->nBytesPerRow;
473
474         /*  Seek to offset and read nBytes into pDst. */
475     if (!IL_SEEK (pPriv->pFile, offset)
476      || !IL_READ (pPriv->pFile, nBytes, pDst))
477         return (IL_ERROR_FILE_IO);
478
479         /*  Set # of lines written - strip height unless last strip (return flag). */
480     if (pPriv->nStripsLeft <= 0) {
481         *pNLines = pPriv->lastStripHeight;
482         return IL_ERROR_LAST_STRIP;
483         }
484     else {
485         *pNLines = pPriv->stripHeight;
486         return IL_OK;
487         }
488 }
489
490
491         /*  ---------------------- ilReadFileImage ---------------------------------- */
492         /*  Public function: see spec.
493             Adds a producer to the given pipe to read the given fileImage.
494         */
495 ilBool ilReadFileImage (
496     ilPipe              pipe,
497     ilFileImage         fileImage,
498     ilRect             *pSrcRect,
499     unsigned long       mustBeZero
500     )
501 {
502 ilDstElementData        dstData;
503 ilFileImagePtr pFileImage;
504 ilReadFilePrivPtr pPriv;
505 unsigned short          *pPalette;
506 ilPtr                   pCompData;
507
508         /*  Validate that pipe and file image have the same context. */
509     pFileImage = (ilFileImagePtr)fileImage;
510     if (mustBeZero != 0)
511         return ilDeclarePipeInvalid (pipe, IL_ERROR_PAR_NOT_ZERO);
512     if (pFileImage->context != pipe->context)
513         return ilDeclarePipeInvalid (pipe, IL_ERROR_CONTEXT_MISMATCH);
514
515         /*  Get pipe state - must be IL_PIPE_EMPTY or declare an error. */
516     if (ilGetPipeInfo (pipe, FALSE, (ilPipeInfo *)NULL, (ilImageDes *)NULL, 
517                                     (ilImageFormat *)NULL) != IL_PIPE_EMPTY) {
518         if (!pFileImage->context->error)
519             ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
520         return FALSE;
521         }
522
523         /*  Planar sample order not yet supported. */
524     if (pFileImage->p.format.sampleOrder != IL_SAMPLE_PIXELS)
525         return ilDeclarePipeInvalid (pipe, IL_ERROR_NOT_IMPLEMENTED);
526
527         /*  If a palette image, allocate space for it (must pass ptr to it when adding
528             pipe element), but don't read it until Init() called.
529         */
530     if (pFileImage->p.des.type == IL_PALETTE) {
531         pPalette = (unsigned short *)IL_MALLOC (sizeof (unsigned short) * 3 * 256);
532         if (!pPalette)
533             return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
534         }
535     else pPalette = (unsigned short *)NULL;
536
537         /*  Allocate and zero pCompData if JPEG (similar to pPalette) */
538     if (pFileImage->p.des.compression == IL_JPEG) {
539         pCompData = (ilPtr)IL_MALLOC_ZERO (sizeof (ilJPEGData));
540         if (!pCompData)
541             return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
542         }
543     else pCompData = (ilPtr)NULL;
544
545         /*  Add a producer pipe element: output data is defined in *pFileImage. */
546     dstData.producerObject = (ilObject)fileImage;
547     dstData.pDes = &pFileImage->p.des;
548     dstData.pFormat = &pFileImage->p.format;
549     dstData.width = pFileImage->p.width;
550     dstData.height = pFileImage->p.height;
551     dstData.stripHeight = pFileImage->p.stripHeight;
552     dstData.constantStrip = TRUE;
553     dstData.pPalette = pPalette;
554     dstData.pCompData = pCompData;
555
556     pPriv = (ilReadFilePrivPtr)ilAddPipeElement (pipe, IL_PRODUCER, 
557             sizeof (ilReadFilePrivRec), 0, (ilSrcElementData *)NULL, &dstData,
558             ilReadFileInit, IL_NPF, ilReadFileDestroy, ilReadFileExecute, NULL, 0);
559     if (!pPriv) {
560         if (pPalette) IL_FREE (pPalette);
561         if (pCompData) IL_FREE (pCompData);
562         return FALSE;
563         }
564
565         /*  Init private. Inc refCount for this file - dec'd in ilReadFileDestroy(). */
566     pPriv->pFile = (ilFilePtr)pFileImage->p.file;
567     pPriv->pFileImage = pFileImage;
568     pPriv->compression = pFileImage->p.des.compression;
569     pPriv->stripHeight = pFileImage->p.stripHeight;
570     pPriv->pPalette = pPalette;
571     pPriv->pCompData = pCompData;
572     pPriv->initDone = FALSE;
573     ((ilObjectPtr)pFileImage->p.file)->refCount++;
574
575         /*  If a src rect given, crop to it.
576             NOTE: IMPLEMENT PARTIAL FILE READ IN THE FUTURE !!!!!
577         */
578     if (pSrcRect)
579         return ilCrop (pipe, pSrcRect);
580
581     pipe->context->error = IL_OK;
582     return TRUE;
583 }
584