~ubuntu-branches/ubuntu/oneiric/tiff/oneiric

« back to all changes in this revision

Viewing changes to tools/tiffcp.c

  • Committer: Bazaar Package Importer
  • Author(s): Jay Berkenbilt
  • Date: 2009-08-28 15:44:23 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090828154423-7oisj77n302jrroa
Tags: 3.9.1-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: tiffcp.c,v 1.37.2.1 2009-01-01 00:10:43 bfriesen Exp $ */
 
2
 
 
3
/*
 
4
 * Copyright (c) 1988-1997 Sam Leffler
 
5
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
 
6
 *
 
7
 *  Revised:  2/18/01 BAR -- added syntax for extracting single images from
 
8
 *                          multi-image TIFF files.
 
9
 *
 
10
 *    New syntax is:  sourceFileName,image#
 
11
 *
 
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
 
14
 * image number.
 
15
 *
 
16
 *    Example:   tiffcp source.tif,1 destination.tif
 
17
 *
 
18
 * Copies the 2nd image in source.tif to the destination.
 
19
 *
 
20
 *****
 
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.
 
28
 * 
 
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.  
 
32
 * 
 
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 
 
38
 * OF THIS SOFTWARE.
 
39
 */
 
40
 
 
41
#include "tif_config.h"
 
42
 
 
43
#include <stdio.h>
 
44
#include <stdlib.h>
 
45
#include <string.h>
 
46
 
 
47
#include <ctype.h>
 
48
#include <assert.h>
 
49
 
 
50
#ifdef HAVE_UNISTD_H
 
51
# include <unistd.h>
 
52
#endif
 
53
 
 
54
#include "tiffio.h"
 
55
 
 
56
#ifndef HAVE_GETOPT
 
57
extern int getopt(int, char**, char*);
 
58
#endif
 
59
 
 
60
#if defined(VMS)
 
61
# define unlink delete
 
62
#endif
 
63
 
 
64
#define streq(a,b)      (strcmp(a,b) == 0)
 
65
#define strneq(a,b,n)   (strncmp(a,b,n) == 0)
 
66
 
 
67
#define TRUE    1
 
68
#define FALSE   0
 
69
 
 
70
static  int outtiled = -1;
 
71
static  uint32 tilewidth;
 
72
static  uint32 tilelength;
 
73
 
 
74
static  uint16 config;
 
75
static  uint16 compression;
 
76
static  uint16 predictor;
 
77
static  uint16 fillorder;
 
78
static  uint16 orientation;
 
79
static  uint32 rowsperstrip;
 
80
static  uint32 g3opts;
 
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
 
 
88
static  int tiffcp(TIFF*, TIFF*);
 
89
static  int processCompressOptions(char*);
 
90
static  void usage(void);
 
91
 
 
92
static char comma = ',';  /* (default) comma separator character */
 
93
static TIFF* bias = NULL;
 
94
static int pageNum = 0;
 
95
 
 
96
static int nextSrcImage (TIFF *tif, char **imageSpec)
 
97
/*
 
98
  seek to the next image specified in *imageSpec
 
99
  returns 1 if success, 0 if no more images to process
 
100
  *imageSpec=NULL if subsequent images should be processed in sequence
 
101
*/
 
102
{
 
103
  if (**imageSpec == comma) {  /* if not @comma, we've done all images */
 
104
    char *start = *imageSpec + 1;
 
105
    tdir_t nextImage = (tdir_t)strtol(start, imageSpec, 0);
 
106
    if (start == *imageSpec) nextImage = TIFFCurrentDirectory (tif);
 
107
    if (**imageSpec)
 
108
    {
 
109
      if (**imageSpec == comma) {  
 
110
        /* a trailing comma denotes remaining images in sequence */
 
111
        if ((*imageSpec)[1] == '\0') *imageSpec = NULL;
 
112
      }else{
 
113
        fprintf (stderr, 
 
114
          "Expected a %c separated image # list after %s\n",
 
115
          comma, TIFFFileName (tif));
 
116
        exit (-4);   /* syntax error */
 
117
      }
 
118
    }
 
119
    if (TIFFSetDirectory (tif, nextImage)) return 1;  
 
120
    fprintf (stderr, "%s%c%d not found!\n", 
 
121
             TIFFFileName(tif), comma, (int) nextImage); 
 
122
  }
 
123
  return 0;
 
124
}
 
125
 
 
126
  
 
127
static TIFF* openSrcImage (char **imageSpec)
 
128
/*
 
129
  imageSpec points to a pointer to a filename followed by optional ,image#'s
 
130
  Open the TIFF file and assign *imageSpec to either NULL if there are
 
131
  no images specified, or a pointer to the next image number text
 
132
*/
 
133
{
 
134
    TIFF *tif;
 
135
    char *fn = *imageSpec;
 
136
    *imageSpec = strchr (fn, comma);
 
137
    if (*imageSpec) {  /* there is at least one image number specifier */
 
138
        **imageSpec = '\0'; 
 
139
        tif = TIFFOpen (fn, "r");
 
140
        /* but, ignore any single trailing comma */
 
141
        if (!(*imageSpec)[1]) {*imageSpec = NULL; return tif;}
 
142
        if (tif) { 
 
143
            **imageSpec = comma;  /* replace the comma */
 
144
            if (!nextSrcImage(tif, imageSpec)) {
 
145
              TIFFClose (tif);
 
146
              tif = NULL;
 
147
            }
 
148
        }
 
149
    }else
 
150
        tif = TIFFOpen (fn, "r");
 
151
    return tif;
 
152
}
 
153
 
 
154
 
 
155
int
 
156
main(int argc, char* argv[])
 
157
{
 
158
        uint16 defconfig = (uint16) -1;
 
159
        uint16 deffillorder = 0;
 
160
        uint32 deftilewidth = (uint32) -1;
 
161
        uint32 deftilelength = (uint32) -1;
 
162
        uint32 defrowsperstrip = (uint32) 0;
 
163
        uint32 diroff = 0;
 
164
        TIFF* in;
 
165
        TIFF* out;
 
166
        char mode[10];
 
167
        char* mp = mode;
 
168
        int c;
 
169
        extern int optind;
 
170
        extern char* optarg;
 
171
 
 
172
        *mp++ = 'w';
 
173
        *mp = '\0';
 
174
        while ((c = getopt(argc, argv, ",:b:c:f:l:o:z:p:r:w:aistBLMC")) != -1)
 
175
                switch (c) {
 
176
                case ',':
 
177
                        if (optarg[0] != '=') usage();
 
178
                        comma = optarg[1];
 
179
                        break;
 
180
                case 'b':   /* this file is bias image subtracted from others */
 
181
                        if (bias) {
 
182
                          fputs ("Only 1 bias image may be specified\n", stderr);
 
183
                          exit (-2);
 
184
                        }
 
185
                        {
 
186
                          uint16    samples = (uint16) -1;
 
187
                          char **biasFn = &optarg;
 
188
                          bias = openSrcImage (biasFn);
 
189
                          if (!bias) exit (-5);
 
190
                          if (TIFFIsTiled (bias)) {
 
191
                     fputs ("Bias image must be organized in strips\n", stderr);
 
192
                            exit (-7);
 
193
                          }
 
194
                          TIFFGetField(bias, TIFFTAG_SAMPLESPERPIXEL, &samples);
 
195
                          if (samples != 1) {
 
196
                     fputs ("Bias image must be monochrome\n", stderr);
 
197
                            exit (-7);
 
198
                          }
 
199
                        }
 
200
                        break;
 
201
                case 'a':               /* append to output */
 
202
                        mode[0] = 'a';
 
203
                        break;
 
204
                case 'c':               /* compression scheme */
 
205
                        if (!processCompressOptions(optarg))
 
206
                                usage();
 
207
                        break;
 
208
                case 'f':               /* fill order */
 
209
                        if (streq(optarg, "lsb2msb"))
 
210
                                deffillorder = FILLORDER_LSB2MSB;
 
211
                        else if (streq(optarg, "msb2lsb"))
 
212
                                deffillorder = FILLORDER_MSB2LSB;
 
213
                        else
 
214
                                usage();
 
215
                        break;
 
216
                case 'i':               /* ignore errors */
 
217
                        ignore = TRUE;
 
218
                        break;
 
219
                case 'l':               /* tile length */
 
220
                        outtiled = TRUE;
 
221
                        deftilelength = atoi(optarg);
 
222
                        break;
 
223
                case 'o':               /* initial directory offset */
 
224
                        diroff = strtoul(optarg, NULL, 0);
 
225
                        break;
 
226
                case 'p':               /* planar configuration */
 
227
                        if (streq(optarg, "separate"))
 
228
                                defconfig = PLANARCONFIG_SEPARATE;
 
229
                        else if (streq(optarg, "contig"))
 
230
                                defconfig = PLANARCONFIG_CONTIG;
 
231
                        else
 
232
                                usage();
 
233
                        break;
 
234
                case 'r':               /* rows/strip */
 
235
                        defrowsperstrip = atol(optarg);
 
236
                        break;
 
237
                case 's':               /* generate stripped output */
 
238
                        outtiled = FALSE;
 
239
                        break;
 
240
                case 't':               /* generate tiled output */
 
241
                        outtiled = TRUE;
 
242
                        break;
 
243
                case 'w':               /* tile width */
 
244
                        outtiled = TRUE;
 
245
                        deftilewidth = atoi(optarg);
 
246
                        break;
 
247
                case 'B':
 
248
                        *mp++ = 'b'; *mp = '\0';
 
249
                        break;
 
250
                case 'L':
 
251
                        *mp++ = 'l'; *mp = '\0';
 
252
                        break;
 
253
                case 'M':
 
254
                        *mp++ = 'm'; *mp = '\0';
 
255
                        break;
 
256
                case 'C':
 
257
                        *mp++ = 'c'; *mp = '\0';
 
258
                        break;
 
259
                case '?':
 
260
                        usage();
 
261
                        /*NOTREACHED*/
 
262
                }
 
263
        if (argc - optind < 2)
 
264
                usage();
 
265
        out = TIFFOpen(argv[argc-1], mode);
 
266
        if (out == NULL)
 
267
                return (-2);
 
268
        if ((argc - optind) == 2)
 
269
          pageNum = -1;
 
270
        for (; optind < argc-1 ; optind++) {
 
271
                char *imageCursor = argv[optind];
 
272
                in = openSrcImage (&imageCursor);
 
273
                if (in == NULL)
 
274
                        return (-3);
 
275
                if (diroff != 0 && !TIFFSetSubDirectory(in, diroff)) {
 
276
                        TIFFError(TIFFFileName(in),
 
277
                            "Error, setting subdirectory at %#x", diroff);
 
278
                        (void) TIFFClose(out);
 
279
                        return (1);
 
280
                }
 
281
                for (;;) {
 
282
                   config = defconfig;
 
283
                   compression = defcompression;
 
284
                   predictor = defpredictor;
 
285
                   fillorder = deffillorder;
 
286
                   rowsperstrip = defrowsperstrip;
 
287
                   tilewidth = deftilewidth;
 
288
                   tilelength = deftilelength;
 
289
                   g3opts = defg3opts;
 
290
                   if (!tiffcp(in, out) || !TIFFWriteDirectory(out)) {
 
291
                        TIFFClose(out);
 
292
                        return (1);
 
293
                   }
 
294
                   if (imageCursor) { /* seek next image directory */
 
295
                        if (!nextSrcImage(in, &imageCursor)) break;
 
296
                   }else
 
297
                        if (!TIFFReadDirectory(in)) break;
 
298
                }
 
299
                TIFFClose(in);
 
300
        }
 
301
 
 
302
        TIFFClose(out);
 
303
        return (0);
 
304
}
 
