4 * Copyright (c) 1988-1997 Sam Leffler
5 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
7 * Revised: 2/18/01 BAR -- added syntax for extracting single images from
8 * multi-image TIFF files.
10 * New syntax is: sourceFileName,image#
12 * image# ranges from 0..<n-1> where n is the # of images in the file.
13 * There may be no white space between the comma and the filename or
16 * Example: tiffcp source.tif,1 destination.tif
18 * Copies the 2nd image in source.tif to the destination.
21 * Permission to use, copy, modify, distribute, and sell this software and
22 * its documentation for any purpose is hereby granted without fee, provided
23 * that (i) the above copyright notices and this permission notice appear in
24 * all copies of the software and related documentation, and (ii) the names of
25 * Sam Leffler and Silicon Graphics may not be used in any advertising or
26 * publicity relating to the software without the specific, prior written
27 * permission of Sam Leffler and Silicon Graphics.
29 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
30 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
31 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
33 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
34 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
35 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
36 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
37 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
41 #include "tif_config.h"
57 extern int getopt(int, char**, char*);
61 # define unlink delete
64 #define streq(a,b) (strcmp(a,b) == 0)
65 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
70 static int outtiled
= -1;
71 static uint32 tilewidth
;
72 static uint32 tilelength
;
75 static uint16 compression
;
76 static uint16 predictor
;
78 static uint16 fillorder
;
79 static uint16 orientation
;
80 static uint32 rowsperstrip
;
82 static int ignore
= FALSE
; /* if true, ignore read errors */
83 static uint32 defg3opts
= (uint32
) -1;
84 static int quality
= 75; /* JPEG quality */
85 static int jpegcolormode
= JPEGCOLORMODE_RGB
;
86 static uint16 defcompression
= (uint16
) -1;
87 static uint16 defpredictor
= (uint16
) -1;
88 static int defpreset
= -1;
90 static int tiffcp(TIFF
*, TIFF
*);
91 static int processCompressOptions(char*);
92 static void usage(void);
94 static char comma
= ','; /* (default) comma separator character */
95 static TIFF
* bias
= NULL
;
96 static int pageNum
= 0;
97 static int pageInSeq
= 0;
99 static int nextSrcImage (TIFF
*tif
, char **imageSpec
)
101 seek to the next image specified in *imageSpec
102 returns 1 if success, 0 if no more images to process
103 *imageSpec=NULL if subsequent images should be processed in sequence
106 if (**imageSpec
== comma
) { /* if not @comma, we've done all images */
107 char *start
= *imageSpec
+ 1;
108 tdir_t nextImage
= (tdir_t
)strtol(start
, imageSpec
, 0);
109 if (start
== *imageSpec
) nextImage
= TIFFCurrentDirectory (tif
);
112 if (**imageSpec
== comma
) {
113 /* a trailing comma denotes remaining images in sequence */
114 if ((*imageSpec
)[1] == '\0') *imageSpec
= NULL
;
117 "Expected a %c separated image # list after %s\n",
118 comma
, TIFFFileName (tif
));
119 exit (-4); /* syntax error */
122 if (TIFFSetDirectory (tif
, nextImage
)) return 1;
123 fprintf (stderr
, "%s%c%d not found!\n",
124 TIFFFileName(tif
), comma
, (int) nextImage
);
130 static TIFF
* openSrcImage (char **imageSpec
)
132 imageSpec points to a pointer to a filename followed by optional ,image#'s
133 Open the TIFF file and assign *imageSpec to either NULL if there are
134 no images specified, or a pointer to the next image number text
138 char *fn
= *imageSpec
;
139 *imageSpec
= strchr (fn
, comma
);
140 if (*imageSpec
) { /* there is at least one image number specifier */
142 tif
= TIFFOpen (fn
, "r");
143 /* but, ignore any single trailing comma */
144 if (!(*imageSpec
)[1]) {*imageSpec
= NULL
; return tif
;}
146 **imageSpec
= comma
; /* replace the comma */
147 if (!nextSrcImage(tif
, imageSpec
)) {
153 tif
= TIFFOpen (fn
, "r");
158 main(int argc
, char* argv
[])
160 uint16 defconfig
= (uint16
) -1;
161 uint16 deffillorder
= 0;
162 uint32 deftilewidth
= (uint32
) -1;
163 uint32 deftilelength
= (uint32
) -1;
164 uint32 defrowsperstrip
= (uint32
) 0;
176 while ((c
= getopt(argc
, argv
, ",:b:c:f:l:o:z:p:r:w:aistBLMC8x")) != -1)
179 if (optarg
[0] != '=') usage();
182 case 'b': /* this file is bias image subtracted from others */
184 fputs ("Only 1 bias image may be specified\n", stderr
);
188 uint16 samples
= (uint16
) -1;
189 char **biasFn
= &optarg
;
190 bias
= openSrcImage (biasFn
);
191 if (!bias
) exit (-5);
192 if (TIFFIsTiled (bias
)) {
193 fputs ("Bias image must be organized in strips\n", stderr
);
196 TIFFGetField(bias
, TIFFTAG_SAMPLESPERPIXEL
, &samples
);
198 fputs ("Bias image must be monochrome\n", stderr
);
203 case 'a': /* append to output */
206 case 'c': /* compression scheme */
207 if (!processCompressOptions(optarg
))
210 case 'f': /* fill order */
211 if (streq(optarg
, "lsb2msb"))
212 deffillorder
= FILLORDER_LSB2MSB
;
213 else if (streq(optarg
, "msb2lsb"))
214 deffillorder
= FILLORDER_MSB2LSB
;
218 case 'i': /* ignore errors */
221 case 'l': /* tile length */
223 deftilelength
= atoi(optarg
);
225 case 'o': /* initial directory offset */
226 diroff
= strtoul(optarg
, NULL
, 0);
228 case 'p': /* planar configuration */
229 if (streq(optarg
, "separate"))
230 defconfig
= PLANARCONFIG_SEPARATE
;
231 else if (streq(optarg
, "contig"))
232 defconfig
= PLANARCONFIG_CONTIG
;
236 case 'r': /* rows/strip */
237 defrowsperstrip
= atol(optarg
);
239 case 's': /* generate stripped output */
242 case 't': /* generate tiled output */
245 case 'w': /* tile width */
247 deftilewidth
= atoi(optarg
);
250 *mp
++ = 'b'; *mp
= '\0';
253 *mp
++ = 'l'; *mp
= '\0';
256 *mp
++ = 'm'; *mp
= '\0';
259 *mp
++ = 'c'; *mp
= '\0';
262 *mp
++ = '8'; *mp
= '\0';
271 if (argc
- optind
< 2)
273 out
= TIFFOpen(argv
[argc
-1], mode
);
276 if ((argc
- optind
) == 2)
278 for (; optind
< argc
-1 ; optind
++) {
279 char *imageCursor
= argv
[optind
];
280 in
= openSrcImage (&imageCursor
);
282 (void) TIFFClose(out
);
285 if (diroff
!= 0 && !TIFFSetSubDirectory(in
, diroff
)) {
286 TIFFError(TIFFFileName(in
),
287 "Error, setting subdirectory at " TIFF_UINT64_FORMAT
, diroff
);
288 (void) TIFFClose(in
);
289 (void) TIFFClose(out
);
294 compression
= defcompression
;
295 predictor
= defpredictor
;
297 fillorder
= deffillorder
;
298 rowsperstrip
= defrowsperstrip
;
299 tilewidth
= deftilewidth
;
300 tilelength
= deftilelength
;
302 if (!tiffcp(in
, out
) || !TIFFWriteDirectory(out
)) {
303 (void) TIFFClose(in
);
304 (void) TIFFClose(out
);
307 if (imageCursor
) { /* seek next image directory */
308 if (!nextSrcImage(in
, &imageCursor
)) break;
310 if (!TIFFReadDirectory(in
)) break;
312 (void) TIFFClose(in
);
315 (void) TIFFClose(out
);
320 processZIPOptions(char* cp
)
322 if ( (cp
= strchr(cp
, ':')) ) {
325 if (isdigit((int)*cp
))
326 defpredictor
= atoi(cp
);
328 defpreset
= atoi(++cp
);
331 } while( (cp
= strchr(cp
, ':')) );
336 processG3Options(char* cp
)
338 if( (cp
= strchr(cp
, ':')) ) {
339 if (defg3opts
== (uint32
) -1)
343 if (strneq(cp
, "1d", 2))
344 defg3opts
&= ~GROUP3OPT_2DENCODING
;
345 else if (strneq(cp
, "2d", 2))
346 defg3opts
|= GROUP3OPT_2DENCODING
;
347 else if (strneq(cp
, "fill", 4))
348 defg3opts
|= GROUP3OPT_FILLBITS
;
351 } while( (cp
= strchr(cp
, ':')) );
356 processCompressOptions(char* opt
)
358 if (streq(opt
, "none")) {
359 defcompression
= COMPRESSION_NONE
;
360 } else if (streq(opt
, "packbits")) {
361 defcompression
= COMPRESSION_PACKBITS
;
362 } else if (strneq(opt
, "jpeg", 4)) {
363 char* cp
= strchr(opt
, ':');
365 defcompression
= COMPRESSION_JPEG
;
368 if (isdigit((int)cp
[1]))
369 quality
= atoi(cp
+1);
370 else if (cp
[1] == 'r' )
371 jpegcolormode
= JPEGCOLORMODE_RAW
;
375 cp
= strchr(cp
+1,':');
377 } else if (strneq(opt
, "g3", 2)) {
378 processG3Options(opt
);
379 defcompression
= COMPRESSION_CCITTFAX3
;
380 } else if (streq(opt
, "g4")) {
381 defcompression
= COMPRESSION_CCITTFAX4
;
382 } else if (strneq(opt
, "lzw", 3)) {
383 char* cp
= strchr(opt
, ':');
385 defpredictor
= atoi(cp
+1);
386 defcompression
= COMPRESSION_LZW
;
387 } else if (strneq(opt
, "zip", 3)) {
388 processZIPOptions(opt
);
389 defcompression
= COMPRESSION_ADOBE_DEFLATE
;
390 } else if (strneq(opt
, "lzma", 4)) {
391 processZIPOptions(opt
);
392 defcompression
= COMPRESSION_LZMA
;
393 } else if (strneq(opt
, "jbig", 4)) {
394 defcompression
= COMPRESSION_JBIG
;
395 } else if (strneq(opt
, "sgilog", 6)) {
396 defcompression
= COMPRESSION_SGILOG
;
403 "usage: tiffcp [options] input... output",
404 "where options are:",
405 " -a append to output instead of overwriting",
406 " -o offset set initial directory offset",
407 " -p contig pack samples contiguously (e.g. RGBRGB...)",
408 " -p separate store samples separately (e.g. RRR...GGG...BBB...)",
409 " -s write output in strips",
410 " -t write output in tiles",
411 " -8 write BigTIFF instead of default ClassicTIFF",
412 " -i ignore read errors",
413 " -b file[,#] bias (dark) monochrome image to be subtracted from all others",
414 " -,=% use % rather than , to separate image #'s (per Note below)",
416 " -r # make each strip have no more than # rows",
417 " -w # set output tile width (pixels)",
418 " -l # set output tile length (pixels)",
420 " -f lsb2msb force lsb-to-msb FillOrder for output",
421 " -f msb2lsb force msb-to-lsb FillOrder for output",
423 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
424 " -c zip[:opts] compress output with deflate encoding",
425 " -c lzma[:opts] compress output with LZMA2 encoding",
426 " -c jpeg[:opts] compress output with JPEG encoding",
427 " -c jbig compress output with ISO JBIG encoding",
428 " -c packbits compress output with packbits encoding",
429 " -c g3[:opts] compress output with CCITT Group 3 encoding",
430 " -c g4 compress output with CCITT Group 4 encoding",
431 " -c sgilog compress output with SGILOG encoding",
432 " -c none use no compression algorithm on output",
433 " -x force the merged tiff pages in sequence",
436 " 1d use default CCITT Group 3 1D-encoding",
437 " 2d use optional CCITT Group 3 2D-encoding",
438 " fill byte-align EOL codes",
439 "For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
442 " # set compression quality level (0-100, default 75)",
443 " r output color image as RGB rather than YCbCr",
444 "For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
446 "LZW, Deflate (ZIP) and LZMA2 options:",
447 " # set predictor value",
448 " p# set compression level (preset)",
449 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing,",
450 "-c zip:3:p9 for Deflate encoding with maximum compression level and floating",
453 "Note that input filenames may be of the form filename,x,y,z",
454 "where x, y, and z specify image numbers in the filename to copy.",
455 "example: tiffcp -c none -b esp.tif,1 esp.tif,0 test.tif",
456 " subtract 2nd image in esp.tif from 1st yielding uncompressed result test.tif",
467 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
468 for (i
= 0; stuff
[i
] != NULL
; i
++)
469 fprintf(stderr
, "%s\n", stuff
[i
]);
473 #define CopyField(tag, v) \
474 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
475 #define CopyField2(tag, v1, v2) \
476 if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
477 #define CopyField3(tag, v1, v2, v3) \
478 if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
479 #define CopyField4(tag, v1, v2, v3, v4) \
480 if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
483 cpTag(TIFF
* in
, TIFF
* out
, uint16 tag
, uint16 count
, TIFFDataType type
)
489 CopyField(tag
, shortv
);
490 } else if (count
== 2) {
491 uint16 shortv1
, shortv2
;
492 CopyField2(tag
, shortv1
, shortv2
);
493 } else if (count
== 4) {
494 uint16
*tr
, *tg
, *tb
, *ta
;
495 CopyField4(tag
, tr
, tg
, tb
, ta
);
496 } else if (count
== (uint16
) -1) {
499 CopyField2(tag
, shortv1
, shortav
);
504 CopyField(tag
, longv
);
510 CopyField(tag
, floatv
);
511 } else if (count
== (uint16
) -1) {
513 CopyField(tag
, floatav
);
518 CopyField(tag
, stringv
);
524 CopyField(tag
, doublev
);
525 } else if (count
== (uint16
) -1) {
527 CopyField(tag
, doubleav
);
531 TIFFError(TIFFFileName(in
),
532 "Data type %d is not supported, tag %d skipped.",
537 static struct cpTag
{
542 { TIFFTAG_SUBFILETYPE
, 1, TIFF_LONG
},
543 { TIFFTAG_THRESHHOLDING
, 1, TIFF_SHORT
},
544 { TIFFTAG_DOCUMENTNAME
, 1, TIFF_ASCII
},
545 { TIFFTAG_IMAGEDESCRIPTION
, 1, TIFF_ASCII
},
546 { TIFFTAG_MAKE
, 1, TIFF_ASCII
},
547 { TIFFTAG_MODEL
, 1, TIFF_ASCII
},
548 { TIFFTAG_MINSAMPLEVALUE
, 1, TIFF_SHORT
},
549 { TIFFTAG_MAXSAMPLEVALUE
, 1, TIFF_SHORT
},
550 { TIFFTAG_XRESOLUTION
, 1, TIFF_RATIONAL
},
551 { TIFFTAG_YRESOLUTION
, 1, TIFF_RATIONAL
},
552 { TIFFTAG_PAGENAME
, 1, TIFF_ASCII
},
553 { TIFFTAG_XPOSITION
, 1, TIFF_RATIONAL
},
554 { TIFFTAG_YPOSITION
, 1, TIFF_RATIONAL
},
555 { TIFFTAG_RESOLUTIONUNIT
, 1, TIFF_SHORT
},
556 { TIFFTAG_SOFTWARE
, 1, TIFF_ASCII
},
557 { TIFFTAG_DATETIME
, 1, TIFF_ASCII
},
558 { TIFFTAG_ARTIST
, 1, TIFF_ASCII
},
559 { TIFFTAG_HOSTCOMPUTER
, 1, TIFF_ASCII
},
560 { TIFFTAG_WHITEPOINT
, (uint16
) -1, TIFF_RATIONAL
},
561 { TIFFTAG_PRIMARYCHROMATICITIES
,(uint16
) -1,TIFF_RATIONAL
},
562 { TIFFTAG_HALFTONEHINTS
, 2, TIFF_SHORT
},
563 { TIFFTAG_INKSET
, 1, TIFF_SHORT
},
564 { TIFFTAG_DOTRANGE
, 2, TIFF_SHORT
},
565 { TIFFTAG_TARGETPRINTER
, 1, TIFF_ASCII
},
566 { TIFFTAG_SAMPLEFORMAT
, 1, TIFF_SHORT
},
567 { TIFFTAG_YCBCRCOEFFICIENTS
, (uint16
) -1,TIFF_RATIONAL
},
568 { TIFFTAG_YCBCRSUBSAMPLING
, 2, TIFF_SHORT
},
569 { TIFFTAG_YCBCRPOSITIONING
, 1, TIFF_SHORT
},
570 { TIFFTAG_REFERENCEBLACKWHITE
, (uint16
) -1,TIFF_RATIONAL
},
571 { TIFFTAG_EXTRASAMPLES
, (uint16
) -1, TIFF_SHORT
},
572 { TIFFTAG_SMINSAMPLEVALUE
, 1, TIFF_DOUBLE
},
573 { TIFFTAG_SMAXSAMPLEVALUE
, 1, TIFF_DOUBLE
},
574 { TIFFTAG_STONITS
, 1, TIFF_DOUBLE
},
576 #define NTAGS (sizeof (tags) / sizeof (tags[0]))
578 #define CopyTag(tag, count, type) cpTag(in, out, tag, count, type)
580 typedef int (*copyFunc
)
581 (TIFF
* in
, TIFF
* out
, uint32 l
, uint32 w
, uint16 samplesperpixel
);
582 static copyFunc
pickCopyFunc(TIFF
*, TIFF
*, uint16
, uint16
);
587 tiffcp(TIFF
* in
, TIFF
* out
)
589 uint16 bitspersample
, samplesperpixel
;
590 uint16 input_compression
, input_photometric
;
592 uint32 width
, length
;
595 CopyField(TIFFTAG_IMAGEWIDTH
, width
);
596 CopyField(TIFFTAG_IMAGELENGTH
, length
);
597 CopyField(TIFFTAG_BITSPERSAMPLE
, bitspersample
);
598 CopyField(TIFFTAG_SAMPLESPERPIXEL
, samplesperpixel
);
599 if (compression
!= (uint16
)-1)
600 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
602 CopyField(TIFFTAG_COMPRESSION
, compression
);
603 TIFFGetFieldDefaulted(in
, TIFFTAG_COMPRESSION
, &input_compression
);
604 TIFFGetFieldDefaulted(in
, TIFFTAG_PHOTOMETRIC
, &input_photometric
);
605 if (input_compression
== COMPRESSION_JPEG
) {
606 /* Force conversion to RGB */
607 TIFFSetField(in
, TIFFTAG_JPEGCOLORMODE
, JPEGCOLORMODE_RGB
);
608 } else if (input_photometric
== PHOTOMETRIC_YCBCR
) {
609 /* Otherwise, can't handle subsampled input */
610 uint16 subsamplinghor
,subsamplingver
;
612 TIFFGetFieldDefaulted(in
, TIFFTAG_YCBCRSUBSAMPLING
,
613 &subsamplinghor
, &subsamplingver
);
614 if (subsamplinghor
!=1 || subsamplingver
!=1) {
615 fprintf(stderr
, "tiffcp: %s: Can't copy/convert subsampled image.\n",
620 if (compression
== COMPRESSION_JPEG
) {
621 if (input_photometric
== PHOTOMETRIC_RGB
&&
622 jpegcolormode
== JPEGCOLORMODE_RGB
)
623 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, PHOTOMETRIC_YCBCR
);
625 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, input_photometric
);
627 else if (compression
== COMPRESSION_SGILOG
628 || compression
== COMPRESSION_SGILOG24
)
629 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
,
630 samplesperpixel
== 1 ?
631 PHOTOMETRIC_LOGL
: PHOTOMETRIC_LOGLUV
);
633 CopyTag(TIFFTAG_PHOTOMETRIC
, 1, TIFF_SHORT
);
635 TIFFSetField(out
, TIFFTAG_FILLORDER
, fillorder
);
637 CopyTag(TIFFTAG_FILLORDER
, 1, TIFF_SHORT
);
639 * Will copy `Orientation' tag from input image
641 TIFFGetFieldDefaulted(in
, TIFFTAG_ORIENTATION
, &orientation
);
642 switch (orientation
) {
643 case ORIENTATION_BOTRIGHT
:
644 case ORIENTATION_RIGHTBOT
: /* XXX */
645 TIFFWarning(TIFFFileName(in
), "using bottom-left orientation");
646 orientation
= ORIENTATION_BOTLEFT
;
648 case ORIENTATION_LEFTBOT
: /* XXX */
649 case ORIENTATION_BOTLEFT
:
651 case ORIENTATION_TOPRIGHT
:
652 case ORIENTATION_RIGHTTOP
: /* XXX */
654 TIFFWarning(TIFFFileName(in
), "using top-left orientation");
655 orientation
= ORIENTATION_TOPLEFT
;
657 case ORIENTATION_LEFTTOP
: /* XXX */
658 case ORIENTATION_TOPLEFT
:
661 TIFFSetField(out
, TIFFTAG_ORIENTATION
, orientation
);
663 * Choose tiles/strip for the output image according to
664 * the command line arguments (-tiles, -strips) and the
665 * structure of the input image.
668 outtiled
= TIFFIsTiled(in
);
671 * Setup output file's tile width&height. If either
672 * is not specified, use either the value from the
673 * input image or, if nothing is defined, use the
676 if (tilewidth
== (uint32
) -1)
677 TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tilewidth
);
678 if (tilelength
== (uint32
) -1)
679 TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tilelength
);
680 TIFFDefaultTileSize(out
, &tilewidth
, &tilelength
);
681 TIFFSetField(out
, TIFFTAG_TILEWIDTH
, tilewidth
);
682 TIFFSetField(out
, TIFFTAG_TILELENGTH
, tilelength
);
685 * RowsPerStrip is left unspecified: use either the
686 * value from the input image or, if nothing is defined,
687 * use the library default.
689 if (rowsperstrip
== (uint32
) 0) {
690 if (!TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
,
693 TIFFDefaultStripSize(out
, rowsperstrip
);
695 if (rowsperstrip
> length
&& rowsperstrip
!= (uint32
)-1)
696 rowsperstrip
= length
;
698 else if (rowsperstrip
== (uint32
) -1)
699 rowsperstrip
= length
;
700 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
);
702 if (config
!= (uint16
) -1)
703 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, config
);
705 CopyField(TIFFTAG_PLANARCONFIG
, config
);
706 if (samplesperpixel
<= 4)
707 CopyTag(TIFFTAG_TRANSFERFUNCTION
, 4, TIFF_SHORT
);
708 CopyTag(TIFFTAG_COLORMAP
, 4, TIFF_SHORT
);
709 /* SMinSampleValue & SMaxSampleValue */
710 switch (compression
) {
711 case COMPRESSION_JPEG
:
712 TIFFSetField(out
, TIFFTAG_JPEGQUALITY
, quality
);
713 TIFFSetField(out
, TIFFTAG_JPEGCOLORMODE
, jpegcolormode
);
715 case COMPRESSION_JBIG
:
716 CopyTag(TIFFTAG_FAXRECVPARAMS
, 1, TIFF_LONG
);
717 CopyTag(TIFFTAG_FAXRECVTIME
, 1, TIFF_LONG
);
718 CopyTag(TIFFTAG_FAXSUBADDRESS
, 1, TIFF_ASCII
);
719 CopyTag(TIFFTAG_FAXDCS
, 1, TIFF_ASCII
);
721 case COMPRESSION_LZW
:
722 case COMPRESSION_ADOBE_DEFLATE
:
723 case COMPRESSION_DEFLATE
:
724 case COMPRESSION_LZMA
:
725 if (predictor
!= (uint16
)-1)
726 TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
);
728 CopyField(TIFFTAG_PREDICTOR
, predictor
);
730 if (compression
== COMPRESSION_ADOBE_DEFLATE
731 || compression
== COMPRESSION_DEFLATE
)
732 TIFFSetField(out
, TIFFTAG_ZIPQUALITY
, preset
);
733 else if (compression
== COMPRESSION_LZMA
)
734 TIFFSetField(out
, TIFFTAG_LZMAPRESET
, preset
);
737 case COMPRESSION_CCITTFAX3
:
738 case COMPRESSION_CCITTFAX4
:
739 if (compression
== COMPRESSION_CCITTFAX3
) {
740 if (g3opts
!= (uint32
) -1)
741 TIFFSetField(out
, TIFFTAG_GROUP3OPTIONS
,
744 CopyField(TIFFTAG_GROUP3OPTIONS
, g3opts
);
746 CopyTag(TIFFTAG_GROUP4OPTIONS
, 1, TIFF_LONG
);
747 CopyTag(TIFFTAG_BADFAXLINES
, 1, TIFF_LONG
);
748 CopyTag(TIFFTAG_CLEANFAXDATA
, 1, TIFF_LONG
);
749 CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES
, 1, TIFF_LONG
);
750 CopyTag(TIFFTAG_FAXRECVPARAMS
, 1, TIFF_LONG
);
751 CopyTag(TIFFTAG_FAXRECVTIME
, 1, TIFF_LONG
);
752 CopyTag(TIFFTAG_FAXSUBADDRESS
, 1, TIFF_ASCII
);
758 if (TIFFGetField(in
, TIFFTAG_ICCPROFILE
, &len32
, &data
))
759 TIFFSetField(out
, TIFFTAG_ICCPROFILE
, len32
, data
);
763 const char* inknames
;
764 if (TIFFGetField(in
, TIFFTAG_NUMBEROFINKS
, &ninks
)) {
765 TIFFSetField(out
, TIFFTAG_NUMBEROFINKS
, ninks
);
766 if (TIFFGetField(in
, TIFFTAG_INKNAMES
, &inknames
)) {
767 int inknameslen
= strlen(inknames
) + 1;
768 const char* cp
= inknames
;
770 cp
= strchr(cp
, '\0');
772 inknameslen
+= (strlen(cp
) + 1);
775 TIFFSetField(out
, TIFFTAG_INKNAMES
, inknameslen
, inknames
);
780 unsigned short pg0
, pg1
;
782 if (pageInSeq
== 1) {
783 if (pageNum
< 0) /* only one input file */ {
784 if (TIFFGetField(in
, TIFFTAG_PAGENUMBER
, &pg0
, &pg1
))
785 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pg0
, pg1
);
787 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pageNum
++, 0);
790 if (TIFFGetField(in
, TIFFTAG_PAGENUMBER
, &pg0
, &pg1
)) {
791 if (pageNum
< 0) /* only one input file */
792 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pg0
, pg1
);
794 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pageNum
++, 0);
799 for (p
= tags
; p
< &tags
[NTAGS
]; p
++)
800 CopyTag(p
->tag
, p
->count
, p
->type
);
802 cf
= pickCopyFunc(in
, out
, bitspersample
, samplesperpixel
);
803 return (cf
? (*cf
)(in
, out
, length
, width
, samplesperpixel
) : FALSE
);
809 #define DECLAREcpFunc(x) \
810 static int x(TIFF* in, TIFF* out, \
811 uint32 imagelength, uint32 imagewidth, tsample_t spp)
813 #define DECLAREreadFunc(x) \
814 static int x(TIFF* in, \
815 uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
816 typedef int (*readFunc
)(TIFF
*, uint8
*, uint32
, uint32
, tsample_t
);
818 #define DECLAREwriteFunc(x) \
819 static int x(TIFF* out, \
820 uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
821 typedef int (*writeFunc
)(TIFF
*, uint8
*, uint32
, uint32
, tsample_t
);
824 * Contig -> contig by scanline for rows/strip change.
826 DECLAREcpFunc(cpContig2ContigByRow
)
828 tsize_t scanlinesize
= TIFFScanlineSize(in
);
832 buf
= _TIFFmalloc(scanlinesize
);
835 _TIFFmemset(buf
, 0, scanlinesize
);
836 (void) imagewidth
; (void) spp
;
837 for (row
= 0; row
< imagelength
; row
++) {
838 if (TIFFReadScanline(in
, buf
, row
, 0) < 0 && !ignore
) {
839 TIFFError(TIFFFileName(in
),
840 "Error, can't read scanline %lu",
841 (unsigned long) row
);
844 if (TIFFWriteScanline(out
, buf
, row
, 0) < 0) {
845 TIFFError(TIFFFileName(out
),
846 "Error, can't write scanline %lu",
847 (unsigned long) row
);
859 typedef void biasFn (void *image
, void *bias
, uint32 pixels
);
861 #define subtract(bits) \
862 static void subtract##bits (void *i, void *b, uint32 pixels)\
864 uint##bits *image = i;\
865 uint##bits *bias = b;\
867 *image = *image > *bias ? *image-*bias : 0;\
876 static biasFn
*lineSubtractFn (unsigned bits
)
879 case 8: return subtract8
;
880 case 16: return subtract16
;
881 case 32: return subtract32
;
887 * Contig -> contig by scanline while subtracting a bias image.
889 DECLAREcpFunc(cpBiasedContig2Contig
)
892 tsize_t biasSize
= TIFFScanlineSize(bias
);
893 tsize_t bufSize
= TIFFScanlineSize(in
);
894 tdata_t buf
, biasBuf
;
895 uint32 biasWidth
= 0, biasLength
= 0;
896 TIFFGetField(bias
, TIFFTAG_IMAGEWIDTH
, &biasWidth
);
897 TIFFGetField(bias
, TIFFTAG_IMAGELENGTH
, &biasLength
);
898 if (biasSize
== bufSize
&&
899 imagelength
== biasLength
&& imagewidth
== biasWidth
) {
900 uint16 sampleBits
= 0;
901 biasFn
*subtractLine
;
902 TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &sampleBits
);
903 subtractLine
= lineSubtractFn (sampleBits
);
906 buf
= _TIFFmalloc(bufSize
);
907 biasBuf
= _TIFFmalloc(bufSize
);
908 for (row
= 0; row
< imagelength
; row
++) {
909 if (TIFFReadScanline(in
, buf
, row
, 0) < 0
911 TIFFError(TIFFFileName(in
),
912 "Error, can't read scanline %lu",
913 (unsigned long) row
);
916 if (TIFFReadScanline(bias
, biasBuf
, row
, 0) < 0
918 TIFFError(TIFFFileName(in
),
919 "Error, can't read biased scanline %lu",
920 (unsigned long) row
);
923 subtractLine (buf
, biasBuf
, imagewidth
);
924 if (TIFFWriteScanline(out
, buf
, row
, 0) < 0) {
925 TIFFError(TIFFFileName(out
),
926 "Error, can't write scanline %lu",
927 (unsigned long) row
);
934 TIFFSetDirectory(bias
,
935 TIFFCurrentDirectory(bias
)); /* rewind */
942 TIFFError(TIFFFileName(in
),
943 "No support for biasing %d bit pixels\n",
948 TIFFError(TIFFFileName(in
),
949 "Bias image %s,%d\nis not the same size as %s,%d\n",
950 TIFFFileName(bias
), TIFFCurrentDirectory(bias
),
951 TIFFFileName(in
), TIFFCurrentDirectory(in
));
954 TIFFError(TIFFFileName(in
),
955 "Can't bias %s,%d as it has >1 Sample/Pixel\n",
956 TIFFFileName(in
), TIFFCurrentDirectory(in
));
964 * Strip -> strip for change in encoding.
966 DECLAREcpFunc(cpDecodedStrips
)
968 tsize_t stripsize
= TIFFStripSize(in
);
969 tdata_t buf
= _TIFFmalloc(stripsize
);
971 (void) imagewidth
; (void) spp
;
973 tstrip_t s
, ns
= TIFFNumberOfStrips(in
);
975 _TIFFmemset(buf
, 0, stripsize
);
976 for (s
= 0; s
< ns
; s
++) {
977 tsize_t cc
= (row
+ rowsperstrip
> imagelength
) ?
978 TIFFVStripSize(in
, imagelength
- row
) : stripsize
;
979 if (TIFFReadEncodedStrip(in
, s
, buf
, cc
) < 0
981 TIFFError(TIFFFileName(in
),
982 "Error, can't read strip %lu",
986 if (TIFFWriteEncodedStrip(out
, s
, buf
, cc
) < 0) {
987 TIFFError(TIFFFileName(out
),
988 "Error, can't write strip %lu",
997 TIFFError(TIFFFileName(in
),
998 "Error, can't allocate memory buffer of size %lu "
999 "to read strips", (unsigned long) stripsize
);
1009 * Separate -> separate by row for rows/strip change.
1011 DECLAREcpFunc(cpSeparate2SeparateByRow
)
1013 tsize_t scanlinesize
= TIFFScanlineSize(in
);
1019 buf
= _TIFFmalloc(scanlinesize
);
1022 _TIFFmemset(buf
, 0, scanlinesize
);
1023 for (s
= 0; s
< spp
; s
++) {
1024 for (row
= 0; row
< imagelength
; row
++) {
1025 if (TIFFReadScanline(in
, buf
, row
, s
) < 0 && !ignore
) {
1026 TIFFError(TIFFFileName(in
),
1027 "Error, can't read scanline %lu",
1028 (unsigned long) row
);
1031 if (TIFFWriteScanline(out
, buf
, row
, s
) < 0) {
1032 TIFFError(TIFFFileName(out
),
1033 "Error, can't write scanline %lu",
1034 (unsigned long) row
);
1047 * Contig -> separate by row.
1049 DECLAREcpFunc(cpContig2SeparateByRow
)
1051 tsize_t scanlinesizein
= TIFFScanlineSize(in
);
1052 tsize_t scanlinesizeout
= TIFFScanlineSize(out
);
1055 register uint8
*inp
, *outp
;
1060 inbuf
= _TIFFmalloc(scanlinesizein
);
1061 outbuf
= _TIFFmalloc(scanlinesizeout
);
1062 if (!inbuf
|| !outbuf
)
1064 _TIFFmemset(inbuf
, 0, scanlinesizein
);
1065 _TIFFmemset(outbuf
, 0, scanlinesizeout
);
1066 /* unpack channels */
1067 for (s
= 0; s
< spp
; s
++) {
1068 for (row
= 0; row
< imagelength
; row
++) {
1069 if (TIFFReadScanline(in
, inbuf
, row
, 0) < 0
1071 TIFFError(TIFFFileName(in
),
1072 "Error, can't read scanline %lu",
1073 (unsigned long) row
);
1076 inp
= ((uint8
*)inbuf
) + s
;
1077 outp
= (uint8
*)outbuf
;
1078 for (n
= imagewidth
; n
-- > 0;) {
1082 if (TIFFWriteScanline(out
, outbuf
, row
, s
) < 0) {
1083 TIFFError(TIFFFileName(out
),
1084 "Error, can't write scanline %lu",
1085 (unsigned long) row
);
1090 if (inbuf
) _TIFFfree(inbuf
);
1091 if (outbuf
) _TIFFfree(outbuf
);
1094 if (inbuf
) _TIFFfree(inbuf
);
1095 if (outbuf
) _TIFFfree(outbuf
);
1100 * Separate -> contig by row.
1102 DECLAREcpFunc(cpSeparate2ContigByRow
)
1104 tsize_t scanlinesizein
= TIFFScanlineSize(in
);
1105 tsize_t scanlinesizeout
= TIFFScanlineSize(out
);
1108 register uint8
*inp
, *outp
;
1113 inbuf
= _TIFFmalloc(scanlinesizein
);
1114 outbuf
= _TIFFmalloc(scanlinesizeout
);
1115 if (!inbuf
|| !outbuf
)
1117 _TIFFmemset(inbuf
, 0, scanlinesizein
);
1118 _TIFFmemset(outbuf
, 0, scanlinesizeout
);
1119 for (row
= 0; row
< imagelength
; row
++) {
1120 /* merge channels */
1121 for (s
= 0; s
< spp
; s
++) {
1122 if (TIFFReadScanline(in
, inbuf
, row
, s
) < 0
1124 TIFFError(TIFFFileName(in
),
1125 "Error, can't read scanline %lu",
1126 (unsigned long) row
);
1129 inp
= (uint8
*)inbuf
;
1130 outp
= ((uint8
*)outbuf
) + s
;
1131 for (n
= imagewidth
; n
-- > 0;) {
1136 if (TIFFWriteScanline(out
, outbuf
, row
, 0) < 0) {
1137 TIFFError(TIFFFileName(out
),
1138 "Error, can't write scanline %lu",
1139 (unsigned long) row
);
1143 if (inbuf
) _TIFFfree(inbuf
);
1144 if (outbuf
) _TIFFfree(outbuf
);
1147 if (inbuf
) _TIFFfree(inbuf
);
1148 if (outbuf
) _TIFFfree(outbuf
);
1153 cpStripToTile(uint8
* out
, uint8
* in
,
1154 uint32 rows
, uint32 cols
, int outskew
, int inskew
)
1156 while (rows
-- > 0) {
1166 cpContigBufToSeparateBuf(uint8
* out
, uint8
* in
,
1167 uint32 rows
, uint32 cols
, int outskew
, int inskew
, tsample_t spp
,
1168 int bytes_per_sample
)
1170 while (rows
-- > 0) {
1174 int n
= bytes_per_sample
;
1179 in
+= (spp
-1) * bytes_per_sample
;
1187 cpSeparateBufToContigBuf(uint8
* out
, uint8
* in
,
1188 uint32 rows
, uint32 cols
, int outskew
, int inskew
, tsample_t spp
,
1189 int bytes_per_sample
)
1191 while (rows
-- > 0) {
1194 int n
= bytes_per_sample
;
1199 out
+= (spp
-1)*bytes_per_sample
;
1207 cpImage(TIFF
* in
, TIFF
* out
, readFunc fin
, writeFunc fout
,
1208 uint32 imagelength
, uint32 imagewidth
, tsample_t spp
)
1212 tsize_t scanlinesize
= TIFFRasterScanlineSize(in
);
1213 tsize_t bytes
= scanlinesize
* (tsize_t
)imagelength
;
1215 * XXX: Check for integer overflow.
1219 && bytes
/ (tsize_t
)imagelength
== scanlinesize
) {
1220 buf
= _TIFFmalloc(bytes
);
1222 if ((*fin
)(in
, (uint8
*)buf
, imagelength
,
1224 status
= (*fout
)(out
, (uint8
*)buf
,
1225 imagelength
, imagewidth
, spp
);
1229 TIFFError(TIFFFileName(in
),
1230 "Error, can't allocate space for image buffer");
1233 TIFFError(TIFFFileName(in
), "Error, no space for image buffer");
1239 DECLAREreadFunc(readContigStripsIntoBuffer
)
1241 tsize_t scanlinesize
= TIFFScanlineSize(in
);
1245 (void) imagewidth
; (void) spp
;
1246 for (row
= 0; row
< imagelength
; row
++) {
1247 if (TIFFReadScanline(in
, (tdata_t
) bufp
, row
, 0) < 0
1249 TIFFError(TIFFFileName(in
),
1250 "Error, can't read scanline %lu",
1251 (unsigned long) row
);
1254 bufp
+= scanlinesize
;
1260 DECLAREreadFunc(readSeparateStripsIntoBuffer
)
1263 tsize_t scanlinesize
= TIFFScanlineSize(in
);
1268 scanline
= _TIFFmalloc(scanlinesize
);
1271 _TIFFmemset(scanline
, 0, scanlinesize
);
1274 uint8
* bufp
= (uint8
*) buf
;
1277 for (row
= 0; row
< imagelength
; row
++) {
1278 /* merge channels */
1279 for (s
= 0; s
< spp
; s
++) {
1280 uint8
* bp
= bufp
+ s
;
1281 tsize_t n
= scanlinesize
;
1282 uint8
* sbuf
= scanline
;
1284 if (TIFFReadScanline(in
, scanline
, row
, s
) < 0
1286 TIFFError(TIFFFileName(in
),
1287 "Error, can't read scanline %lu",
1288 (unsigned long) row
);
1293 *bp
= *sbuf
++, bp
+= spp
;
1295 bufp
+= scanlinesize
* spp
;
1300 _TIFFfree(scanline
);
1304 DECLAREreadFunc(readContigTilesIntoBuffer
)
1307 tsize_t tilesize
= TIFFTileSize(in
);
1309 uint32 imagew
= TIFFScanlineSize(in
);
1310 uint32 tilew
= TIFFTileRowSize(in
);
1311 int iskew
= imagew
- tilew
;
1312 uint8
* bufp
= (uint8
*) buf
;
1317 tilebuf
= _TIFFmalloc(tilesize
);
1320 _TIFFmemset(tilebuf
, 0, tilesize
);
1321 (void) TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
);
1322 (void) TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
);
1324 for (row
= 0; row
< imagelength
; row
+= tl
) {
1325 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1329 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1330 if (TIFFReadTile(in
, tilebuf
, col
, row
, 0, 0) < 0
1332 TIFFError(TIFFFileName(in
),
1333 "Error, can't read tile at %lu %lu",
1334 (unsigned long) col
,
1335 (unsigned long) row
);
1339 if (colb
+ tilew
> imagew
) {
1340 uint32 width
= imagew
- colb
;
1341 uint32 oskew
= tilew
- width
;
1342 cpStripToTile(bufp
+ colb
,
1343 tilebuf
, nrow
, width
,
1344 oskew
+ iskew
, oskew
);
1346 cpStripToTile(bufp
+ colb
,
1347 tilebuf
, nrow
, tilew
,
1351 bufp
+= imagew
* nrow
;
1358 DECLAREreadFunc(readSeparateTilesIntoBuffer
)
1361 uint32 imagew
= TIFFRasterScanlineSize(in
);
1362 uint32 tilew
= TIFFTileRowSize(in
);
1363 int iskew
= imagew
- tilew
*spp
;
1364 tsize_t tilesize
= TIFFTileSize(in
);
1366 uint8
* bufp
= (uint8
*) buf
;
1369 uint16 bps
, bytes_per_sample
;
1371 tilebuf
= _TIFFmalloc(tilesize
);
1374 _TIFFmemset(tilebuf
, 0, tilesize
);
1375 (void) TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
);
1376 (void) TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
);
1377 (void) TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &bps
);
1378 assert( bps
% 8 == 0 );
1379 bytes_per_sample
= bps
/8;
1381 for (row
= 0; row
< imagelength
; row
+= tl
) {
1382 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1386 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1389 for (s
= 0; s
< spp
; s
++) {
1390 if (TIFFReadTile(in
, tilebuf
, col
, row
, 0, s
) < 0
1392 TIFFError(TIFFFileName(in
),
1393 "Error, can't read tile at %lu %lu, "
1395 (unsigned long) col
,
1396 (unsigned long) row
,
1402 * Tile is clipped horizontally. Calculate
1403 * visible portion and skewing factors.
1405 if (colb
+ tilew
*spp
> imagew
) {
1406 uint32 width
= imagew
- colb
;
1407 int oskew
= tilew
*spp
- width
;
1408 cpSeparateBufToContigBuf(
1409 bufp
+colb
+s
*bytes_per_sample
,
1411 width
/(spp
*bytes_per_sample
),
1416 cpSeparateBufToContigBuf(
1417 bufp
+colb
+s
*bytes_per_sample
,
1424 bufp
+= imagew
* nrow
;
1431 DECLAREwriteFunc(writeBufferToContigStrips
)
1433 uint32 row
, rowsperstrip
;
1436 (void) imagewidth
; (void) spp
;
1437 (void) TIFFGetFieldDefaulted(out
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
);
1438 for (row
= 0; row
< imagelength
; row
+= rowsperstrip
) {
1439 uint32 nrows
= (row
+rowsperstrip
> imagelength
) ?
1440 imagelength
-row
: rowsperstrip
;
1441 tsize_t stripsize
= TIFFVStripSize(out
, nrows
);
1442 if (TIFFWriteEncodedStrip(out
, strip
++, buf
, stripsize
) < 0) {
1443 TIFFError(TIFFFileName(out
),
1444 "Error, can't write strip %u", strip
- 1);
1452 DECLAREwriteFunc(writeBufferToSeparateStrips
)
1454 uint32 rowsize
= imagewidth
* spp
;
1455 uint32 rowsperstrip
;
1456 tsize_t stripsize
= TIFFStripSize(out
);
1461 obuf
= _TIFFmalloc(stripsize
);
1464 _TIFFmemset(obuf
, 0, stripsize
);
1465 (void) TIFFGetFieldDefaulted(out
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
);
1466 for (s
= 0; s
< spp
; s
++) {
1468 for (row
= 0; row
< imagelength
; row
+= rowsperstrip
) {
1469 uint32 nrows
= (row
+rowsperstrip
> imagelength
) ?
1470 imagelength
-row
: rowsperstrip
;
1471 tsize_t stripsize
= TIFFVStripSize(out
, nrows
);
1473 cpContigBufToSeparateBuf(
1474 obuf
, (uint8
*) buf
+ row
*rowsize
+ s
,
1475 nrows
, imagewidth
, 0, 0, spp
, 1);
1476 if (TIFFWriteEncodedStrip(out
, strip
++, obuf
, stripsize
) < 0) {
1477 TIFFError(TIFFFileName(out
),
1478 "Error, can't write strip %u",
1490 DECLAREwriteFunc(writeBufferToContigTiles
)
1492 uint32 imagew
= TIFFScanlineSize(out
);
1493 uint32 tilew
= TIFFTileRowSize(out
);
1494 int iskew
= imagew
- tilew
;
1495 tsize_t tilesize
= TIFFTileSize(out
);
1497 uint8
* bufp
= (uint8
*) buf
;
1503 obuf
= _TIFFmalloc(TIFFTileSize(out
));
1506 _TIFFmemset(obuf
, 0, tilesize
);
1507 (void) TIFFGetField(out
, TIFFTAG_TILELENGTH
, &tl
);
1508 (void) TIFFGetField(out
, TIFFTAG_TILEWIDTH
, &tw
);
1509 for (row
= 0; row
< imagelength
; row
+= tilelength
) {
1510 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1514 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1516 * Tile is clipped horizontally. Calculate
1517 * visible portion and skewing factors.
1519 if (colb
+ tilew
> imagew
) {
1520 uint32 width
= imagew
- colb
;
1521 int oskew
= tilew
- width
;
1522 cpStripToTile(obuf
, bufp
+ colb
, nrow
, width
,
1523 oskew
, oskew
+ iskew
);
1525 cpStripToTile(obuf
, bufp
+ colb
, nrow
, tilew
,
1527 if (TIFFWriteTile(out
, obuf
, col
, row
, 0, 0) < 0) {
1528 TIFFError(TIFFFileName(out
),
1529 "Error, can't write tile at %lu %lu",
1530 (unsigned long) col
,
1531 (unsigned long) row
);
1537 bufp
+= nrow
* imagew
;
1543 DECLAREwriteFunc(writeBufferToSeparateTiles
)
1545 uint32 imagew
= TIFFScanlineSize(out
);
1546 tsize_t tilew
= TIFFTileRowSize(out
);
1547 uint32 iimagew
= TIFFRasterScanlineSize(out
);
1548 int iskew
= iimagew
- tilew
*spp
;
1549 tsize_t tilesize
= TIFFTileSize(out
);
1551 uint8
* bufp
= (uint8
*) buf
;
1554 uint16 bps
, bytes_per_sample
;
1556 obuf
= _TIFFmalloc(TIFFTileSize(out
));
1559 _TIFFmemset(obuf
, 0, tilesize
);
1560 (void) TIFFGetField(out
, TIFFTAG_TILELENGTH
, &tl
);
1561 (void) TIFFGetField(out
, TIFFTAG_TILEWIDTH
, &tw
);
1562 (void) TIFFGetField(out
, TIFFTAG_BITSPERSAMPLE
, &bps
);
1563 assert( bps
% 8 == 0 );
1564 bytes_per_sample
= bps
/8;
1566 for (row
= 0; row
< imagelength
; row
+= tl
) {
1567 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1571 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1573 for (s
= 0; s
< spp
; s
++) {
1575 * Tile is clipped horizontally. Calculate
1576 * visible portion and skewing factors.
1578 if (colb
+ tilew
> imagew
) {
1579 uint32 width
= (imagew
- colb
);
1580 int oskew
= tilew
- width
;
1582 cpContigBufToSeparateBuf(obuf
,
1583 bufp
+ (colb
*spp
) + s
,
1584 nrow
, width
/bytes_per_sample
,
1585 oskew
, (oskew
*spp
)+iskew
, spp
,
1588 cpContigBufToSeparateBuf(obuf
,
1589 bufp
+ (colb
*spp
) + s
,
1593 if (TIFFWriteTile(out
, obuf
, col
, row
, 0, s
) < 0) {
1594 TIFFError(TIFFFileName(out
),
1595 "Error, can't write tile at %lu %lu "
1597 (unsigned long) col
,
1598 (unsigned long) row
,
1606 bufp
+= nrow
* iimagew
;
1613 * Contig strips -> contig tiles.
1615 DECLAREcpFunc(cpContigStrips2ContigTiles
)
1617 return cpImage(in
, out
,
1618 readContigStripsIntoBuffer
,
1619 writeBufferToContigTiles
,
1620 imagelength
, imagewidth
, spp
);
1624 * Contig strips -> separate tiles.
1626 DECLAREcpFunc(cpContigStrips2SeparateTiles
)
1628 return cpImage(in
, out
,
1629 readContigStripsIntoBuffer
,
1630 writeBufferToSeparateTiles
,
1631 imagelength
, imagewidth
, spp
);
1635 * Separate strips -> contig tiles.
1637 DECLAREcpFunc(cpSeparateStrips2ContigTiles
)
1639 return cpImage(in
, out
,
1640 readSeparateStripsIntoBuffer
,
1641 writeBufferToContigTiles
,
1642 imagelength
, imagewidth
, spp
);
1646 * Separate strips -> separate tiles.
1648 DECLAREcpFunc(cpSeparateStrips2SeparateTiles
)
1650 return cpImage(in
, out
,
1651 readSeparateStripsIntoBuffer
,
1652 writeBufferToSeparateTiles
,
1653 imagelength
, imagewidth
, spp
);
1657 * Contig strips -> contig tiles.
1659 DECLAREcpFunc(cpContigTiles2ContigTiles
)
1661 return cpImage(in
, out
,
1662 readContigTilesIntoBuffer
,
1663 writeBufferToContigTiles
,
1664 imagelength
, imagewidth
, spp
);
1668 * Contig tiles -> separate tiles.
1670 DECLAREcpFunc(cpContigTiles2SeparateTiles
)
1672 return cpImage(in
, out
,
1673 readContigTilesIntoBuffer
,
1674 writeBufferToSeparateTiles
,
1675 imagelength
, imagewidth
, spp
);
1679 * Separate tiles -> contig tiles.
1681 DECLAREcpFunc(cpSeparateTiles2ContigTiles
)
1683 return cpImage(in
, out
,
1684 readSeparateTilesIntoBuffer
,
1685 writeBufferToContigTiles
,
1686 imagelength
, imagewidth
, spp
);
1690 * Separate tiles -> separate tiles (tile dimension change).
1692 DECLAREcpFunc(cpSeparateTiles2SeparateTiles
)
1694 return cpImage(in
, out
,
1695 readSeparateTilesIntoBuffer
,
1696 writeBufferToSeparateTiles
,
1697 imagelength
, imagewidth
, spp
);
1701 * Contig tiles -> contig tiles (tile dimension change).
1703 DECLAREcpFunc(cpContigTiles2ContigStrips
)
1705 return cpImage(in
, out
,
1706 readContigTilesIntoBuffer
,
1707 writeBufferToContigStrips
,
1708 imagelength
, imagewidth
, spp
);
1712 * Contig tiles -> separate strips.
1714 DECLAREcpFunc(cpContigTiles2SeparateStrips
)
1716 return cpImage(in
, out
,
1717 readContigTilesIntoBuffer
,
1718 writeBufferToSeparateStrips
,
1719 imagelength
, imagewidth
, spp
);
1723 * Separate tiles -> contig strips.
1725 DECLAREcpFunc(cpSeparateTiles2ContigStrips
)
1727 return cpImage(in
, out
,
1728 readSeparateTilesIntoBuffer
,
1729 writeBufferToContigStrips
,
1730 imagelength
, imagewidth
, spp
);
1734 * Separate tiles -> separate strips.
1736 DECLAREcpFunc(cpSeparateTiles2SeparateStrips
)
1738 return cpImage(in
, out
,
1739 readSeparateTilesIntoBuffer
,
1740 writeBufferToSeparateStrips
,
1741 imagelength
, imagewidth
, spp
);
1745 * Select the appropriate copy function to use.
1748 pickCopyFunc(TIFF
* in
, TIFF
* out
, uint16 bitspersample
, uint16 samplesperpixel
)
1751 uint32 w
, l
, tw
, tl
;
1754 (void) TIFFGetField(in
, TIFFTAG_PLANARCONFIG
, &shortv
);
1755 if (shortv
!= config
&& bitspersample
!= 8 && samplesperpixel
> 1) {
1757 "%s: Cannot handle different planar configuration w/ bits/sample != 8\n",
1761 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &w
);
1762 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &l
);
1763 if (!(TIFFIsTiled(out
) || TIFFIsTiled(in
))) {
1764 uint32 irps
= (uint32
) -1L;
1765 TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
, &irps
);
1766 /* if biased, force decoded copying to allow image subtraction */
1767 bychunk
= !bias
&& (rowsperstrip
== irps
);
1768 }else{ /* either in or out is tiled */
1771 "%s: Cannot handle tiled configuration w/bias image\n",
1775 if (TIFFIsTiled(out
)) {
1776 if (!TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
))
1778 if (!TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
))
1780 bychunk
= (tw
== tilewidth
&& tl
== tilelength
);
1781 } else { /* out's not, so in must be tiled */
1782 TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
);
1783 TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
);
1784 bychunk
= (tw
== w
&& tl
== rowsperstrip
);
1789 #define pack(a,b,c,d,e) ((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
1790 switch(pack(shortv
,config
,TIFFIsTiled(in
),TIFFIsTiled(out
),bychunk
)) {
1791 /* Strips -> Tiles */
1792 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,T
,F
):
1793 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,T
,T
):
1794 return cpContigStrips2ContigTiles
;
1795 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,T
,F
):
1796 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,T
,T
):
1797 return cpContigStrips2SeparateTiles
;
1798 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,T
,F
):
1799 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,T
,T
):
1800 return cpSeparateStrips2ContigTiles
;
1801 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,T
,F
):
1802 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,T
,T
):
1803 return cpSeparateStrips2SeparateTiles
;
1804 /* Tiles -> Tiles */
1805 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,T
,F
):
1806 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,T
,T
):
1807 return cpContigTiles2ContigTiles
;
1808 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,T
,F
):
1809 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,T
,T
):
1810 return cpContigTiles2SeparateTiles
;
1811 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,T
,F
):
1812 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,T
,T
):
1813 return cpSeparateTiles2ContigTiles
;
1814 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,T
,F
):
1815 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,T
,T
):
1816 return cpSeparateTiles2SeparateTiles
;
1817 /* Tiles -> Strips */
1818 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,F
,F
):
1819 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,F
,T
):
1820 return cpContigTiles2ContigStrips
;
1821 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,F
,F
):
1822 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,F
,T
):
1823 return cpContigTiles2SeparateStrips
;
1824 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,F
,F
):
1825 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,F
,T
):
1826 return cpSeparateTiles2ContigStrips
;
1827 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,F
,F
):
1828 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,F
,T
):
1829 return cpSeparateTiles2SeparateStrips
;
1830 /* Strips -> Strips */
1831 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,F
,F
):
1832 return bias
? cpBiasedContig2Contig
: cpContig2ContigByRow
;
1833 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,F
,T
):
1834 return cpDecodedStrips
;
1835 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,F
,F
):
1836 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,F
,T
):
1837 return cpContig2SeparateByRow
;
1838 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,F
,F
):
1839 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,F
,T
):
1840 return cpSeparate2ContigByRow
;
1841 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,F
,F
):
1842 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,F
,T
):
1843 return cpSeparate2SeparateByRow
;
1848 fprintf(stderr
, "tiffcp: %s: Don't know how to copy/convert image.\n",
1853 /* vim: set ts=8 sts=8 sw=8 noet: */