1 /* libhpojip -- HP OfficeJet image-processing library. */
3 /* Copyright (C) 1995-2002 Hewlett-Packard Company
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
13 * NON-INFRINGEMENT. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 * In addition, as a special exception, Hewlett-Packard Company
21 * gives permission to link the code of this program with any
22 * version of the OpenSSL library which is distributed under a
23 * license identical to that listed in the included LICENSE.OpenSSL
24 * file, and distribute linked combinations including the two.
25 * You must obey the GNU General Public License in all respects
26 * for all of the code used other than OpenSSL. If you modify
27 * this file, you may extend this exception to your version of the
28 * file, but you are not obligated to do so. If you do not wish to
29 * do so, delete this exception statement from your version.
32 /* Original author: Mark Overton and others.
34 * Ported to Linux by David Paschal.
37 /*****************************************************************************\
39 * xtiff.c - encoder and decoder for TIFF files for image processor
41 *****************************************************************************
43 * Name of Global Jump-Table:
45 * tifEncodeTbl = the encoder,
46 * tifDecodeTbl = the decoder.
48 * Encoder: Items in aXformInfo array passed into setXformSpec:
50 * aXformInfo[IP_TIFF_FILE_PATH] = pointer to a file-path, or NULL
52 * If NULL, a one-page TIFF is output in the normal manner.
53 * If not NULL, this must be a pointer to a string containing a file-path.
54 * If the given file does not exist, it will be created and one image will
55 * be put in it. If it does exist, the image will be APPENDED to this file,
56 * and no data will be output by this xform. So if one or more pages are
57 * already in the file, we will add another page to it. This xform does
58 * the opening and closing of the file.
60 * Decoder: Items in aXformInfo array passed into setXformSpec:
64 * Capabilities and Limitations:
66 * Handles 1, 8, 16, 24 and 48 bits per pixel.
68 * Default Input Traits, and Output Traits:
70 * trait default input output
71 * ------------------- --------------------- ------------------------
72 * iPixelsPerRow * passed into output same as default input
73 * iBitsPerPixel * passed into output same as default input
74 * iComponentsPerPixel passed into output same as default input
75 * lHorizDPI passed into output same as default input
76 * lVertDPI passed into output same as default input
77 * lNumRows passed into output same as default input
78 * iNumPages passed into output same as default input
79 * iPageNum passed into output same as default input
81 * Above, a "*" by an item indicates it must be valid (not negative).
83 * Apr 2000, Mark Overton, ported header-setup from TWAIN source, and added
84 * multi-page capability
85 * Feb 1998, Mark Overton, ported to new Image Processor code
86 * May 1996, Mark Overton, wrote original code
87 * Jun 2000, Mark Overton, wrote a simple decoder that does no file-seeks
89 *****************************************************************************/
92 #include "stdio.h" /* for FILE operations */
103 #define PRINT(msg,arg1,arg2) \
104 _ftprintf(stderr, msg, (int)arg1, (int)arg2)
106 #define PRINT(msg,arg1,arg2)
109 #define CHECK_VALUE 0x1ce5ca7e
113 /*____________________________________________________________________________
115 | Constants pertaining to tags |
116 |____________________________________________________________________________|
120 /* TIF_INST - our instance variables */
123 IP_IMAGE_TRAITS traits; /* traits of the image */
124 int iBitsPerSample; /* bits per channel (1, 8 or 16) */
125 BOOL bByteSwap; /* bytes are in wrong endian order, so must swap? */
126 char sFilePath[200]; /* path to the file (empty string means none) */
127 FILE *fileOut; /* handle of opened file */
128 DWORD dwRawRowBytes; /* bytes per raw row */
129 DWORD dwRowsDone; /* number of rows converted so far */
130 DWORD dwValidChk; /* struct validity check value */
131 DWORD dwInNextPos; /* file pos for subsequent input */
132 DWORD dwOutNextPos; /* file pos for subsequent output */
133 BOOL fDidHeader; /* already sent the header? */
134 } TIF_INST, *PTIF_INST;
137 /* Types having known sizes */
138 typedef unsigned char TIFF_UBYTE; /* 8 bits */
139 typedef unsigned short TIFF_USHORT; /* 16 bits */
140 typedef unsigned int TIFF_ULONG; /* 32 bits */
141 typedef signed char TIFF_SBYTE; /* 8 bits */
142 typedef signed short TIFF_SSHORT; /* 16 bits */
143 typedef signed int TIFF_SLONG; /* 32 bits */
145 /* TIFF file header defines */
147 #define TIFF_VERSION 42
149 /* TIFF field lengths */
154 #define TIFFRATIONAL 5
156 #define TIFFUNDEFINED 7
159 #define TIFFSRATIONAL 10
161 /* TIFF compression type */
162 #define NOCOMPRESSION 1
164 /* TIFF planar configuration */
168 /* TIFF photometric interpretations */
169 #define ZERO_IS_WHITE 0
170 #define ZERO_IS_BLACK 1
173 /* TIFF resolution units */
174 #define DOTS_PER_INCH 2
179 #define BITS_PER_SAMPLE 258 // 0x0102
180 #define COMPRESSION 259 // 0x0103
181 #define IMAGE_LENGTH 257 // 0x0101
182 #define IMAGE_WIDTH 256 // 0x0100
183 #define NEW_SUBFILE 254 // 0x00fe
184 #define PHOTO_INTERPRET 262 // 0x0106
185 #define RESOLUTION_UNIT 296 // 0x0128
186 #define ROWS_PER_STRIP 278 // 0x0116
187 #define SAMPLES_PER_PIXEL 277 // 0x0115
188 #define STRIP_COUNTS 279 // 0x0117
189 #define STRIP_OFFSETS 273 // 0x0111
190 #define XRESOLUTION 282 // 0x011A
191 #define YRESOLUTION 283 // 0x011B
196 } __attribute__((packed)) RATIONAL;
203 } __attribute__((packed)) TIFFVALUE;
208 TIFF_ULONG Length; /* number of items, NOT number of bytes */
210 } __attribute__((packed)) TIFFTAG;
214 TIFFTAG Tag[NUMTAGS];
215 TIFF_ULONG OffsetNextIFD;
216 } __attribute__((packed)) TIFFIFD;
219 TIFF_UBYTE ByteOrder[2];
221 TIFF_ULONG OffsetFirstIFD;
222 } __attribute__((packed)) TIFFHEADER;
224 #define NUMEXTBYTES (2*sizeof(RATIONAL) + 3*sizeof(TIFF_USHORT))
225 #define MAX_HEADER_SIZE (sizeof(TIFFHEADER) + sizeof(TIFFIFD) + NUMEXTBYTES)
229 /*****************************************************************************\
231 * tifEncode_openXform - Creates a new instance of the transformer
233 *****************************************************************************
235 * This returns a handle for the new instance to be passed into
236 * all subsequent calls.
238 * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
240 \*****************************************************************************/
242 static WORD tifEncode_openXform (
243 IP_XFORM_HANDLE *pXform) /* out: returned handle */
247 INSURE (pXform != NULL);
248 IP_MEM_ALLOC (sizeof(TIF_INST), g);
250 memset (g, 0, sizeof(TIF_INST));
251 g->dwValidChk = CHECK_VALUE;
255 return IP_FATAL_ERROR;
260 /*****************************************************************************\
262 * tifEncode_setDefaultInputTraits - Specifies default input image traits
264 *****************************************************************************
266 * The header of the file-type handled by the transform probably does
267 * not include *all* the image traits we'd like to know. Those not
268 * specified in the file-header are filled in from info provided by
271 * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
273 \*****************************************************************************/
275 static WORD tifEncode_setDefaultInputTraits (
276 IP_XFORM_HANDLE hXform, /* in: handle for xform */
277 PIP_IMAGE_TRAITS pTraits) /* in: default image traits */
282 HANDLE_TO_PTR (hXform, g);
283 ppr = pTraits->iPixelsPerRow;
284 bpp = pTraits->iBitsPerPixel;
286 /* Insure that values we actually use are known */
290 g->dwRawRowBytes = (ppr*bpp + 7) / 8;
291 g->traits = *pTraits; /* a structure copy */
296 return IP_FATAL_ERROR;
301 /*****************************************************************************\
303 * tifEncode_setXformSpec - Provides xform-specific information
305 \*****************************************************************************/
307 static WORD tifEncode_setXformSpec (
308 IP_XFORM_HANDLE hXform, /* in: handle for xform */
309 DWORD_OR_PVOID aXformInfo[]) /* in: xform information */
314 HANDLE_TO_PTR (hXform, g);
315 s = (char*)aXformInfo[IP_TIFF_FILE_PATH].pvoid;
317 strcpy (g->sFilePath, s);
321 return IP_FATAL_ERROR;
326 /*****************************************************************************\
328 * tifEncode_getHeaderBufSize- Returns size of input buf needed to hold header
330 \*****************************************************************************/
332 static WORD tifEncode_getHeaderBufSize (
333 IP_XFORM_HANDLE hXform, /* in: handle for xform */
334 DWORD *pdwInBufLen) /* out: buf size for parsing header */
336 /* since input is raw pixels, there is no header, so set it to zero */
343 /*****************************************************************************\
345 * tifEncode_getActualTraits - Parses header, and returns input & output traits
347 \*****************************************************************************/
349 static WORD tifEncode_getActualTraits (
350 IP_XFORM_HANDLE hXform, /* in: handle for xform */
351 DWORD dwInputAvail, /* in: # avail bytes in input buf */
352 PBYTE pbInputBuf, /* in: ptr to input buffer */
353 PDWORD pdwInputUsed, /* out: # bytes used from input buf */
354 PDWORD pdwInputNextPos,/* out: file-pos to read from next */
355 PIP_IMAGE_TRAITS pInTraits, /* out: input image traits */
356 PIP_IMAGE_TRAITS pOutTraits) /* out: output image traits */
360 HANDLE_TO_PTR (hXform, g);
362 /* Since there is no header, we'll report no usage of input */
364 *pdwInputNextPos = 0;
366 /* Since we don't change traits, just copy out the default traits */
367 *pInTraits = g->traits;
368 *pOutTraits = g->traits;
369 return IP_DONE | IP_READY_FOR_DATA;
372 return IP_FATAL_ERROR;
377 /****************************************************************************\
379 * tifEncode_getActualBufSizes - Returns buf sizes needed for remainder of job
381 \****************************************************************************/
383 static WORD tifEncode_getActualBufSizes (
384 IP_XFORM_HANDLE hXform, /* in: handle for xform */
385 PDWORD pdwMinInBufLen, /* out: min input buf size */
386 PDWORD pdwMinOutBufLen) /* out: min output buf size */
391 HANDLE_TO_PTR (hXform, g);
392 len = g->dwRawRowBytes;
393 *pdwMinInBufLen = len;
395 if (len < MAX_HEADER_SIZE)
396 len = MAX_HEADER_SIZE;
397 *pdwMinOutBufLen = len;
402 return IP_FATAL_ERROR;
407 /****************************************************************************\
409 * outputHeader - Only called by tifEncode_convert
411 \****************************************************************************/
415 static void SetTag (TIFFTAG *pTag,
416 unsigned short TagID, short Kind, long Length, int Value)
418 pTag->TagID = (TIFF_USHORT)TagID;
419 pTag->Kind = (TIFF_USHORT)Kind;
420 pTag->Length = (TIFF_ULONG)Length;
421 pTag->Value.l = (TIFF_ULONG)Value; /* assumes little-endian computer */
426 static int WriteFileHeader (PBYTE pTIFF)
430 pHead = (TIFFHEADER*) pTIFF;
431 pHead->ByteOrder[0] = 'I';
432 pHead->ByteOrder[1] = 'I'; /* assumes little-endian computer */
434 pHead->OffsetFirstIFD = 8;
436 return 8; /* we output 8 bytes */
441 static int WriteIFD (
442 PBYTE pTIFF, /* out: the IFD is written to this buffer */
443 int iStartOffset, /* in: file-offset at which this IFD starts */
444 int WidthBytes, /* in: row-width in bytes */
445 int WidthPixels, /* in: row-width in pixels */
446 int Height, /* in: number of rows */
447 int BPP, /* in: bits per pixel */
448 int XRes, /* in: dpi in X */
449 int YRes) /* in: dpi in Y */
455 int iBPSOffset, iImageOffset;
458 pIFD = (TIFFIFD*)pTIFF;
459 pMore = pTIFF + sizeof(TIFFIFD); /* 1st byte after the IFD */
461 /* allocate space for the 3 shorts for the 3 bps values (if needed) */
462 iBPSOffset = iStartOffset + (pMore-pTIFF);
463 pBPS = (TIFF_USHORT*)pMore;
464 pMore += 3*sizeof(TIFF_USHORT);
466 /* the pixels are put after the above items */
467 iImageOffset = iStartOffset + (pMore-pTIFF);
471 PI = ZERO_IS_WHITE; SPP = 1; BPS = 1; break; /* 1-bit bilevel */
473 PI = ZERO_IS_BLACK; SPP = 1; BPS = 8; break; /* 8-bit grayscale */
475 PI = ZERO_IS_BLACK; SPP = 1; BPS = 16; break; /* 16-bit grayscale */
477 PI = RGB_COLOR; SPP = 3; BPS = 8; break; /* 24-bit color */
479 PI = RGB_COLOR; SPP = 3; BPS = 16; break; /* 48-bit color */
481 PI = RGB_COLOR; SPP = 3; BPS = 8; /* guess 24-bit color */
482 assert (0); /* crash if in debug mode */
485 pIFD->NumTags = NUMTAGS;
487 SetTag (pTag++, NEW_SUBFILE, TIFFSHORT, 1, 0);
488 SetTag (pTag++, IMAGE_WIDTH, TIFFLONG, 1, WidthPixels);
489 SetTag (pTag++, IMAGE_LENGTH, TIFFLONG, 1, Height);
490 SetTag (pTag++, BITS_PER_SAMPLE, TIFFSHORT, SPP, SPP>1 ? iBPSOffset : BPS);
491 SetTag (pTag++, COMPRESSION, TIFFSHORT, 1, 1);
492 SetTag (pTag++, PHOTO_INTERPRET, TIFFSHORT, 1, PI);
493 SetTag (pTag++, STRIP_OFFSETS, TIFFLONG, 1, iImageOffset);
494 SetTag (pTag++, SAMPLES_PER_PIXEL, TIFFSHORT, 1, SPP);
495 SetTag (pTag++, ROWS_PER_STRIP, TIFFLONG, 1, Height);
496 SetTag (pTag++, STRIP_COUNTS, TIFFLONG, 1, WidthBytes*Height);
497 SetTag (pTag++, XRESOLUTION, TIFFSHORT, 1, XRes);
498 SetTag (pTag++, YRESOLUTION, TIFFSHORT, 1, YRes);
499 SetTag (pTag++, RESOLUTION_UNIT, TIFFSHORT, 1, 2);
500 assert ((pTag - pIFD->Tag) == NUMTAGS);
501 pIFD->OffsetNextIFD = 0L; /* assume there is no next IFD */
503 /* Stick Samples Per Pixel here for color; Only used if pointed to by tag */
508 return pMore - pTIFF;
513 static WORD AppendIFDToFile (
514 PTIF_INST g, /* in: ptr to instance structure */
515 PBYTE pbTempBuf) /* in: temp buffer large enough to hold an IFD */
518 TIFF_ULONG fileEndPos, IFDPos, pointerPos;
520 int iHeaderLen, iIFDLen, iTotalLen;
522 /***** If the file is empty, do usual set-up *****/
524 g->fileOut = fopen (g->sFilePath, "a+b");
525 INSURE (g->fileOut != NULL);
526 result = fseek (g->fileOut, 0, SEEK_END);
527 INSURE (result == 0);
528 fileEndPos = ftell (g->fileOut);
529 INSURE (result >= 0);
531 if (fileEndPos == 0) {
532 iHeaderLen = WriteFileHeader(pbTempBuf);
533 iIFDLen = WriteIFD (pbTempBuf+iHeaderLen, iHeaderLen,
534 g->dwRawRowBytes, g->traits.iPixelsPerRow,
535 g->traits.lNumRows, g->traits.iBitsPerPixel,
536 g->traits.lHorizDPI>>16, g->traits.lVertDPI>>16);
538 iTotalLen = iHeaderLen + iIFDLen;
539 INSURE (iTotalLen <= MAX_HEADER_SIZE);
541 result = fwrite (pbTempBuf, 1, iTotalLen, g->fileOut);
542 INSURE (result == iTotalLen);
544 return IP_READY_FOR_DATA;
547 /***** Find the last IFD *****/
549 result = fseek (g->fileOut, 4, SEEK_SET);
550 INSURE (result == 0);
551 result = fread (&IFDPos, 4, 1, g->fileOut); /* assumes little-endian file */
552 INSURE (result == 1);
554 do { /* hop thru the IFDs until we hit the last one */
555 result = fseek (g->fileOut, IFDPos, SEEK_SET);
556 INSURE (result == 0);
557 result = fread (&numTags, 2, 1, g->fileOut); /* assumes little-endian file */
558 INSURE (result==1 && numTags>0);
559 pointerPos = IFDPos + 2 + numTags*sizeof(TIFFTAG);
560 result = fseek (g->fileOut, pointerPos, SEEK_SET);
561 INSURE (result == 0);
562 result = fread (&IFDPos, 4, 1, g->fileOut); /* assumes little-endian file */
563 INSURE (result == 1);
564 } while (IFDPos != 0);
566 /***** PointerPos is the final IFD offset in the file; change it *****/
568 /* switch to writing from now on */
570 g->fileOut = fopen(g->sFilePath, "r+b");
571 INSURE (g->fileOut != NULL);
573 result = fseek (g->fileOut, pointerPos, SEEK_SET);
574 INSURE (result == 0);
575 result = fwrite (&fileEndPos, 4, 1, g->fileOut); /* assumes little-endian file */
576 INSURE (result == 1);
578 /***** Output a new IFD for the new page *****/
580 iIFDLen = WriteIFD (pbTempBuf, fileEndPos,
581 g->dwRawRowBytes, g->traits.iPixelsPerRow,
582 g->traits.lNumRows, g->traits.iBitsPerPixel,
583 g->traits.lHorizDPI>>16, g->traits.lVertDPI>>16);
585 result = fseek (g->fileOut, 0, SEEK_END);
586 INSURE (result == 0);
587 result = fwrite (pbTempBuf, 1, iIFDLen, g->fileOut);
588 INSURE (result == iIFDLen);
589 /* leave the file-position at the end, where image-data will go */
591 return IP_READY_FOR_DATA;
594 return IP_FATAL_ERROR;
599 static WORD outputHeader (
600 PTIF_INST g, /* in: ptr to instance structure */
601 DWORD dwOutputAvail, /* in: # avail bytes in out-buf */
602 PBYTE pbOutputBuf, /* in: ptr to out-buffer */
603 PDWORD pdwOutputUsed, /* out: # bytes written in out-buf */
604 PDWORD pdwOutputThisPos) /* out: file-pos to write the data */
606 int iHeaderLen, iIFDLen, iTotalLen;
608 INSURE (dwOutputAvail >= MAX_HEADER_SIZE);
609 *pdwOutputThisPos = 0;
611 if (g->sFilePath[0] != 0) {
613 return AppendIFDToFile (g, pbOutputBuf);
616 iHeaderLen = WriteFileHeader(pbOutputBuf);
617 iIFDLen = WriteIFD (pbOutputBuf+iHeaderLen, iHeaderLen,
618 g->dwRawRowBytes, g->traits.iPixelsPerRow,
619 g->traits.lNumRows, g->traits.iBitsPerPixel,
620 g->traits.lHorizDPI>>16, g->traits.lVertDPI>>16);
622 iTotalLen = iHeaderLen + iIFDLen;
623 INSURE (iTotalLen <= MAX_HEADER_SIZE);
624 *pdwOutputUsed = iTotalLen;
625 *pdwOutputThisPos = 0;
626 g->dwOutNextPos = iTotalLen;
628 return IP_READY_FOR_DATA;
631 return IP_FATAL_ERROR;
636 /*****************************************************************************\
638 * tifEncode_convert - the work-horse routine
640 \*****************************************************************************/
642 static WORD tifEncode_convert (
643 IP_XFORM_HANDLE hXform,
644 DWORD dwInputAvail, /* in: # avail bytes in in-buf */
645 PBYTE pbInputBuf, /* in: ptr to in-buffer */
646 PDWORD pdwInputUsed, /* out: # bytes used from in-buf */
647 PDWORD pdwInputNextPos, /* out: file-pos to read from next */
648 DWORD dwOutputAvail, /* in: # avail bytes in out-buf */
649 PBYTE pbOutputBuf, /* in: ptr to out-buffer */
650 PDWORD pdwOutputUsed, /* out: # bytes written in out-buf */
651 PDWORD pdwOutputThisPos) /* out: file-pos to write the data */
656 HANDLE_TO_PTR (hXform, g);
658 /**** Output the Header if we haven't already ****/
660 if (! g->fDidHeader) {
661 g->fDidHeader = TRUE;
663 *pdwInputNextPos = 0;
664 return outputHeader (g, dwOutputAvail, pbOutputBuf,
665 pdwOutputUsed, pdwOutputThisPos);
668 /**** Check if we were told to flush ****/
670 if (pbInputBuf == NULL) {
671 PRINT (_T("tif_encode_convert_row: Told to flush.\n"), 0, 0);
672 if (g->traits.lNumRows < 0) {
673 /* # rows wasn't known at first, so output header again
674 * now that we know the number of rows */
675 INSURE (g->sFilePath[0] == 0);
676 g->traits.lNumRows = g->dwRowsDone;
678 *pdwInputNextPos = g->dwInNextPos;
679 return outputHeader (g, dwOutputAvail, pbOutputBuf,
680 pdwOutputUsed, pdwOutputThisPos);
683 *pdwInputUsed = *pdwOutputUsed = 0;
684 *pdwInputNextPos = g->dwInNextPos;
685 *pdwOutputThisPos = g->dwOutNextPos;
689 /**** Output a Row ****/
691 n = g->dwRawRowBytes;
692 INSURE (dwInputAvail >= n);
693 INSURE (dwOutputAvail >= n);
695 if (g->sFilePath[0] == 0) {
696 memcpy (pbOutputBuf, pbInputBuf, n);
699 *pdwOutputThisPos = g->dwOutNextPos;
700 g->dwOutNextPos += n;
703 INSURE (g->fileOut != NULL);
704 result = fwrite (pbInputBuf, 1, n, g->fileOut);
705 INSURE (result == n);
708 *pdwOutputThisPos = 0;
713 *pdwInputNextPos = g->dwInNextPos;
717 return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA;
720 return IP_FATAL_ERROR;
725 /*****************************************************************************\
727 * tifEncode_insertedData - client inserted into our output stream
729 \*****************************************************************************/
731 static WORD tifEncode_insertedData (
732 IP_XFORM_HANDLE hXform,
736 return IP_FATAL_ERROR; /* must never be called (can't insert data) */
741 /*****************************************************************************\
743 * tifEncode_newPage - Tells us to flush this page, and start a new page
745 \*****************************************************************************/
747 static WORD tifEncode_newPage (
748 IP_XFORM_HANDLE hXform)
752 HANDLE_TO_PTR (hXform, g);
753 /* todo: return fatal error if convert is called again? */
754 return IP_DONE; /* can't insert page-breaks, so ignore this call */
757 return IP_FATAL_ERROR;
763 /*****************************************************************************\
765 * tifEncode_closeXform - Destroys this instance
767 \*****************************************************************************/
769 static WORD tifEncode_closeXform (IP_XFORM_HANDLE hXform)
773 HANDLE_TO_PTR (hXform, g);
774 if (g->fileOut != NULL)
777 IP_MEM_FREE (g); /* free memory for the instance */
781 return IP_FATAL_ERROR;
786 /*****************************************************************************\
788 * tifEncodeTbl - Jump-table for encoder
790 \*****************************************************************************/
792 IP_XFORM_TBL tifEncodeTbl = {
794 tifEncode_setDefaultInputTraits,
795 tifEncode_setXformSpec,
796 tifEncode_getHeaderBufSize,
797 tifEncode_getActualTraits,
798 tifEncode_getActualBufSizes,
801 tifEncode_insertedData,
808 /*****************************************************************************\
809 *****************************************************************************
813 *****************************************************************************
814 \*****************************************************************************/
819 /*****************************************************************************\
821 * tifDecode_openXform - Creates a new instance of the transformer
823 *****************************************************************************
825 * This returns a handle for the new instance to be passed into
826 * all subsequent calls.
828 * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
830 \*****************************************************************************/
832 static WORD tifDecode_openXform (
833 IP_XFORM_HANDLE *pXform) /* out: returned handle */
837 INSURE (pXform != NULL);
838 IP_MEM_ALLOC (sizeof(TIF_INST), g);
840 memset (g, 0, sizeof(TIF_INST));
841 g->dwValidChk = CHECK_VALUE;
845 return IP_FATAL_ERROR;
850 /*****************************************************************************\
852 * tifDecode_setDefaultInputTraits - Specifies default input image traits
854 *****************************************************************************
856 * The header of the file-type handled by the transform probably does
857 * not include *all* the image traits we'd like to know. Those not
858 * specified in the file-header are filled in from info provided by
861 * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
863 \*****************************************************************************/
865 static WORD tifDecode_setDefaultInputTraits (
866 IP_XFORM_HANDLE hXform, /* in: handle for xform */
867 PIP_IMAGE_TRAITS pTraits) /* in: default image traits */
871 HANDLE_TO_PTR (hXform, g);
872 g->traits = *pTraits; /* a structure copy */
876 return IP_FATAL_ERROR;
881 /*****************************************************************************\
883 * tifDecode_setXformSpec - Provides xform-specific information
885 \*****************************************************************************/
887 static WORD tifDecode_setXformSpec (
888 IP_XFORM_HANDLE hXform, /* in: handle for xform */
889 DWORD_OR_PVOID aXformInfo[]) /* in: xform information */
894 HANDLE_TO_PTR (hXform, g);
895 /* file-path is not used, but might be later, so save it */
896 s = (char*)aXformInfo[IP_TIFF_FILE_PATH].pvoid;
898 strcpy (g->sFilePath, s);
902 return IP_FATAL_ERROR;
907 /*****************************************************************************\
909 * tifDecode_getHeaderBufSize - Returns size of input buf needed to hold header
911 \*****************************************************************************/
913 static WORD tifDecode_getHeaderBufSize (
914 IP_XFORM_HANDLE hXform, /* in: handle for xform */
915 DWORD *pdwInBufLen) /* out: buf size for parsing header */
917 *pdwInBufLen = MAX_HEADER_SIZE + 10000; /* 10000 gives us huge margin */
923 /*****************************************************************************\
925 * ByteSwap - Reverses endian-type of the given variable (1, 2, 4 or 8 bytes)
927 \*****************************************************************************/
929 static void ByteSwap (
934 BYTE *pb = (BYTE*)pvVar;
941 b = pb[0]; pb[0] = pb[1]; pb[1] = b;
944 b = pb[1]; pb[1] = pb[2]; pb[2] = b;
945 b = pb[0]; pb[0] = pb[3]; pb[3] = b;
948 /* this is actually two longs, so fix each one */
950 ByteSwap ((BYTE*)pvVar+4, 4);
957 /*****************************************************************************\
959 * ParseTag - Parses a tag, putting value in traits or dwImageOffset
961 \*****************************************************************************/
963 static BOOL ParseTag (
964 PTIF_INST g, /* in: our instance variables */
965 TIFFTAG *pTag, /* in: the tag to parse */
966 BYTE *pbInputBuf, /* in: input buffer containing TIFF header */
967 BYTE *pbBufAfter, /* in: 1st byte after the input buffer */
968 DWORD *pdwImageOffset) /* out: image start offset set by STRIP_OFFSETS */
975 int nTypeBytes, nValueBytes;
979 ByteSwap (&(pTag->TagID ), 2);
980 ByteSwap (&(pTag->Kind ), 2);
981 ByteSwap (&(pTag->Length), 4);
986 count = pTag->Length;
989 case TIFFUNDEFINED: nTypeBytes = 1; break;
990 case TIFFBYTE: nTypeBytes = 1; break;
991 case TIFFSBYTE: nTypeBytes = 1; break;
992 case TIFFSHORT: nTypeBytes = 2; break;
993 case TIFFSSHORT: nTypeBytes = 2; break;
994 case TIFFLONG: nTypeBytes = 4; break;
995 case TIFFSLONG: nTypeBytes = 4; break;
996 case TIFFRATIONAL: nTypeBytes = 8; break;
997 case TIFFSRATIONAL: nTypeBytes = 8; break;
1001 nValueBytes = count * nTypeBytes;
1003 if (nValueBytes <= 4)
1004 pValue = &(pTag->Value.l);
1007 ByteSwap (&(pTag->Value.l), 4);
1008 pValue = pbInputBuf + pTag->Value.l;
1010 INSURE ((BYTE*)pValue>pbInputBuf && (BYTE*)pValue<pbBufAfter);
1013 for (i=0; i<(int)count; i++)
1014 ByteSwap ((BYTE*)pValue + i*nTypeBytes, nTypeBytes);
1018 case TIFFUNDEFINED: value = *(TIFF_UBYTE *)pValue; break;
1019 case TIFFBYTE: value = *(TIFF_UBYTE *)pValue; break;
1020 case TIFFSBYTE: value = *(TIFF_SBYTE *)pValue; break;
1021 case TIFFSHORT: value = *(TIFF_USHORT*)pValue; break;
1022 case TIFFSSHORT: value = *(TIFF_SSHORT*)pValue; break;
1023 case TIFFLONG: value = *(TIFF_ULONG *)pValue; break;
1024 case TIFFSLONG: value = *(TIFF_SLONG *)pValue; break;
1025 case TIFFRATIONAL: value = ((RATIONAL*)pValue)->n / ((RATIONAL*)pValue)->d; break;
1026 case TIFFSRATIONAL: value = ((RATIONAL*)pValue)->n / ((RATIONAL*)pValue)->d; break;
1035 g->traits.iPixelsPerRow = value;
1038 g->traits.lNumRows = value;
1040 case BITS_PER_SAMPLE:
1041 g->iBitsPerSample = value;
1044 INSURE (value == 1); /* we only support uncompressed */
1046 case PHOTO_INTERPRET:
1050 INSURE (count == 1); /* we only support one strip */
1051 *pdwImageOffset = value;
1053 case SAMPLES_PER_PIXEL:
1054 g->traits.iComponentsPerPixel = value;
1056 case ROWS_PER_STRIP:
1057 /* do nothing -- we assume entire image is in one strip */
1060 /* do nothing -- this should be the # bytes in the raw data */
1063 g->traits.lHorizDPI = value << 16;
1066 g->traits.lVertDPI = value << 16;
1068 case RESOLUTION_UNIT:
1069 /* do nothing -- if it's not DPI, then reported DPI will be wrong */
1072 /* ignore the unknown tag */
1084 /*****************************************************************************\
1086 * tifDecode_getActualTraits - Parses header, and returns input & output traits
1088 \*****************************************************************************/
1090 static WORD tifDecode_getActualTraits (
1091 IP_XFORM_HANDLE hXform, /* in: handle for xform */
1092 DWORD dwInputAvail, /* in: # avail bytes in input buf */
1093 PBYTE pbInputBuf, /* in: ptr to input buffer */
1094 PDWORD pdwInputUsed, /* out: # bytes used from input buf */
1095 PDWORD pdwInputNextPos,/* out: file-pos to read from next */
1096 PIP_IMAGE_TRAITS pInTraits, /* out: input image traits */
1097 PIP_IMAGE_TRAITS pOutTraits) /* out: output image traits */
1100 DWORD dwImageOffset;
1106 HANDLE_TO_PTR (hXform, g);
1109 /**** Parse the file-header ****/
1111 pHead = (TIFFHEADER*)pb;
1112 INSURE (pHead->ByteOrder[0]=='I' || pHead->ByteOrder[0]=='M');
1113 INSURE (pHead->ByteOrder[1]=='I' || pHead->ByteOrder[1]=='M');
1114 g->bByteSwap = pHead->ByteOrder[0] == 'M';
1116 ByteSwap (&(pHead->OffsetFirstIFD), 4);
1117 INSURE (pHead->OffsetFirstIFD < dwInputAvail);
1118 /* ignore the file-version */
1119 pb = pbInputBuf + pHead->OffsetFirstIFD;
1121 /**** Parse the IFD (i.e., the tags), setting traits ****/
1123 pIFD = (TIFFIFD*)pb;
1125 ByteSwap (&(pIFD->NumTags), 2);
1126 nTags = pIFD->NumTags;
1127 INSURE (nTags>0 && nTags<100); /* sanity check */
1128 INSURE (nTags*sizeof(TIFFTAG) < dwInputAvail);
1131 for (iTag=0; iTag<nTags; iTag++) {
1132 if (! ParseTag (g, pIFD->Tag+iTag, pbInputBuf, pbInputBuf+dwInputAvail, &dwImageOffset))
1136 INSURE (g->iBitsPerSample==1 || g->iBitsPerSample==8 || g->iBitsPerSample==16);
1137 g->traits.iBitsPerPixel = g->iBitsPerSample * g->traits.iComponentsPerPixel;
1138 INSURE (dwImageOffset <= dwInputAvail);
1139 g->dwRawRowBytes = (g->traits.iBitsPerPixel*g->traits.iPixelsPerRow + 7) / 8;
1141 /**** Finish up ****/
1143 g->dwInNextPos = dwImageOffset;
1144 *pdwInputUsed = dwImageOffset;
1145 *pdwInputNextPos = dwImageOffset;
1147 *pInTraits = g->traits;
1148 *pOutTraits = g->traits;
1149 return IP_DONE | IP_READY_FOR_DATA;
1152 return IP_FATAL_ERROR;
1157 /****************************************************************************\
1159 * tifDecode_getActualBufSizes - Returns buf sizes needed for remainder of job
1161 \****************************************************************************/
1163 static WORD tifDecode_getActualBufSizes (
1164 IP_XFORM_HANDLE hXform, /* in: handle for xform */
1165 PDWORD pdwMinInBufLen, /* out: min input buf size */
1166 PDWORD pdwMinOutBufLen) /* out: min output buf size */
1170 HANDLE_TO_PTR (hXform, g);
1171 *pdwMinInBufLen = g->dwRawRowBytes;
1172 *pdwMinOutBufLen = g->dwRawRowBytes;
1176 return IP_FATAL_ERROR;
1181 /*****************************************************************************\
1183 * tifDecode_convert - the work-horse routine
1185 \*****************************************************************************/
1187 static WORD tifDecode_convert (
1188 IP_XFORM_HANDLE hXform,
1189 DWORD dwInputAvail, /* in: # avail bytes in in-buf */
1190 PBYTE pbInputBuf, /* in: ptr to in-buffer */
1191 PDWORD pdwInputUsed, /* out: # bytes used from in-buf */
1192 PDWORD pdwInputNextPos, /* out: file-pos to read from next */
1193 DWORD dwOutputAvail, /* in: # avail bytes in out-buf */
1194 PBYTE pbOutputBuf, /* in: ptr to out-buffer */
1195 PDWORD pdwOutputUsed, /* out: # bytes written in out-buf */
1196 PDWORD pdwOutputThisPos) /* out: file-pos to write the data */
1201 HANDLE_TO_PTR (hXform, g);
1203 /**** Check if we were told to flush ****/
1205 if (pbInputBuf == NULL) {
1206 PRINT (_T("tif_decode_convert_row: Told to flush.\n"), 0, 0);
1207 *pdwInputUsed = *pdwOutputUsed = 0;
1208 *pdwInputNextPos = g->dwInNextPos;
1209 *pdwOutputThisPos = g->dwOutNextPos;
1213 /**** Output a Row ****/
1215 n = g->dwRawRowBytes;
1217 if (dwInputAvail < n) {
1218 /* we got a partial row at the end -- just toss it */
1219 g->dwInNextPos += dwInputAvail;
1220 *pdwInputNextPos = g->dwInNextPos;
1221 *pdwInputUsed = dwInputAvail;
1223 *pdwOutputThisPos = g->dwOutNextPos;
1224 return IP_READY_FOR_DATA;
1227 INSURE (dwOutputAvail >= n);
1228 memcpy (pbOutputBuf, pbInputBuf, n);
1230 if (g->bByteSwap && g->iBitsPerSample==16) {
1231 /* we need to swap bytes in the 16-bit words in the pixels */
1232 BYTE *pb, *pbAfter, b;
1233 pbAfter = pbInputBuf + n;
1234 for (pb=pbInputBuf; pb<pbAfter; pb+=4) {
1235 /* process two words at a time for speed */
1236 b = pb[0]; pb[0] = pb[1]; pb[1] = b;
1237 b = pb[2]; pb[2] = pb[3]; pb[3] = b;
1242 *pdwOutputThisPos = g->dwOutNextPos;
1243 g->dwOutNextPos += n;
1245 g->dwInNextPos += n;
1246 *pdwInputNextPos = g->dwInNextPos;
1250 return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA;
1253 return IP_FATAL_ERROR;
1258 /*****************************************************************************\
1260 * tifDecode_insertedData - client inserted into our output stream
1262 \*****************************************************************************/
1264 static WORD tifDecode_insertedData (
1265 IP_XFORM_HANDLE hXform,
1269 return IP_FATAL_ERROR; /* must never be called (can't insert data) */
1274 /*****************************************************************************\
1276 * tifDecode_newPage - Tells us to flush this page, and start a new page
1278 \*****************************************************************************/
1280 static WORD tifDecode_newPage (
1281 IP_XFORM_HANDLE hXform)
1285 HANDLE_TO_PTR (hXform, g);
1286 /* todo: return fatal error if convert is called again? */
1287 return IP_DONE; /* can't insert page-breaks, so ignore this call */
1290 return IP_FATAL_ERROR;
1296 /*****************************************************************************\
1298 * tifDecode_closeXform - Destroys this instance
1300 \*****************************************************************************/
1302 static WORD tifDecode_closeXform (IP_XFORM_HANDLE hXform)
1306 HANDLE_TO_PTR (hXform, g);
1307 if (g->fileOut != NULL)
1308 fclose (g->fileOut);
1310 IP_MEM_FREE (g); /* free memory for the instance */
1314 return IP_FATAL_ERROR;
1319 /*****************************************************************************\
1321 * tifDecodeTbl - Jump-table for decoder
1323 \*****************************************************************************/
1325 IP_XFORM_TBL tifDecodeTbl = {
1326 tifDecode_openXform,
1327 tifDecode_setDefaultInputTraits,
1328 tifDecode_setXformSpec,
1329 tifDecode_getHeaderBufSize,
1330 tifDecode_getActualTraits,
1331 tifDecode_getActualBufSizes,
1334 tifDecode_insertedData,
1335 tifDecode_closeXform