305
 
 
306
 
 
307
static void
 
308
processG3Options(char* cp)
 
309
{
 
310
        if( (cp = strchr(cp, ':')) ) {
 
311
                if (defg3opts == (uint32) -1)
 
312
                        defg3opts = 0;
 
313
                do {
 
314
                        cp++;
 
315
                        if (strneq(cp, "1d", 2))
 
316
                                defg3opts &= ~GROUP3OPT_2DENCODING;
 
317
                        else if (strneq(cp, "2d", 2))
 
318
                                defg3opts |= GROUP3OPT_2DENCODING;
 
319
                        else if (strneq(cp, "fill", 4))
 
320
                                defg3opts |= GROUP3OPT_FILLBITS;
 
321
                        else
 
322
                                usage();
 
323
                } while( (cp = strchr(cp, ':')) );
 
324
        }
 
325
}
 
326
 
 
327
static int
 
328
processCompressOptions(char* opt)
 
329
{
 
330
        if (streq(opt, "none")) {
 
331
                defcompression = COMPRESSION_NONE;
 
332
        } else if (streq(opt, "packbits")) {
 
333
                defcompression = COMPRESSION_PACKBITS;
 
334
        } else if (strneq(opt, "jpeg", 4)) {
 
335
                char* cp = strchr(opt, ':');
 
336
 
 
337
                defcompression = COMPRESSION_JPEG;
 
338
                while( cp )
 
339
                {
 
340
                    if (isdigit((int)cp[1]))
 
341
                        quality = atoi(cp+1);
 
342
                    else if (cp[1] == 'r' )
 
343
                        jpegcolormode = JPEGCOLORMODE_RAW;
 
344
                    else
 
345
                        usage();
 
346
 
 
347
                    cp = strchr(cp+1,':');
 
348
                }
 
349
        } else if (strneq(opt, "g3", 2)) {
 
350
                processG3Options(opt);
 
351
                defcompression = COMPRESSION_CCITTFAX3;
 
352
        } else if (streq(opt, "g4")) {
 
353
                defcompression = COMPRESSION_CCITTFAX4;
 
354
        } else if (strneq(opt, "lzw", 3)) {
 
355
                char* cp = strchr(opt, ':');
 
356
                if (cp)
 
357
                        defpredictor = atoi(cp+1);
 
358
                defcompression = COMPRESSION_LZW;
 
359
        } else if (strneq(opt, "zip", 3)) {
 
360
                char* cp = strchr(opt, ':');
 
361
                if (cp)
 
362
                        defpredictor = atoi(cp+1);
 
363
                defcompression = COMPRESSION_ADOBE_DEFLATE;
 
364
        } else if (strneq(opt, "jbig", 4)) {
 
365
                defcompression = COMPRESSION_JBIG;
 
366
        } else
 
367
                return (0);
 
368
        return (1);
 
369
}
 
370
 
 
371
char* stuff[] = {
 
372
"usage: tiffcp [options] input... output",
 
373
"where options are:",
 
374
" -a            append to output instead of overwriting",
 
375
" -o offset     set initial directory offset",
 
376
" -p contig     pack samples contiguously (e.g. RGBRGB...)",
 
377
" -p separate   store samples separately (e.g. RRR...GGG...BBB...)",
 
378
" -s            write output in strips",
 
379
" -t            write output in tiles",
 
380
" -i            ignore read errors",
 
381
" -b file[,#]   bias (dark) monochrome image to be subtracted from all others",
 
382
" -,=%          use % rather than , to separate image #'s (per Note below)",           
 
383
"",
 
384
" -r #          make each strip have no more than # rows",
 
385
" -w #          set output tile width (pixels)",
 
386
" -l #          set output tile length (pixels)",
 
387
"",
 
388
" -f lsb2msb    force lsb-to-msb FillOrder for output",
 
389
" -f msb2lsb    force msb-to-lsb FillOrder for output",
 
390
"",
 
391
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
 
392
" -c zip[:opts] compress output with deflate encoding",
 
393
" -c jpeg[:opts]        compress output with JPEG encoding",
 
394
" -c jbig       compress output with ISO JBIG encoding",
 
395
" -c packbits   compress output with packbits encoding",
 
396
" -c g3[:opts]  compress output with CCITT Group 3 encoding",
 
397
" -c g4         compress output with CCITT Group 4 encoding",
 
398
" -c none       use no compression algorithm on output",
 
399
"",
 
400
"Group 3 options:",
 
401
" 1d            use default CCITT Group 3 1D-encoding",
 
402
" 2d            use optional CCITT Group 3 2D-encoding",
 
403
" fill          byte-align EOL codes",
 
404
"For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
 
405
"",
 
406
"JPEG options:",
 
407
" #             set compression quality level (0-100, default 75)",
 
408
" r             output color image as RGB rather than YCbCr",
 
409
"For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
 
410
"",
 
411
"LZW and deflate options:",
 
412
" #             set predictor value",
 
413
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
 
414
"",
 
415
"Note that input filenames may be of the form filename,x,y,z",
 
416
"where x, y, and z specify image numbers in the filename to copy.",
 
417
"example:  tiffcp -c none -b esp.tif,1 esp.tif,0 test.tif",
 
418
"  subtract 2nd image in esp.tif from 1st yielding uncompressed result test.tif",
 
419
NULL
 
420
};
 
421
 
 
422
static void
 
423
usage(void)
 
424
{
 
425
        char buf[BUFSIZ];
 
426
        int i;
 
427
 
 
428
        setbuf(stderr, buf);
 
429
        fprintf(stderr, "%s\n\n", TIFFGetVersion());
 
430
        for (i = 0; stuff[i] != NULL; i++)
 
431
                fprintf(stderr, "%s\n", stuff[i]);
 
432
        exit(-1);
 
433
}
 
434
 
 
435
#define CopyField(tag, v) \
 
436
    if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
 
437
#define CopyField2(tag, v1, v2) \
 
438
    if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
 
439
#define CopyField3(tag, v1, v2, v3) \
 
440
    if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
 
441
#define CopyField4(tag, v1, v2, v3, v4) \
 
442
    if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
 
443
 
 
444
static void
 
445
cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type)
 
