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"
60 #define streq(a,b) (strcmp(a,b) == 0)
61 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
66 static int outtiled
= -1;
67 static uint32 tilewidth
;
68 static uint32 tilelength
;
71 static uint16 compression
;
72 static uint16 predictor
;
73 static uint16 fillorder
;
74 static uint16 orientation
;
75 static uint32 rowsperstrip
;
77 static int ignore
= FALSE
; /* if true, ignore read errors */
78 static uint32 defg3opts
= (uint32
) -1;
79 static int quality
= 75; /* JPEG quality */
80 static int jpegcolormode
= JPEGCOLORMODE_RGB
;
81 static uint16 defcompression
= (uint16
) -1;
82 static uint16 defpredictor
= (uint16
) -1;
84 static int tiffcp(TIFF
*, TIFF
*);
85 static int processCompressOptions(char*);
86 static void usage(void);
88 static char comma
= ','; /* (default) comma separator character */
89 static TIFF
* bias
= NULL
;
90 static int pageNum
= 0;
92 static int nextSrcImage (TIFF
*tif
, char **imageSpec
)
94 seek to the next image specified in *imageSpec
95 returns 1 if success, 0 if no more images to process
96 *imageSpec=NULL if subsequent images should be processed in sequence
99 if (**imageSpec
== comma
) { /* if not @comma, we've done all images */
100 char *start
= *imageSpec
+ 1;
101 tdir_t nextImage
= (tdir_t
)strtol(start
, imageSpec
, 0);
102 if (start
== *imageSpec
) nextImage
= TIFFCurrentDirectory (tif
);
105 if (**imageSpec
== comma
) {
106 /* a trailing comma denotes remaining images in sequence */
107 if ((*imageSpec
)[1] == '\0') *imageSpec
= NULL
;
110 "Expected a %c separated image # list after %s\n",
111 comma
, TIFFFileName (tif
));
112 exit (-4); /* syntax error */
115 if (TIFFSetDirectory (tif
, nextImage
)) return 1;
116 fprintf (stderr
, "%s%c%d not found!\n",
117 TIFFFileName(tif
), comma
, (int) nextImage
);
123 static TIFF
* openSrcImage (char **imageSpec
)
125 imageSpec points to a pointer to a filename followed by optional ,image#'s
126 Open the TIFF file and assign *imageSpec to either NULL if there are
127 no images specified, or a pointer to the next image number text
131 char *fn
= *imageSpec
;
132 *imageSpec
= strchr (fn
, comma
);
133 if (*imageSpec
) { /* there is at least one image number specifier */
135 tif
= TIFFOpen (fn
, "r");
136 /* but, ignore any single trailing comma */
137 if (!(*imageSpec
)[1]) {*imageSpec
= NULL
; return tif
;}
139 **imageSpec
= comma
; /* replace the comma */
140 if (!nextSrcImage(tif
, imageSpec
)) {
146 tif
= TIFFOpen (fn
, "r");
152 main(int argc
, char* argv
[])
154 uint16 defconfig
= (uint16
) -1;
155 uint16 deffillorder
= 0;
156 uint32 deftilewidth
= (uint32
) -1;
157 uint32 deftilelength
= (uint32
) -1;
158 uint32 defrowsperstrip
= (uint32
) 0;
170 while ((c
= getopt(argc
, argv
, ",:b:c:f:l:o:z:p:r:w:aistBLMC")) != -1)
173 if (optarg
[0] != '=') usage();
176 case 'b': /* this file is bias image subtracted from others */
178 fputs ("Only 1 bias image may be specified\n", stderr
);
182 uint16 samples
= (uint16
) -1;
183 char **biasFn
= &optarg
;
184 bias
= openSrcImage (biasFn
);
185 if (!bias
) exit (-5);
186 if (TIFFIsTiled (bias
)) {
187 fputs ("Bias image must be organized in strips\n", stderr
);
190 TIFFGetField(bias
, TIFFTAG_SAMPLESPERPIXEL
, &samples
);
192 fputs ("Bias image must be monochrome\n", stderr
);
197 case 'a': /* append to output */
200 case 'c': /* compression scheme */
201 if (!processCompressOptions(optarg
))
204 case 'f': /* fill order */
205 if (streq(optarg
, "lsb2msb"))
206 deffillorder
= FILLORDER_LSB2MSB
;
207 else if (streq(optarg
, "msb2lsb"))
208 deffillorder
= FILLORDER_MSB2LSB
;
212 case 'i': /* ignore errors */
215 case 'l': /* tile length */
217 deftilelength
= atoi(optarg
);
219 case 'o': /* initial directory offset */
220 diroff
= strtoul(optarg
, NULL
, 0);
222 case 'p': /* planar configuration */
223 if (streq(optarg
, "separate"))
224 defconfig
= PLANARCONFIG_SEPARATE
;
225 else if (streq(optarg
, "contig"))
226 defconfig
= PLANARCONFIG_CONTIG
;
230 case 'r': /* rows/strip */
231 defrowsperstrip
= atol(optarg
);
233 case 's': /* generate stripped output */
236 case 't': /* generate tiled output */
239 case 'w': /* tile width */
241 deftilewidth
= atoi(optarg
);
244 *mp
++ = 'b'; *mp
= '\0';
247 *mp
++ = 'l'; *mp
= '\0';
250 *mp
++ = 'm'; *mp
= '\0';
253 *mp
++ = 'c'; *mp
= '\0';
259 if (argc
- optind
< 2)
261 out
= TIFFOpen(argv
[argc
-1], mode
);
264 if ((argc
- optind
) == 2)
266 for (; optind
< argc
-1 ; optind
++) {
267 char *imageCursor
= argv
[optind
];
268 in
= openSrcImage (&imageCursor
);
271 if (diroff
!= 0 && !TIFFSetSubDirectory(in
, diroff
)) {
272 TIFFError(TIFFFileName(in
),
273 "Error, setting subdirectory at %#x", diroff
);
274 (void) TIFFClose(out
);
279 compression
= defcompression
;
280 predictor
= defpredictor
;
281 fillorder
= deffillorder
;
282 rowsperstrip
= defrowsperstrip
;
283 tilewidth
= deftilewidth
;
284 tilelength
= deftilelength
;
286 if (!tiffcp(in
, out
) || !TIFFWriteDirectory(out
)) {
290 if (imageCursor
) { /* seek next image directory */
291 if (!nextSrcImage(in
, &imageCursor
)) break;
293 if (!TIFFReadDirectory(in
)) break;
304 processG3Options(char* cp
)
306 if( (cp
= strchr(cp
, ':')) ) {
307 if (defg3opts
== (uint32
) -1)
311 if (strneq(cp
, "1d", 2))
312 defg3opts
&= ~GROUP3OPT_2DENCODING
;
313 else if (strneq(cp
, "2d", 2))
314 defg3opts
|= GROUP3OPT_2DENCODING
;
315 else if (strneq(cp
, "fill", 4))
316 defg3opts
|= GROUP3OPT_FILLBITS
;
319 } while( (cp
= strchr(cp
, ':')) );
324 processCompressOptions(char* opt
)
326 if (streq(opt
, "none")) {
327 defcompression
= COMPRESSION_NONE
;
328 } else if (streq(opt
, "packbits")) {
329 defcompression
= COMPRESSION_PACKBITS
;
330 } else if (strneq(opt
, "jpeg", 4)) {
331 char* cp
= strchr(opt
, ':');
333 defcompression
= COMPRESSION_JPEG
;
336 if (isdigit((int)cp
[1]))
337 quality
= atoi(cp
+1);
338 else if (cp
[1] == 'r' )
339 jpegcolormode
= JPEGCOLORMODE_RAW
;
343 cp
= strchr(cp
+1,':');
345 } else if (strneq(opt
, "g3", 2)) {
346 processG3Options(opt
);
347 defcompression
= COMPRESSION_CCITTFAX3
;
348 } else if (streq(opt
, "g4")) {
349 defcompression
= COMPRESSION_CCITTFAX4
;
350 } else if (strneq(opt
, "lzw", 3)) {
351 char* cp
= strchr(opt
, ':');
353 defpredictor
= atoi(cp
+1);
354 defcompression
= COMPRESSION_LZW
;
355 } else if (strneq(opt
, "zip", 3)) {
356 char* cp
= strchr(opt
, ':');
358 defpredictor
= atoi(cp
+1);
359 defcompression
= COMPRESSION_ADOBE_DEFLATE
;
366 "usage: tiffcp [options] input... output",
367 "where options are:",
368 " -a append to output instead of overwriting",
369 " -o offset set initial directory offset",
370 " -p contig pack samples contiguously (e.g. RGBRGB...)",
371 " -p separate store samples separately (e.g. RRR...GGG...BBB...)",
372 " -s write output in strips",
373 " -t write output in tiles",
374 " -i ignore read errors",
375 " -b file[,#] bias (dark) monochrome image to be subtracted from all others",
376 " -,=% use % rather than , to separate image #'s (per Note below)",
378 " -r # make each strip have no more than # rows",
379 " -w # set output tile width (pixels)",
380 " -l # set output tile length (pixels)",
382 " -f lsb2msb force lsb-to-msb FillOrder for output",
383 " -f msb2lsb force msb-to-lsb FillOrder for output",
385 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
386 " -c zip[:opts] compress output with deflate encoding",
387 " -c jpeg[:opts] compress output with JPEG encoding",
388 " -c packbits compress output with packbits encoding",
389 " -c g3[:opts] compress output with CCITT Group 3 encoding",
390 " -c g4 compress output with CCITT Group 4 encoding",
391 " -c none use no compression algorithm on output",
394 " 1d use default CCITT Group 3 1D-encoding",
395 " 2d use optional CCITT Group 3 2D-encoding",
396 " fill byte-align EOL codes",
397 "For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
400 " # set compression quality level (0-100, default 75)",
401 " r output color image as RGB rather than YCbCr",
402 "For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
404 "LZW and deflate options:",
405 " # set predictor value",
406 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
408 "Note that input filenames may be of the form filename,x,y,z",
409 "where x, y, and z specify image numbers in the filename to copy.",
410 "example: tiffcp -c none -b esp.tif,1 esp.tif,0 test.tif",
411 " subtract 2nd image in esp.tif from 1st yielding uncompressed result test.tif",
422 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
423 for (i
= 0; stuff
[i
] != NULL
; i
++)
424 fprintf(stderr
, "%s\n", stuff
[i
]);
428 #define CopyField(tag, v) \
429 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
430 #define CopyField2(tag, v1, v2) \
431 if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
432 #define CopyField3(tag, v1, v2, v3) \
433 if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
434 #define CopyField4(tag, v1, v2, v3, v4) \
435 if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
438 cpTag(TIFF
* in
, TIFF
* out
, uint16 tag
, uint16 count
, TIFFDataType type
)
444 CopyField(tag
, shortv
);
445 } else if (count
== 2) {
446 uint16 shortv1
, shortv2
;
447 CopyField2(tag
, shortv1
, shortv2
);
448 } else if (count
== 4) {
449 uint16
*tr
, *tg
, *tb
, *ta
;
450 CopyField4(tag
, tr
, tg
, tb
, ta
);
451 } else if (count
== (uint16
) -1) {
454 CopyField2(tag
, shortv1
, shortav
);
459 CopyField(tag
, longv
);
465 CopyField(tag
, floatv
);
466 } else if (count
== (uint16
) -1) {
468 CopyField(tag
, floatav
);
473 CopyField(tag
, stringv
);
479 CopyField(tag
, doublev
);
480 } else if (count
== (uint16
) -1) {
482 CopyField(tag
, doubleav
);
486 TIFFError(TIFFFileName(in
),
487 "Data type %d is not supported, tag %d skipped.",
492 static struct cpTag
{
497 { TIFFTAG_SUBFILETYPE
, 1, TIFF_LONG
},
498 { TIFFTAG_THRESHHOLDING
, 1, TIFF_SHORT
},
499 { TIFFTAG_DOCUMENTNAME
, 1, TIFF_ASCII
},
500 { TIFFTAG_IMAGEDESCRIPTION
, 1, TIFF_ASCII
},
501 { TIFFTAG_MAKE
, 1, TIFF_ASCII
},
502 { TIFFTAG_MODEL
, 1, TIFF_ASCII
},
503 { TIFFTAG_MINSAMPLEVALUE
, 1, TIFF_SHORT
},
504 { TIFFTAG_MAXSAMPLEVALUE
, 1, TIFF_SHORT
},
505 { TIFFTAG_XRESOLUTION
, 1, TIFF_RATIONAL
},
506 { TIFFTAG_YRESOLUTION
, 1, TIFF_RATIONAL
},
507 { TIFFTAG_PAGENAME
, 1, TIFF_ASCII
},
508 { TIFFTAG_XPOSITION
, 1, TIFF_RATIONAL
},
509 { TIFFTAG_YPOSITION
, 1, TIFF_RATIONAL
},
510 { TIFFTAG_RESOLUTIONUNIT
, 1, TIFF_SHORT
},
511 { TIFFTAG_SOFTWARE
, 1, TIFF_ASCII
},
512 { TIFFTAG_DATETIME
, 1, TIFF_ASCII
},
513 { TIFFTAG_ARTIST
, 1, TIFF_ASCII
},
514 { TIFFTAG_HOSTCOMPUTER
, 1, TIFF_ASCII
},
515 { TIFFTAG_WHITEPOINT
, (uint16
) -1, TIFF_RATIONAL
},
516 { TIFFTAG_PRIMARYCHROMATICITIES
,(uint16
) -1,TIFF_RATIONAL
},
517 { TIFFTAG_HALFTONEHINTS
, 2, TIFF_SHORT
},
518 { TIFFTAG_INKSET
, 1, TIFF_SHORT
},
519 { TIFFTAG_DOTRANGE
, 2, TIFF_SHORT
},
520 { TIFFTAG_TARGETPRINTER
, 1, TIFF_ASCII
},
521 { TIFFTAG_SAMPLEFORMAT
, 1, TIFF_SHORT
},
522 { TIFFTAG_YCBCRCOEFFICIENTS
, (uint16
) -1,TIFF_RATIONAL
},
523 { TIFFTAG_YCBCRSUBSAMPLING
, 2, TIFF_SHORT
},
524 { TIFFTAG_YCBCRPOSITIONING
, 1, TIFF_SHORT
},
525 { TIFFTAG_REFERENCEBLACKWHITE
, (uint16
) -1,TIFF_RATIONAL
},
526 { TIFFTAG_EXTRASAMPLES
, (uint16
) -1, TIFF_SHORT
},
527 { TIFFTAG_SMINSAMPLEVALUE
, 1, TIFF_DOUBLE
},
528 { TIFFTAG_SMAXSAMPLEVALUE
, 1, TIFF_DOUBLE
},
529 { TIFFTAG_STONITS
, 1, TIFF_DOUBLE
},
531 #define NTAGS (sizeof (tags) / sizeof (tags[0]))
533 #define CopyTag(tag, count, type) cpTag(in, out, tag, count, type)
535 typedef int (*copyFunc
)
536 (TIFF
* in
, TIFF
* out
, uint32 l
, uint32 w
, uint16 samplesperpixel
);
537 static copyFunc
pickCopyFunc(TIFF
*, TIFF
*, uint16
, uint16
);
540 tiffcp(TIFF
* in
, TIFF
* out
)
542 uint16 bitspersample
, samplesperpixel
;
544 uint32 width
, length
;
547 CopyField(TIFFTAG_IMAGEWIDTH
, width
);
548 CopyField(TIFFTAG_IMAGELENGTH
, length
);
549 CopyField(TIFFTAG_BITSPERSAMPLE
, bitspersample
);
550 CopyField(TIFFTAG_SAMPLESPERPIXEL
, samplesperpixel
);
551 if (compression
!= (uint16
)-1)
552 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
554 CopyField(TIFFTAG_COMPRESSION
, compression
);
555 if (compression
== COMPRESSION_JPEG
) {
556 uint16 input_compression
, input_photometric
;
558 if (TIFFGetField(in
, TIFFTAG_COMPRESSION
, &input_compression
)
559 && input_compression
== COMPRESSION_JPEG
) {
560 TIFFSetField(in
, TIFFTAG_JPEGCOLORMODE
, JPEGCOLORMODE_RGB
);
562 if (TIFFGetField(in
, TIFFTAG_PHOTOMETRIC
, &input_photometric
)) {
563 if(input_photometric
== PHOTOMETRIC_RGB
) {
564 if (jpegcolormode
== JPEGCOLORMODE_RGB
)
565 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
,
568 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
,
571 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
,
575 else if (compression
== COMPRESSION_SGILOG
576 || compression
== COMPRESSION_SGILOG24
)
577 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
,
578 samplesperpixel
== 1 ?
579 PHOTOMETRIC_LOGL
: PHOTOMETRIC_LOGLUV
);
581 CopyTag(TIFFTAG_PHOTOMETRIC
, 1, TIFF_SHORT
);
583 TIFFSetField(out
, TIFFTAG_FILLORDER
, fillorder
);
585 CopyTag(TIFFTAG_FILLORDER
, 1, TIFF_SHORT
);
587 * Will copy `Orientation' tag from input image
589 TIFFGetFieldDefaulted(in
, TIFFTAG_ORIENTATION
, &orientation
);
590 switch (orientation
) {
591 case ORIENTATION_BOTRIGHT
:
592 case ORIENTATION_RIGHTBOT
: /* XXX */
593 TIFFWarning(TIFFFileName(in
), "using bottom-left orientation");
594 orientation
= ORIENTATION_BOTLEFT
;
596 case ORIENTATION_LEFTBOT
: /* XXX */
597 case ORIENTATION_BOTLEFT
:
599 case ORIENTATION_TOPRIGHT
:
600 case ORIENTATION_RIGHTTOP
: /* XXX */
602 TIFFWarning(TIFFFileName(in
), "using top-left orientation");
603 orientation
= ORIENTATION_TOPLEFT
;
605 case ORIENTATION_LEFTTOP
: /* XXX */
606 case ORIENTATION_TOPLEFT
:
609 TIFFSetField(out
, TIFFTAG_ORIENTATION
, orientation
);
611 * Choose tiles/strip for the output image according to
612 * the command line arguments (-tiles, -strips) and the
613 * structure of the input image.
616 outtiled
= TIFFIsTiled(in
);
619 * Setup output file's tile width&height. If either
620 * is not specified, use either the value from the
621 * input image or, if nothing is defined, use the
624 if (tilewidth
== (uint32
) -1)
625 TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tilewidth
);
626 if (tilelength
== (uint32
) -1)
627 TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tilelength
);
628 TIFFDefaultTileSize(out
, &tilewidth
, &tilelength
);
629 TIFFSetField(out
, TIFFTAG_TILEWIDTH
, tilewidth
);
630 TIFFSetField(out
, TIFFTAG_TILELENGTH
, tilelength
);
633 * RowsPerStrip is left unspecified: use either the
634 * value from the input image or, if nothing is defined,
635 * use the library default.
637 if (rowsperstrip
== (uint32
) 0) {
638 if (!TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
,
641 TIFFDefaultStripSize(out
, rowsperstrip
);
643 if (rowsperstrip
> length
)
644 rowsperstrip
= length
;
646 else if (rowsperstrip
== (uint32
) -1)
647 rowsperstrip
= length
;
648 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
);
650 if (config
!= (uint16
) -1)
651 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, config
);
653 CopyField(TIFFTAG_PLANARCONFIG
, config
);
654 if (samplesperpixel
<= 4)
655 CopyTag(TIFFTAG_TRANSFERFUNCTION
, 4, TIFF_SHORT
);
656 CopyTag(TIFFTAG_COLORMAP
, 4, TIFF_SHORT
);
657 /* SMinSampleValue & SMaxSampleValue */
658 switch (compression
) {
659 case COMPRESSION_JPEG
:
660 TIFFSetField(out
, TIFFTAG_JPEGQUALITY
, quality
);
661 TIFFSetField(out
, TIFFTAG_JPEGCOLORMODE
, jpegcolormode
);
663 case COMPRESSION_LZW
:
664 case COMPRESSION_ADOBE_DEFLATE
:
665 case COMPRESSION_DEFLATE
:
666 if (predictor
!= (uint16
)-1)
667 TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
);
669 CopyField(TIFFTAG_PREDICTOR
, predictor
);
671 case COMPRESSION_CCITTFAX3
:
672 case COMPRESSION_CCITTFAX4
:
673 if (compression
== COMPRESSION_CCITTFAX3
) {
674 if (g3opts
!= (uint32
) -1)
675 TIFFSetField(out
, TIFFTAG_GROUP3OPTIONS
,
678 CopyField(TIFFTAG_GROUP3OPTIONS
, g3opts
);
680 CopyTag(TIFFTAG_GROUP4OPTIONS
, 1, TIFF_LONG
);
681 CopyTag(TIFFTAG_BADFAXLINES
, 1, TIFF_LONG
);
682 CopyTag(TIFFTAG_CLEANFAXDATA
, 1, TIFF_LONG
);
683 CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES
, 1, TIFF_LONG
);
684 CopyTag(TIFFTAG_FAXRECVPARAMS
, 1, TIFF_LONG
);
685 CopyTag(TIFFTAG_FAXRECVTIME
, 1, TIFF_LONG
);
686 CopyTag(TIFFTAG_FAXSUBADDRESS
, 1, TIFF_ASCII
);
691 if (TIFFGetField(in
, TIFFTAG_ICCPROFILE
, &len32
, &data
))
692 TIFFSetField(out
, TIFFTAG_ICCPROFILE
, len32
, data
);
695 const char* inknames
;
696 if (TIFFGetField(in
, TIFFTAG_NUMBEROFINKS
, &ninks
)) {
697 TIFFSetField(out
, TIFFTAG_NUMBEROFINKS
, ninks
);
698 if (TIFFGetField(in
, TIFFTAG_INKNAMES
, &inknames
)) {
699 int inknameslen
= strlen(inknames
) + 1;
700 const char* cp
= inknames
;
702 cp
= strchr(cp
, '\0');
705 inknameslen
+= (strlen(cp
) + 1);
709 TIFFSetField(out
, TIFFTAG_INKNAMES
, inknameslen
, inknames
);
714 unsigned short pg0
, pg1
;
715 if (TIFFGetField(in
, TIFFTAG_PAGENUMBER
, &pg0
, &pg1
)) {
716 if (pageNum
< 0) /* only one input file */
717 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pg0
, pg1
);
719 TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pageNum
++, 0);
723 for (p
= tags
; p
< &tags
[NTAGS
]; p
++)
724 CopyTag(p
->tag
, p
->count
, p
->type
);
726 cf
= pickCopyFunc(in
, out
, bitspersample
, samplesperpixel
);
727 return (cf
? (*cf
)(in
, out
, length
, width
, samplesperpixel
) : FALSE
);
733 #define DECLAREcpFunc(x) \
734 static int x(TIFF* in, TIFF* out, \
735 uint32 imagelength, uint32 imagewidth, tsample_t spp)
737 #define DECLAREreadFunc(x) \
738 static int x(TIFF* in, \
739 uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
740 typedef int (*readFunc
)(TIFF
*, uint8
*, uint32
, uint32
, tsample_t
);
742 #define DECLAREwriteFunc(x) \
743 static int x(TIFF* out, \
744 uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
745 typedef int (*writeFunc
)(TIFF
*, uint8
*, uint32
, uint32
, tsample_t
);
748 * Contig -> contig by scanline for rows/strip change.
750 DECLAREcpFunc(cpContig2ContigByRow
)
752 tdata_t buf
= _TIFFmalloc(TIFFScanlineSize(in
));
755 (void) imagewidth
; (void) spp
;
756 for (row
= 0; row
< imagelength
; row
++) {
757 if (TIFFReadScanline(in
, buf
, row
, 0) < 0 && !ignore
) {
758 TIFFError(TIFFFileName(in
),
759 "Error, can't read scanline %lu",
760 (unsigned long) row
);
763 if (TIFFWriteScanline(out
, buf
, row
, 0) < 0) {
764 TIFFError(TIFFFileName(out
),
765 "Error, can't write scanline %lu",
766 (unsigned long) row
);
778 typedef void biasFn (void *image
, void *bias
, uint32 pixels
);
780 #define subtract(bits) \
781 static void subtract##bits (void *i, void *b, uint32 pixels)\
783 uint##bits *image = i;\
784 uint##bits *bias = b;\
786 *image = *image > *bias ? *image-*bias : 0;\
795 static biasFn
*lineSubtractFn (unsigned bits
)
798 case 8: return subtract8
;
799 case 16: return subtract16
;
800 case 32: return subtract32
;
806 * Contig -> contig by scanline while subtracting a bias image.
808 DECLAREcpFunc(cpBiasedContig2Contig
)
811 tsize_t biasSize
= TIFFScanlineSize(bias
);
812 tsize_t bufSize
= TIFFScanlineSize(in
);
813 tdata_t buf
, biasBuf
;
814 uint32 biasWidth
= 0, biasLength
= 0;
815 TIFFGetField(bias
, TIFFTAG_IMAGEWIDTH
, &biasWidth
);
816 TIFFGetField(bias
, TIFFTAG_IMAGELENGTH
, &biasLength
);
817 if (biasSize
== bufSize
&&
818 imagelength
== biasLength
&& imagewidth
== biasWidth
) {
819 uint16 sampleBits
= 0;
820 biasFn
*subtractLine
;
821 TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &sampleBits
);
822 subtractLine
= lineSubtractFn (sampleBits
);
825 buf
= _TIFFmalloc(bufSize
);
826 biasBuf
= _TIFFmalloc(bufSize
);
827 for (row
= 0; row
< imagelength
; row
++) {
828 if (TIFFReadScanline(in
, buf
, row
, 0) < 0
830 TIFFError(TIFFFileName(in
),
831 "Error, can't read scanline %lu",
832 (unsigned long) row
);
835 if (TIFFReadScanline(bias
, biasBuf
, row
, 0) < 0
837 TIFFError(TIFFFileName(in
),
838 "Error, can't read biased scanline %lu",
839 (unsigned long) row
);
842 subtractLine (buf
, biasBuf
, imagewidth
);
843 if (TIFFWriteScanline(out
, buf
, row
, 0) < 0) {
844 TIFFError(TIFFFileName(out
),
845 "Error, can't write scanline %lu",
846 (unsigned long) row
);
853 TIFFSetDirectory(bias
,
854 TIFFCurrentDirectory(bias
)); /* rewind */
861 TIFFError(TIFFFileName(in
),
862 "No support for biasing %d bit pixels\n",
867 TIFFError(TIFFFileName(in
),
868 "Bias image %s,%d\nis not the same size as %s,%d\n",
869 TIFFFileName(bias
), TIFFCurrentDirectory(bias
),
870 TIFFFileName(in
), TIFFCurrentDirectory(in
));
873 TIFFError(TIFFFileName(in
),
874 "Can't bias %s,%d as it has >1 Sample/Pixel\n",
875 TIFFFileName(in
), TIFFCurrentDirectory(in
));
883 * Strip -> strip for change in encoding.
885 DECLAREcpFunc(cpDecodedStrips
)
887 tsize_t stripsize
= TIFFStripSize(in
);
888 tdata_t buf
= _TIFFmalloc(stripsize
);
890 (void) imagewidth
; (void) spp
;
892 tstrip_t s
, ns
= TIFFNumberOfStrips(in
);
894 for (s
= 0; s
< ns
; s
++) {
895 tsize_t cc
= (row
+ rowsperstrip
> imagelength
) ?
896 TIFFVStripSize(in
, imagelength
- row
) : stripsize
;
897 if (TIFFReadEncodedStrip(in
, s
, buf
, cc
) < 0
899 TIFFError(TIFFFileName(in
),
900 "Error, can't read strip %lu",
904 if (TIFFWriteEncodedStrip(out
, s
, buf
, cc
) < 0) {
905 TIFFError(TIFFFileName(out
),
906 "Error, can't write strip %lu",
915 TIFFError(TIFFFileName(in
),
916 "Error, can't allocate memory buffer of size %lu "
917 "to read strips", (unsigned long) stripsize
);
927 * Separate -> separate by row for rows/strip change.
929 DECLAREcpFunc(cpSeparate2SeparateByRow
)
931 tdata_t buf
= _TIFFmalloc(TIFFScanlineSize(in
));
936 for (s
= 0; s
< spp
; s
++) {
937 for (row
= 0; row
< imagelength
; row
++) {
938 if (TIFFReadScanline(in
, buf
, row
, s
) < 0 && !ignore
) {
939 TIFFError(TIFFFileName(in
),
940 "Error, can't read scanline %lu",
941 (unsigned long) row
);
944 if (TIFFWriteScanline(out
, buf
, row
, s
) < 0) {
945 TIFFError(TIFFFileName(out
),
946 "Error, can't write scanline %lu",
947 (unsigned long) row
);
960 * Contig -> separate by row.
962 DECLAREcpFunc(cpContig2SeparateByRow
)
964 tdata_t inbuf
= _TIFFmalloc(TIFFScanlineSize(in
));
965 tdata_t outbuf
= _TIFFmalloc(TIFFScanlineSize(out
));
966 register uint8
*inp
, *outp
;
971 /* unpack channels */
972 for (s
= 0; s
< spp
; s
++) {
973 for (row
= 0; row
< imagelength
; row
++) {
974 if (TIFFReadScanline(in
, inbuf
, row
, 0) < 0
976 TIFFError(TIFFFileName(in
),
977 "Error, can't read scanline %lu",
978 (unsigned long) row
);
981 inp
= ((uint8
*)inbuf
) + s
;
982 outp
= (uint8
*)outbuf
;
983 for (n
= imagewidth
; n
-- > 0;) {
987 if (TIFFWriteScanline(out
, outbuf
, row
, s
) < 0) {
988 TIFFError(TIFFFileName(out
),
989 "Error, can't write scanline %lu",
990 (unsigned long) row
);
995 if (inbuf
) _TIFFfree(inbuf
);
996 if (outbuf
) _TIFFfree(outbuf
);
999 if (inbuf
) _TIFFfree(inbuf
);
1000 if (outbuf
) _TIFFfree(outbuf
);
1005 * Separate -> contig by row.
1007 DECLAREcpFunc(cpSeparate2ContigByRow
)
1009 tdata_t inbuf
= _TIFFmalloc(TIFFScanlineSize(in
));
1010 tdata_t outbuf
= _TIFFmalloc(TIFFScanlineSize(out
));
1011 register uint8
*inp
, *outp
;
1016 for (row
= 0; row
< imagelength
; row
++) {
1017 /* merge channels */
1018 for (s
= 0; s
< spp
; s
++) {
1019 if (TIFFReadScanline(in
, inbuf
, row
, s
) < 0
1021 TIFFError(TIFFFileName(in
),
1022 "Error, can't read scanline %lu",
1023 (unsigned long) row
);
1026 inp
= (uint8
*)inbuf
;
1027 outp
= ((uint8
*)outbuf
) + s
;
1028 for (n
= imagewidth
; n
-- > 0;) {
1033 if (TIFFWriteScanline(out
, outbuf
, row
, 0) < 0) {
1034 TIFFError(TIFFFileName(out
),
1035 "Error, can't write scanline %lu",
1036 (unsigned long) row
);
1040 if (inbuf
) _TIFFfree(inbuf
);
1041 if (outbuf
) _TIFFfree(outbuf
);
1044 if (inbuf
) _TIFFfree(inbuf
);
1045 if (outbuf
) _TIFFfree(outbuf
);
1050 cpStripToTile(uint8
* out
, uint8
* in
,
1051 uint32 rows
, uint32 cols
, int outskew
, int inskew
)
1053 while (rows
-- > 0) {
1063 cpContigBufToSeparateBuf(uint8
* out
, uint8
* in
,
1064 uint32 rows
, uint32 cols
, int outskew
, int inskew
, tsample_t spp
,
1065 int bytes_per_sample
)
1067 while (rows
-- > 0) {
1071 int n
= bytes_per_sample
;
1076 in
+= (spp
-1) * bytes_per_sample
;
1084 cpSeparateBufToContigBuf(uint8
* out
, uint8
* in
,
1085 uint32 rows
, uint32 cols
, int outskew
, int inskew
, tsample_t spp
,
1086 int bytes_per_sample
)
1088 while (rows
-- > 0) {
1091 int n
= bytes_per_sample
;
1096 out
+= (spp
-1)*bytes_per_sample
;
1104 cpImage(TIFF
* in
, TIFF
* out
, readFunc fin
, writeFunc fout
,
1105 uint32 imagelength
, uint32 imagewidth
, tsample_t spp
)
1109 tsize_t scanlinesize
= TIFFRasterScanlineSize(in
);
1110 tsize_t bytes
= scanlinesize
* (tsize_t
)imagelength
;
1112 * XXX: Check for integer overflow.
1116 && bytes
/ (tsize_t
)imagelength
== scanlinesize
) {
1117 buf
= _TIFFmalloc(bytes
);
1119 if ((*fin
)(in
, (uint8
*)buf
, imagelength
,
1121 status
= (*fout
)(out
, (uint8
*)buf
,
1122 imagelength
, imagewidth
, spp
);
1126 TIFFError(TIFFFileName(in
),
1127 "Error, can't allocate space for image buffer");
1130 TIFFError(TIFFFileName(in
), "Error, no space for image buffer");
1136 DECLAREreadFunc(readContigStripsIntoBuffer
)
1138 tsize_t scanlinesize
= TIFFScanlineSize(in
);
1142 (void) imagewidth
; (void) spp
;
1143 for (row
= 0; row
< imagelength
; row
++) {
1144 if (TIFFReadScanline(in
, (tdata_t
) bufp
, row
, 0) < 0
1146 TIFFError(TIFFFileName(in
),
1147 "Error, can't read scanline %lu",
1148 (unsigned long) row
);
1151 bufp
+= scanlinesize
;
1157 DECLAREreadFunc(readSeparateStripsIntoBuffer
)
1160 tsize_t scanlinesize
= TIFFScanlineSize(in
);
1161 tdata_t scanline
= _TIFFmalloc(scanlinesize
);
1167 uint8
* bufp
= (uint8
*) buf
;
1170 for (row
= 0; row
< imagelength
; row
++) {
1171 /* merge channels */
1172 for (s
= 0; s
< spp
; s
++) {
1173 uint8
* bp
= bufp
+ s
;
1174 tsize_t n
= scanlinesize
;
1175 uint8
* sbuf
= scanline
;
1177 if (TIFFReadScanline(in
, scanline
, row
, s
) < 0
1179 TIFFError(TIFFFileName(in
),
1180 "Error, can't read scanline %lu",
1181 (unsigned long) row
);
1186 *bp
= *sbuf
++, bp
+= spp
;
1188 bufp
+= scanlinesize
* spp
;
1193 _TIFFfree(scanline
);
1197 DECLAREreadFunc(readContigTilesIntoBuffer
)
1200 tdata_t tilebuf
= _TIFFmalloc(TIFFTileSize(in
));
1201 uint32 imagew
= TIFFScanlineSize(in
);
1202 uint32 tilew
= TIFFTileRowSize(in
);
1203 int iskew
= imagew
- tilew
;
1204 uint8
* bufp
= (uint8
*) buf
;
1211 (void) TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
);
1212 (void) TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
);
1214 for (row
= 0; row
< imagelength
; row
+= tl
) {
1215 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1219 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1220 if (TIFFReadTile(in
, tilebuf
, col
, row
, 0, 0) < 0
1222 TIFFError(TIFFFileName(in
),
1223 "Error, can't read tile at %lu %lu",
1224 (unsigned long) col
,
1225 (unsigned long) row
);
1229 if (colb
+ tilew
> imagew
) {
1230 uint32 width
= imagew
- colb
;
1231 uint32 oskew
= tilew
- width
;
1232 cpStripToTile(bufp
+ colb
,
1233 tilebuf
, nrow
, width
,
1234 oskew
+ iskew
, oskew
);
1236 cpStripToTile(bufp
+ colb
,
1237 tilebuf
, nrow
, tilew
,
1241 bufp
+= imagew
* nrow
;
1248 DECLAREreadFunc(readSeparateTilesIntoBuffer
)
1251 uint32 imagew
= TIFFRasterScanlineSize(in
);
1252 uint32 tilew
= TIFFTileRowSize(in
);
1253 int iskew
= imagew
- tilew
*spp
;
1254 tdata_t tilebuf
= _TIFFmalloc(TIFFTileSize(in
));
1255 uint8
* bufp
= (uint8
*) buf
;
1258 uint16 bps
, bytes_per_sample
;
1262 (void) TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
);
1263 (void) TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
);
1264 (void) TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &bps
);
1265 assert( bps
% 8 == 0 );
1266 bytes_per_sample
= bps
/8;
1268 for (row
= 0; row
< imagelength
; row
+= tl
) {
1269 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1273 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1276 for (s
= 0; s
< spp
; s
++) {
1277 if (TIFFReadTile(in
, tilebuf
, col
, row
, 0, s
) < 0
1279 TIFFError(TIFFFileName(in
),
1280 "Error, can't read tile at %lu %lu, "
1282 (unsigned long) col
,
1283 (unsigned long) row
,
1289 * Tile is clipped horizontally. Calculate
1290 * visible portion and skewing factors.
1292 if (colb
+ tilew
*spp
> imagew
) {
1293 uint32 width
= imagew
- colb
;
1294 int oskew
= tilew
*spp
- width
;
1295 cpSeparateBufToContigBuf(
1296 bufp
+colb
+s
*bytes_per_sample
,
1298 width
/(spp
*bytes_per_sample
),
1303 cpSeparateBufToContigBuf(
1304 bufp
+colb
+s
*bytes_per_sample
,
1311 bufp
+= imagew
* nrow
;
1318 DECLAREwriteFunc(writeBufferToContigStrips
)
1320 uint32 row
, rowsperstrip
;
1323 (void) imagewidth
; (void) spp
;
1324 (void) TIFFGetFieldDefaulted(out
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
);
1325 for (row
= 0; row
< imagelength
; row
+= rowsperstrip
) {
1326 uint32 nrows
= (row
+rowsperstrip
> imagelength
) ?
1327 imagelength
-row
: rowsperstrip
;
1328 tsize_t stripsize
= TIFFVStripSize(out
, nrows
);
1329 if (TIFFWriteEncodedStrip(out
, strip
++, buf
, stripsize
) < 0) {
1330 TIFFError(TIFFFileName(out
),
1331 "Error, can't write strip %lu", strip
- 1);
1339 DECLAREwriteFunc(writeBufferToSeparateStrips
)
1341 uint32 rowsize
= imagewidth
* spp
;
1342 uint32 rowsperstrip
;
1343 tdata_t obuf
= _TIFFmalloc(TIFFStripSize(out
));
1349 (void) TIFFGetFieldDefaulted(out
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
);
1350 for (s
= 0; s
< spp
; s
++) {
1352 for (row
= 0; row
< imagelength
; row
+= rowsperstrip
) {
1353 uint32 nrows
= (row
+rowsperstrip
> imagelength
) ?
1354 imagelength
-row
: rowsperstrip
;
1355 tsize_t stripsize
= TIFFVStripSize(out
, nrows
);
1357 cpContigBufToSeparateBuf(
1358 obuf
, (uint8
*) buf
+ row
*rowsize
+ s
,
1359 nrows
, imagewidth
, 0, 0, spp
, 1);
1360 if (TIFFWriteEncodedStrip(out
, strip
++, obuf
, stripsize
) < 0) {
1361 TIFFError(TIFFFileName(out
),
1362 "Error, can't write strip %lu",
1374 DECLAREwriteFunc(writeBufferToContigTiles
)
1376 uint32 imagew
= TIFFScanlineSize(out
);
1377 uint32 tilew
= TIFFTileRowSize(out
);
1378 int iskew
= imagew
- tilew
;
1379 tdata_t obuf
= _TIFFmalloc(TIFFTileSize(out
));
1380 uint8
* bufp
= (uint8
*) buf
;
1387 (void) TIFFGetField(out
, TIFFTAG_TILELENGTH
, &tl
);
1388 (void) TIFFGetField(out
, TIFFTAG_TILEWIDTH
, &tw
);
1389 for (row
= 0; row
< imagelength
; row
+= tilelength
) {
1390 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1394 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1396 * Tile is clipped horizontally. Calculate
1397 * visible portion and skewing factors.
1399 if (colb
+ tilew
> imagew
) {
1400 uint32 width
= imagew
- colb
;
1401 int oskew
= tilew
- width
;
1402 cpStripToTile(obuf
, bufp
+ colb
, nrow
, width
,
1403 oskew
, oskew
+ iskew
);
1405 cpStripToTile(obuf
, bufp
+ colb
, nrow
, tilew
,
1407 if (TIFFWriteTile(out
, obuf
, col
, row
, 0, 0) < 0) {
1408 TIFFError(TIFFFileName(out
),
1409 "Error, can't write tile at %lu %lu",
1410 (unsigned long) col
,
1411 (unsigned long) row
);
1417 bufp
+= nrow
* imagew
;
1423 DECLAREwriteFunc(writeBufferToSeparateTiles
)
1425 uint32 imagew
= TIFFScanlineSize(out
);
1426 tsize_t tilew
= TIFFTileRowSize(out
);
1427 uint32 iimagew
= TIFFRasterScanlineSize(out
);
1428 int iskew
= iimagew
- tilew
*spp
;
1429 tdata_t obuf
= _TIFFmalloc(TIFFTileSize(out
));
1430 uint8
* bufp
= (uint8
*) buf
;
1433 uint16 bps
, bytes_per_sample
;
1437 (void) TIFFGetField(out
, TIFFTAG_TILELENGTH
, &tl
);
1438 (void) TIFFGetField(out
, TIFFTAG_TILEWIDTH
, &tw
);
1439 (void) TIFFGetField(out
, TIFFTAG_BITSPERSAMPLE
, &bps
);
1440 assert( bps
% 8 == 0 );
1441 bytes_per_sample
= bps
/8;
1443 for (row
= 0; row
< imagelength
; row
+= tl
) {
1444 uint32 nrow
= (row
+tl
> imagelength
) ? imagelength
-row
: tl
;
1448 for (col
= 0; col
< imagewidth
; col
+= tw
) {
1450 for (s
= 0; s
< spp
; s
++) {
1452 * Tile is clipped horizontally. Calculate
1453 * visible portion and skewing factors.
1455 if (colb
+ tilew
> imagew
) {
1456 uint32 width
= (imagew
- colb
);
1457 int oskew
= tilew
- width
;
1459 cpContigBufToSeparateBuf(obuf
,
1460 bufp
+ (colb
*spp
) + s
,
1461 nrow
, width
/bytes_per_sample
,
1462 oskew
, (oskew
*spp
)+iskew
, spp
,
1465 cpContigBufToSeparateBuf(obuf
,
1466 bufp
+ (colb
*spp
) + s
,
1470 if (TIFFWriteTile(out
, obuf
, col
, row
, 0, s
) < 0) {
1471 TIFFError(TIFFFileName(out
),
1472 "Error, can't write tile at %lu %lu "
1474 (unsigned long) col
,
1475 (unsigned long) row
,
1483 bufp
+= nrow
* iimagew
;
1490 * Contig strips -> contig tiles.
1492 DECLAREcpFunc(cpContigStrips2ContigTiles
)
1494 return cpImage(in
, out
,
1495 readContigStripsIntoBuffer
,
1496 writeBufferToContigTiles
,
1497 imagelength
, imagewidth
, spp
);
1501 * Contig strips -> separate tiles.
1503 DECLAREcpFunc(cpContigStrips2SeparateTiles
)
1505 return cpImage(in
, out
,
1506 readContigStripsIntoBuffer
,
1507 writeBufferToSeparateTiles
,
1508 imagelength
, imagewidth
, spp
);
1512 * Separate strips -> contig tiles.
1514 DECLAREcpFunc(cpSeparateStrips2ContigTiles
)
1516 return cpImage(in
, out
,
1517 readSeparateStripsIntoBuffer
,
1518 writeBufferToContigTiles
,
1519 imagelength
, imagewidth
, spp
);
1523 * Separate strips -> separate tiles.
1525 DECLAREcpFunc(cpSeparateStrips2SeparateTiles
)
1527 return cpImage(in
, out
,
1528 readSeparateStripsIntoBuffer
,
1529 writeBufferToSeparateTiles
,
1530 imagelength
, imagewidth
, spp
);
1534 * Contig strips -> contig tiles.
1536 DECLAREcpFunc(cpContigTiles2ContigTiles
)
1538 return cpImage(in
, out
,
1539 readContigTilesIntoBuffer
,
1540 writeBufferToContigTiles
,
1541 imagelength
, imagewidth
, spp
);
1545 * Contig tiles -> separate tiles.
1547 DECLAREcpFunc(cpContigTiles2SeparateTiles
)
1549 return cpImage(in
, out
,
1550 readContigTilesIntoBuffer
,
1551 writeBufferToSeparateTiles
,
1552 imagelength
, imagewidth
, spp
);
1556 * Separate tiles -> contig tiles.
1558 DECLAREcpFunc(cpSeparateTiles2ContigTiles
)
1560 return cpImage(in
, out
,
1561 readSeparateTilesIntoBuffer
,
1562 writeBufferToContigTiles
,
1563 imagelength
, imagewidth
, spp
);
1567 * Separate tiles -> separate tiles (tile dimension change).
1569 DECLAREcpFunc(cpSeparateTiles2SeparateTiles
)
1571 return cpImage(in
, out
,
1572 readSeparateTilesIntoBuffer
,
1573 writeBufferToSeparateTiles
,
1574 imagelength
, imagewidth
, spp
);
1578 * Contig tiles -> contig tiles (tile dimension change).
1580 DECLAREcpFunc(cpContigTiles2ContigStrips
)
1582 return cpImage(in
, out
,
1583 readContigTilesIntoBuffer
,
1584 writeBufferToContigStrips
,
1585 imagelength
, imagewidth
, spp
);
1589 * Contig tiles -> separate strips.
1591 DECLAREcpFunc(cpContigTiles2SeparateStrips
)
1593 return cpImage(in
, out
,
1594 readContigTilesIntoBuffer
,
1595 writeBufferToSeparateStrips
,
1596 imagelength
, imagewidth
, spp
);
1600 * Separate tiles -> contig strips.
1602 DECLAREcpFunc(cpSeparateTiles2ContigStrips
)
1604 return cpImage(in
, out
,
1605 readSeparateTilesIntoBuffer
,
1606 writeBufferToContigStrips
,
1607 imagelength
, imagewidth
, spp
);
1611 * Separate tiles -> separate strips.
1613 DECLAREcpFunc(cpSeparateTiles2SeparateStrips
)
1615 return cpImage(in
, out
,
1616 readSeparateTilesIntoBuffer
,
1617 writeBufferToSeparateStrips
,
1618 imagelength
, imagewidth
, spp
);
1622 * Select the appropriate copy function to use.
1625 pickCopyFunc(TIFF
* in
, TIFF
* out
, uint16 bitspersample
, uint16 samplesperpixel
)
1628 uint32 w
, l
, tw
, tl
;
1631 (void) TIFFGetField(in
, TIFFTAG_PLANARCONFIG
, &shortv
);
1632 if (shortv
!= config
&& bitspersample
!= 8 && samplesperpixel
> 1) {
1634 "%s: Cannot handle different planar configuration w/ bits/sample != 8\n",
1638 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &w
);
1639 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &l
);
1640 if (!(TIFFIsTiled(out
) || TIFFIsTiled(in
))) {
1641 uint32 irps
= (uint32
) -1L;
1642 TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
, &irps
);
1643 /* if biased, force decoded copying to allow image subtraction */
1644 bychunk
= !bias
&& (rowsperstrip
== irps
);
1645 }else{ /* either in or out is tiled */
1648 "%s: Cannot handle tiled configuration w/bias image\n",
1652 if (TIFFIsTiled(out
)) {
1653 if (!TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
))
1655 if (!TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
))
1657 bychunk
= (tw
== tilewidth
&& tl
== tilelength
);
1658 } else { /* out's not, so in must be tiled */
1659 TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
);
1660 TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
);
1661 bychunk
= (tw
== w
&& tl
== rowsperstrip
);
1666 #define pack(a,b,c,d,e) ((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
1667 switch(pack(shortv
,config
,TIFFIsTiled(in
),TIFFIsTiled(out
),bychunk
)) {
1668 /* Strips -> Tiles */
1669 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,T
,F
):
1670 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,T
,T
):
1671 return cpContigStrips2ContigTiles
;
1672 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,T
,F
):
1673 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,T
,T
):
1674 return cpContigStrips2SeparateTiles
;
1675 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,T
,F
):
1676 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,T
,T
):
1677 return cpSeparateStrips2ContigTiles
;
1678 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,T
,F
):
1679 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,T
,T
):
1680 return cpSeparateStrips2SeparateTiles
;
1681 /* Tiles -> Tiles */
1682 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,T
,F
):
1683 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,T
,T
):
1684 return cpContigTiles2ContigTiles
;
1685 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,T
,F
):
1686 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,T
,T
):
1687 return cpContigTiles2SeparateTiles
;
1688 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,T
,F
):
1689 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,T
,T
):
1690 return cpSeparateTiles2ContigTiles
;
1691 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,T
,F
):
1692 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,T
,T
):
1693 return cpSeparateTiles2SeparateTiles
;
1694 /* Tiles -> Strips */
1695 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,F
,F
):
1696 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, T
,F
,T
):
1697 return cpContigTiles2ContigStrips
;
1698 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,F
,F
):
1699 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, T
,F
,T
):
1700 return cpContigTiles2SeparateStrips
;
1701 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,F
,F
):
1702 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, T
,F
,T
):
1703 return cpSeparateTiles2ContigStrips
;
1704 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,F
,F
):
1705 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,F
,T
):
1706 return cpSeparateTiles2SeparateStrips
;
1707 /* Strips -> Strips */
1708 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,F
,F
):
1709 return bias
? cpBiasedContig2Contig
: cpContig2ContigByRow
;
1710 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_CONTIG
, F
,F
,T
):
1711 return cpDecodedStrips
;
1712 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,F
,F
):
1713 case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
, F
,F
,T
):
1714 return cpContig2SeparateByRow
;
1715 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,F
,F
):
1716 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
, F
,F
,T
):
1717 return cpSeparate2ContigByRow
;
1718 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,F
,F
):
1719 case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,F
,T
):
1720 return cpSeparate2SeparateByRow
;
1725 fprintf(stderr
, "tiffcp: %s: Don't know how to copy/convert image.\n",
1730 /* vim: set ts=8 sts=8 sw=8 noet: */