~ubuntu-branches/ubuntu/precise/tiff/precise-security

« back to all changes in this revision

Viewing changes to .pc/CVE-2014-81xx-2.patch/tools/tiffcp.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2015-03-30 08:11:18 UTC
  • Revision ID: package-import@ubuntu.com-20150330081118-bvaoaii1act27voq
Tags: 3.9.5-2ubuntu1.7
* SECURITY UPDATE: Fix multiple security issues
  - debian/patches/CVE-2014-81xx-1.patch to CVE-2014-81xx-11.patch
  - debian/patches/CVE-2014-8128-5.patch
  - debian/patches/CVE-2014-9655-1.patch to CVE-2014-9655-3.patch
  - debian/patches/read_overrun.patch
  - debian/patches/CVE-2014-8130.patch
  - CVE-2014-8127 (partially)
  - CVE-2014-8128
  - CVE-2014-8129
  - CVE-2014-8130
  - CVE-2014-9330
  - CVE-2014-9655

Show diffs side-by-side

added added

removed removed

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