446
{
 
447
        switch (type) {
 
448
        case TIFF_SHORT:
 
449
                if (count == 1) {
 
450
                        uint16 shortv;
 
451
                        CopyField(tag, shortv);
 
452
                } else if (count == 2) {
 
453
                        uint16 shortv1, shortv2;
 
454
                        CopyField2(tag, shortv1, shortv2);
 
455
                } else if (count == 4) {
 
456
                        uint16 *tr, *tg, *tb, *ta;
 
457
                        CopyField4(tag, tr, tg, tb, ta);
 
458
                } else if (count == (uint16) -1) {
 
459
                        uint16 shortv1;
 
460
                        uint16* shortav;
 
461
                        CopyField2(tag, shortv1, shortav);
 
462
                }
 
463
                break;
 
464
        case TIFF_LONG:
 
465
                { uint32 longv;
 
466
                  CopyField(tag, longv);
 
467
                }
 
468
                break;
 
469
        case TIFF_RATIONAL:
 
470
                if (count == 1) {
 
471
                        float floatv;
 
472
                        CopyField(tag, floatv);
 
473
                } else if (count == (uint16) -1) {
 
474
                        float* floatav;
 
475
                        CopyField(tag, floatav);
 
476
                }
 
477
                break;
 
478
        case TIFF_ASCII:
 
479
                { char* stringv;
 
480
                  CopyField(tag, stringv);
 
481
                }
 
482
                break;
 
483
        case TIFF_DOUBLE:
 
484
                if (count == 1) {
 
485
                        double doublev;
 
486
                        CopyField(tag, doublev);
 
487
                } else if (count == (uint16) -1) {
 
488
                        double* doubleav;
 
489
                        CopyField(tag, doubleav);
 
490
                }
 
491
                break;
 
492
          default:
 
493
                TIFFError(TIFFFileName(in),
 
494
                          "Data type %d is not supported, tag %d skipped.",
 
495
                          tag, type);
 
496
        }
 
497
}
 
498
 
 
499
static struct cpTag {
 
500
        uint16  tag;
 
501
        uint16  count;
 
502
        TIFFDataType type;
 
503
} tags[] = {
 
504
        { TIFFTAG_SUBFILETYPE,          1, TIFF_LONG },
 
505
        { TIFFTAG_THRESHHOLDING,        1, TIFF_SHORT },
 
506
        { TIFFTAG_DOCUMENTNAME,         1, TIFF_ASCII },
 
507
        { TIFFTAG_IMAGEDESCRIPTION,     1, TIFF_ASCII },
 
508
        { TIFFTAG_MAKE,                 1, TIFF_ASCII },
 
509
        { TIFFTAG_MODEL,                1, TIFF_ASCII },
 
510
        { TIFFTAG_MINSAMPLEVALUE,       1, TIFF_SHORT },
 
511
        { TIFFTAG_MAXSAMPLEVALUE,       1, TIFF_SHORT },
 
512
        { TIFFTAG_XRESOLUTION,          1, TIFF_RATIONAL },
 
513
        { TIFFTAG_YRESOLUTION,          1, TIFF_RATIONAL },
 
514
        { TIFFTAG_PAGENAME,             1, TIFF_ASCII },
 
515
        { TIFFTAG_XPOSITION,            1, TIFF_RATIONAL },
 
516
        { TIFFTAG_YPOSITION,            1, TIFF_RATIONAL },
 
517
        { TIFFTAG_RESOLUTIONUNIT,       1, TIFF_SHORT },
 
518
        { TIFFTAG_SOFTWARE,             1, TIFF_ASCII },
 
519
        { TIFFTAG_DATETIME,             1, TIFF_ASCII },
 
520
        { TIFFTAG_ARTIST,               1, TIFF_ASCII },
 
521
        { TIFFTAG_HOSTCOMPUTER,         1, TIFF_ASCII },
 
522
        { TIFFTAG_WHITEPOINT,           (uint16) -1, TIFF_RATIONAL },
 
523
        { TIFFTAG_PRIMARYCHROMATICITIES,(uint16) -1,TIFF_RATIONAL },
 
524
        { TIFFTAG_HALFTONEHINTS,        2, TIFF_SHORT },
 
525
        { TIFFTAG_INKSET,               1, TIFF_SHORT },
 
526
        { TIFFTAG_DOTRANGE,             2, TIFF_SHORT },
 
527
        { TIFFTAG_TARGETPRINTER,        1, TIFF_ASCII },
 
528
        { TIFFTAG_SAMPLEFORMAT,         1, TIFF_SHORT },
 
529
        { TIFFTAG_YCBCRCOEFFICIENTS,    (uint16) -1,TIFF_RATIONAL },
 
530
        { TIFFTAG_YCBCRSUBSAMPLING,     2, TIFF_SHORT },
 
531
        { TIFFTAG_YCBCRPOSITIONING,     1, TIFF_SHORT },
 
532
        { TIFFTAG_REFERENCEBLACKWHITE,  (uint16) -1,TIFF_RATIONAL },
 
533
        { TIFFTAG_EXTRASAMPLES,         (uint16) -1, TIFF_SHORT },
 
534
        { TIFFTAG_SMINSAMPLEVALUE,      1, TIFF_DOUBLE },
 
535
        { TIFFTAG_SMAXSAMPLEVALUE,      1, TIFF_DOUBLE },
 
536
        { TIFFTAG_STONITS,              1, TIFF_DOUBLE },
 
537
};
 
538
#define NTAGS   (sizeof (tags) / sizeof (tags[0]))
 
539
 
 
540
#define CopyTag(tag, count, type)       cpTag(in, out, tag, count, type)
 
541
 
 
542
typedef int (*copyFunc)
 
543
    (TIFF* in, TIFF* out, uint32 l, uint32 w, uint16 samplesperpixel);
 
544
static  copyFunc pickCopyFunc(TIFF*, TIFF*, uint16, uint16);
 
545
 
 
546
static int
 
547
tiffcp(TIFF* in, TIFF* out)
 
548
{
 
549
        uint16 bitspersample, samplesperpixel;
 
550
        copyFunc cf;
 
551
        uint32 width, length;
 
552
        struct cpTag* p;
 
553
 
 
554
        CopyField(TIFFTAG_IMAGEWIDTH, width);
 
555
        CopyField(TIFFTAG_IMAGELENGTH, length);
 
556
        CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample);
 
557
        CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
 
558
        if (compression != (uint16)-1)
 
559
                TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
 
560
        else
 
561
                CopyField(TIFFTAG_COMPRESSION, compression);
 
562
        if (compression == COMPRESSION_JPEG) {
 
563
            uint16 input_compression, input_photometric;
 
564
 
 
565
            if (TIFFGetField(in, TIFFTAG_COMPRESSION, &input_compression)
 
566
                 && input_compression == COMPRESSION_JPEG) {
 
567
                TIFFSetField(in, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
 
568
            }
 
569
            if (TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &input_photometric)) {
 
570
                if(input_photometric == PHOTOMETRIC_RGB) {
 
571
                        if (jpegcolormode == JPEGCOLORMODE_RGB)
 
572
                                TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
 
573
                                             PHOTOMETRIC_YCBCR);
 
574
                        else
 
575
                                TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
 
576
                                             PHOTOMETRIC_RGB);
 
577
                } else
 
578
                        TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
 
579
                                     input_photometric);
 
580
            }
 
581
        }
 
582
        else if (compression == COMPRESSION_SGILOG
 
583
                 || compression == COMPRESSION_SGILOG24)
 
584
                TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
 
585
                    samplesperpixel == 1 ?
 
586
                        PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV);
 
587
        else
 
588
                CopyTag(TIFFTAG_PHOTOMETRIC, 1, TIFF_SHORT);
 
589
        if (fillorder != 0)
 
590
                TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
 
591
        else
 
592
                CopyTag(TIFFTAG_FILLORDER, 1, TIFF_SHORT);
 
593
        /*
 
594
         * Will copy `Orientation' tag from input image
 
595
         */
 
596
        TIFFGetFieldDefaulted(in, TIFFTAG_ORIENTATION, &orientation);
 
597
        switch (orientation) {
 
598
                case ORIENTATION_BOTRIGHT:
 
599
                case ORIENTATION_RIGHTBOT:      /* XXX */
 
600
                        TIFFWarning(TIFFFileName(in), "using bottom-left orientation");
 
601
                        orientation = ORIENTATION_BOTLEFT;
 
602
                /* fall thru... */
 
603
                case ORIENTATION_LEFTBOT:       /* XXX */
 
604
                case ORIENTATION_BOTLEFT:
 
605
                        break;
 
606
                case ORIENTATION_TOPRIGHT:
 
607
                case ORIENTATION_RIGHTTOP:      /* XXX */
 
608
                default:
 
609
                        TIFFWarning(TIFFFileName(in), "using top-left orientation");
 
610
                        orientation = ORIENTATION_TOPLEFT;
 
611
                /* fall thru... */
 
612
                case ORIENTATION_LEFTTOP:       /* XXX */
 
613
                case ORIENTATION_TOPLEFT:
 
614
                        break;
 
615
        }
 
616
        TIFFSetField(out, TIFFTAG_ORIENTATION, orientation);
 
617
        /*
 
618
         * Choose tiles/strip for the output image according to
 
619
         * the command line arguments (-tiles, -strips) and the
 
620
         * structure of the input image.
 
621
         */
 
622
        if (outtiled == -1)
 
623
                outtiled = TIFFIsTiled(in);
 
624
        if (outtiled) {
 
625
                /*
 
626
                 * Setup output file's tile width&height.  If either
 
627
                 * is not specified, use either the value from the
 
628
                 * input image or, if nothing is defined, use the
 
629
                 * library default.
 
630
                 */
 
631
                if (tilewidth == (uint32) -1)
 
632
                        TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth);
 
633
                if (tilelength == (uint32) -1)
 
634
                        TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength);
 
635
                TIFFDefaultTileSize(out, &tilewidth, &tilelength);
 
636
                TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
 
637
                TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
 
