3 * Copyright (c) 1988-1997 Sam Leffler
4 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6 * Revised: 2/18/01 BAR -- added syntax for extracting single images from
7 * multi-image TIFF files.
9 * New syntax is: sourceFileName,image#
11 * image# ranges from 0..<n-1> where n is the # of images in the file.
12 * There may be no white space between the comma and the filename or
15 * Example: tiffcp source.tif,1 destination.tif
17 * Copies the 2nd image in source.tif to the destination.
20 * Permission to use, copy, modify, distribute, and sell this software and
21 * its documentation for any purpose is hereby granted without fee, provided
22 * that (i) the above copyright notices and this permission notice appear in
23 * all copies of the software and related documentation, and (ii) the names of
24 * Sam Leffler and Silicon Graphics may not be used in any advertising or
25 * publicity relating to the software without the specific, prior written
26 * permission of Sam Leffler and Silicon Graphics.
28 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
30 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
32 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
33 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
34 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
35 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
36 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
40 #include "tif_config.h"
56 extern int getopt(int, char**, char*);
60 # define unlink delete
63 #define streq(a,b) (strcmp(a,b) == 0)
64 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
69 static int outtiled
= -1;
70 static uint32 tilewidth
;
71 static uint32 tilelength
;
74 static uint16 compression
;
75 static uint16 predictor
;
77 static uint16 fillorder
;
78 static uint16 orientation
;
79 static uint32 rowsperstrip
;
81 static int ignore
= FALSE
; /* if true, ignore read errors */
82 static uint32 defg3opts
= (uint32
) -1;
83 static int quality
= 75; /* JPEG quality */
84 static int jpegcolormode
= JPEGCOLORMODE_RGB
;
85 static uint16 defcompression
= (uint16
) -1;
86 static uint16 defpredictor
= (uint16
) -1;
87 static int defpreset
= -1;
89 static int tiffcp(TIFF
*, TIFF
*);
90 static int processCompressOptions(char*);
91 static void usage(void);
93 static char comma
= ','; /* (default) comma separator character */
94 static TIFF
* bias
= NULL
;
95 static int pageNum
= 0;
96 static int pageInSeq
= 0;
98 static int nextSrcImage (TIFF
*tif
, char **imageSpec
)
100 seek to the next image specified in *imageSpec
101 returns 1 if success, 0 if no more images to process
102 *imageSpec=NULL if subsequent images should be processed in sequence
105 if (**imageSpec
== comma
) { /* if not @comma, we've done all images */
106 char *start
= *imageSpec
+ 1;
107 tdir_t nextImage
= (tdir_t
)strtol(start
, imageSpec
, 0);
108 if (start
== *imageSpec
) nextImage
= TIFFCurrentDirectory (tif
);
111 if (**imageSpec
== comma
) {
112 /* a trailing comma denotes remaining images in sequence */
113 if ((*imageSpec
)[1] == '\0') *imageSpec
= NULL
;
116 "Expected a %c separated image # list after %s\n",
117 comma
, TIFFFileName (tif
));
118 exit (-4); /* syntax error */
121 if (TIFFSetDirectory (tif
, nextImage
)) return 1;
122 fprintf (stderr
, "%s%c%d not found!\n",
123 TIFFFileName(tif
), comma
, (int) nextImage
);
129 static TIFF
* openSrcImage (char **imageSpec
)
131 imageSpec points to a pointer to a filename followed by optional ,image#'s
132 Open the TIFF file and assign *imageSpec to either NULL if there are
133 no images specified, or a pointer to the next image number text
137 char *fn
= *imageSpec
;
138 *imageSpec
= strchr (fn
, comma
);
139 if (*imageSpec
) { /* there is at least one image number specifier */
141 tif
= TIFFOpen (fn
, "r");
142 /* but, ignore any single trailing comma */
143 if (!(*imageSpec
)[1]) {*imageSpec
= NULL
; return tif
;}
145 **imageSpec
= comma
; /* replace the comma */
146 if (!nextSrcImage(tif
, imageSpec
)) {
152 tif
= TIFFOpen (fn
, "r");
157 main(int argc
, char* argv
[])
159 uint16 defconfig
= (uint16
) -1;
160 uint16 deffillorder
= 0;
161 uint32 deftilewidth
= (uint32
) -1;
162 uint32 deftilelength
= (uint32
) -1;
163 uint32 defrowsperstrip
= (uint32
) 0;
175 while ((c
= getopt(argc
, argv
, ",:b:c:f:l:o:z:p:r:w:aistBLMC8x")) != -1)
178 if (optarg
[0] != '=') usage();
181 case 'b': /* this file is bias image subtracted from others */
183 fputs ("Only 1 bias image may be specified\n", stderr
);
187 uint16 samples
= (uint16
) -1;
188 char **biasFn
= &optarg
;
189 bias
= openSrcImage (biasFn
);
190 if (!bias
) exit (-5);
191 if (TIFFIsTiled (bias
)) {
192 fputs ("Bias image must be organized in strips\n", stderr
);
195 TIFFGetField(bias
, TIFFTAG_SAMPLESPERPIXEL
, &samples
);
197 fputs ("Bias image must be monochrome\n", stderr
);
202 case 'a': /* append to output */
205 case 'c': /* compression scheme */
206 if (!processCompressOptions(optarg
))
209 case 'f': /* fill order */
210 if (streq(optarg
, "lsb2msb"))
211 deffillorder
= FILLORDER_LSB2MSB
;
212 else if (streq(optarg
, "msb2lsb"))
213 deffillorder
= FILLORDER_MSB2LSB
;
217 case 'i': /* ignore errors */
220 case 'l': /* tile length */
222 deftilelength
= atoi(optarg
);
224 case 'o': /* initial directory offset */
225 diroff
= strtoul(optarg
, NULL
, 0);
227 case 'p': /* planar configuration */
228 if (streq(optarg
, "separate"))
229 defconfig
= PLANARCONFIG_SEPARATE
;
230 else if (streq(optarg
, "contig"))
231 defconfig
= PLANARCONFIG_CONTIG
;
235 case 'r': /* rows/strip */
236 defrowsperstrip
= atol(optarg
);
238 case 's': /* generate stripped output */
241 case 't': /* generate tiled output */
244 case 'w': /* tile width */
246 deftilewidth
= atoi(optarg
);
249 *mp
++ = 'b'; *mp
= '\0';
252 *mp
++ = 'l'; *mp
= '\0';
255 *mp
++ = 'm'; *mp
= '\0';
258 *mp
++ = 'c'; *mp
= '\0';
261 *mp
++ = '8'; *mp
= '\0';
270 if (argc
- optind
< 2)
272 out
= TIFFOpen(argv
[argc
-1], mode
);
275 if ((argc
- optind
) == 2)
277 for (; optind
< argc
-1 ; optind
++) {
278 char *imageCursor
= argv
[optind
];
279 in
= openSrcImage (&imageCursor
);
281 (void) TIFFClose(out
);
284 if (diroff
!= 0 && !TIFFSetSubDirectory(in
, diroff
)) {
285 TIFFError(TIFFFileName(in
),
286 "Error, setting subdirectory at " TIFF_UINT64_FORMAT
, diroff
);
287 (void) TIFFClose(in
);
288 (void) TIFFClose(out
);
293 compression
= defcompression
;
294 predictor
= defpredictor
;
296 fillorder
= deffillorder
;
297 rowsperstrip
= defrowsperstrip
;
298 tilewidth
= deftilewidth
;
299 tilelength
= deftilelength
;
301 if (!tiffcp(in
, out
) || !TIFFWriteDirectory(out
)) {
302 (void) TIFFClose(in
);
303 (void) TIFFClose(out
);
306 if (imageCursor
) { /* seek next image directory */
307 if (!nextSrcImage(in
, &imageCursor
)) break;
309 if (!TIFFReadDirectory(in
)) break;
311 (void) TIFFClose(in
);
314 (void) TIFFClose(out
);
319 processZIPOptions(char* cp
)
321 if ( (cp
= strchr(cp
, ':')) ) {
324 if (isdigit((int)*cp
))
325 defpredictor
= atoi(cp
);
327 defpreset
= atoi(++cp
);
330 } while( (cp
= strchr(cp
, ':')) );
335 processG3Options(char* cp
)
337 if( (cp
= strchr(cp
, ':')) ) {
338 if (defg3opts
== (uint32
) -1)
342 if (strneq(cp
, "1d", 2))
343 defg3opts
&= ~GROUP3OPT_2DENCODING
;
344 else if (strneq(cp
, "2d", 2))
345 defg3opts
|= GROUP3OPT_2DENCODING
;
346 else if (strneq(cp
, "fill", 4))
347 defg3opts
|= GROUP3OPT_FILLBITS
;
350 } while( (cp
= strchr(cp
, ':')) );
355 processCompressOptions(char* opt
)
357 if (streq(opt
, "none")) {
358 defcompression
= COMPRESSION_NONE
;
359 } else if (streq(opt
, "packbits")) {
360 defcompression
= COMPRESSION_PACKBITS
;
361 } else if (strneq(opt
, "jpeg", 4)) {
362 char* cp
= strchr(opt
, ':');
364 defcompression
= COMPRESSION_JPEG
;
367 if (isdigit((int)cp
[1]))
368 quality
= atoi(cp
+1);
369 else if (cp
[1] == 'r' )
370 jpegcolormode
= JPEGCOLORMODE_RAW
;
374 cp
= strchr(cp
+1,':');
376 } else if (strneq(opt
, "g3", 2)) {
377 processG3Options(opt
);
378 defcompression
= COMPRESSION_CCITTFAX3
;
379 } else if (streq(opt
, "g4")) {
380 defcompression
= COMPRESSION_CCITTFAX4
;
381 } else if (strneq(opt
, "lzw", 3)) {
382 char* cp
= strchr(opt
, ':');
384 defpredictor
= atoi(cp
+1);
385 defcompression
= COMPRESSION_LZW
;
386 } else if (strneq(opt
, "zip", 3)) {
387 processZIPOptions(opt
);
388 defcompression
= COMPRESSION_ADOBE_DEFLATE
;
389 } else if (strneq(opt
, "lzma", 4)) {
390 processZIPOptions(opt
);
391 defcompression
= COMPRESSION_LZMA
;
392 } else if (strneq(opt
, "jbig", 4)) {
393 defcompression
= COMPRESSION_JBIG
;
394 } else if (strneq(opt
, "sgilog", 6)) {
395 defcompression
= COMPRESSION_SGILOG
;
402 "usage: tiffcp [options] input... output",
403 "where options are:",
404 " -a append to output instead of overwriting",
405 " -o offset set initial directory offset",
406 " -p contig pack samples contiguously (e.g. RGBRGB...)",
407 " -p separate store samples separately (e.g. RRR...GGG...BBB...)",
408 " -s write output in strips",
409 " -t write output in tiles",
410 " -8 write BigTIFF instead of default ClassicTIFF",
411 " -i ignore read errors",
412 " -b file[,#] bias (dark) monochrome image to be subtracted from all others",
413 " -,=% use % rather than , to separate image #'s (per Note below)",
415 " -r # make each strip have no more than # rows",
416 " -w # set output tile width (pixels)",
417 " -l # set output tile length (pixels)",
419 " -f lsb2msb force lsb-to-msb FillOrder for output",
420 " -f msb2lsb force msb-to-lsb FillOrder for output",
422 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
423 " -c zip[:opts] compress output with deflate encoding",
424 " -c lzma[:opts] compress output with LZMA2 encoding",
425 " -c jpeg[:opts] compress output with JPEG encoding",
426 " -c jbig compress output with ISO JBIG encoding",
427 " -c packbits compress output with packbits encoding",
428 " -c g3[:opts] compress output with CCITT Group 3 encoding",
429 " -c g4 compress output with CCITT Group 4 encoding",
430 " -c sgilog compress output with SGILOG encoding",
431 " -c none use no compression algorithm on output",
432 " -x force the merged tiff pages in sequence",
435 " 1d use default CCITT Group 3 1D-encoding",
436 " 2d use optional CCITT Group 3 2D-encoding",
437 " fill byte-align EOL codes",
438 "For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
441 " # set compression quality level (0-100, default 75)",
442 " r output color image as RGB rather than YCbCr",
443 "For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
445 "LZW, Deflate (ZIP) and LZMA2 options:",
446 " # set predictor value",
447 " p# set compression level (preset)",
448 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing,",
449 "-c zip:3:p9 for Deflate encoding with maximum compression level and floating",
452 "Note that input filenames may be of the form filename,x,y,z",
453 "where x, y, and z specify image numbers in the filename to copy.",
454 "example: tiffcp -c none -b esp.tif,1 esp.tif,0 test.tif",
455 " subtract 2nd image in esp.tif from 1st yielding uncompressed result test.tif",
466 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
467 for (i
= 0; stuff
[i
] != NULL
; i
++)
468 fprintf(stderr
, "%s\n", stuff
[i
]);
472 #define CopyField(tag, v) \
473 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
474 #define CopyField2(tag, v1, v2) \
475 if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
476 #define CopyField3(tag, v1, v2, v3) \
477 if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
478 #define CopyField4(tag, v1, v2, v3, v4) \
479 if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
482 cpTag(TIFF
* in
, TIFF
* out
, uint16 tag
, uint16 count
, TIFFDataType type
)
488 CopyField(tag
, shortv
);
489 } else if (count
== 2) {
490 uint16 shortv1
, shortv2
;
491 CopyField2(tag
, shortv1
, shortv2
);
492 } else if (count
== 4) {
493 uint16
*tr
, *tg
, *tb
, *ta
;
494 CopyField4(tag
, tr
, tg
, tb
, ta
);
495 } else if (count
== (uint16
) -1) {
498 CopyField2(tag
, shortv1
, shortav
);
503 CopyField(tag
, longv
);
509 CopyField(tag
, floatv
);
510 } else if (count
== (uint16
) -1) {
512 CopyField(tag
, floatav
);
517 CopyField(tag
, stringv
);
523 CopyField(tag
, doublev
);
524 } else if (count
== (uint16
) -1) {
526 CopyField(tag
, doubleav
);
530 TIFFError(TIFFFileName(in
),
531 "Data type %d is not supported, tag %d skipped.",
536 static struct cpTag
{
541 { TIFFTAG_SUBFILETYPE
, 1, TIFF_LONG
},
542 { TIFFTAG_THRESHHOLDING
, 1, TIFF_SHORT
},
543 { TIFFTAG_DOCUMENTNAME
, 1, TIFF_ASCII
},
544 { TIFFTAG_IMAGEDESCRIPTION
, 1, TIFF_ASCII
},
545 { TIFFTAG_MAKE
, 1, TIFF_ASCII
},
546 { TIFFTAG_MODEL
, 1, TIFF_ASCII
},
547 { TIFFTAG_MINSAMPLEVALUE
, 1, TIFF_SHORT
},
548 { TIFFTAG_MAXSAMPLEVALUE
, 1, TIFF_SHORT
},
549 { TIFFTAG_XRESOLUTION
, 1, TIFF_RATIONAL
},
550 { TIFFTAG_YRESOLUTION
, 1, TIFF_RATIONAL
},
551 { TIFFTAG_PAGENAME
, 1, TIFF_ASCII
},
552 { TIFFTAG_XPOSITION
, 1, TIFF_RATIONAL
},
553 { TIFFTAG_YPOSITION
, 1, TIFF_RATIONAL
},
554 { TIFFTAG_RESOLUTIONUNIT
, 1, TIFF_SHORT
},
555 { TIFFTAG_SOFTWARE
, 1, TIFF_ASCII
},
556 { TIFFTAG_DATETIME
, 1, TIFF_ASCII
},
557 { TIFFTAG_ARTIST
, 1, TIFF_ASCII
},
558 { TIFFTAG_HOSTCOMPUTER
, 1, TIFF_ASCII
},
559 { TIFFTAG_WHITEPOINT
, (uint16
) -1, TIFF_RATIONAL
},
560 { TIFFTAG_PRIMARYCHROMATICITIES
,(uint16
) -1,TIFF_RATIONAL
},
561 { TIFFTAG_HALFTONEHINTS
, 2, TIFF_SHORT
},
562 { TIFFTAG_INKSET
, 1, TIFF_SHORT
},
563 { TIFFTAG_DOTRANGE
, 2, TIFF_SHORT
},
564 { TIFFTAG_TARGETPRINTER
, 1, TIFF_ASCII
},
565 { TIFFTAG_SAMPLEFORMAT
, 1, TIFF_SHORT
},
566 { TIFFTAG_YCBCRCOEFFICIENTS
, (uint16
) -1,TIFF_RATIONAL
},
567 { TIFFTAG_YCBCRSUBSAMPLING
, 2, TIFF_SHORT
},
568 { TIFFTAG_YCBCRPOSITIONING
, 1, TIFF_SHORT
},
569 { TIFFTAG_REFERENCEBLACKWHITE
, (uint16
) -1,TIFF_RATIONAL
},
570 { TIFFTAG_EXTRASAMPLES
, (uint16
) -1, TIFF_SHORT
},
571 { TIFFTAG_SMINSAMPLEVALUE
, 1, TIFF_DOUBLE
},
572 { TIFFTAG_SMAXSAMPLEVALUE
, 1, TIFF_DOUBLE
},
573 { TIFFTAG_STONITS
, 1, TIFF_DOUBLE
},
575 #define NTAGS (sizeof (tags) / sizeof (tags[0]))
577 #define CopyTag(tag, count, type) cpTag(in, out, tag, count, type)
579 typedef int (*copyFunc
)
580 (TIFF
* in
, TIFF
* out
, uint32 l
, uint32 w
, uint16 samplesperpixel
);
581 static copyFunc
pickCopyFunc(TIFF
*, TIFF
*, uint16
, uint16
);
586 tiffcp(TIFF
* in
, TIFF
* out
)
588 uint16 bitspersample
, samplesperpixel
;
589 uint16 input_compression
, input_photometric
;
591 uint32 width
, length
;
594 CopyField(TIFFTAG_IMAGEWIDTH
, width
);
595 CopyField(TIFFTAG_IMAGELENGTH
, length
);
596 CopyField(TIFFTAG_BITSPERSAMPLE
, bitspersample
);
597 CopyField(TIFFTAG_SAMPLESPERPIXEL
, samplesperpixel
);
598 if (compression
!= (uint16
)-1)
599 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
601 CopyField(TIFFTAG_COMPRESSION
, compression
);
602 TIFFGetFieldDefaulted(in
, TIFFTAG_COMPRESSION
, &input_compression
);
603 TIFFGetFieldDefaulted(in
, TIFFTAG_PHOTOMETRIC
, &input_photometric
);
604 if (input_compression
== COMPRESSION_JPEG
) {
605 /* Force conversion to RGB */
606 TIFFSetField(in
, TIFFTAG_JPEGCOLORMODE
, JPEGCOLORMODE_RGB
);
607 } else if (input_photometric
== PHOTOMETRIC_YCBCR
) {
608 /* Otherwise, can't handle subsampled input */
609 uint16 subsamplinghor
,subsamplingver
;
611 TIFFGetFieldDefaulted(in
, TIFFTAG_YCBCRSUBSAMPLING
,
612 &subsamplinghor
, &subsamplingver
);
613 if (subsamplinghor
!=1 || subsamplingver
!=1) {
614 fprintf(stderr
, "tiffcp: %s: Can't copy/convert subsampled image.\n",
619 if (compression
== COMPRESSION_JPEG
) {
620 if (input_photometric
== PHOTOMETRIC_RGB
&&
621 jpegcolormode
== JPEGCOLORMODE_RGB
)
622 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, PHOTOMETRIC_YCBCR
);
624 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, input_photometric
);
626 else if (compression
== COMPRESSION_SGILOG
627 || compression
== COMPRESSION_SGILOG24
)
628 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
,
629 samplesperpixel
== 1 ?
630 PHOTOMETRIC_LOGL
: PHOTOMETRIC_LOGLUV
);
632 CopyTag(TIFFTAG_PHOTOMETRIC
, 1, TIFF_SHORT
);
634 TIFFSetField(out
, TIFFTAG_FILLORDER
, fillorder
);
636 CopyTag(TIFFTAG_FILLORDER
, 1, TIFF_SHORT
);
638 * Will copy `Orientation' tag from input image
640 TIFFGetFieldDefaulted(in
, TIFFTAG_ORIENTATION
, &orientation
);
641 switch (orientation
) {
642 case ORIENTATION_BOTRIGHT
:
643 case ORIENTATION_RIGHTBOT
: /* XXX */
644 TIFFWarning(TIFFFileName(in
), "using bottom-left orientation");
645 orientation
= ORIENTATION_BOTLEFT
;
647 case ORIENTATION_LEFTBOT
: /* XXX */
648 case ORIENTATION_BOTLEFT
:
650 case ORIENTATION_TOPRIGHT
:
651 case ORIENTATION_RIGHTTOP
: /* XXX */
653 TIFFWarning(TIFFFileName(in
), "using top-left orientation");
654 orientation
= ORIENTATION_TOPLEFT
;
656 case ORIENTATION_LEFTTOP
: /* XXX */
657 case ORIENTATION_TOPLEFT
:
660 TIFFSetField(out
, TIFFTAG_ORIENTATION
, orientation
);
662 * Choose tiles/strip for the output image according to
663 * the command line arguments (-tiles, -strips) and the
664 * structure of the input image.
667 outtiled
= TIFFIsTiled(in
);
670 * Setup output file's tile width&height. If either
671 * is not specified, use either the value from the
672 * input image or, if nothing is defined, use the
675 if (tilewidth
== (uint32
) -1)
676 TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tilewidth
);
677 if (tilelength
== (uint32
) -1)
678 TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tilelength
);
679 TIFFDefaultTileSize(out
, &tilewidth
, &tilelength
);
680 TIFFSetField(out
, TIFFTAG_TILEWIDTH
, tilewidth
);
681 TIFFSetField(out
, TIFFTAG_TILELENGTH
, tilelength
);
684 * RowsPerStrip is left unspecified: use either the
685 * value from the input image or, if nothing is defined,
686 * use the library default.
688 if (rowsperstrip
== (uint32
) 0) {
689 if (!TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
,
692 TIFFDefaultStripSize(out
, rowsperstrip
);
694 if (rowsperstrip
> length
&& rowsperstrip
!= (uint32
)-1)
695 rowsperstrip
= length
;
697 else if (rowsperstrip
== (uint32
) -1)
698 rowsperstrip
= length
;
699 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
);
701 if (config
!= (uint16
) -1)
702 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, config
);
704 CopyField(TIFFTAG_PLANARCONFIG
, config
);
705 if (samplesperpixel
<= 4)
706 CopyTag(TIFFTAG_TRANSFERFUNCTION
, 4, TIFF_SHORT
);
707 CopyTag(TIFFTAG_COLORMAP
, 4, TIFF_SHORT
);
708 /* SMinSampleValue & SMaxSampleValue */
709 switch (compression
) {
710 case COMPRESSION_JPEG
:
711 TIFFSetField(out
, TIFFTAG_JPEGQUALITY
, quality
);
712 TIFFSetField(out
, TIFFTAG_JPEGCOLORMODE
, jpegcolormode
);
714 case COMPRESSION_JBIG
:
715 CopyTag(TIFFTAG_FAXRECVPARAMS
, 1, TIFF_LONG
);
716 CopyTag(TIFFTAG_FAXRECVTIME
, 1, TIFF_LONG
);
717 CopyTag(TIFFTAG_FAXSUBADDRESS
, 1, TIFF_ASCII
);
718 CopyTag(TIFFTAG_FAXDCS
, 1, TIFF_ASCII
);
720 case COMPRESSION_LZW
:
721 case COMPRESSION_ADOBE_DEFLATE
:
722 case COMPRESSION_DEFLATE
:
723 case COMPRESSION_LZMA
:
724 if (predictor
!= (uint16
)-1)
725 TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
);
727 CopyField(TIFFTAG_PREDICTOR
, predictor
);
729 if (compression
== COMPRESSION_ADOBE_DEFLATE
730 || compression
== COMPRESSION_DEFLATE
)
731 TIFFSetField(out
, TIFFTAG_ZIPQUALITY
, preset
);
732 else if (compression
== COMPRESSION_LZMA
)
733 TIFFSetField(out
, TIFFTAG_LZMAPRESET
, preset
);
736 case COMPRESSION_CCITTFAX3
:
737 case COMPRESSION_CCITTFAX4
:
738 if (compression
== COMPRESSION_CCITTFAX3
) {
739 if (g3opts
!= (uint32
) -1)
740 TIFFSetField(out
, TIFFTAG_GROUP3OPTIONS
,
743 CopyField(TIFFTAG_GROUP3OPTIONS
, g3opts
);
745 CopyTag(TIFFTAG_GROUP4OPTIONS
, 1, TIFF_LONG
);
746 CopyTag(TIFFTAG_BADFAXLINES
, 1, TIFF_LONG
);
747 CopyTag(TIFFTAG_CLEANFAXDATA
, 1, TIFF_LONG
);
748 CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES
, 1, TIFF_LONG
);
749 CopyTag(TIFFTAG_FAXRECVPARAMS
, 1, TIFF_LONG
);
750 CopyTag(TIFFTAG_FAXRECVTIME
, 1, TIFF_LONG
);
751 CopyTag(TIFFTAG_FAXSUBADDRESS
, 1, TIFF_ASCII
);
757 if (TIFFGetField(in
, TIFFTAG_ICCPROFILE
, &len32
, &data
))
758 TIFFSetField(out
, TIFFTAG_ICCPROFILE
, len32
, data
);
762 const char* inknames
;
763 if (TIFFGetField(in
, TIFFTAG_NUMBEROFINKS
, &ninks
)) {
764 TIFFSetField(out
, TIFFTAG_NUMBEROFINKS
, ninks
);
765 if (TIFFGetField(in
, TIFFTAG_INKNAMES
, &inknames
)) {
766 int inknameslen
= strlen(inknames
) + 1;
767 const char* cp
= inknames
;
769 cp
= strchr(cp
, '\0');
771 inknameslen
+= (strlen(cp
) + 1);
774 TIFFSetField(out
, TIFFTAG_INKNAMES
, inknameslen
, inknames
);
779 unsigned short pg0
, pg1
;
781 if (pageInSeq
== 1) {
782 if (pageNum
< 0) /* only one input file */ {
783 if (TIFFGetField(in
, TIFFTAG_PAGENUMBER
, &pg0
, &pg1
))
784 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pg0
, pg1
);
786 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pageNum
++, 0);
789 if (TIFFGetField(in
, TIFFTAG_PAGENUMBER
, &pg0
, &pg1
)) {
790 if (pageNum
< 0) /* only one input file */
791 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pg0
, pg1
);
793 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pageNum
++, 0);
798 for (p
= tags
; p
< &tags
[NTAGS
]; p
++)
799 CopyTag(p
->tag
, p
->count
, p
->type
);
801 cf
= pickCopyFunc(in
, out
, bitspersample
, samplesperpixel
);
802 return (cf
? (*cf
)(in
, out
, length
, width
, samplesperpixel
) : FALSE
);
808 #define DECLAREcpFunc(x) \
809 static int x(TIFF* in, TIFF* out, \
810 uint32 imagelength, uint32 imagewidth, tsample_t spp)
812 #define DECLAREreadFunc(x) \
813 static int x(TIFF* in, \
814 uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
815 typedef int (*readFunc
)(TIFF
*, uint8
*, uint32
, uint32
, tsample_t
);
817 #define DECLAREwriteFunc(x) \
818 static int x(TIFF* out, \
819 uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
820 typedef int (*writeFunc
)(TIFF
*, uint8
*, uint32
, uint32
, tsample_t
);
823 * Contig -> contig by scanline for rows/strip change.
825 DECLAREcpFunc(cpContig2ContigByRow
)
827 tsize_t scanlinesize
= TIFFScanlineSize(in
);
831 buf
= _TIFFmalloc(scanlinesize
);
834 _TIFFmemset(buf
, 0, scanlinesize
);
835 (void) imagewidth
; (void) spp
;
836 for (row
= 0; row
< imagelength
; row
++) {
837 if (TIFFReadScanline(in
, buf
, row
, 0) < 0 && !ignore
) {
838 TIFFError(TIFFFileName(in
),
839 "Error, can't read scanline %lu",
840 (unsigned long) row
);
843 if (TIFFWriteScanline(out
, buf
, row
, 0) < 0) {
844 TIFFError(TIFFFileName(out
),
845 "Error, can't write scanline %lu",
846 (unsigned long) row
);
858 typedef void biasFn (void *image
, void *bias
, uint32 pixels
);
860 #define subtract(bits) \
861 static void subtract##bits (void *i, void *b, uint32 pixels)\
863 uint##bits *image = i;\
864 uint##bits *bias = b;\
866 *image = *image > *bias ? *image-*bias : 0;\
875 static biasFn
*lineSubtractFn (unsigned bits
)
878 case 8: return subtract8
;
879 case 16: return subtract16
;
880 case 32: return subtract32
;
886 * Contig -> contig by scanline while subtracting a bias image.
888 DECLAREcpFunc(cpBiasedContig2Contig
)
891 tsize_t biasSize
= TIFFScanlineSize(bias
);
892 tsize_t bufSize
= TIFFScanlineSize(in
);
893 tdata_t buf
, biasBuf
;
894 uint32 biasWidth
= 0, biasLength
= 0;
895 TIFFGetField(bias
, TIFFTAG_IMAGEWIDTH
, &biasWidth
);
896 TIFFGetField(bias
, TIFFTAG_IMAGELENGTH
, &biasLength
);
897 if (biasSize
== bufSize
&&
898 imagelength
== biasLength
&& imagewidth
== biasWidth
) {
899 uint16 sampleBits
= 0;
900 biasFn
*subtractLine
;
901 TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &sampleBits
);
902 subtractLine
= lineSubtractFn (sampleBits
);
905 buf
= _TIFFmalloc(bufSize
);
906 biasBuf
= _TIFFmalloc(bufSize
);
907 for (row
= 0; row
< imagelength
; row
++) {
908 if (TIFFReadScanline(in
, buf
, row
, 0) < 0
910 TIFFError(TIFFFileName(in
),
911 "Error, can't read scanline %lu",
912 (unsigned long) row
);
915 if (TIFFReadScanline(bias
, biasBuf
, row
, 0) < 0
917 TIFFError(TIFFFileName(in
),
918 "Error, can't read biased scanline %lu",
919 (unsigned long) row
);
922 subtractLine (buf
, biasBuf
, imagewidth
);
923 if (TIFFWriteScanline(out
, buf
, row
, 0) < 0) {
924 TIFFError(TIFFFileName(out
),
925 "Error, can't write scanline %lu",
926 (unsigned long) row
);
933 TIFFSetDirectory(bias
,
934 TIFFCurrentDirectory(bias
)); /* rewind */
941 TIFFError(TIFFFileName(in
),
942 "No support for biasing %d bit pixels\n",
947 TIFFError(TIFFFileName(in
),
948 "Bias image %s,%d\nis not the same size as %s,%d\n",
949 TIFFFileName(bias
), TIFFCurrentDirectory(bias
),
950 TIFFFileName(in
), TIFFCurrentDirectory(in
));
953 TIFFError(TIFFFileName(in
),
954 "Can't bias %s,%d as it has >1 Sample/Pixel\n",
955 TIFFFileName(in
), TIFFCurrentDirectory(in
));
963 * Strip -> strip for change in encoding.
965 DECLAREcpFunc(cpDecodedStrips
)
967 tsize_t stripsize
= TIFFStripSize(in
);
968 tdata_t buf
= _TIFFmalloc(stripsize
);
970 (void) imagewidth
; (void) spp
;
972 tstrip_t s
, ns
= TIFFNumberOfStrips(in
);
974 _TIFFmemset(buf
, 0, stripsize
);
975 for (s
= 0; s
< ns
; s
++) {
976 tsize_t cc
= (row
+ rowsperstrip
> imagelength
) ?
977 TIFFVStripSize(in
, imagelength
- row
) : stripsize
;
978 if (TIFFReadEncodedStrip(in
, s
, buf
, cc
) < 0
980 TIFFError(TIFFFileName(in
),
981 "Error, can't read strip %lu",
985 if (TIFFWriteEncodedStrip(out
, s
, buf
, cc
) < 0) {
986 TIFFError(TIFFFileName(out
),
987 "Error, can't write strip %lu",
996 TIFFError(TIFFFileName(in
),
997 "Error, can't allocate memory buffer of size %lu "
998 "to read strips", (unsigned long) stripsize
);
1008 * Separate -> separate by row for rows/strip change.
1010 DECLAREcpFunc(cpSeparate2SeparateByRow
)
1012 tsize_t scanlinesize
= TIFFScanlineSize(in
);
1018 buf
= _TIFFmalloc(scanlinesize
);
1021 _TIFFmemset(buf
, 0, scanlinesize
);
1022 for (s
= 0; s
< spp
; s
++) {
1023 for (row
= 0; row
< imagelength
; row
++) {
1024 if (TIFFReadScanline(in
, buf
, row
, s
) < 0 && !ignore
) {
1025 TIFFError(TIFFFileName(in
),
1026 "Error, can't read scanline %lu",
1027 (unsigned long) row
);
1030 if (TIFFWriteScanline(out
, buf
, row
, s
) < 0) {
1031 TIFFError(TIFFFileName(out
),
1032 "Error, can't write scanline %lu",
1033 (unsigned long) row
);
1046 * Contig -> separate by row.
1048 DECLAREcpFunc(cpContig2SeparateByRow
)
1050 tsize_t scanlinesizein
= TIFFScanlineSize(in
);
1051 tsize_t scanlinesizeout
= TIFFScanlineSize(out
);
1054 register uint8
*inp
, *outp
;
1059 inbuf
= _TIFFmalloc(scanlinesizein
);
1060 outbuf
= _TIFFmalloc(scanlinesizeout
);
1061 if (!inbuf
|| !outbuf
)
1063 _TIFFmemset(inbuf
, 0, scanlinesizein
);
1064 _TIFFmemset(outbuf
, 0, scanlinesizeout
);
1065 /* unpack channels */
1066 for (s
= 0; s
< spp
; s
++) {
1067 for (row
= 0; row
< imagelength
; row
++) {
1068 if (TIFFReadScanline(in
, inbuf
, row
, 0) < 0
1070 TIFFError(TIFFFileName(in
),
1071 "Error, can't read scanline %lu",
1072 (unsigned long) row
);
1075 inp
= ((uint8
*)inbuf
) + s
;
1076 outp
= (uint8
*)outbuf
;
1077 for (n
= imagewidth
; n
-- > 0;) {
1081 if (TIFFWriteScanline(out
, outbuf
, row
, s
) < 0) {
1082 TIFFError(TIFFFileName(out
),
1083 "Error, can't write scanline %lu",
1084 (unsigned long) row
);
1089 if (inbuf
) _TIFFfree(inbuf
);
1090 if (outbuf
) _TIFFfree(outbuf
);
1093 if (inbuf
) _TIFFfree(inbuf
);
1094 if (outbuf
) _TIFFfree(outbuf
);
1099 * Separate -> contig by row.
1101 DECLAREcpFunc(cpSeparate2ContigByRow
)
1103 tsize_t scanlinesizein
= TIFFScanlineSize(in
);
1104 tsize_t scanlinesizeout
= TIFFScanlineSize(out
);
1107 register uint8
*inp
, *outp
;
1112 inbuf
= _TIFFmalloc(scanlinesizein
);
1113 outbuf
= _TIFFmalloc(scanlinesizeout
);
1114 if (!inbuf
|| !outbuf
)
1116 _TIFFmemset(inbuf
, 0, scanlinesizein
);
1117 _TIFFmemset(outbuf
, 0, scanlinesizeout
);
1118 for (row
= 0; row
< imagelength
; row
++) {
1119 /* merge channels */
1120 for (s
= 0; s
< spp
; s
++) {
1121 if (TIFFReadScanline(in
, inbuf
, row
, s
) < 0
1123 TIFFError(TIFFFileName(in
),
1124 "Error, can't read scanline %lu",
1125 (unsigned long) row
);
1128 inp
= (uint8
*)inbuf
;
1129 outp
= ((uint8
*)outbuf
) + s
;
1130 for (n
= imagewidth
; n
-- > 0;) {
1135 if (TIFFWriteScanline(out
, outbuf
, row
, 0) < 0) {
1136 TIFFError(TIFFFileName(out
),
1137 "Error, can't write scanline %lu",
1138 (unsigned long) row
);
1142 if (inbuf
) _TIFFfree(inbuf
);
1143 if (outbuf
) _TIFFfree(outbuf
);
1146 if (inbuf
) _TIFFfree(inbuf
);
1147 if (outbuf
) _TIFFfree(outbuf
);
1152 cpStripToTile(uint8
* out
, uint8
* in
,
1153 uint32 rows
, uint32 cols
, int outskew
, int inskew
)
1155 while (rows
-- > 0) {
1165 cpContigBufToSeparateBuf(uint8
* out
, uint8
* in
,
1166 uint32 rows
, uint32 cols
, int outskew
, int inskew
, tsample_t spp
,
1167 int bytes_per_sample
)
1169 while (rows
-- > 0) {
1173 int n
= bytes_per_sample
;
1178 in
+= (spp
-1) * bytes_per_sample
;
1186 cpSeparateBufToContigBuf(uint8
* out
, uint8
* in
,
1187 uint32 rows
, uint32 cols
, int outskew
, int inskew
, tsample_t spp
,
1188 int bytes_per_sample
)
1190 while (rows
-- > 0) {
1193 int n
= bytes_per_sample
;
1198 out
+= (spp
-1)*bytes_per_sample
;
1206 cpImage(TIFF
* in
, TIFF
* out
, readFunc fin
, writeFunc fout
,
1207 uint32 imagelength
, uint32 imagewidth
, tsample_t spp
)
1211 tsize_t scanlinesize
= TIFFRasterScanlineSize(in
);
1212 tsize_t bytes
= scanlinesize
* (tsize_t
)imagelength
;
1214 * XXX: Check for integer overflow.
1218 && bytes
/ (tsize_t
)imagelength
== scanlinesize
) {
1219 buf
= _TIFFmalloc(bytes
);
1221 if ((*fin
)(in
, (uint8
*)buf
, imagelength
,
1223 status
= (*fout
)(out
, (uint8
*)buf
,
1224 imagelength
, imagewidth
, spp
);
1228 TIFFError(TIFFFileName(in
),
1229 "Error, can't allocate space for image buffer");
1232 TIFFError(TIFFFileName(in
), "Error, no space for image buffer");
1238 DECLAREreadFunc(readContigStripsIntoBuffer
)
1240 tsize_t scanlinesize
= TIFFScanlineSize(in
);
1244 (void) imagewidth
; (void) spp
;
1245 for (row
= 0; row
< imagelength
; row
++) {
1246 if (TIFFReadScanline(in
, (tdata_t
) bufp
, row
, 0) < 0
1248 TIFFError(TIFFFileName(in
),
1249 "Error, can't read scanline %lu",
1250 (unsigned long) row
);
1253 bufp
+= scanlinesize
;
1259 DECLAREreadFunc(readSeparateStripsIntoBuffer
)
1262 tsize_t scanlinesize
= TIFFScanlineSize(in
);
1267 scanline
= _TIFFmalloc(scanlinesize
);
1270 _TIFFmemset(scanline
, 0, scanlinesize
);
1273 uint8
* bufp
= (uint8
*) buf
;
1276 for (row
= 0; row
< imagelength
; row
++) {
1277 /* merge channels */
1278 for (s
= 0; s
< spp
; s
++) {
1279 uint8
* bp
= bufp
+ s
;
1280 tsize_t n
= scanlinesize
;
1281 uint8
* sbuf
= scanline
;
1283 if (TIFFReadScanline(in
, scanline
, row
, s
) < 0
1285 TIFFError(TIFFFileName(in
),
1286 "Error, can't read scanline %lu",
1287 (unsigned long) row
);
1292 *bp
= *sbuf
++, bp
+= spp
;
1294 bufp
+= scanlinesize
* spp
;
1299 _TIFFfree(scanline
);
1303 DECLAREreadFunc(readContigTilesIntoBuffer
)
1306 tsize_t tilesize
= TIFFTileSize(in
);
1308 uint32 imagew
= TIFFScanlineSize(in
);
1309 uint32 tilew
= TIFFTileRowSize(in
);
1310 int iskew
= imagew
- tilew
;
1311 uint8
* bufp
= (uint8
*) buf
;
1316 tilebuf
= _TIFFmalloc(tilesize
);
1319 _TIFFmemset(tilebuf
, 0, tilesize
);
1320 (void) TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
);
1321 (void) TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
);
1323 for (row
= 0; row
< imagelength
; row
+= tl
) {
1324 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1328 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1329 if (TIFFReadTile(in
, tilebuf
, col
, row
, 0, 0) < 0
1331 TIFFError(TIFFFileName(in
),
1332 "Error, can't read tile at %lu %lu",
1333 (unsigned long) col
,
1334 (unsigned long) row
);
1338 if (colb
+ tilew
> imagew
) {
1339 uint32 width
= imagew
- colb
;
1340 uint32 oskew
= tilew
- width
;
1341 cpStripToTile(bufp
+ colb
,
1342 tilebuf
, nrow
, width
,
1343 oskew
+ iskew
, oskew
);
1345 cpStripToTile(bufp
+ colb
,
1346 tilebuf
, nrow
, tilew
,
1350 bufp
+= imagew
* nrow
;
1357 DECLAREreadFunc(readSeparateTilesIntoBuffer
)
1360 uint32 imagew
= TIFFRasterScanlineSize(in
);
1361 uint32 tilew
= TIFFTileRowSize(in
);
1362 int iskew
= imagew
- tilew
*spp
;
1363 tsize_t tilesize
= TIFFTileSize(in
);
1365 uint8
* bufp
= (uint8
*) buf
;
1368 uint16 bps
, bytes_per_sample
;
1370 tilebuf
= _TIFFmalloc(tilesize
);
1373 _TIFFmemset(tilebuf
, 0, tilesize
);
1374 (void) TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
);
1375 (void) TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
);
1376 (void) TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &bps
);
1377 assert( bps
% 8 == 0 );
1378 bytes_per_sample
= bps
/8;
1380 for (row
= 0; row
< imagelength
; row
+= tl
) {
1381 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1385 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1388 for (s
= 0; s
< spp
; s
++) {
1389 if (TIFFReadTile(in
, tilebuf
, col
, row
, 0, s
) < 0
1391 TIFFError(TIFFFileName(in
),
1392 "Error, can't read tile at %lu %lu, "
1394 (unsigned long) col
,
1395 (unsigned long) row
,
1401 * Tile is clipped horizontally. Calculate
1402 * visible portion and skewing factors.
1404 if (colb
+ tilew
*spp
> imagew
) {
1405 uint32 width
= imagew
- colb
;
1406 int oskew
= tilew
*spp
- width
;
1407 cpSeparateBufToContigBuf(
1408 bufp
+colb
+s
*bytes_per_sample
,
1410 width
/(spp
*bytes_per_sample
),
1415 cpSeparateBufToContigBuf(
1416 bufp
+colb
+s
*bytes_per_sample
,
1423 bufp
+= imagew
* nrow
;
1430 DECLAREwriteFunc(writeBufferToContigStrips
)
1432 uint32 row
, rowsperstrip
;
1435 (void) imagewidth
; (void) spp
;
1436 (void) TIFFGetFieldDefaulted(out
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
);
1437 for (row
= 0; row
< imagelength
; row
+= rowsperstrip
) {
1438 uint32 nrows
= (row
+rowsperstrip
> imagelength
) ?
1439 imagelength
-row
: rowsperstrip
;
1440 tsize_t stripsize
= TIFFVStripSize(out
, nrows
);
1441 if (TIFFWriteEncodedStrip(out
, strip
++, buf
, stripsize
) < 0) {
1442 TIFFError(TIFFFileName(out
),
1443 "Error, can't write strip %u", strip
- 1);
1451 DECLAREwriteFunc(writeBufferToSeparateStrips
)
1453 uint32 rowsize
= imagewidth
* spp
;
1454 uint32 rowsperstrip
;
1455 tsize_t stripsize
= TIFFStripSize(out
);
1460 obuf
= _TIFFmalloc(stripsize
);
1463 _TIFFmemset(obuf
, 0, stripsize
);
1464 (void) TIFFGetFieldDefaulted(out
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
);
1465 for (s
= 0; s
< spp
; s
++) {
1467 for (row
= 0; row
< imagelength
; row
+= rowsperstrip
) {
1468 uint32 nrows
= (row
+rowsperstrip
> imagelength
) ?
1469 imagelength
-row
: rowsperstrip
;
1470 tsize_t stripsize
= TIFFVStripSize(out
, nrows
);
1472 cpContigBufToSeparateBuf(
1473 obuf
, (uint8
*) buf
+ row
*rowsize
+ s
,
1474 nrows
, imagewidth
, 0, 0, spp
, 1);
1475 if (TIFFWriteEncodedStrip(out
, strip
++, obuf
, stripsize
) < 0) {
1476 TIFFError(TIFFFileName(out
),
1477 "Error, can't write strip %u",
1489 DECLAREwriteFunc(writeBufferToContigTiles
)
1491 uint32 imagew
= TIFFScanlineSize(out
);
1492 uint32 tilew
= TIFFTileRowSize(out
);
1493 int iskew
= imagew
- tilew
;
1494 tsize_t tilesize
= TIFFTileSize(out
);
1496 uint8
* bufp
= (uint8
*) buf
;
1502 obuf
= _TIFFmalloc(TIFFTileSize(out
));
1505 _TIFFmemset(obuf
, 0, tilesize
);
1506 (void) TIFFGetField(out
, TIFFTAG_TILELENGTH
, &tl
);
1507 (void) TIFFGetField(out
, TIFFTAG_TILEWIDTH
, &tw
);
1508 for (row
= 0; row
< imagelength
; row
+= tilelength
) {
1509 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1513 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1515 * Tile is clipped horizontally. Calculate
1516 * visible portion and skewing factors.
1518 if (colb
+ tilew
> imagew
) {
1519 uint32 width
= imagew
- colb
;
1520 int oskew
= tilew
- width
;
1521 cpStripToTile(obuf
, bufp
+ colb
, nrow
, width
,
1522 oskew
, oskew
+ iskew
);
1524 cpStripToTile(obuf
, bufp
+ colb
, nrow
, tilew
,
1526 if (TIFFWriteTile(out
, obuf
, col
, row
, 0, 0) < 0) {
1527 TIFFError(TIFFFileName(out
),
1528 "Error, can't write tile at %lu %lu",
1529 (unsigned long) col
,
1530 (unsigned long) row
);
1536 bufp
+= nrow
* imagew
;
1542 DECLAREwriteFunc(writeBufferToSeparateTiles
)
1544 uint32 imagew
= TIFFScanlineSize(out
);
1545 tsize_t tilew
= TIFFTileRowSize(out
);
1546 uint32 iimagew
= TIFFRasterScanlineSize(out
);
1547 int iskew
= iimagew
- tilew
*spp
;
1548 tsize_t tilesize
= TIFFTileSize(out
);
1550 uint8
* bufp
= (uint8
*) buf
;
1553 uint16 bps
, bytes_per_sample
;
1555 obuf
= _TIFFmalloc(TIFFTileSize(out
));
1558 _TIFFmemset(obuf
, 0, tilesize
);
1559 (void) TIFFGetField(out
, TIFFTAG_TILELENGTH
, &tl
);
1560 (void) TIFFGetField(out
, TIFFTAG_TILEWIDTH
, &tw
);
1561 (void) TIFFGetField(out
, TIFFTAG_BITSPERSAMPLE
, &bps
);
1562 assert( bps
% 8 == 0 );
1563 bytes_per_sample
= bps
/8;
1565 for (row
= 0; row
< imagelength
; row
+= tl
) {
1566 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1570 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1572 for (s
= 0; s
< spp
; s
++) {
1574 * Tile is clipped horizontally. Calculate
1575 * visible portion and skewing factors.
1577 if (colb
+ tilew
> imagew
) {
1578 uint32 width
= (imagew
- colb
);
1579 int oskew
= tilew
- width
;
1581 cpContigBufToSeparateBuf(obuf
,
1582 bufp
+ (colb
*spp
) + s
,
1583 nrow
, width
/bytes_per_sample
,
1584 oskew
, (oskew
*spp
)+iskew
, spp
,
1587 cpContigBufToSeparateBuf(obuf
,
1588 bufp
+ (colb
*spp
) + s
,
1592 if (TIFFWriteTile(out
, obuf
, col
, row
, 0, s
) < 0) {
1593 TIFFError(TIFFFileName(out
),
1594 "Error, can't write tile at %lu %lu "
1596 (unsigned long) col
,
1597 (unsigned long) row
,
1605 bufp
+= nrow
* iimagew
;
1612 * Contig strips -> contig tiles.
1614 DECLAREcpFunc(cpContigStrips2ContigTiles
)
1616 return cpImage(in
, out
,
1617 readContigStripsIntoBuffer
,
1618 writeBufferToContigTiles
,
1619 imagelength
, imagewidth
, spp
);
1623 * Contig strips -> separate tiles.
1625 DECLAREcpFunc(cpContigStrips2SeparateTiles
)
1627 return cpImage(in
, out
,
1628 readContigStripsIntoBuffer
,
1629 writeBufferToSeparateTiles
,
1630 imagelength
, imagewidth
, spp
);
1634 * Separate strips -> contig tiles.
1636 DECLAREcpFunc(cpSeparateStrips2ContigTiles
)
1638 return cpImage(in
, out
,
1639 readSeparateStripsIntoBuffer
,
1640 writeBufferToContigTiles
,
1641 imagelength
, imagewidth
, spp
);
1645 * Separate strips -> separate tiles.
1647 DECLAREcpFunc(cpSeparateStrips2SeparateTiles
)
1649 return cpImage(in
, out
,
1650 readSeparateStripsIntoBuffer
,
1651 writeBufferToSeparateTiles
,
1652 imagelength
, imagewidth
, spp
);
1656 * Contig strips -> contig tiles.
1658 DECLAREcpFunc(cpContigTiles2ContigTiles
)
1660 return cpImage(in
, out
,
1661 readContigTilesIntoBuffer
,
1662 writeBufferToContigTiles
,
1663 imagelength
, imagewidth
, spp
);
1667 * Contig tiles -> separate tiles.
1669 DECLAREcpFunc(cpContigTiles2SeparateTiles
)
1671 return cpImage(in
, out
,
1672 readContigTilesIntoBuffer
,
1673 writeBufferToSeparateTiles
,
1674 imagelength
, imagewidth
, spp
);
1678 * Separate tiles -> contig tiles.
1680 DECLAREcpFunc(cpSeparateTiles2ContigTiles
)
1682 return cpImage(in
, out
,
1683 readSeparateTilesIntoBuffer
,
1684 writeBufferToContigTiles
,
1685 imagelength
, imagewidth
, spp
);
1689 * Separate tiles -> separate tiles (tile dimension change).
1691 DECLAREcpFunc(cpSeparateTiles2SeparateTiles
)
1693 return cpImage(in
, out
,
1694 readSeparateTilesIntoBuffer
,
1695 writeBufferToSeparateTiles
,
1696 imagelength
, imagewidth
, spp
);
1700 * Contig tiles -> contig tiles (tile dimension change).
1702 DECLAREcpFunc(cpContigTiles2ContigStrips
)
1704 return cpImage(in
, out
,
1705 readContigTilesIntoBuffer
,
1706 writeBufferToContigStrips
,
1707 imagelength
, imagewidth
, spp
);
1711 * Contig tiles -> separate strips.
1713 DECLAREcpFunc(cpContigTiles2SeparateStrips
)
1715 return cpImage(in
, out
,
1716 readContigTilesIntoBuffer
,
1717 writeBufferToSeparateStrips
,
1718 imagelength
, imagewidth
, spp
);
1722 * Separate tiles -> contig strips.
1724 DECLAREcpFunc(cpSeparateTiles2ContigStrips
)
1726 return cpImage(in
, out
,
1727 readSeparateTilesIntoBuffer
,
1728 writeBufferToContigStrips
,
1729 imagelength
, imagewidth
, spp
);
1733 * Separate tiles -> separate strips.
1735 DECLAREcpFunc(cpSeparateTiles2SeparateStrips
)
1737 return cpImage(in
, out
,
1738 readSeparateTilesIntoBuffer
,
1739 writeBufferToSeparateStrips
,
1740 imagelength
, imagewidth
, spp
);
1744 * Select the appropriate copy function to use.
1747 pickCopyFunc(TIFF
* in
, TIFF
* out
, uint16 bitspersample
, uint16 samplesperpixel
)
1750 uint32 w
, l
, tw
, tl
;
1753 (void) TIFFGetField(in
, TIFFTAG_PLANARCONFIG
, &shortv
);
1754 if (shortv
!= config
&& bitspersample
!= 8 && samplesperpixel
> 1) {
1756 "%s: Cannot handle different planar configuration w/ bits/sample != 8\n",
1760 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &w
);
1761 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &l
);
1762 if (!(TIFFIsTiled(out
) || TIFFIsTiled(in
))) {
1763 uint32 irps
= (uint32
) -1L;
1764 TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
, &irps
);
1765 /* if biased, force decoded copying to allow image subtraction */
1766 bychunk
= !bias
&& (rowsperstrip
== irps
);
1767 }else{ /* either in or out is tiled */
1770 "%s: Cannot handle tiled configuration w/bias image\n",
1774 if (TIFFIsTiled(out
)) {
1775 if (!TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
))
1777 if (!TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
))
1779 bychunk
= (tw
== tilewidth
&& tl
== tilelength
);
1780 } else { /* out's not, so in must be tiled */
1781 TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
);
1782 TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
);
1783 bychunk
= (tw
== w
&& tl
== rowsperstrip
);
1788 #define pack(a,b,c,d,e) ((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
1789 switch(pack(shortv
,config
,TIFFIsTiled(in
),TIFFIsTiled(out
),bychunk
)) {
1790 /* Strips -> Tiles */
1791 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,T
,F
):
1792 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,T
,T
):
1793 return cpContigStrips2ContigTiles
;
1794 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,T
,F
):
1795 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,T
,T
):
1796 return cpContigStrips2SeparateTiles
;
1797 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,T
,F
):
1798 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,T
,T
):
1799 return cpSeparateStrips2ContigTiles
;
1800 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,T
,F
):
1801 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,T
,T
):
1802 return cpSeparateStrips2SeparateTiles
;
1803 /* Tiles -> Tiles */
1804 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,T
,F
):
1805 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,T
,T
):
1806 return cpContigTiles2ContigTiles
;
1807 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,T
,F
):
1808 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,T
,T
):
1809 return cpContigTiles2SeparateTiles
;
1810 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,T
,F
):
1811 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,T
,T
):
1812 return cpSeparateTiles2ContigTiles
;
1813 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,T
,F
):
1814 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,T
,T
):
1815 return cpSeparateTiles2SeparateTiles
;
1816 /* Tiles -> Strips */
1817 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,F
,F
):
1818 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,F
,T
):
1819 return cpContigTiles2ContigStrips
;
1820 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,F
,F
):
1821 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,F
,T
):
1822 return cpContigTiles2SeparateStrips
;
1823 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,F
,F
):
1824 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,F
,T
):
1825 return cpSeparateTiles2ContigStrips
;
1826 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,F
,F
):
1827 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,F
,T
):
1828 return cpSeparateTiles2SeparateStrips
;
1829 /* Strips -> Strips */
1830 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,F
,F
):
1831 return bias
? cpBiasedContig2Contig
: cpContig2ContigByRow
;
1832 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,F
,T
):
1833 return cpDecodedStrips
;
1834 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,F
,F
):
1835 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,F
,T
):
1836 return cpContig2SeparateByRow
;
1837 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,F
,F
):
1838 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,F
,T
):
1839 return cpSeparate2ContigByRow
;
1840 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,F
,F
):
1841 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,F
,T
):
1842 return cpSeparate2SeparateByRow
;
1847 fprintf(stderr
, "tiffcp: %s: Don't know how to copy/convert image.\n",
1852 /* vim: set ts=8 sts=8 sw=8 noet: */