638
        } else {
 
639
                /*
 
640
                 * RowsPerStrip is left unspecified: use either the
 
641
                 * value from the input image or, if nothing is defined,
 
642
                 * use the library default.
 
643
                 */
 
644
                if (rowsperstrip == (uint32) 0) {
 
645
                        if (!TIFFGetField(in, TIFFTAG_ROWSPERSTRIP,
 
646
                                          &rowsperstrip)) {
 
647
                                rowsperstrip =
 
648
                                        TIFFDefaultStripSize(out, rowsperstrip);
 
649
                        }
 
650
                        if (rowsperstrip > length && rowsperstrip != (uint32)-1)
 
651
                                rowsperstrip = length;
 
652
                }
 
653
                else if (rowsperstrip == (uint32) -1)
 
654
                        rowsperstrip = length;
 
655
                TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
 
656
        }
 
657
        if (config != (uint16) -1)
 
658
                TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
 
659
        else
 
660
                CopyField(TIFFTAG_PLANARCONFIG, config);
 
661
        if (samplesperpixel <= 4)
 
662
                CopyTag(TIFFTAG_TRANSFERFUNCTION, 4, TIFF_SHORT);
 
663
        CopyTag(TIFFTAG_COLORMAP, 4, TIFF_SHORT);
 
664
/* SMinSampleValue & SMaxSampleValue */
 
665
        switch (compression) {
 
666
        case COMPRESSION_JPEG:
 
667
                TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
 
668
                TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
 
669
                break;
 
670
        case COMPRESSION_JBIG:
 
671
                CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
 
672
                CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
 
673
                CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
 
674
                CopyTag(TIFFTAG_FAXDCS, 1, TIFF_ASCII);
 
675
                break;
 
676
        case COMPRESSION_LZW:
 
677
        case COMPRESSION_ADOBE_DEFLATE:
 
678
        case COMPRESSION_DEFLATE:
 
679
                if (predictor != (uint16)-1)
 
680
                        TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
 
681
                else
 
682
                        CopyField(TIFFTAG_PREDICTOR, predictor);
 
683
                break;
 
684
        case COMPRESSION_CCITTFAX3:
 
685
        case COMPRESSION_CCITTFAX4:
 
686
                if (compression == COMPRESSION_CCITTFAX3) {
 
687
                        if (g3opts != (uint32) -1)
 
688
                                TIFFSetField(out, TIFFTAG_GROUP3OPTIONS,
 
689
                                    g3opts);
 
690
                        else
 
691
                                CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
 
692
                } else
 
693
                        CopyTag(TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG);
 
694
                CopyTag(TIFFTAG_BADFAXLINES, 1, TIFF_LONG);
 
695
                CopyTag(TIFFTAG_CLEANFAXDATA, 1, TIFF_LONG);
 
696
                CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG);
 
697
                CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
 
698
                CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
 
699
                CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
 
700
                break;
 
701
        }
 
702
        { uint32 len32;
 
703
          void** data;
 
704
          if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &len32, &data))
 
705
                TIFFSetField(out, TIFFTAG_ICCPROFILE, len32, data);
 
706
        }
 
707
        { uint16 ninks;
 
708
          const char* inknames;
 
709
          if (TIFFGetField(in, TIFFTAG_NUMBEROFINKS, &ninks)) {
 
710
                TIFFSetField(out, TIFFTAG_NUMBEROFINKS, ninks);
 
711
                if (TIFFGetField(in, TIFFTAG_INKNAMES, &inknames)) {
 
712
                    int inknameslen = strlen(inknames) + 1;
 
713
                    const char* cp = inknames;
 
714
                    while (ninks > 1) {
 
715
                            cp = strchr(cp, '\0');
 
716
                            if (cp) {
 
717
                                    cp++;
 
718
                                    inknameslen += (strlen(cp) + 1);
 
719
                            }
 
720
                            ninks--;
 
721
                    }
 
722
                    TIFFSetField(out, TIFFTAG_INKNAMES, inknameslen, inknames);
 
723
                }
 
724
          }
 
725
        }
 
726
        {
 
727
          unsigned short pg0, pg1;
 
728
          if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1)) {
 
729
                if (pageNum < 0) /* only one input file */
 
730
                        TIFFSetField(out, TIFFTAG_PAGENUMBER, pg0, pg1);
 
731
                else 
 
732
                        TIFFSetField(out, TIFFTAG_PAGENUMBER, pageNum++, 0);
 
733
          }
 
734
        }
 
735
 
 
736
        for (p = tags; p < &tags[NTAGS]; p++)
 
737
                CopyTag(p->tag, p->count, p->type);
 
738
 
 
739
        cf = pickCopyFunc(in, out, bitspersample, samplesperpixel);
 
740
        return (cf ? (*cf)(in, out, length, width, samplesperpixel) : FALSE);
 
741
}
 
742
 
 
743
/*
 
744
 * Copy Functions.
 
745
 */
 
746
#define DECLAREcpFunc(x) \
 
747
static int x(TIFF* in, TIFF* out, \
 
748
    uint32 imagelength, uint32 imagewidth, tsample_t spp)
 
749
 
 
750
#define DECLAREreadFunc(x) \
 
751
static int x(TIFF* in, \
 
752
    uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
 
753
typedef int (*readFunc)(TIFF*, uint8*, uint32, uint32, tsample_t);
 
754
 
 
755
#define DECLAREwriteFunc(x) \
 
756
static int x(TIFF* out, \
 
757
    uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
 
758
typedef int (*writeFunc)(TIFF*, uint8*, uint32, uint32, tsample_t);
 
759
 
 
760
/*
 
761
 * Contig -> contig by scanline for rows/strip change.
 
762
 */
 
763
DECLAREcpFunc(cpContig2ContigByRow)
 
764
{
 
765
        tdata_t buf = _TIFFmalloc(TIFFScanlineSize(in));
 
766
        uint32 row;
 
767
 
 
768
        (void) imagewidth; (void) spp;
 
769
        for (row = 0; row < imagelength; row++) {
 
770
                if (TIFFReadScanline(in, buf, row, 0) < 0 && !ignore) {
 
771
                        TIFFError(TIFFFileName(in),
 
772
                                  "Error, can't read scanline %lu",
 
773
                                  (unsigned long) row);
 
774
                        goto bad;
 
775
                }
 
776
                if (TIFFWriteScanline(out, buf, row, 0) < 0) {
 
777
                        TIFFError(TIFFFileName(out),
 
778
                                  "Error, can't write scanline %lu",
 
779
                                  (unsigned long) row);
 
780
                        goto bad;
 
781
                }
 
782
        }
 
783
        _TIFFfree(buf);
 
784
        return 1;
 
785
bad:
 
786
        _TIFFfree(buf);
 
787
        return 0;
 
788
}
 
789
 
 
790
 
 
791
typedef void biasFn (void *image, void *bias, uint32 pixels);
 
792
 
 
793
#define subtract(bits) \
 
794
static void subtract##bits (void *i, void *b, uint32 pixels)\
 
795
{\
 
796
   uint##bits *image = i;\
 
797
   uint##bits *bias = b;\
 
798
   while (pixels--) {\
 
799
     *image = *image > *bias ? *image-*bias : 0;\
 
800
     image++, bias++; \
 
801
   } \
 
802
}
 
803
 
 
804
subtract(8)
 
805
subtract(16)
 
806
subtract(32)
 
807
 
 
808
static biasFn *lineSubtractFn (unsigned bits)
 
809
{
 
810
    switch (bits) {
 
811
      case  8:  return subtract8;
 
812
      case 16:  return subtract16;
 
813
      case 32:  return subtract32;
 
814
    }
 
815
    return NULL;
 
816
}
 
817
 
 
818
/*
 
819
 * Contig -> contig by scanline while subtracting a bias image.
 
820
 */
 
821
DECLAREcpFunc(cpBiasedContig2Contig)
 
822
{
 
823
        if (spp == 1) {
 
824
          tsize_t biasSize = TIFFScanlineSize(bias);
 
825
          tsize_t bufSize = TIFFScanlineSize(in);
 
826
          tdata_t buf, biasBuf;
 
827
          uint32 biasWidth = 0, biasLength = 0;
 
828
          TIFFGetField(bias, TIFFTAG_IMAGEWIDTH, &biasWidth);
 
829
          TIFFGetField(bias, TIFFTAG_IMAGELENGTH, &biasLength);
 
830
          if (biasSize == bufSize && 
 
831
              imagelength == biasLength && imagewidth == biasWidth) {
 
832
                uint16 sampleBits = 0;
 
833
                biasFn *subtractLine;
 
834
                TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &sampleBits);
 
835
                subtractLine = lineSubtractFn (sampleBits);
 
836
                if (subtractLine) {
 
837
                        uint32 row;
 
838
                        buf = _TIFFmalloc(bufSize);
 
839
                        biasBuf = _TIFFmalloc(bufSize);
 
840
                        for (row = 0; row < imagelength; row++) {
 
841
                                if (TIFFReadScanline(in, buf, row, 0) < 0
 
842
                                    && !ignore) {
 
843
                                        TIFFError(TIFFFileName(in),
 
844
                                        "Error, can't read scanline %lu",
 
845
                                        (unsigned long) row);
 
846
                                        goto bad;
 
847
                                }
 
848
                                if (TIFFReadScanline(bias, biasBuf, row, 0) < 0
 
849
                                    && !ignore) {
 
850
                                        TIFFError(TIFFFileName(in),
 
851
                                        "Error, can't read biased scanline %lu",
 
852
                                        (unsigned long) row);
 
853
                                        goto bad;
 
854
                                }
 
855
                                subtractLine (buf, biasBuf, imagewidth);
 
856
                                if (TIFFWriteScanline(out, buf, row, 0) < 0) {
 
857
                                        TIFFError(TIFFFileName(out),
 
858
                                        "Error, can't write scanline %lu",
 
859
                                        (unsigned long) row);
 
860
                                        goto bad;
 
861
                                }
 
862
                        }
 
863
                
 
864
                        _TIFFfree(buf);
 
865
                        _TIFFfree(biasBuf);
 
866
                        TIFFSetDirectory(bias,
 
867
                                TIFFCurrentDirectory(bias)); /* rewind */
 
868
                        return 1;
 
869
bad:
 
870
                        _TIFFfree(buf);
 
871
                        _TIFFfree(biasBuf);
 
872
                        return 0;
 
873
            } else {
 
874
              TIFFError(TIFFFileName(in),
 
875
                        "No support for biasing %d bit pixels\n",
 
876
                        sampleBits);
 
877
              return 0;
 
878
            }
 
879
          }
 
880
          TIFFError(TIFFFileName(in),
 
881
                    "Bias image %s,%d\nis not the same size as %s,%d\n",
 
882
                    TIFFFileName(bias), TIFFCurrentDirectory(bias),
 
883
                    TIFFFileName(in), TIFFCurrentDirectory(in));
 
884
          return 0;
 
885
        } else {
 
886
          TIFFError(TIFFFileName(in),
 
887
                    "Can't bias %s,%d as it has >1 Sample/Pixel\n",
 
888
                    TIFFFileName(in), TIFFCurrentDirectory(in));
 
889
          return 0;
 
890
        }
 
891
 
 
892
}
 
893
 
 
894
 
 
895
/*
 
896
 * Strip -> strip for change in encoding.
 
897
 */
 
898
DECLAREcpFunc(cpDecodedStrips)
 
899
{
 
900
        tsize_t stripsize  = TIFFStripSize(in);
 
901
        tdata_t buf = _TIFFmalloc(stripsize);
 
902
 
 
903
        (void) imagewidth; (void) spp;
 
904
        if (buf) {
 
905
                tstrip_t s, ns = TIFFNumberOfStrips(in);
 
906
                uint32 row = 0;
 
907
                for (s = 0; s < ns; s++) {
 
908
                        tsize_t cc = (row + rowsperstrip > imagelength) ?
 
909
                            TIFFVStripSize(in, imagelength - row) : stripsize;
 
910
                        if (TIFFReadEncodedStrip(in, s, buf, cc) < 0
 
911
                            && !ignore) {
 
912
                                TIFFError(TIFFFileName(in),
 
913
                                          "Error, can't read strip %lu",
 
914
                                          (unsigned long) s);
 
915
                                goto bad;
 
916
                        }
 
917
                        if (TIFFWriteEncodedStrip(out, s, buf, cc) < 0) {
 
918
                                TIFFError(TIFFFileName(out),
 
919
                                          "Error, can't write strip %lu",
 
920
                                          (unsigned long) s);
 
921
                                goto bad;
 
922
                        }
 
923
                        row += rowsperstrip;
 
924
                }
 
925
                _TIFFfree(buf);
 
926
                return 1;
 
927
        } else {
 
928
                TIFFError(TIFFFileName(in),
 
929
                          "Error, can't allocate memory buffer of size %lu "
 
930
                          "to read strips", (unsigned long) stripsize);
 
931
                return 0;
 
932
        }
 
933
 
 
934
bad:
 
935
        _TIFFfree(buf);
 
936
        return 0;
 
937
}
 
938
 
 
939
/*
 
940
 * Separate -> separate by row for rows/strip change.
 
941
 */
 
942
DECLAREcpFunc(cpSeparate2SeparateByRow)
 
943
{
 
944
        tdata_t buf = _TIFFmalloc(TIFFScanlineSize(in));
 
945
        uint32 row;
 
946
        tsample_t s;
 
947
 
 
948
        (void) imagewidth;
 
949
        for (s = 0; s < spp; s++) {
 
950
                for (row = 0; row < imagelength; row++) {
 
951
                        if (TIFFReadScanline(in, buf, row, s) < 0 && !ignore) {
 
952
                                TIFFError(TIFFFileName(in),
 
953
                                          "Error, can't read scanline %lu",
 
954
                                          (unsigned long) row);
 
955
                                goto bad;
 
956
                        }
 
957
                        if (TIFFWriteScanline(out, buf, row, s) < 0) {
 
958
                                TIFFError(TIFFFileName(out),
 
959
                                          "Error, can't write scanline %lu",
 
960
                                          (unsigned long) row);
 
961
                                goto bad;
 
962
                        }
 
963
                }
 
964
        }
 
965
        _TIFFfree(buf);
 
966
        return 1;
 
967
bad:
 
968
        _TIFFfree(buf);
 
969
        return 0;
 
970
}
 
971
 
 
972
/*
 
973
 * Contig -> separate by row.
 
974
 */
 
975
DECLAREcpFunc(cpContig2SeparateByRow)
 
976
{
 
977
        tdata_t inbuf = _TIFFmalloc(TIFFScanlineSize(in));
 
978
        tdata_t outbuf = _TIFFmalloc(TIFFScanlineSize(out));
 
979
        register uint8 *inp, *outp;
 
980
        register uint32 n;
 
981
        uint32 row;
 
982
        tsample_t s;
 
983
 
 
984
        /* unpack channels */
 
985
        for (s = 0; s < spp; s++) {
 
986
                for (row = 0; row < imagelength; row++) {
 
987
                        if (TIFFReadScanline(in, inbuf, row, 0) < 0
 
988
                            && !ignore) {
 
989
                                TIFFError(TIFFFileName(in),
 
990
                                          "Error, can't read scanline %lu",
 
991
                                          (unsigned long) row);
 
992
                                goto bad;
 
993
                        }
 
994
                        inp = ((uint8*)inbuf) + s;
 
995
                        outp = (uint8*)outbuf;
 
996
                        for (n = imagewidth; n-- > 0;) {
 
997
                                *outp++ = *inp;
 
998
                                inp += spp;
 
999
                        }
 
1000
                        if (TIFFWriteScanline(out, outbuf, row, s) < 0) {
 
1001
                                TIFFError(TIFFFileName(out),
 
1002
                                          "Error, can't write scanline %lu",
 
1003
                                          (unsigned long) row);
 
1004
                                goto bad;
 
1005
                        }
 
1006
                }
 
1007
        }
 
1008
        if (inbuf) _TIFFfree(inbuf);
 
1009
        if (outbuf) _TIFFfree(outbuf);
 
1010
        return 1;
 
1011
bad:
 
1012
        if (inbuf) _TIFFfree(inbuf);
 
1013
        if (outbuf) _TIFFfree(outbuf);
 
1014
        return 0;
 
1015
}
 
1016
 
 
1017
/*
 
1018
 * Separate -> contig by row.
 
1019
 */
 
1020
DECLAREcpFunc(cpSeparate2ContigByRow)
 
1021
{
 
1022
        tdata_t inbuf = _TIFFmalloc(TIFFScanlineSize(in));
 
1023
        tdata_t outbuf = _TIFFmalloc(TIFFScanlineSize(out));
 
1024
        register uint8 *inp, *outp;
 
1025
        register uint32 n;
 
1026
        uint32 row;
 
1027
        tsample_t s;
 
1028
 
 
1029
        for (row = 0; row < imagelength; row++) {
 
1030
                /* merge channels */
 
1031
                for (s = 0; s < spp; s++) {
 
1032
                        if (TIFFReadScanline(in, inbuf, row, s) < 0
 
1033
                            && !ignore) {
 
1034
                                TIFFError(TIFFFileName(in),
 
1035
                                          "Error, can't read scanline %lu",
 
1036
                                          (unsigned long) row);
 
1037
                                goto bad;
 
1038
                        }
 
1039
                        inp = (uint8*)inbuf;
 
1040
                        outp = ((uint8*)outbuf) + s;
 
1041
                        for (n = imagewidth; n-- > 0;) {
 
1042
                                *outp = *inp++;
 
1043
                                outp += spp;
 
1044
                        }
 
1045
                }
 
1046
                if (TIFFWriteScanline(out, outbuf, row, 0) < 0) {
 
1047
                        TIFFError(TIFFFileName(out),
 
1048
                                  "Error, can't write scanline %lu",
 
1049
                                  (unsigned long) row);
 
1050
                        goto bad;
 
1051
                }
 
1052
        }
 
1053
        if (inbuf) _TIFFfree(inbuf);
 
1054
        if (outbuf) _TIFFfree(outbuf);
 
1055
        return 1;
 
1056
bad:
 
1057
        if (inbuf) _TIFFfree(inbuf);
 
1058
        if (outbuf) _TIFFfree(outbuf);
 
1059
        return 0;
 
1060
}
 
1061
 
 
1062
static void
 
1063
cpStripToTile(uint8* out, uint8* in,
 
1064
        uint32 rows, uint32 cols, int outskew, int inskew)
 
1065
{
 
1066
        while (rows-- > 0) {
 
1067
                uint32 j = cols;
 
1068
                while (j-- > 0)
 
1069
                        *out++ = *in++;
 
1070
                out += outskew;
 
1071
                in += inskew;
 
1072
        }
 
1073
}
 
1074
 
 
1075
static void
 
1076
cpContigBufToSeparateBuf(uint8* out, uint8* in,
 
1077
           uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp,
 
1078
           int bytes_per_sample )
 
1079
{
 
1080
        while (rows-- > 0) {
 
1081
                uint32 j = cols;
 
1082
                while (j-- > 0)
 
1083
                {
 
1084
                        int n = bytes_per_sample;
 
1085
 
 
1086
                        while( n-- ) {
 
1087
                            *out++ = *in++;
 
1088
                        }
 
1089
                        in += (spp-1) * bytes_per_sample;
 
1090
                }
 
1091
                out += outskew;
 
1092
                in += inskew;
 
1093
        }
 
1094
}
 
1095
 
 
1096
static void
 
1097
cpSeparateBufToContigBuf(uint8* out, uint8* in,
 
1098
        uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp,
 
1099
                         int bytes_per_sample)
 
1100
{
 
1101
        while (rows-- > 0) {
 
1102
                uint32 j = cols;
 
1103
                while (j-- > 0) {
 
1104
                        int n = bytes_per_sample;
 
1105
 
 
1106
                        while( n-- ) {
 
1107
                                *out++ = *in++;
 
1108
                        }
 
1109
                        out += (spp-1)*bytes_per_sample;
 
1110
                }
 
1111
                out += outskew;
 
1112
                in += inskew;
 
1113
        }
 
1114
}
 
1115
 
 
1116
static int
 
1117
cpImage(TIFF* in, TIFF* out, readFunc fin, writeFunc fout,
 
1118
        uint32 imagelength, uint32 imagewidth, tsample_t spp)
 
1119
{
 
1120
        int status = 0;
 
1121
        tdata_t buf = NULL;
 
1122
        tsize_t scanlinesize = TIFFRasterScanlineSize(in);
 
1123
        tsize_t bytes = scanlinesize * (tsize_t)imagelength;                                      
 
1124
        /*
 
1125
         * XXX: Check for integer overflow.
 
1126
         */
 
1127
        if (scanlinesize
 
1128
            && imagelength
 
1129
            && bytes / (tsize_t)imagelength == scanlinesize) {
 
1130
                buf = _TIFFmalloc(bytes);
 
1131
                if (buf) {
 
1132
                        if ((*fin)(in, (uint8*)buf, imagelength, 
 
1133
                                   imagewidth, spp)) {
 
1134
                                status = (*fout)(out, (uint8*)buf,
 
1135
                                                 imagelength, imagewidth, spp);
 
1136
                        }
 
1137
                        _TIFFfree(buf);
 
1138
                } else {
 
1139
                        TIFFError(TIFFFileName(in),
 
1140
                                "Error, can't allocate space for image buffer");
 
1141
                }
 
1142
        } else {
 
1143
                TIFFError(TIFFFileName(in), "Error, no space for image buffer");
 
1144
        }
 
1145
 
 
1146
        return status;
 
1147
}
 
1148
 
 
1149
DECLAREreadFunc(readContigStripsIntoBuffer)
 
1150
{
 
1151
        tsize_t scanlinesize = TIFFScanlineSize(in);
 
1152
        uint8* bufp = buf;
 
1153
        uint32 row;
 
1154
 
 
1155
        (void) imagewidth; (void) spp;
 
1156
        for (row = 0; row < imagelength; row++) {
 
1157
                if (TIFFReadScanline(in, (tdata_t) bufp, row, 0) < 0
 
1158
                    && !ignore) {
 
1159
                        TIFFError(TIFFFileName(in),
 
1160
                                  "Error, can't read scanline %lu",
 
1161
                                  (unsigned long) row);
 
1162
                        return 0;
 
1163
                }
 
1164
                bufp += scanlinesize;
 
1165
        }
 
1166
 
 
1167
        return 1;
 
1168
}
 
1169
 
 
1170
DECLAREreadFunc(readSeparateStripsIntoBuffer)
 
1171
{
 
1172
        int status = 1;
 
1173
        tsize_t scanlinesize = TIFFScanlineSize(in);
 
1174
        tdata_t scanline = _TIFFmalloc(scanlinesize);
 
1175
        if (!scanlinesize)
 
1176
                return 0;
 
1177
 
 
1178
        (void) imagewidth;
 
1179
        if (scanline) {
 
1180
                uint8* bufp = (uint8*) buf;
 
1181
                uint32 row;
 
1182
                tsample_t s;
 
1183
                for (row = 0; row < imagelength; row++) {
 
1184
                        /* merge channels */
 
1185
                        for (s = 0; s < spp; s++) {
 
1186
                                uint8* bp = bufp + s;
 
1187
                                tsize_t n = scanlinesize;
 
1188
                                uint8* sbuf = scanline;
 
1189
 
 
1190
                                if (TIFFReadScanline(in, scanline, row, s) < 0
 
1191
                                    && !ignore) {
 
1192
                                        TIFFError(TIFFFileName(in),
 
1193
                                        "Error, can't read scanline %lu",
 
1194
                                        (unsigned long) row);
 
1195
                                        status = 0;
 
1196
                                        goto done;
 
1197
                                }
 
1198
                                while (n-- > 0)
 
1199
                                        *bp = *sbuf++, bp += spp;
 
1200
                        }
 
1201
                        bufp += scanlinesize * spp;
 
1202
                }
 
1203
        }
 
1204
 
 
1205
done:
 
1206
        _TIFFfree(scanline);
 
1207
        return status;
 
1208
}
 
1209
 
 
1210
DECLAREreadFunc(readContigTilesIntoBuffer)
 
1211
{
 
1212
        int status = 1;
 
1213
        tdata_t tilebuf = _TIFFmalloc(TIFFTileSize(in));
 
1214
        uint32 imagew = TIFFScanlineSize(in);
 
1215
        uint32 tilew  = TIFFTileRowSize(in);
 
1216
        int iskew = imagew - tilew;
 
1217
        uint8* bufp = (uint8*) buf;
 
1218
        uint32 tw, tl;
 
1219
        uint32 row;
 
1220
 
 
1221
        (void) spp;
 
1222
        if (tilebuf == 0)
 
1223
                return 0;
 
1224
        (void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
 
1225
        (void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
 
1226
        
 
1227
        for (row = 0; row < imagelength; row += tl) {
 
1228
                uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
 
1229
                uint32 colb = 0;
 
1230
                uint32 col;
 
1231
 
 
1232
                for (col = 0; col < imagewidth; col += tw) {
 
1233
                        if (TIFFReadTile(in, tilebuf, col, row, 0, 0) < 0
 
1234
                            && !ignore) {
 
1235
                                TIFFError(TIFFFileName(in),
 
1236
                                          "Error, can't read tile at %lu %lu",
 
1237
                                          (unsigned long) col,
 
1238
                                          (unsigned long) row);
 
1239
                                status = 0;
 
1240
                                goto done;
 
1241
                        }
 
1242
                        if (colb + tilew > imagew) {
 
1243
                                uint32 width = imagew - colb;
 
1244
                                uint32 oskew = tilew - width;
 
1245
                                cpStripToTile(bufp + colb,
 
1246
                                              tilebuf, nrow, width,
 
1247
                                              oskew + iskew, oskew );
 
1248
                        } else
 
1249
                                cpStripToTile(bufp + colb,
 
1250
                                              tilebuf, nrow, tilew,
 
1251
                                              iskew, 0);
 
1252
                        colb += tilew;
 
1253
                }
 
1254
                bufp += imagew * nrow;
 
1255
        }
 
1256
done:
 
1257
        _TIFFfree(tilebuf);
 
1258
        return status;
 
1259
}
 
1260
 
 
1261
DECLAREreadFunc(readSeparateTilesIntoBuffer)
 
1262
{
 
1263
        int status = 1;
 
1264
        uint32 imagew = TIFFRasterScanlineSize(in);
 
1265
        uint32 tilew = TIFFTileRowSize(in);
 
1266
        int iskew  = imagew - tilew*spp;
 
1267
        tdata_t tilebuf = _TIFFmalloc(TIFFTileSize(in));
 
1268
        uint8* bufp = (uint8*) buf;
 
1269
        uint32 tw, tl;
 
1270
        uint32 row;
 
1271
        uint16 bps, bytes_per_sample;
 
1272
 
 
1273
        if (tilebuf == 0)
 
1274
                return 0;
 
1275
        (void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
 
1276
        (void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
 
1277
        (void) TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps);
 
1278
        assert( bps % 8 == 0 );
 
1279
        bytes_per_sample = bps/8;
 
1280
 
 
1281
        for (row = 0; row < imagelength; row += tl) {
 
1282
                uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
 
1283
                uint32 colb = 0;
 
1284
                uint32 col;
 
1285
 
 
1286
                for (col = 0; col < imagewidth; col += tw) {
 
1287
                        tsample_t s;
 
1288
 
 
1289
                        for (s = 0; s < spp; s++) {
 
1290
                                if (TIFFReadTile(in, tilebuf, col, row, 0, s) < 0
 
1291
                                    && !ignore) {
 
1292
                                        TIFFError(TIFFFileName(in),
 
1293
                                          "Error, can't read tile at %lu %lu, "
 
1294
                                          "sample %lu",
 
1295
                                          (unsigned long) col,
 
1296
                                          (unsigned long) row,
 
1297
                                          (unsigned long) s);
 
1298
                                        status = 0;
 
1299
                                        goto done;
 
1300
                                }
 
1301
                                /*
 
1302
                                 * Tile is clipped horizontally.  Calculate
 
1303
                                 * visible portion and skewing factors.
 
1304
                                 */
 
1305
                                if (colb + tilew*spp > imagew) {
 
1306
                                        uint32 width = imagew - colb;
 
1307
                                        int oskew = tilew*spp - width;
 
1308
                                        cpSeparateBufToContigBuf(
 
1309
                                            bufp+colb+s*bytes_per_sample,
 
1310
                                            tilebuf, nrow,
 
1311
                                            width/(spp*bytes_per_sample),
 
1312
                                            oskew + iskew,
 
1313
                                            oskew/spp, spp,
 
1314
                                            bytes_per_sample);
 
1315
                                } else
 
1316
                                        cpSeparateBufToContigBuf(
 
1317
                                            bufp+colb+s*bytes_per_sample,
 
1318
                                            tilebuf, nrow, tw,
 
1319
                                            iskew, 0, spp,
 
1320
                                            bytes_per_sample);
 
1321
                        }
 
1322
                        colb += tilew*spp;
 
1323
                }
 
1324
                bufp += imagew * nrow;
 
1325
        }
 
1326
done:
 
1327
        _TIFFfree(tilebuf);
 
1328
        return status;
 
1329
}
 
1330
 
 
1331
DECLAREwriteFunc(writeBufferToContigStrips)
 
1332
{
 
1333
        uint32 row, rowsperstrip;
 
1334
        tstrip_t strip = 0;
 
1335
 
 
1336
        (void) imagewidth; (void) spp;
 
1337
        (void) TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
 
1338
        for (row = 0; row < imagelength; row += rowsperstrip) {
 
1339
                uint32 nrows = (row+rowsperstrip > imagelength) ?
 
1340
                    imagelength-row : rowsperstrip;
 
1341
                tsize_t stripsize = TIFFVStripSize(out, nrows);
 
1342
                if (TIFFWriteEncodedStrip(out, strip++, buf, stripsize) < 0) {
 
1343
                        TIFFError(TIFFFileName(out),
 
1344
                                  "Error, can't write strip %u", strip - 1);
 
1345
                        return 0;
 
1346
                }
 
1347
                buf += stripsize;
 
1348
        }
 
1349
        return 1;
 
1350
}
 
1351
 
 
1352
DECLAREwriteFunc(writeBufferToSeparateStrips)
 
1353
{
 
1354
        uint32 rowsize = imagewidth * spp;
 
1355
        uint32 rowsperstrip;
 
1356
        tdata_t obuf = _TIFFmalloc(TIFFStripSize(out));
 
1357
        tstrip_t strip = 0;
 
1358
        tsample_t s;
 
1359
 
 
1360
        if (obuf == NULL)
 
1361
                return (0);
 
1362
        (void) TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
 
1363
        for (s = 0; s < spp; s++) {
 
1364
                uint32 row;
 
1365
                for (row = 0; row < imagelength; row += rowsperstrip) {
 
1366
                        uint32 nrows = (row+rowsperstrip > imagelength) ?
 
1367
                            imagelength-row : rowsperstrip;
 
1368
                        tsize_t stripsize = TIFFVStripSize(out, nrows);
 
1369
 
 
1370
                        cpContigBufToSeparateBuf(
 
1371
                            obuf, (uint8*) buf + row*rowsize + s, 
 
1372
                            nrows, imagewidth, 0, 0, spp, 1);
 
1373
                        if (TIFFWriteEncodedStrip(out, strip++, obuf, stripsize) < 0) {
 
1374
                                TIFFError(TIFFFileName(out),
 
1375
                                          "Error, can't write strip %u",
 
1376
                                          strip - 1);
 
1377
                                _TIFFfree(obuf);
 
1378
                                return 0;
 
1379
                        }
 
1380
                }
 
1381
        }
 
1382
        _TIFFfree(obuf);
 
1383
        return 1;
 
1384
 
 
1385
}
 
1386
 
 
1387
DECLAREwriteFunc(writeBufferToContigTiles)
 
1388
{
 
1389
        uint32 imagew = TIFFScanlineSize(out);
 
1390
        uint32 tilew  = TIFFTileRowSize(out);
 
1391
        int iskew = imagew - tilew;
 
1392
        tdata_t obuf = _TIFFmalloc(TIFFTileSize(out));
 
1393
        uint8* bufp = (uint8*) buf;
 
1394
        uint32 tl, tw;
 
1395
        uint32 row;
 
1396
 
 
1397
        (void) spp;
 
1398
        if (obuf == NULL)
 
1399
                return 0;
 
1400
        (void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
 
1401
        (void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
 
1402
        for (row = 0; row < imagelength; row += tilelength) {
 
1403
                uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
 
1404
                uint32 colb = 0;
 
1405
                uint32 col;
 
1406
 
 
1407
                for (col = 0; col < imagewidth; col += tw) {
 
1408
                        /*
 
1409
                         * Tile is clipped horizontally.  Calculate
 
1410
                         * visible portion and skewing factors.
 
1411
                         */
 
1412
                        if (colb + tilew > imagew) {
 
1413
                                uint32 width = imagew - colb;
 
1414
                                int oskew = tilew - width;
 
1415
                                cpStripToTile(obuf, bufp + colb, nrow, width,
 
1416
                                    oskew, oskew + iskew);
 
1417
                        } else
 
1418
                                cpStripToTile(obuf, bufp + colb, nrow, tilew,
 
1419
                                    0, iskew);
 
1420
                        if (TIFFWriteTile(out, obuf, col, row, 0, 0) < 0) {
 
1421
                                TIFFError(TIFFFileName(out),
 
1422
                                          "Error, can't write tile at %lu %lu",
 
1423
                                          (unsigned long) col,
 
1424
                                          (unsigned long) row);
 
1425
                                _TIFFfree(obuf);
 
1426
                                return 0;
 
1427
                        }
 
1428
                        colb += tilew;
 
1429
                }
 
1430
                bufp += nrow * imagew;
 
1431
        }
 
1432
        _TIFFfree(obuf);
 
1433
        return 1;
 
1434
}
 
1435
 
 
1436
DECLAREwriteFunc(writeBufferToSeparateTiles)
 
1437
{
 
1438
        uint32 imagew = TIFFScanlineSize(out);
 
1439
        tsize_t tilew  = TIFFTileRowSize(out);
 
1440
        uint32 iimagew = TIFFRasterScanlineSize(out);
 
1441
        int iskew = iimagew - tilew*spp;
 
1442
        tdata_t obuf = _TIFFmalloc(TIFFTileSize(out));
 
1443
        uint8* bufp = (uint8*) buf;
 
1444
        uint32 tl, tw;
 
1445
        uint32 row;
 
1446
        uint16 bps, bytes_per_sample;
 
1447
 
 
1448
        if (obuf == NULL)
 
1449
                return 0;
 
1450
        (void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
 
1451
        (void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
 
1452
        (void) TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps);
 
1453
        assert( bps % 8 == 0 );
 
1454
        bytes_per_sample = bps/8;
 
1455
        
 
1456
        for (row = 0; row < imagelength; row += tl) {
 
1457
                uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
 
1458
                uint32 colb = 0;
 
1459
                uint32 col;
 
1460
 
 
1461
                for (col = 0; col < imagewidth; col += tw) {
 
1462
                        tsample_t s;
 
1463
                        for (s = 0; s < spp; s++) {
 
1464
                                /*
 
1465
                                 * Tile is clipped horizontally.  Calculate
 
1466
                                 * visible portion and skewing factors.
 
1467
                                 */
 
1468
                                if (colb + tilew > imagew) {
 
1469
                                        uint32 width = (imagew - colb);
 
1470
                                        int oskew = tilew - width;
 
1471
 
 
1472
                                        cpContigBufToSeparateBuf(obuf,
 
1473
                                            bufp + (colb*spp) + s,
 
1474
                                            nrow, width/bytes_per_sample,
 
1475
                                            oskew, (oskew*spp)+iskew, spp,
 
1476
                                            bytes_per_sample);
 
1477
                                } else
 
1478
                                        cpContigBufToSeparateBuf(obuf,
 
1479
                                            bufp + (colb*spp) + s,
 
1480
                                            nrow, tilewidth,
 
1481
                                            0, iskew, spp,
 
1482
                                            bytes_per_sample);
 
1483
                                if (TIFFWriteTile(out, obuf, col, row, 0, s) < 0) {
 
1484
                                        TIFFError(TIFFFileName(out),
 
1485
                                        "Error, can't write tile at %lu %lu "
 
1486
                                        "sample %lu",
 
1487
                                        (unsigned long) col,
 
1488
                                        (unsigned long) row,
 
1489
                                        (unsigned long) s);
 
1490
                                        _TIFFfree(obuf);
 
1491
                                        return 0;
 
1492
                                }
 
1493
                        }
 
1494
                        colb += tilew;
 
1495
                }
 
1496
                bufp += nrow * iimagew;
 
1497
        }
 
1498
        _TIFFfree(obuf);
 
1499
        return 1;
 
1500
}
 
1501
 
 
1502
/*
 
1503
 * Contig strips -> contig tiles.
 
1504
 */
 
1505
DECLAREcpFunc(cpContigStrips2ContigTiles)
 
1506
{
 
1507
        return cpImage(in, out,
 
1508
            readContigStripsIntoBuffer,
 
1509
            writeBufferToContigTiles,
 
1510
            imagelength, imagewidth, spp);
 
1511
}
 
1512
 
 
1513
/*
 
1514
 * Contig strips -> separate tiles.
 
1515
 */
 
1516
DECLAREcpFunc(cpContigStrips2SeparateTiles)
 
1517
{
 
1518
        return cpImage(in, out,
 
1519
            readContigStripsIntoBuffer,
 
1520
            writeBufferToSeparateTiles,
 
1521
            imagelength, imagewidth, spp);
 
1522
}
 
1523
 
 
1524
/*
 
1525
 * Separate strips -> contig tiles.
 
1526
 */
 
1527
DECLAREcpFunc(cpSeparateStrips2ContigTiles)
 
1528
{
 
1529
        return cpImage(in, out,
 
1530
            readSeparateStripsIntoBuffer,
 
1531
            writeBufferToContigTiles,
 
1532
            imagelength, imagewidth, spp);
 
1533
}
 
1534
 
 
1535
/*
 
1536
 * Separate strips -> separate tiles.
 
1537
 */
 
1538
DECLAREcpFunc(cpSeparateStrips2SeparateTiles)
 
1539
{
 
1540
        return cpImage(in, out,
 
1541
            readSeparateStripsIntoBuffer,
 
1542
            writeBufferToSeparateTiles,
 
1543
            imagelength, imagewidth, spp);
 
1544
}
 
1545
 
 
1546
/*
 
1547
 * Contig strips -> contig tiles.
 
1548
 */
 
1549
DECLAREcpFunc(cpContigTiles2ContigTiles)
 
1550
{
 
1551
        return cpImage(in, out,
 
1552
            readContigTilesIntoBuffer,
 
1553
            writeBufferToContigTiles,
 
1554
            imagelength, imagewidth, spp);
 
1555
}
 
1556
 
 
1557
/*
 
1558
 * Contig tiles -> separate tiles.
 
1559
 */
 
1560
DECLAREcpFunc(cpContigTiles2SeparateTiles)
 
1561
{
 
1562
        return cpImage(in, out,
 
1563
            readContigTilesIntoBuffer,
 
1564
            writeBufferToSeparateTiles,
 
1565
            imagelength, imagewidth, spp);
 
1566
}
 
1567
 
 
1568
/*
 
1569
 * Separate tiles -> contig tiles.
 
1570
 */
 
1571
DECLAREcpFunc(cpSeparateTiles2ContigTiles)
 
1572
{
 
1573
        return cpImage(in, out,
 
1574
            readSeparateTilesIntoBuffer,
 
1575
            writeBufferToContigTiles,
 
1576
            imagelength, imagewidth, spp);
 
1577
}
 
1578
 
 
1579
/*
 
1580
 * Separate tiles -> separate tiles (tile dimension change).
 
1581
 */
 
1582
DECLAREcpFunc(cpSeparateTiles2SeparateTiles)
 
1583
{
 
1584
        return cpImage(in, out,
 
1585
            readSeparateTilesIntoBuffer,
 
1586
            writeBufferToSeparateTiles,
 
1587
            imagelength, imagewidth, spp);
 
1588
}
 
1589
 
 
1590
/*
 
1591
 * Contig tiles -> contig tiles (tile dimension change).
 
1592
 */
 
1593
DECLAREcpFunc(cpContigTiles2ContigStrips)
 
1594
{
 
1595
        return cpImage(in, out,
 
1596
            readContigTilesIntoBuffer,
 
1597
            writeBufferToContigStrips,
 
1598
            imagelength, imagewidth, spp);
 
1599
}
 
1600
 
 
1601
/*
 
1602
 * Contig tiles -> separate strips.
 
1603
 */
 
1604
DECLAREcpFunc(cpContigTiles2SeparateStrips)
 
1605
{
 
1606
        return cpImage(in, out,
 
1607
            readContigTilesIntoBuffer,
 
1608
            writeBufferToSeparateStrips,
 
1609
            imagelength, imagewidth, spp);
 
1610
}
 
1611
 
 
1612
/*
 
1613
 * Separate tiles -> contig strips.
 
1614
 */
 
1615
DECLAREcpFunc(cpSeparateTiles2ContigStrips)
 
1616
{
 
1617
        return cpImage(in, out,
 
1618
            readSeparateTilesIntoBuffer,
 
1619
            writeBufferToContigStrips,
 
1620
            imagelength, imagewidth, spp);
 
1621
}
 
1622
 
 
1623
/*
 
1624
 * Separate tiles -> separate strips.
 
1625
 */
 
1626
DECLAREcpFunc(cpSeparateTiles2SeparateStrips)
 
1627
{
 
1628
        return cpImage(in, out,
 
1629
            readSeparateTilesIntoBuffer,
 
1630
            writeBufferToSeparateStrips,
 
1631
            imagelength, imagewidth, spp);
 
1632
}
 
1633
 
 
1634
/*
 
1635
 * Select the appropriate copy function to use.
 
1636
 */
 
1637
static copyFunc
 
1638
pickCopyFunc(TIFF* in, TIFF* out, uint16 bitspersample, uint16 samplesperpixel)
 
1639
{
 
1640
        uint16 shortv;
 
1641
        uint32 w, l, tw, tl;
 
1642
        int bychunk;
 
1643
 
 
1644
        (void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
 
1645
        if (shortv != config && bitspersample != 8 && samplesperpixel > 1) {
 
1646
                fprintf(stderr,
 
1647
"%s: Cannot handle different planar configuration w/ bits/sample != 8\n",
 
1648
                    TIFFFileName(in));
 
1649
                return (NULL);
 
1650
        }
 
1651
        TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w);
 
1652
        TIFFGetField(in, TIFFTAG_IMAGELENGTH, &l);
 
1653
        if (!(TIFFIsTiled(out) || TIFFIsTiled(in))) {
 
1654
            uint32 irps = (uint32) -1L;
 
1655
            TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &irps);
 
1656
            /* if biased, force decoded copying to allow image subtraction */
 
1657
            bychunk = !bias && (rowsperstrip == irps);
 
1658
        }else{  /* either in or out is tiled */
 
1659
            if (bias) {
 
1660
                  fprintf(stderr,
 
1661
"%s: Cannot handle tiled configuration w/bias image\n",
 
1662
                  TIFFFileName(in));
 
1663
                  return (NULL);
 
1664
            }
 
1665
            if (TIFFIsTiled(out)) {
 
1666
                if (!TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw))
 
1667
                        tw = w;
 
1668
                if (!TIFFGetField(in, TIFFTAG_TILELENGTH, &tl))
 
1669
                        tl = l;
 
1670
                bychunk = (tw == tilewidth && tl == tilelength);
 
1671
            } else {  /* out's not, so in must be tiled */
 
1672
                TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
 
1673
                TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
 
1674
                bychunk = (tw == w && tl == rowsperstrip);
 
1675
            }
 
1676
        }
 
1677
#define T 1
 
1678
#define F 0
 
1679
#define pack(a,b,c,d,e) ((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
 
1680
        switch(pack(shortv,config,TIFFIsTiled(in),TIFFIsTiled(out),bychunk)) {
 
1681
/* Strips -> Tiles */
 
1682
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,F):
 
1683
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,T):
 
1684
                return cpContigStrips2ContigTiles;
 
1685
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,F):
 
1686
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,T):
 
1687
                return cpContigStrips2SeparateTiles;
 
1688
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,F):
 
1689
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,T):
 
1690
                return cpSeparateStrips2ContigTiles;
 
1691
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,F):
 
1692
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,T):
 
1693
                return cpSeparateStrips2SeparateTiles;
 
1694
/* Tiles -> Tiles */
 
1695
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,F):
 
1696
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,T):
 
1697
                return cpContigTiles2ContigTiles;
 
1698
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,F):
 
1699
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,T):
 
1700
                return cpContigTiles2SeparateTiles;
 
1701
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,F):
 
1702
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,T):
 
1703
                return cpSeparateTiles2ContigTiles;
 
1704
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,F):
 
1705
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,T):
 
1706
                return cpSeparateTiles2SeparateTiles;
 
1707
/* Tiles -> Strips */
 
1708
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,F):
 
1709
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,T):
 
1710
                return cpContigTiles2ContigStrips;
 
1711
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,F):
 
1712
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,T):
 
1713
                return cpContigTiles2SeparateStrips;
 
1714
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,F):
 
1715
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,T):
 
1716
                return cpSeparateTiles2ContigStrips;
 
1717
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,F):
 
1718
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,T):
 
1719
                return cpSeparateTiles2SeparateStrips;
 
1720
/* Strips -> Strips */
 
1721
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,F):
 
1722
                return bias ? cpBiasedContig2Contig : cpContig2ContigByRow;
 
1723
        case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,T):
 
1724
                return cpDecodedStrips;
 
1725
        case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,F):
 
1726
        case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,T):
 
1727
                return cpContig2SeparateByRow;
 
1728
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,F):
 
1729
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,T):
 
1730
                return cpSeparate2ContigByRow;
 
1731
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,F):
 
1732
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,T):
 
1733
                return cpSeparate2SeparateByRow;
 
1734
        }
 
1735
#undef pack
 
1736
#undef F
 
1737
#undef T
 
1738
        fprintf(stderr, "tiffcp: %s: Don't know how to copy/convert image.\n",
 
1739
            TIFFFileName(in));
 
1740
        return (NULL);
 
1741
}
 
1742
 
 
1743
/* vim: set ts=8 sts=8 sw=8 noet: */