Coverage Report

Created: 2026-05-24 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/tiff.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2026 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
5
%
6
% This program is covered by multiple licenses, which are described in
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9
%
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11
%                                                                             %
12
%                                                                             %
13
%                                                                             %
14
%                        TTTTT  IIIII  FFFFF  FFFFF                           %
15
%                          T      I    F      F                               %
16
%                          T      I    FFF    FFF                             %
17
%                          T      I    F      F                               %
18
%                          T    IIIII  F      F                               %
19
%                                                                             %
20
%                                                                             %
21
%                       Read/Write TIFF Image Format.                         %
22
%                                                                             %
23
%                                                                             %
24
%                        Original Software Design                             %
25
%                                John Cristy                                  %
26
%                                 July 1992                                   %
27
%                     Re-Written For GraphicsMagick                           %
28
%                             Bob Friesenhahn                                 %
29
%                                2002-2015                                    %
30
%                             Jaroslav Fojtik                                 %
31
%                                2023-2024                                    %
32
%                                                                             %
33
%                                                                             %
34
%                                                                             %
35
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36
%
37
%
38
*/
39

40
/*
41
  Include declarations.
42
*/
43
#include "magick/studio.h"
44
#include "magick/analyze.h"
45
#include "magick/attribute.h"
46
#include "magick/bit_stream.h"
47
#include "magick/blob.h"
48
#include "magick/colormap.h"
49
#include "magick/constitute.h"
50
#include "magick/log.h"
51
#include "magick/magick.h"
52
#include "magick/monitor.h"
53
#include "magick/pixel_cache.h"
54
#include "magick/profile.h"
55
#include "magick/quantize.h"
56
#include "magick/resize.h"
57
#include "magick/resource.h"
58
#include "magick/tempfile.h"
59
#include "magick/tsd.h"
60
#include "magick/utility.h"
61
#include "magick/version.h"
62
#include "magick/static.h"
63
#if defined(HasTIFF)
64
#  if defined(HAVE_TIFFCONF_H)
65
#    include "tiffconf.h"
66
#  endif
67
#  include "tiff.h"
68
#  include "tiffio.h"
69
#  if !defined(COMPRESSION_ADOBE_DEFLATE)
70
#     define COMPRESSION_ADOBE_DEFLATE  8
71
#  endif  /* !defined(COMPRESSION_ADOBE_DEFLATE) */
72
#  if defined(COMPRESSION_ZSTD) && defined(HasZSTD)
73
#    include "zstd.h"
74
#  endif /* if defined(COMPRESSION_ZSTD) && defined(HasZSTD) */
75
76
#if !defined(EXPERIMENTAL_EXIF_TAGS)
77
#  define EXPERIMENTAL_EXIF_TAGS 1
78
#endif /* if !defined(EXPERIMENTAL_EXIF_TAGS) */
79
80
/*
81
  JPEG headers are needed in order to obtain BITS_IN_JSAMPLE
82
*/
83
#  if !defined(_VISUALC_)
84
#    if defined(HasJPEG)
85
#      if defined(__MINGW32__)
86
#         define XMD_H 1
87
#      endif
88
#      undef HAVE_STDLIB_H
89
#      include <jpeglib.h>
90
#    endif /* defined(HasJPEG) */
91
#  endif /* !defined(_VISUALC_) */
92
93
#if defined(TIFF_VERSION_BIG)
94
#  define HasBigTIFF 1
95
#endif /* defined(TIFF_BIGTIFF_VERSION) */
96
97
#if (TIFFLIB_VERSION >= 20201219)
98
#  undef uint16
99
1.04M
#  define uint16 uint16_t
100
#  undef uint32
101
996k
#  define uint32 uint32_t
102
#endif /* TIFFLIB_VERSION */
103
104
/*
105
  Set to 1 in order to log low-level BLOB I/O at "coder" level.
106
*/
107
#if !defined(LOG_TIFF_BLOB_IO)
108
#  define LOG_TIFF_BLOB_IO 0
109
#endif /* !defined(LOG_TIFF_BLOB_IO) */
110
111
/*
112
  The number of bytes to try to allocate per uncompressed strip by default.
113
  This is used to determine the default number of rows per strip.
114
115
  Target that each uncompressed strip is ~1MB.
116
 */
117
#if !defined(TIFF_BYTES_PER_STRIP)
118
34.0k
#  define TIFF_BYTES_PER_STRIP 1048576
119
#endif /* !defined(TIFF_BYTES_PER_STRIP) */
120
121
#if !defined(PREDICTOR_NONE)
122
#define     PREDICTOR_NONE              1
123
#endif
124
#if !defined(PREDICTOR_HORIZONTAL)
125
#define     PREDICTOR_HORIZONTAL        2
126
#endif
127
#if !defined(PREDICTOR_FLOATINGPOINT)
128
#define     PREDICTOR_FLOATINGPOINT     3
129
#endif
130
#if !defined(SAMPLEFORMAT_COMPLEXINT)
131
#define     SAMPLEFORMAT_COMPLEXINT     5
132
#endif
133
#if !defined(SAMPLEFORMAT_COMPLEXIEEEFP)
134
#define     SAMPLEFORMAT_COMPLEXIEEEFP  6
135
#endif
136
137
#if !defined(TIFFTAG_COPYRIGHT)
138
#define     TIFFTAG_COPYRIGHT 33432
139
#endif
140
#if !defined(TIFFTAG_OPIIMAGEID)
141
#define     TIFFTAG_OPIIMAGEID 32781
142
#endif
143

144
/*
145
  Global declarations.
146
*/
147
static MagickTsdKey_t tsd_key = (MagickTsdKey_t) 0;
148
149
/* static ExceptionInfo */
150
/*   *tiff_exception; */
151
152
typedef struct _Magick_TIFF_ClientData
153
{
154
  Image
155
    *image;
156
157
  const ImageInfo
158
    *image_info;
159
} Magick_TIFF_ClientData;
160

161
/*
162
  Forward declarations.
163
*/
164
#if defined(__cplusplus) || defined(c_plusplus)
165
extern "C" {
166
#endif
167
168
static tsize_t
169
  TIFFReadBlob(thandle_t,tdata_t,tsize_t);
170
171
static MagickPassFail
172
  WriteGROUP4RAWImage(const ImageInfo *image_info,Image *image),
173
  WritePTIFImage(const ImageInfo *,Image *),
174
  WriteTIFFImage(const ImageInfo *,Image *);
175
176
#if defined(__cplusplus) || defined(c_plusplus)
177
}
178
#endif
179

180
/*
181
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
182
%                                                                             %
183
%                                                                             %
184
%                                                                             %
185
%   I s T I F F                                                               %
186
%                                                                             %
187
%                                                                             %
188
%                                                                             %
189
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190
%
191
%  Method IsTIFF returns True if the image format type, identified by the
192
%  magick string, is TIFF.
193
%
194
%  The format of the IsTIFF method is:
195
%
196
%      MagickBool IsTIFF(const unsigned char *magick,const size_t length)
197
%
198
%  A description of each parameter follows:
199
%
200
%    o status:  Method IsTIFF returns MagickTrue if the image format type
201
%               is TIFF.
202
%
203
%    o magick: This string is generally the first few bytes of an image file
204
%      or blob.
205
%
206
%    o length: Specifies the length of the magick string.
207
%
208
%
209
*/
210
static MagickBool
211
IsTIFF(const unsigned char *magick,const size_t length)
212
0
{
213
0
  if (length < 8)
214
0
    return(False);
215
216
  /* Big endian Classic TIFF*/
217
0
  if (memcmp(magick,"\115\115\000\052",4) == 0)
218
0
    return(True);
219
220
  /* Little endian Classic TIFF */
221
0
  if (memcmp(magick,"\111\111\052\000",4) == 0)
222
0
    return(True);
223
224
0
#if defined(HasBigTIFF)
225
  /*
226
   * From http://www.remotesensing.org/libtiff/bigtiffdesign.html
227
   *
228
   * * The Version ID, in header bytes 2-3, formerly decimal 42, now changes to 43
229
   * * Header bytes 4-5 contain the decimal number 8.
230
   *   - If there is some other number here, a reader should give up.
231
   *   - This is to provide a nice way to move to 16-byte pointers some day.
232
   *
233
   * * Header bytes 6-7 are reserved and must be zero.
234
   *    - If they're not, a reader should give up.
235
   *
236
   * Also http://www.awaresystems.be/imaging/tiff/bigtiff.html
237
   */
238
239
  /* Big endian BigTIFF*/
240
0
  if (memcmp(magick,"\115\115\000\053\000\010\000\000",8) == 0)
241
0
    return(True);
242
243
  /* Little endian BigTIFF */
244
0
  if (memcmp(magick,"\111\111\053\000\010\000\000\000",8) == 0)
245
0
    return(True);
246
0
#endif
247
248
0
  return(False);
249
0
}
250

251
/*
252
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253
%                                                                             %
254
%                                                                             %
255
%                                                                             %
256
%   R e a d T I F F I m a g e                                                 %
257
%                                                                             %
258
%                                                                             %
259
%                                                                             %
260
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261
%
262
%  Method ReadTIFFImage reads a Tagged image file and returns it.  It
263
%  allocates the memory necessary for the new Image structure and returns a
264
%  pointer to the new image.
265
%
266
%  The format of the ReadTIFFImage method is:
267
%
268
%      Image *ReadTIFFImage(const ImageInfo *image_info,
269
%        ExceptionInfo *exception)
270
%
271
%  A description of each parameter follows:
272
%
273
%    o image:  Method ReadTIFFImage returns a pointer to the image after
274
%      reading.  A null image is returned if there is a memory shortage or
275
%      if the image cannot be read.
276
%
277
%    o image_info: Specifies a pointer to a ImageInfo structure.
278
%
279
%    o exception: return any errors or warnings in this structure.
280
%
281
%
282
*/
283
#if defined(HAVE_TIFFMERGEFIELDINFO) && defined(HAVE_TIFFSETTAGEXTENDER)
284
#  define EXTEND_TIFF_TAGS 1
285
#  if !defined(TIFFTAG_EXIFIFD)
286
#    define TIFFTAG_EXIFIFD 34665
287
#  endif
288
#  if TIFFLIB_VERSION < 20050704
289
/* It seems that support was added for the EXIFIFDOffset tag in
290
   libtiff release 3-7-3 which corresponds with TIFFLIB_VERSION
291
   20050704 */
292
static const TIFFFieldInfo
293
  ExtensionTiffFieldInfo[] =
294
  {
295
    {
296
      TIFFTAG_EXIFIFD, -1, -1, TIFF_LONG, FIELD_CUSTOM,
297
      MagickFalse, MagickTrue, "EXIFIFDOffset"
298
    }
299
  };
300
#  endif
301
302
/*
303
  Ignore specific tags
304
*/
305
static void
306
TIFFIgnoreTags(TIFF *tiff)
307
847k
{
308
847k
  char
309
847k
    *q;
310
311
847k
  const char
312
847k
    *p,
313
847k
    *tags;
314
315
847k
  Magick_TIFF_ClientData
316
847k
    *client_data;
317
318
847k
  register ssize_t
319
847k
    i;
320
321
847k
  size_t
322
847k
    count;
323
324
847k
  TIFFFieldInfo
325
847k
    *ignore;
326
327
847k
  if (TIFFGetReadProc(tiff) != TIFFReadBlob)
328
1.67k
    return;
329
330
846k
  client_data=((Magick_TIFF_ClientData *) TIFFClientdata(tiff));
331
846k
  if (client_data == (Magick_TIFF_ClientData *) NULL)
332
0
    return;
333
846k
  tags=AccessDefinition(client_data->image_info,"tiff","ignore-tags");
334
846k
  if (tags == (const char *) NULL)
335
846k
    return;
336
0
  count=0;
337
0
  p=tags;
338
0
  while (*p != '\0')
339
0
    {
340
0
      while ((isspace((int) ((unsigned char) *p)) != 0))
341
0
        p++;
342
343
0
      {
344
0
        (void) strtol(p,&q,10);
345
0
      }
346
0
      if (p == q)
347
0
        return;
348
349
0
      p=q;
350
0
      count++;
351
352
0
      while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
353
0
        p++;
354
0
    }
355
0
  if (count == 0)
356
0
    return;
357
0
  i=0;
358
0
  p=tags;
359
0
  ignore=MagickAllocateResourceLimitedArray(TIFFFieldInfo*,count,sizeof(*ignore));
360
0
  if (ignore == (TIFFFieldInfo*) NULL)
361
0
    {
362
0
      ThrowException(&client_data->image->exception,ResourceLimitError,
363
0
                     MemoryAllocationFailed,client_data->image->filename);
364
0
      return;
365
0
    }
366
  /* This also sets field_bit to 0 (FIELD_IGNORE) */
367
0
  (void) memset(ignore,0,count*sizeof(*ignore));
368
0
  while (*p != '\0')
369
0
    {
370
0
      while ((isspace((int) ((unsigned char) *p)) != 0))
371
0
        p++;
372
373
0
      ignore[i].field_tag=(ttag_t) strtol(p,&q,10);
374
375
0
      p=q;
376
0
      i++;
377
378
0
      while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
379
0
        p++;
380
0
    }
381
0
  (void) TIFFMergeFieldInfo(tiff,ignore,(uint32) count);
382
0
  MagickFreeResourceLimitedMemory(TIFFFieldInfo*,ignore);
383
0
}
384
385
/*
386
  Merge in our new fields and then call the next extender if there is
387
  one in effect.
388
*/
389
static TIFFExtendProc _ParentExtender = NULL;
390
static void
391
ExtensionTagsDefaultDirectory(TIFF *tif)
392
847k
{
393
#  if TIFFLIB_VERSION < 20050704
394
  /* Install the extended Tag field info */
395
  TIFFMergeFieldInfo(tif, ExtensionTiffFieldInfo,
396
                     sizeof(ExtensionTiffFieldInfo)/
397
                     sizeof(ExtensionTiffFieldInfo[0]));
398
#  endif
399
400
  /* Since an XTIFF client module may have overridden
401
   * the default directory method, we call it now to
402
   * allow it to set up the rest of its own methods.
403
   */
404
847k
  if (_ParentExtender)
405
0
    (*_ParentExtender)(tif);
406
847k
  TIFFIgnoreTags(tif);
407
847k
}
408
409
/*
410
  Obtain the current handler at the front of the chain, and register
411
  ourselves as the new first handler.
412
*/
413
static
414
void ExtensionTagsInitialize(void)
415
7
{
416
7
  static int
417
7
    not_first_time=0;
418
419
7
  if (not_first_time) return; /* Been there. Done that. */
420
7
  not_first_time = 1;
421
422
  /* Grab the inherited method and install */
423
7
  _ParentExtender = TIFFSetTagExtender(ExtensionTagsDefaultDirectory);
424
7
}
425
426
#endif /* defined(HAVE_TIFFMERGEFIELDINFO) && defined(HAVE_TIFFSETTAGEXTENDER) */
427
428
/*
429
  Return MagickTrue if libtiff supports the indicated compression type.
430
  Sets buffer pointed to by 'compression_name' to the name of the compression.
431
*/
432
static MagickBool
433
CompressionSupported(const CompressionType compression,
434
                     char *compression_name,
435
                     const size_t sizeof_compression_name)
436
34.3k
{
437
34.3k
  uint16
438
34.3k
    compress_tag;
439
440
34.3k
  MagickBool
441
34.3k
    status;
442
443
34.3k
  status = MagickFalse;
444
34.3k
  compress_tag=COMPRESSION_NONE;
445
34.3k
  strlcpy(compression_name,"Undefined",sizeof_compression_name);
446
447
  /*
448
    This switch statement should match all the values of CompressionType.
449
  */
450
34.3k
  switch (compression)
451
34.3k
    {
452
0
    case UndefinedCompression:
453
0
      {
454
0
        strlcpy(compression_name,"Undefined",sizeof_compression_name);
455
0
        break;
456
0
      }
457
9.85k
    case NoCompression:
458
9.85k
      {
459
9.85k
        strlcpy(compression_name,"No",sizeof_compression_name);
460
9.85k
        compress_tag=COMPRESSION_NONE;
461
9.85k
        status=MagickTrue;
462
9.85k
        break;
463
0
      }
464
0
    case BZipCompression:
465
0
      {
466
0
        strlcpy(compression_name,"BZip",sizeof_compression_name);
467
0
        break;
468
0
      }
469
1.58k
    case FaxCompression:
470
1.58k
      {
471
1.58k
        strlcpy(compression_name,"Group3 FAX",sizeof_compression_name);
472
1.58k
#if defined(COMPRESSION_CCITTFAX3)
473
1.58k
        compress_tag=COMPRESSION_CCITTFAX3;
474
1.58k
        status=MagickTrue;
475
1.58k
#endif
476
1.58k
        break;
477
0
      }
478
4.95k
    case Group4Compression:
479
4.95k
      {
480
4.95k
        strlcpy(compression_name,"Group4 FAX",sizeof_compression_name);
481
4.95k
#if defined(COMPRESSION_CCITTFAX4)
482
4.95k
        compress_tag=COMPRESSION_CCITTFAX4;
483
4.95k
        status=MagickTrue;
484
4.95k
#endif
485
4.95k
        break;
486
0
      }
487
0
    case JBIG1Compression:
488
0
      {
489
0
        strlcpy(compression_name,"JBIG",sizeof_compression_name);
490
0
#if defined(COMPRESSION_JBIG)
491
0
        compress_tag=COMPRESSION_JBIG;
492
0
        status=MagickTrue;
493
0
#endif
494
0
        break;
495
0
      }
496
0
    case JBIG2Compression:
497
0
      {
498
0
        strlcpy(compression_name,"JBIG2",sizeof_compression_name);
499
0
        break;
500
0
      }
501
8.15k
    case JPEGCompression:
502
8.15k
      {
503
8.15k
        strlcpy(compression_name,"JPEG",sizeof_compression_name);
504
8.15k
#if defined(COMPRESSION_JPEG)
505
8.15k
        compress_tag=COMPRESSION_JPEG;
506
8.15k
        status=MagickTrue;
507
8.15k
#endif
508
8.15k
        break;
509
0
      }
510
0
    case JPEG2000Compression:
511
0
      {
512
0
        strlcpy(compression_name,"JPEG2000",sizeof_compression_name);
513
0
        break;
514
0
      }
515
0
    case LERCCompression:
516
0
      {
517
0
        strlcpy(compression_name,"LERC",sizeof_compression_name);
518
0
#if defined(COMPRESSION_LERC)
519
0
        compress_tag=COMPRESSION_LERC;
520
0
        status=MagickTrue;
521
0
#endif
522
0
        break;
523
0
      }
524
0
    case LosslessJPEGCompression:
525
0
      {
526
0
        strlcpy(compression_name,"Lossless JPEG",sizeof_compression_name);
527
0
        break;
528
0
      }
529
0
    case LZMACompression:
530
0
      {
531
0
        strlcpy(compression_name,"LZMA",sizeof_compression_name);
532
0
#if defined(COMPRESSION_LZMA)
533
0
        compress_tag=COMPRESSION_LZMA;
534
0
        status=MagickTrue;
535
0
#endif
536
0
        break;
537
0
      }
538
750
    case LZWCompression:
539
750
      {
540
750
        strlcpy(compression_name,"LZW",sizeof_compression_name);
541
750
#if defined(COMPRESSION_LZW)
542
750
        compress_tag=COMPRESSION_LZW;
543
750
        status=MagickTrue;
544
750
#endif
545
750
        break;
546
0
      }
547
0
    case RLECompression:
548
0
      {
549
0
        strlcpy(compression_name,"Macintosh RLE (Packbits)",sizeof_compression_name);
550
0
#if defined(COMPRESSION_PACKBITS)
551
0
        compress_tag=COMPRESSION_PACKBITS;
552
0
        status=MagickTrue;
553
0
#endif
554
0
        break;
555
0
      }
556
3.12k
    case WebPCompression:
557
3.12k
      {
558
3.12k
        strlcpy(compression_name,"WebP",sizeof_compression_name);
559
3.12k
#if defined(COMPRESSION_WEBP)
560
3.12k
        compress_tag=COMPRESSION_WEBP;
561
3.12k
        status=MagickTrue;
562
3.12k
#endif
563
3.12k
        break;
564
0
      }
565
3.52k
    case ZipCompression:
566
3.52k
      {
567
3.52k
        strlcpy(compression_name,"Adobe Deflate",sizeof_compression_name);
568
3.52k
#if defined(COMPRESSION_ADOBE_DEFLATE)
569
3.52k
        compress_tag=COMPRESSION_ADOBE_DEFLATE;
570
3.52k
        status=MagickTrue;
571
3.52k
#endif
572
3.52k
        break;
573
0
      }
574
2.42k
    case ZSTDCompression:
575
2.42k
      {
576
2.42k
        strlcpy(compression_name,"Zstandard",sizeof_compression_name);
577
2.42k
#if defined(COMPRESSION_ZSTD)
578
2.42k
        compress_tag=COMPRESSION_ZSTD;
579
2.42k
        status=MagickTrue;
580
2.42k
#endif
581
2.42k
        break;
582
0
      }
583
34.3k
    }
584
585
34.3k
  if (MagickTrue == status)
586
34.3k
    {
587
34.3k
#if defined(HAVE_TIFFISCODECCONFIGURED) || (TIFFLIB_VERSION > 20040919)
588
34.3k
      if (compress_tag != COMPRESSION_NONE)
589
24.5k
        {
590
          /*
591
            Returns 1 if the codec is configured and
592
            working. Otherwise 0 will be returned.
593
          */
594
24.5k
          if (!TIFFIsCODECConfigured(compress_tag))
595
0
            status = MagickFalse;
596
24.5k
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
597
24.5k
                                "TIFFIsCODECConfigured says support for %s "
598
24.5k
                                "compression %s configured.",
599
24.5k
                                compression_name,
600
24.5k
                                (status == MagickTrue ? "is" : "is not"));
601
24.5k
        }
602
#else
603
      switch (compress_tag)
604
        {
605
#  if defined(CCITT_SUPPORT)
606
        case COMPRESSION_CCITTFAX3:
607
        case COMPRESSION_CCITTFAX4:
608
#  endif
609
#  if defined(YCBCR_SUPPORT) && defined(JPEG_SUPPORT)
610
        case COMPRESSION_JPEG:
611
#  endif
612
#  if defined(LZW_SUPPORT)
613
        case COMPRESSION_LZW:
614
#  endif
615
#  if defined(PACKBITS_SUPPORT)
616
        case COMPRESSION_PACKBITS:
617
#  endif
618
#  if defined(ZIP_SUPPORT)
619
        case COMPRESSION_ADOBE_DEFLATE:
620
#  endif
621
        case COMPRESSION_NONE:
622
          {
623
            status = MagickTrue;
624
            break;
625
          }
626
        default:
627
          {
628
            status = MagickFalse;
629
            break;
630
          }
631
        }
632
#endif
633
34.3k
    }
634
34.3k
  return status;
635
34.3k
}
636
637
/*
638
  Convert a libtiff compression tag to a human readable string.
639
*/
640
static const char *
641
CompressionTagToString(unsigned int compress_tag)
642
72
{
643
72
  const char
644
72
    *result = "Unknown";
645
646
72
  switch (compress_tag)
647
72
    {
648
0
    case COMPRESSION_ADOBE_DEFLATE:
649
0
      result="ZIP deflate (Adobe)";
650
0
      break;
651
0
#if defined(COMPRESSION_DEFLATE)
652
0
    case COMPRESSION_DEFLATE:
653
0
      result="ZIP deflate (Pixar)";
654
0
      break;
655
0
#endif
656
28
    case COMPRESSION_CCITTFAX3:
657
28
      result="CCITT Group 3 fax";
658
28
      break;
659
22
    case COMPRESSION_CCITTFAX4:
660
22
      result="CCITT Group 4 fax";
661
22
      break;
662
0
    case COMPRESSION_CCITTRLE:
663
0
      result="CCITT modified Huffman RLE";
664
0
      break;
665
0
    case COMPRESSION_CCITTRLEW:
666
0
      result="CCITT modified Huffman RLE (Word aligned)";
667
0
      break;
668
0
#if defined(COMPRESSION_OJPEG)
669
0
    case COMPRESSION_OJPEG:
670
0
      result="JPEG DCT (Old)";
671
0
      break;
672
0
#endif
673
0
    case COMPRESSION_JPEG:
674
0
      result="JPEG DCT";
675
0
      break;
676
0
#if defined(COMPRESSION_JBIG)
677
0
    case COMPRESSION_JBIG:
678
0
      result="JBIG";
679
0
      break;
680
0
#endif
681
0
    case COMPRESSION_LZW:
682
0
      result="LZW";
683
0
      break;
684
0
#if defined(COMPRESSION_NEXT)
685
0
    case COMPRESSION_NEXT:
686
0
      result="NeXT 2-bit RLE";
687
0
      break;
688
0
#endif
689
0
    case COMPRESSION_NONE:
690
0
      result="not compressed";
691
0
      break;
692
0
    case COMPRESSION_PACKBITS:
693
0
      result="Macintosh RLE (Packbits)";
694
0
      break;
695
0
#if defined(COMPRESSION_THUNDERSCAN)
696
0
    case COMPRESSION_THUNDERSCAN:
697
0
      result="ThunderScan RLE";
698
0
      break;
699
0
#endif
700
0
#if defined(COMPRESSION_LZMA)
701
0
    case COMPRESSION_LZMA:
702
0
      result="LZMA";
703
0
      break;
704
0
#endif
705
0
#if defined(COMPRESSION_ZSTD)
706
0
    case COMPRESSION_ZSTD:
707
0
      result="Zstandard";
708
0
      break;
709
0
#endif
710
0
#if defined(COMPRESSION_WEBP)
711
22
    case COMPRESSION_WEBP:
712
22
      result="WebP";
713
22
      break;
714
0
#endif
715
0
#if defined(COMPRESSION_LERC)
716
0
    case COMPRESSION_LERC:
717
0
      result="LERC";
718
0
      break;
719
72
#endif
720
72
  }
721
72
  return result;
722
72
}
723
724
static const char *
725
PhotometricTagToString(unsigned int photometric)
726
2.38k
{
727
2.38k
  const char
728
2.38k
    *result = "Unknown";
729
730
2.38k
  switch (photometric)
731
2.38k
    {
732
0
    case  PHOTOMETRIC_CIELAB:
733
0
      result="CIELAB";
734
0
      break;
735
0
    case PHOTOMETRIC_LOGL:
736
0
      result="CIE Log2(L)";
737
0
      break;
738
0
    case PHOTOMETRIC_LOGLUV:
739
0
      result="LOGLUV";
740
0
      break;
741
0
#if defined(PHOTOMETRIC_MASK)
742
0
    case PHOTOMETRIC_MASK:
743
0
      result="MASK";
744
0
      break;
745
0
#endif
746
347
    case PHOTOMETRIC_MINISBLACK:
747
347
      result="MINISBLACK";
748
347
      break;
749
110
    case PHOTOMETRIC_MINISWHITE:
750
110
      result="MINISWHITE";
751
110
      break;
752
0
    case PHOTOMETRIC_PALETTE:
753
0
      result="PALETTE";
754
0
      break;
755
1.93k
    case PHOTOMETRIC_RGB:
756
1.93k
      result="RGB";
757
1.93k
      break;
758
0
    case PHOTOMETRIC_SEPARATED:
759
0
      result="SEPARATED";
760
0
      break;
761
0
    case PHOTOMETRIC_YCBCR:
762
0
      result="YCBCR";
763
0
      break;
764
2.38k
    }
765
766
2.38k
  return result;
767
2.38k
}
768
769
static const char *ExtraSampleToString(const unsigned int sample_info)
770
786k
{
771
786k
  const char
772
786k
    *result = "Unknown";
773
774
786k
  switch (sample_info)
775
786k
    {
776
778k
    case EXTRASAMPLE_UNSPECIFIED:
777
778k
      result="Unspecified data";
778
778k
      break;
779
4.22k
    case EXTRASAMPLE_ASSOCALPHA:
780
4.22k
      result="Associated alpha data (with pre-multiplied color)";
781
4.22k
      break;
782
3.63k
    case EXTRASAMPLE_UNASSALPHA:
783
3.63k
      result="Unassociated alpha data";
784
3.63k
      break;
785
786k
    }
786
787
786k
  return result;
788
786k
}
789
790
/*
791
  Locate and store Photoshop or IPTC profiles.
792
793
  Arguments:
794
795
  text - Pointer to octet buffer
796
  length - Number of bytes or 32-bit words in buffer
797
  image  - Image to store into
798
  type   - TIFF tag (TIFFTAG_PHOTOSHOP or TIFFTAG_RICHTIFFIPTC)
799
800
  If the tag is TIFFTAG_RICHTIFFIPTC then it appears that the length
801
  represents the number of 32-bit words.  If the tag is
802
  TIFFTAG_PHOTOSHOP then the length is in bytes, but the underlying
803
  data is stored in units of 16-bit words.
804
 */
805
27.2k
#define NEWSP_REMAINING(base_p,current_p,length) ((ssize_t) length-(current_p-base_p))
806
static unsigned int
807
ReadNewsProfile(const unsigned char *text,const size_t length,Image *image,const int type)
808
98
{
809
98
  register const unsigned char
810
98
    *p;
811
812
#if defined(GET_ONLY_IPTC_DATA)
813
  static const char tag_header [] = "8BIM44";
814
#else
815
98
  static const char tag_header [] = "8BIM";
816
98
#endif
817
818
98
  MagickBool found_header=MagickFalse;
819
820
98
  if ((length == 0) || ((ssize_t) length < 0))
821
3
    return MagickFail;
822
823
95
  p=(unsigned char *) text;
824
95
  if (type == TIFFTAG_RICHTIFFIPTC)
825
0
    {
826
      /*
827
        Handle IPTC tag (length is number of 32-bit words).
828
      */
829
0
      return SetImageProfile(image,"IPTC",p,(size_t) length*4U);
830
0
    }
831
  /*
832
    Handle PHOTOSHOP tag (length is in bytes, but data is organized as
833
    array of 16-bit values.
834
  */
835
27.1k
  while (NEWSP_REMAINING(text,p,length) > (ssize_t) sizeof(tag_header))
836
27.1k
    {
837
27.1k
      if (LocaleNCompare((char *) p,tag_header,sizeof(tag_header)-1) == 0)
838
73
        {
839
73
          found_header=MagickTrue;
840
73
          break;
841
73
        }
842
27.0k
      p+=2;
843
27.0k
    }
844
95
  if (!found_header)
845
22
    {
846
22
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
847
22
                            "Failed to find %s header, ignoring profile.",
848
22
                            tag_header);
849
22
      return MagickFail;
850
22
    }
851
#if defined(GET_ONLY_IPTC_DATA)
852
  /*
853
    Eat OSType, IPTC ID code, and Pascal string length bytes.
854
  */
855
  do
856
    {
857
      magick_uint32_t
858
        hdr_length;
859
860
      p+=sizeof(tag_header)-1;
861
      if (NEWSP_REMAINING(text,p,length) < 8)
862
        {
863
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
864
                                "Truncated profile: %" MAGICK_SIZE_T_F "u"
865
                                " bytes, %" MAGICK_SSIZE_T_F "u remaining"
866
                                ", ignoring profile.",
867
                                (MAGICK_SIZE_T) length,
868
                                (MAGICK_SSIZE_T) NEWSP_REMAINING(text,p,length));
869
          break;
870
        }
871
      hdr_length=(*p++);
872
      p+=hdr_length;
873
      if (NEWSP_REMAINING(text,p,length) < 8)
874
        {
875
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
876
                                "Truncated profile: %" MAGICK_SIZE_T_F "u"
877
                                " bytes, %" MAGICK_SSIZE_T_F "u remaining"
878
                                ", ignoring profile.",
879
                                (MAGICK_SIZE_T) length,
880
                                (MAGICK_SSIZE_T) NEWSP_REMAINING(text,p,length));
881
          break;
882
        }
883
      if ((hdr_length & 0x01) == 0)
884
        p++;  /* align to an even byte boundary */
885
      hdr_length=(p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
886
      p+=4;
887
      if (((ssize_t) hdr_length <= 0) ||
888
          ((ssize_t) hdr_length > NEWSP_REMAINING(text,p,length)))
889
        {
890
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
891
                                "Truncated profile: %" MAGICK_SIZE_T_F "u"
892
                                " bytes, %" MAGICK_SSIZE_T_F "u "
893
                                "remaining (need %u more bytes)"
894
                                ", ignoring profile.",
895
                                (MAGICK_SIZE_T) length,
896
                                (MAGICK_SSIZE_T) NEWSP_REMAINING(text,p,length),
897
                                hdr_length);
898
          return MagickFail;
899
        }
900
      return SetImageProfile(image,"8BIM",p,hdr_length);
901
    } while (0);
902
  return MagickFail;
903
#else
904
73
  return SetImageProfile(image,"8BIM",p,(size_t) NEWSP_REMAINING(text,p,length));
905
95
#endif
906
95
}
907
908
/*
909
  Return MagickTrue if TIFF warnings should be thrown as a warning
910
  exception rather than logged.
911
*/
912
static MagickBool
913
CheckThrowWarnings(const ImageInfo *image_info)
914
1.82M
{
915
1.82M
  const char *
916
1.82M
    definition_value;
917
918
1.82M
  MagickBool
919
1.82M
    report_warnings=MagickFalse;
920
921
1.82M
  if ((definition_value=AccessDefinition(image_info,"tiff","report-warnings")))
922
0
    {
923
0
      if (LocaleCompare(definition_value,"TRUE") == 0)
924
0
        report_warnings=MagickTrue;
925
0
    }
926
927
1.82M
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
928
1.82M
                        "Reporting TIFF warnings via %s",
929
1.82M
                        (report_warnings ? "exception" :
930
1.82M
                         "log message"));
931
932
1.82M
  return report_warnings;
933
1.82M
}
934
935
936
#if defined(__cplusplus) || defined(c_plusplus)
937
extern "C" {
938
#endif
939
940
/* Close BLOB */
941
static int
942
TIFFCloseBlob(thandle_t image_handle)
943
136k
{
944
136k
  Image
945
136k
    *image = ((Magick_TIFF_ClientData *) image_handle)->image;
946
947
136k
  int
948
136k
    status = MagickPass;
949
950
#if LOG_TIFF_BLOB_IO
951
  if (image->logging)
952
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"TIFF close blob");
953
#endif /* LOG_TIFF_BLOB_IO */
954
136k
  while (image->previous != (Image *) NULL)
955
0
    image=image->previous;
956
136k
  status &= CloseBlob(image);
957
136k
  return(status);
958
136k
}
959
960
/* Report errors. */
961
static void
962
TIFFReadErrorsHandler(const char *module,const char *format,
963
                      va_list warning)
964
  MAGICK_FUNC_PRINTF_FORMAT(2,0);
965
#if defined(HAVE_TIFFERROREXTR)
966
static int
967
TIFFReadErrorsHandlerExtR(TIFF *tif, void *user_data,
968
                          const char *module, const char *format, va_list warning)
969
  MAGICK_FUNC_PRINTF_FORMAT(4,0);
970
#endif /* if defined(HAVE_TIFFERROREXTR) */
971
static void
972
TIFFWriteErrorsHandler(const char *module,const char *format,
973
                       va_list warning) MAGICK_FUNC_PRINTF_FORMAT(2,0);
974
#if defined(HAVE_TIFFERROREXTR)
975
static int
976
TIFFWriteErrorsHandlerExtR(TIFF *tif, void *user_data,
977
                           const char *module, const char *format, va_list warning)
978
  MAGICK_FUNC_PRINTF_FORMAT(4,0);
979
#endif /* if defined(HAVE_TIFFERROREXTR) */
980
static void
981
TIFFReadErrorsHandler(const char *module,const char *format,
982
  va_list warning)
983
0
{
984
0
  ExceptionInfo
985
0
    *tiff_exception;
986
987
0
  char
988
0
    message[MaxTextExtent];
989
990
0
  errno=0;
991
0
  (void) vsnprintf(message,MaxTextExtent-2,format,warning);
992
0
  message[MaxTextExtent-2]='\0';
993
0
#define UNKNOWN_TAG_ERROR "Internal error, unknown tag"
994
0
  if (LocaleNCompare(message,UNKNOWN_TAG_ERROR,sizeof(UNKNOWN_TAG_ERROR)-1) == 0)
995
0
    return;
996
0
  (void) strlcat(message,".",MaxTextExtent);
997
0
  tiff_exception=(ExceptionInfo *) MagickTsdGetSpecific(tsd_key);
998
0
  ThrowException2(tiff_exception,CorruptImageError,message,module);
999
0
}
1000
1001
#if defined(HAVE_TIFFERROREXTR)
1002
static int TIFFReadErrorsHandlerExtR(TIFF *tif, void *user_data,
1003
                                     const char *module, const char *format,
1004
                                     va_list warning)
1005
4.17M
{
1006
4.17M
  ExceptionInfo
1007
4.17M
    *tiff_exception;
1008
1009
4.17M
  char
1010
4.17M
    message[MaxTextExtent];
1011
1012
4.17M
  (void) tif;
1013
4.17M
  errno=0;
1014
4.17M
  (void) vsnprintf(message,MaxTextExtent-2,format,warning);
1015
4.17M
  message[MaxTextExtent-2]='\0';
1016
8.35M
#define UNKNOWN_TAG_ERROR "Internal error, unknown tag"
1017
4.17M
  if (LocaleNCompare(message,UNKNOWN_TAG_ERROR,sizeof(UNKNOWN_TAG_ERROR)-1) == 0)
1018
0
    return 0;
1019
4.17M
  (void) strlcat(message,".",MaxTextExtent);
1020
4.17M
  tiff_exception=(ExceptionInfo *) user_data;
1021
4.17M
  ThrowException2(tiff_exception,CorruptImageError,message,module);
1022
  /*
1023
    0: both functions TIFFErrorHandler() and TIFFErrorHandlerExt() are called.
1024
    non-zero: no further error message function is called.
1025
  */
1026
4.17M
  return 1;
1027
4.17M
}
1028
#endif /* if defined(HAVE_TIFFERROREXTR) */
1029
1030
static void
1031
TIFFWriteErrorsHandler(const char *module,const char *format,
1032
  va_list warning)
1033
36
{
1034
36
  ExceptionInfo
1035
36
    *tiff_exception;
1036
1037
36
  char
1038
36
    message[MaxTextExtent];
1039
1040
36
  errno=0;
1041
36
  (void) vsnprintf(message,MaxTextExtent-2,format,warning);
1042
36
  message[MaxTextExtent-2]='\0';
1043
36
  (void) strlcat(message,".",MaxTextExtent);
1044
36
  tiff_exception=(ExceptionInfo *) MagickTsdGetSpecific(tsd_key);
1045
36
  ThrowException2(tiff_exception,CoderError,message,module);
1046
36
}
1047
1048
#if defined(HAVE_TIFFERROREXTR)
1049
static int
1050
TIFFWriteErrorsHandlerExtR(TIFF *tif, void *user_data,
1051
                           const char *module, const char *format, va_list warning)
1052
369
{
1053
369
  ExceptionInfo
1054
369
    *tiff_exception;
1055
1056
369
  char
1057
369
    message[MaxTextExtent];
1058
1059
369
  (void) tif;
1060
369
  errno=0;
1061
369
  (void) vsnprintf(message,MaxTextExtent-2,format,warning);
1062
369
  message[MaxTextExtent-2]='\0';
1063
369
  (void) strlcat(message,".",MaxTextExtent);
1064
369
  tiff_exception=(ExceptionInfo *) user_data;
1065
369
  ThrowException2(tiff_exception,CoderError,message,module);
1066
1067
  /*
1068
    0: both functions TIFFWarningHandler() and TIFFWarningHandlerExt() are called.
1069
    non-zero: no further warning message function is called.
1070
   */
1071
369
  return 1;
1072
369
}
1073
#endif /* if defined(HAVE_TIFFERROREXTR) */
1074
1075
/* Memory map entire input file in read-only mode. */
1076
static int
1077
TIFFMapBlob(thandle_t image_handle,tdata_t *base,toff_t *size)
1078
893k
{
1079
893k
  Image
1080
893k
    *image = ((Magick_TIFF_ClientData *) image_handle)->image;
1081
1082
893k
  *base = (tdata_t *) GetBlobStreamData(image);
1083
893k
  if (*base)
1084
891k
    *size = (toff_t) GetBlobSize(image);
1085
1086
893k
  if (*base)
1087
891k
    {
1088
#if LOG_TIFF_BLOB_IO
1089
      if (image->logging)
1090
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1091
                              "TIFF mapped blob: base=0x%p size=%" MAGICK_OFF_F
1092
                              "d",*base, (magick_off_t) *size);
1093
#endif
1094
891k
      return 1;
1095
891k
    }
1096
2.46k
  return(0);
1097
893k
}
1098
1099
/* Read BLOB data at current offset */
1100
static tsize_t
1101
TIFFReadBlob(thandle_t image_handle,tdata_t data,tsize_t size)
1102
1.73M
{
1103
1.73M
  Image
1104
1.73M
    *image = ((Magick_TIFF_ClientData *) image_handle)->image;
1105
1106
1.73M
  tsize_t
1107
1.73M
    result;
1108
1109
1.73M
  result=(tsize_t) ReadBlob(image,(size_t) size,data);
1110
1111
#if LOG_TIFF_BLOB_IO
1112
  if (image->logging)
1113
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1114
                          "TIFF read blob: data=0x%p size="
1115
                          "%" MAGICK_SIZE_T_F "u, returns "
1116
                          "%" MAGICK_SIZE_T_F "u",
1117
                          data, (MAGICK_SIZE_T) size,
1118
                          (MAGICK_SIZE_T) result);
1119
#endif /* LOG_TIFF_BLOB_IO */
1120
1121
1.73M
  return result;
1122
1.73M
}
1123
1124
/* Seek to BLOB offset */
1125
static toff_t
1126
TIFFSeekBlob(thandle_t image_handle,toff_t offset,int whence)
1127
902k
{
1128
902k
  Image
1129
902k
    *image = ((Magick_TIFF_ClientData *) image_handle)->image;
1130
1131
902k
  toff_t
1132
902k
    result;
1133
1134
902k
  result=SeekBlob(image,offset,whence);
1135
#if LOG_TIFF_BLOB_IO
1136
  if (image->logging)
1137
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1138
                          "TIFF seek blob: offset=%" MAGICK_OFF_F
1139
                          "u whence=%d (%s), returns %" MAGICK_OFF_F "d",
1140
                          (magick_off_t) offset,
1141
                          whence,
1142
                          (whence == SEEK_SET ? "SET" :
1143
                           (whence == SEEK_CUR ? "CUR" :
1144
                            (whence == SEEK_END ? "END" : "unknown"))),
1145
                          (magick_off_t) result);
1146
#endif  /* LOG_TIFF_BLOB_IO */
1147
902k
  return result;
1148
902k
}
1149
1150
/* Obtain BLOB size */
1151
static toff_t
1152
TIFFGetBlobSize(thandle_t image_handle)
1153
889k
{
1154
889k
  Image
1155
889k
    *image = ((Magick_TIFF_ClientData *) image_handle)->image;
1156
1157
889k
  toff_t
1158
889k
    result;
1159
1160
889k
  result=(toff_t) GetBlobSize(image);
1161
1162
#if LOG_TIFF_BLOB_IO
1163
  if (image->logging)
1164
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1165
                          "TIFF get blob size returns %" MAGICK_OFF_F "d",
1166
                          (magick_off_t) result);
1167
#endif /* LOG_TIFF_BLOB_IO */
1168
1169
889k
  return result;
1170
889k
}
1171
1172
/* Unmap BLOB memory */
1173
static void
1174
TIFFUnmapBlob(thandle_t image_handle,
1175
              tdata_t base,
1176
              toff_t size)
1177
897k
{
1178
#if LOG_TIFF_BLOB_IO
1179
  Image
1180
    *image = ((Magick_TIFF_ClientData *) image_handle)->image;
1181
1182
  if (image->logging)
1183
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1184
                          "TIFF unmap blob: base=0x%p size=%" MAGICK_OFF_F "d",
1185
                          base,(magick_off_t) size);
1186
#else
1187
897k
  ARG_NOT_USED(image_handle);
1188
897k
  ARG_NOT_USED(base);
1189
897k
  ARG_NOT_USED(size);
1190
897k
#endif  /* LOG_TIFF_BLOB_IO */
1191
897k
}
1192
1193
#if defined(HAVE_TIFFERROREXTR)
1194
static int
1195
TIFFReadWarningHandlerExtRLogOnly(TIFF *tif, void *user_data,
1196
                                  const char *module, const char *format, va_list warning)
1197
  MAGICK_FUNC_PRINTF_FORMAT(4,0);
1198
static int TIFFReadWarningHandlerExtRLogOnly(TIFF *tif, void *user_data,
1199
                                             const char *module, const char *format,
1200
                                             va_list warning)
1201
5.52M
{
1202
5.52M
  char
1203
5.52M
    message[MaxTextExtent];
1204
1205
5.52M
  (void) tif;
1206
5.52M
  (void) user_data;
1207
5.52M
  (void) module;
1208
5.52M
  errno=0;
1209
5.52M
  (void) vsnprintf(message,MaxTextExtent-2,format,warning);
1210
5.52M
  message[MaxTextExtent-2]='\0';
1211
5.52M
  (void) strlcat(message,".",MaxTextExtent);
1212
5.52M
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1213
5.52M
                        "TIFF Warning: %s",message);
1214
  /*
1215
    0: both functions TIFFErrorHandler() and TIFFErrorHandlerExt() are called.
1216
    non-zero: no further error message function is called.
1217
  */
1218
5.52M
  return 1;
1219
5.52M
}
1220
1221
static int
1222
TIFFReadWarningHandlerExtRThrowException(TIFF *tif, void *user_data,
1223
                                         const char *module, const char *format, va_list warning)
1224
  MAGICK_FUNC_PRINTF_FORMAT(4,0);
1225
static int TIFFReadWarningHandlerExtRThrowException(TIFF *tif, void *user_data,
1226
                                                    const char *module, const char *format,
1227
                                                    va_list warning)
1228
0
{
1229
0
  ExceptionInfo
1230
0
    *tiff_exception;
1231
1232
0
  char
1233
0
    message[MaxTextExtent];
1234
1235
0
  (void) tif;
1236
0
  errno=0;
1237
0
  (void) vsnprintf(message,MaxTextExtent-2,format,warning);
1238
0
  message[MaxTextExtent-2]='\0';
1239
0
#define UNKNOWN_TAG_ERROR "Internal error, unknown tag"
1240
0
  if (LocaleNCompare(message,UNKNOWN_TAG_ERROR,sizeof(UNKNOWN_TAG_ERROR)-1) == 0)
1241
0
    return 0;
1242
0
  (void) strlcat(message,".",MaxTextExtent);
1243
0
  tiff_exception=(ExceptionInfo *) user_data;
1244
0
  ThrowException2(tiff_exception,CoderWarning,message,module);
1245
0
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1246
0
                        "TIFF Warning: %s",message);
1247
  /*
1248
    0: both functions TIFFWarningHandler() and then TIFFWarningHandlerExt() are called.
1249
    non-zero: no further error message function is called.
1250
  */
1251
0
  return 1;
1252
0
}
1253
#endif /* if defined(HAVE_TIFFERROREXTR) */
1254
1255
/* Report warnings as a coder log message. */
1256
static void
1257
TIFFWarningsLogOnly(const char *module,const char *format,va_list warning)
1258
  MAGICK_FUNC_PRINTF_FORMAT(2,0);
1259
static void
1260
TIFFWarningsLogOnly(const char *module,const char *format,va_list warning)
1261
0
{
1262
/*   ExceptionInfo */
1263
/*     *tiff_exception; */
1264
1265
0
  char
1266
0
    message[MaxTextExtent];
1267
1268
0
  (void) module;
1269
0
  errno=0;
1270
0
  (void) vsnprintf(message,MaxTextExtent-2,format,warning);
1271
0
  message[MaxTextExtent-2]='\0';
1272
0
  (void) strlcat(message,".",MaxTextExtent);
1273
/*   tiff_exception=(ExceptionInfo *) MagickTsdGetSpecific(tsd_key); */
1274
/*   ThrowException2(tiff_exception,CoderWarning,message,module); */
1275
0
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1276
0
                        "TIFF Warning: %s",message);
1277
0
}
1278
1279
/* Report warnings as exception in thread-specific ExceptionInfo */
1280
static void
1281
TIFFWarningsThrowException(const char *module,const char *format,va_list warning)
1282
  MAGICK_FUNC_PRINTF_FORMAT(2,0);
1283
static void
1284
TIFFWarningsThrowException(const char *module,const char *format,va_list warning)
1285
0
{
1286
0
  ExceptionInfo
1287
0
    *tiff_exception;
1288
1289
0
  char
1290
0
    message[MaxTextExtent];
1291
1292
0
  (void) module;
1293
0
  errno=0;
1294
0
  (void) vsnprintf(message,MaxTextExtent-2,format,warning);
1295
0
  message[MaxTextExtent-2]='\0';
1296
0
  (void) strlcat(message,".",MaxTextExtent);
1297
0
  tiff_exception=(ExceptionInfo *) MagickTsdGetSpecific(tsd_key);
1298
0
  ThrowException2(tiff_exception,CoderWarning,message,module);
1299
0
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1300
0
                        "TIFF Warning: %s",message);
1301
0
}
1302
1303
/* Write data at current offset */
1304
static tsize_t
1305
TIFFWriteBlob(thandle_t image_handle,tdata_t data,tsize_t size)
1306
234k
{
1307
234k
  Image
1308
234k
    *image = ((Magick_TIFF_ClientData *) image_handle)->image;
1309
1310
234k
  tsize_t
1311
234k
    result;
1312
1313
234k
  result=(tsize_t) WriteBlob(image,(size_t) size,data);
1314
1315
#if LOG_TIFF_BLOB_IO
1316
  if (image->logging)
1317
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1318
                          "TIFF write blob: data=0x%p size="
1319
                          "%" MAGICK_SIZE_T_F "u, returns "
1320
                          "%" MAGICK_SIZE_T_F "u",
1321
                          data, (MAGICK_SIZE_T) size,
1322
                          (MAGICK_SIZE_T) result);
1323
#endif  /* LOG_TIFF_BLOB_IO */
1324
1325
234k
  return result;
1326
234k
}
1327
1328
/*
1329
  Convert TIFF data from libtiff "native" format to byte-parsable big endian
1330
*/
1331
#if !defined(WORDS_BIGENDIAN)
1332
static void
1333
SwabDataToBigEndian(const uint16 bits_per_sample, tdata_t data,
1334
                    const tsize_t size)
1335
3.75k
{
1336
3.75k
  if (bits_per_sample == 64U)
1337
0
    {
1338
0
      TIFFSwabArrayOfDouble((double*) data,
1339
0
                            NumberOfObjectsInArray(size,sizeof(double)));
1340
0
    }
1341
3.75k
  else if (bits_per_sample == 32U)
1342
0
    {
1343
0
      TIFFSwabArrayOfLong((uint32*) data,
1344
0
                          NumberOfObjectsInArray(size,sizeof(uint32)));
1345
0
    }
1346
3.75k
#if defined(HAVE_TIFFSWABARRAYOFTRIPLES)
1347
  /* New libtiff function to swap 24 bit values.  Grumble ... */
1348
3.75k
  else if (bits_per_sample == 24U)
1349
3.75k
    {
1350
3.75k
      TIFFSwabArrayOfTriples((uint8_t*) data,
1351
3.75k
                             NumberOfObjectsInArray(size,3));
1352
3.75k
    }
1353
0
#endif
1354
0
  else if (bits_per_sample == 16U)
1355
0
    {
1356
0
      TIFFSwabArrayOfShort((uint16*) data,
1357
0
                           NumberOfObjectsInArray(size,sizeof(uint16)));
1358
0
    }
1359
3.75k
}
1360
#endif
1361
1362
/*
1363
  Convert TIFF data from byte-parsable big endian to libtiff "native" format.
1364
*/
1365
#if !defined(WORDS_BIGENDIAN)
1366
static void
1367
SwabDataToNativeEndian(const uint16 bits_per_sample, tdata_t data,
1368
                       const tsize_t size)
1369
0
{
1370
0
  if (bits_per_sample == 64)
1371
0
    {
1372
0
      TIFFSwabArrayOfDouble((double*) data,
1373
0
                            NumberOfObjectsInArray(size,sizeof(double)));
1374
0
    }
1375
0
  else if (bits_per_sample == 32)
1376
0
    {
1377
0
      TIFFSwabArrayOfLong((uint32*) data,
1378
0
                          NumberOfObjectsInArray(size,sizeof(uint32)));
1379
0
    }
1380
0
#if defined(HAVE_TIFFSWABARRAYOFTRIPLES)
1381
  /* New libtiff function to swap 24 bit values.  Grumble ... */
1382
0
  else if (bits_per_sample == 24U)
1383
0
    {
1384
0
      TIFFSwabArrayOfTriples((uint8_t*) data,
1385
0
                             NumberOfObjectsInArray(size,3));
1386
0
    }
1387
0
#endif
1388
0
  else if (bits_per_sample == 16)
1389
0
    {
1390
0
      TIFFSwabArrayOfShort((uint16*) data,
1391
0
                           NumberOfObjectsInArray(size,sizeof(uint16)));
1392
0
    }
1393
0
}
1394
#endif
1395
1396
/*
1397
  Initialize the image colormap.
1398
*/
1399
static MagickPassFail
1400
InitializeImageColormap(Image *image, TIFF *tiff)
1401
2.25k
{
1402
2.25k
  uint16
1403
2.25k
    bits_per_sample,
1404
2.25k
    photometric;
1405
1406
2.25k
  register unsigned int
1407
2.25k
    i;
1408
1409
2.25k
  unsigned int
1410
2.25k
    max_sample_value,
1411
2.25k
    status = MagickFail;
1412
1413
2.25k
  if (TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,&bits_per_sample) != 1)
1414
0
    return status;
1415
2.25k
  if (TIFFGetFieldDefaulted(tiff,TIFFTAG_PHOTOMETRIC,&photometric) != 1)
1416
0
    return status;
1417
1418
  /*
1419
    Compute colormap size
1420
  */
1421
2.25k
  if (bits_per_sample > 64)
1422
0
    {
1423
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1424
0
                            "Bits per sample (%u) is out of range!",
1425
0
                            (unsigned) bits_per_sample);
1426
0
      ThrowException(&image->exception,CorruptImageError,ImproperImageHeader,
1427
0
                     image->filename);
1428
0
      return status;
1429
0
    }
1430
2.25k
  max_sample_value=MaxValueGivenBits(bits_per_sample);
1431
1432
2.25k
  image->colors=0;
1433
2.25k
  if (MaxColormapSize > max_sample_value)
1434
2.25k
    image->colors=max_sample_value+1;
1435
0
  else if (MaxColormapSize > MaxRGB)
1436
0
    {
1437
0
      if (photometric == PHOTOMETRIC_PALETTE)
1438
0
        return status;
1439
0
      else
1440
0
        image->colors=MaxColormapSize;
1441
0
    }
1442
1443
2.25k
  if (image->colors > 0)
1444
2.25k
    {
1445
2.25k
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1446
2.25k
                            "Allocating colormap with %u colors",
1447
2.25k
                            image->colors);
1448
1449
      /*
1450
        Allocate colormap.
1451
      */
1452
2.25k
      if (AllocateImageColormap(image,image->colors) == MagickFail)
1453
0
        return status;
1454
1455
      /*
1456
        Create colormap.
1457
      */
1458
2.25k
      switch (photometric)
1459
2.25k
        {
1460
0
        case PHOTOMETRIC_MINISBLACK:
1461
0
        case PHOTOMETRIC_MINISWHITE:
1462
0
        default:
1463
0
          {
1464
            /*
1465
              Ascending order produced by AllocateImageColormap() is sufficient.
1466
            */
1467
0
            status = MagickPass;
1468
0
            break;
1469
0
          }
1470
2.25k
        case PHOTOMETRIC_PALETTE:
1471
2.25k
          {
1472
2.25k
            long
1473
2.25k
              range;
1474
1475
2.25k
            uint16
1476
2.25k
              *blue_colormap,
1477
2.25k
              *green_colormap,
1478
2.25k
              *red_colormap;
1479
1480
2.25k
            (void) TIFFGetField(tiff,TIFFTAG_COLORMAP,&red_colormap,
1481
2.25k
                                &green_colormap,&blue_colormap);
1482
2.25k
            range=256L;  /* might be old style 8-bit colormap */
1483
36.1k
            for (i=0; i < image->colors; i++)
1484
35.8k
              if ((red_colormap[i] >= 256) || (green_colormap[i] >= 256) ||
1485
34.2k
                  (blue_colormap[i] >= 256))
1486
1.95k
                {
1487
1.95k
                  range=65535L;
1488
1.95k
                  break;
1489
1.95k
                }
1490
398k
            for (i=0; i < image->colors; i++)
1491
396k
              {
1492
396k
                image->colormap[i].red=(Quantum)
1493
396k
                  (((double) MaxRGB*red_colormap[i])/range+0.5);
1494
396k
                image->colormap[i].green=(Quantum)
1495
396k
                  (((double) MaxRGB*green_colormap[i])/range+0.5);
1496
396k
                image->colormap[i].blue=(Quantum)
1497
396k
                  (((double) MaxRGB*blue_colormap[i])/range+0.5);
1498
396k
              }
1499
2.25k
            status = MagickPass;
1500
2.25k
            break;
1501
0
          }
1502
2.25k
        }
1503
2.25k
      if (status == MagickPass)
1504
2.25k
        {
1505
2.25k
          register const PixelPacket
1506
2.25k
            *p;
1507
1508
2.25k
          register unsigned int
1509
2.25k
            scale;
1510
1511
2.25k
          unsigned int
1512
2.25k
            depth=1;
1513
1514
          /*
1515
            Evaluate colormap depth.
1516
          */
1517
2.25k
          p=image->colormap;
1518
2.25k
          scale=MaxRGB / (MaxRGB >> (QuantumDepth-depth));
1519
44.6k
          for (i=image->colors; i != 0; i--)
1520
44.0k
            {
1521
44.0k
              if ((p->red != scale*(p->red/scale)) ||
1522
30.5k
                  (p->green != scale*(p->green/scale)) ||
1523
23.0k
                  (p->blue != scale*(p->blue/scale)))
1524
26.6k
                {
1525
26.6k
                  depth++;
1526
26.6k
                  if (depth == QuantumDepth)
1527
1.63k
                    break;
1528
25.0k
                  scale=MaxRGB / (MaxRGB >> (QuantumDepth-depth));
1529
25.0k
                  continue;
1530
26.6k
                }
1531
17.3k
              p++;
1532
17.3k
            }
1533
2.25k
          if (depth < 8)
1534
571
            depth=8;
1535
1.68k
          else
1536
1.68k
            depth=16;
1537
2.25k
          image->depth=depth;
1538
2.25k
        }
1539
2.25k
    }
1540
1541
2.25k
  return status;
1542
2.25k
}
1543
1544
/*
1545
  Determine the quauntum import/export method to use with
1546
  ImportImagePixelArea() and ExportImagePixelArea() based on the
1547
  nature of the image, the TIFF photometric, sample format, samples
1548
  per pixel, the desired planar configuration, and the specified plane
1549
  (0 for contiguous planar configuration). Updates quantum_type with
1550
  the import/export method, and quantum_samples with the number of
1551
  samples consumed by one pixel. Returns MagickPass if the photometric
1552
  is supported.
1553
*/
1554
static MagickPassFail
1555
QuantumTransferMode(const Image *image,
1556
                    const uint16 photometric,
1557
                    const uint16 compress_tag,
1558
                    const uint16 sample_format,
1559
                    const unsigned int samples_per_pixel,
1560
                    const uint16 planar_config,
1561
                    const unsigned int plane,
1562
                    QuantumType *quantum_type,
1563
                    int *quantum_samples,
1564
                    ExceptionInfo *exception)
1565
1.69M
{
1566
1.69M
  ARG_NOT_USED(exception);
1567
1568
1.69M
  *quantum_type=UndefinedQuantum;
1569
1.69M
  *quantum_samples=0;
1570
1.69M
  if ((sample_format == SAMPLEFORMAT_INT) ||
1571
1.69M
      (sample_format == SAMPLEFORMAT_UINT) ||
1572
99.3k
      (sample_format == SAMPLEFORMAT_VOID) ||
1573
95.6k
      (sample_format == SAMPLEFORMAT_IEEEFP))
1574
1.68M
    {
1575
1.68M
      switch (photometric)
1576
1.68M
        {
1577
82.7k
        case PHOTOMETRIC_CIELAB:
1578
82.7k
          {
1579
            /* samples_per_pixel may be 1 or 3 */
1580
82.7k
            if (planar_config == PLANARCONFIG_SEPARATE)
1581
10.2k
              {
1582
10.2k
                switch (plane)
1583
10.2k
                  {
1584
10.2k
                  case 0:
1585
10.2k
                    if (samples_per_pixel == 1)
1586
10.1k
                      *quantum_type=GrayQuantum;
1587
39
                    else
1588
39
                      *quantum_type=RedQuantum;
1589
10.2k
                    break;
1590
16
                  case 1:
1591
16
                    *quantum_type=GreenQuantum;
1592
16
                    break;
1593
16
                  case 2:
1594
16
                    *quantum_type=BlueQuantum;
1595
16
                    break;
1596
8
                  case 3:
1597
8
                    *quantum_type=AlphaQuantum;
1598
8
                    break;
1599
10.2k
                  }
1600
10.2k
                *quantum_samples=1;
1601
10.2k
              }
1602
72.4k
            else
1603
72.4k
              {
1604
72.4k
                if (samples_per_pixel == 1)
1605
45.7k
                  {
1606
45.7k
                    if (image->matte)
1607
5
                      {
1608
5
                        *quantum_type=GrayAlphaQuantum;
1609
5
                        *quantum_samples=2;
1610
5
                      }
1611
45.7k
                    else
1612
45.7k
                      {
1613
45.7k
                        *quantum_type=GrayQuantum;
1614
45.7k
                        *quantum_samples=1;
1615
45.7k
                      }
1616
45.7k
                  }
1617
26.7k
                else
1618
26.7k
                  {
1619
26.7k
                    if (image->matte)
1620
2.63k
                      {
1621
2.63k
                        *quantum_type=RGBAQuantum;
1622
2.63k
                        *quantum_samples=4;
1623
2.63k
                      }
1624
24.1k
                    else
1625
24.1k
                      {
1626
24.1k
                        *quantum_type=RGBQuantum;
1627
24.1k
                        *quantum_samples=3;
1628
24.1k
                      }
1629
26.7k
                  }
1630
72.4k
              }
1631
82.7k
            break;
1632
82.7k
          }
1633
82.7k
        case PHOTOMETRIC_LOGL:
1634
5.48k
          {
1635
5.48k
            if (((compress_tag == COMPRESSION_SGILOG) ||
1636
4.27k
                 (compress_tag == COMPRESSION_SGILOG24)) &&
1637
5.48k
                (planar_config == PLANARCONFIG_CONTIG) &&
1638
5.48k
                (samples_per_pixel == 1) &&
1639
5.47k
                (!image->matte))
1640
5.47k
              {
1641
5.47k
                *quantum_type=CIEYQuantum;
1642
5.47k
                *quantum_samples=1;
1643
5.47k
              }
1644
5.48k
            break;
1645
82.7k
          }
1646
6.24k
        case PHOTOMETRIC_LOGLUV:
1647
6.24k
          {
1648
6.24k
            if (((compress_tag == COMPRESSION_SGILOG) ||
1649
1.56k
                 (compress_tag == COMPRESSION_SGILOG24)) &&
1650
6.24k
                (planar_config == PLANARCONFIG_CONTIG) &&
1651
6.24k
                (!image->matte))
1652
6.23k
              {
1653
6.23k
                if (samples_per_pixel == 1)
1654
4.10k
                  {
1655
                    /* FIXME: this might not work. */
1656
4.10k
                    *quantum_type=CIEYQuantum;
1657
4.10k
                    *quantum_samples=1;
1658
4.10k
                  }
1659
2.12k
                else if (samples_per_pixel == 3)
1660
2.12k
                  {
1661
2.12k
                    *quantum_type=CIEXYZQuantum;
1662
2.12k
                    *quantum_samples=3;
1663
2.12k
                  }
1664
6.23k
              }
1665
6.24k
            break;
1666
82.7k
          }
1667
644k
        case PHOTOMETRIC_MINISBLACK:
1668
1.32M
        case PHOTOMETRIC_MINISWHITE:
1669
1.32M
          {
1670
1.32M
            if (planar_config == PLANARCONFIG_SEPARATE)
1671
10.0k
              {
1672
10.0k
                switch (plane)
1673
10.0k
                  {
1674
9.39k
                  case 0:
1675
9.39k
                    *quantum_type=GrayQuantum;
1676
9.39k
                    *quantum_samples=1;
1677
9.39k
                    break;
1678
674
                  case 1:
1679
674
                    *quantum_type=AlphaQuantum;
1680
674
                    *quantum_samples=1;
1681
674
                    break;
1682
10.0k
                  }
1683
10.0k
              }
1684
1.31M
            else
1685
1.31M
              {
1686
1.31M
                if (image->matte)
1687
4.50k
                  {
1688
4.50k
                    *quantum_type=GrayAlphaQuantum;
1689
4.50k
                    *quantum_samples=2;
1690
4.50k
                  }
1691
1.30M
                else
1692
1.30M
                  {
1693
1.30M
                    *quantum_type=GrayQuantum;
1694
1.30M
                    *quantum_samples=1;
1695
1.30M
                  }
1696
1.31M
              }
1697
1.32M
            break;
1698
1.32M
          }
1699
1.32M
        case PHOTOMETRIC_PALETTE:
1700
45.0k
          {
1701
45.0k
            if (sample_format == SAMPLEFORMAT_UINT)
1702
44.0k
              {
1703
44.0k
                if (image->matte)
1704
270
                  {
1705
270
                    *quantum_type=IndexAlphaQuantum;
1706
270
                    *quantum_samples=2;
1707
270
                  }
1708
43.7k
                else
1709
43.7k
                  {
1710
43.7k
                    *quantum_type=IndexQuantum;
1711
43.7k
                    *quantum_samples=1;
1712
43.7k
                  }
1713
44.0k
              }
1714
45.0k
            break;
1715
1.32M
          }
1716
109k
        case PHOTOMETRIC_RGB:
1717
109k
          {
1718
109k
            if (compress_tag != COMPRESSION_OJPEG)
1719
109k
              {
1720
109k
                if (planar_config == PLANARCONFIG_SEPARATE)
1721
5.62k
                  {
1722
5.62k
                    switch (plane)
1723
5.62k
                      {
1724
2.07k
                      case 0:
1725
2.07k
                        *quantum_type=RedQuantum;
1726
2.07k
                        break;
1727
1.56k
                      case 1:
1728
1.56k
                        *quantum_type=GreenQuantum;
1729
1.56k
                        break;
1730
1.53k
                      case 2:
1731
1.53k
                        *quantum_type=BlueQuantum;
1732
1.53k
                        break;
1733
461
                      case 3:
1734
461
                        *quantum_type=AlphaQuantum;
1735
461
                        break;
1736
5.62k
                      }
1737
5.62k
                    *quantum_samples=1;
1738
5.62k
                  }
1739
104k
                else
1740
104k
                  {
1741
104k
                    if (image->matte)
1742
24.0k
                      {
1743
24.0k
                        *quantum_type=RGBAQuantum;
1744
24.0k
                        *quantum_samples=4;
1745
24.0k
                      }
1746
80.2k
                    else
1747
80.2k
                      {
1748
80.2k
                        *quantum_type=RGBQuantum;
1749
80.2k
                        *quantum_samples=3;
1750
80.2k
                      }
1751
104k
                  }
1752
109k
              }
1753
109k
            break;
1754
109k
          }
1755
113k
        case PHOTOMETRIC_SEPARATED:
1756
113k
          {
1757
113k
            if (planar_config == PLANARCONFIG_SEPARATE)
1758
4.93k
              {
1759
4.93k
                switch (plane)
1760
4.93k
                  {
1761
1.65k
                  case 0:
1762
1.65k
                    *quantum_type=CyanQuantum;
1763
1.65k
                    break;
1764
1.04k
                  case 1:
1765
1.04k
                    *quantum_type=MagentaQuantum;
1766
1.04k
                    break;
1767
1.04k
                  case 2:
1768
1.04k
                    *quantum_type=YellowQuantum;
1769
1.04k
                    break;
1770
1.04k
                  case 3:
1771
1.04k
                    *quantum_type=BlackQuantum;
1772
1.04k
                    break;
1773
132
                  case 4:
1774
132
                    *quantum_type=AlphaQuantum;
1775
132
                    break;
1776
4.93k
                  }
1777
4.93k
                *quantum_samples=1;
1778
4.93k
              }
1779
108k
            else
1780
108k
              {
1781
108k
                if (image->matte)
1782
1.69k
                  {
1783
1.69k
                    *quantum_type=CMYKAQuantum;
1784
1.69k
                    *quantum_samples=5;
1785
1.69k
                  }
1786
106k
                else
1787
106k
                  {
1788
106k
                    *quantum_type=CMYKQuantum;
1789
106k
                    *quantum_samples=4;
1790
106k
                  }
1791
108k
              }
1792
113k
            break;
1793
113k
          }
1794
113k
        case PHOTOMETRIC_YCBCR:
1795
2.72k
          {
1796
            /*
1797
              This is here to support JPEGCOLORMODE_RGB which claims a
1798
              YCbCr photometric, but passes RGB to libtiff.
1799
            */
1800
2.72k
            if (compress_tag == COMPRESSION_JPEG)
1801
1.51k
              {
1802
1.51k
                *quantum_type=RGBQuantum;
1803
1.51k
                *quantum_samples=3;
1804
1.51k
              }
1805
2.72k
            break;
1806
113k
          }
1807
1.68M
        }
1808
1.68M
    }
1809
1.69M
  if (image->logging)
1810
1.65M
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1811
1.65M
                          "Quantum Type: %s, Quantum Samples: %d",
1812
1.65M
                          QuantumTypeToString(*quantum_type),*quantum_samples);
1813
  /* FIXME: We do need to support YCbCr! */
1814
1815
1.69M
  if (*quantum_samples != 0)
1816
1.68M
    {
1817
      /*
1818
        Enforce that there are no buffer-overruns.
1819
      */
1820
1.68M
      if (((planar_config == PLANARCONFIG_SEPARATE) && (*quantum_samples != 1)) ||
1821
1.68M
          ((unsigned int) (*quantum_samples) > samples_per_pixel))
1822
60
        {
1823
60
          if (image->logging)
1824
60
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1825
60
                                  "Expected >= %u samples per pixel, have only %d!",
1826
60
                                  *quantum_samples, samples_per_pixel);
1827
60
          ThrowException(exception,CorruptImageError,ImproperImageHeader,
1828
60
                         image->filename);
1829
60
          *quantum_type=UndefinedQuantum;
1830
60
          *quantum_samples=0;
1831
60
        }
1832
1.68M
    }
1833
1834
1.69M
  if ((image->logging) && (*quantum_samples == 0))
1835
7.47k
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1836
7.47k
                          "QuantumTransferMode reports failure");
1837
1838
1.69M
  return (*quantum_samples != 0 ? MagickPass : MagickFail);
1839
1.69M
}
1840
1841
/*
1842
  Compact samples to only contain raster data. This may seem
1843
  inefficient, but it allows us to easily deal with contiguous images
1844
  which contain extra samples while optimizing performance for images
1845
  without extra samples.
1846
*/
1847
static void
1848
CompactSamples( const unsigned long total_pixels,
1849
                const unsigned int bits_per_sample,
1850
                const unsigned int samples_per_pixel,
1851
                const unsigned int quantum_samples,
1852
                unsigned char *samples)
1853
2.56M
{
1854
2.56M
  if ((samples_per_pixel > quantum_samples) &&
1855
2.56M
      (bits_per_sample > 0) && bits_per_sample <= 32)
1856
2.40M
    {
1857
      /*
1858
        Compact scanline to only contain raster data.
1859
      */
1860
1861
2.40M
      BitStreamReadHandle
1862
2.40M
        read_stream;
1863
1864
2.40M
      BitStreamWriteHandle
1865
2.40M
        write_stream;
1866
1867
2.40M
      unsigned long
1868
2.40M
        pixels;
1869
1870
2.40M
      unsigned int
1871
2.40M
        count,
1872
2.40M
        quantum_value;
1873
1874
2.40M
      MagickBitStreamInitializeRead(&read_stream,samples);
1875
2.40M
      MagickBitStreamInitializeWrite(&write_stream,samples);
1876
1877
114M
      for (pixels = total_pixels; pixels != 0 ; pixels--)
1878
111M
        {
1879
523M
          for (count = quantum_samples; count != 0 ; count--)
1880
411M
            {
1881
411M
              quantum_value=MagickBitStreamMSBRead(&read_stream,bits_per_sample);
1882
411M
              MagickBitStreamMSBWrite(&write_stream,bits_per_sample,quantum_value);
1883
411M
            }
1884
277M
          for (count = samples_per_pixel-quantum_samples; count != 0 ; count--)
1885
165M
            {
1886
165M
              (void) MagickBitStreamMSBRead(&read_stream,bits_per_sample);
1887
165M
            }
1888
111M
        }
1889
2.40M
    }
1890
2.56M
}
1891
1892
1893
/*
1894
  Convert selected pixel area to associated alpha representation.
1895
*/
1896
static void
1897
AssociateAlphaRegion(Image *image)
1898
611k
{
1899
611k
  register PixelPacket
1900
611k
    *q;
1901
1902
611k
  register long
1903
611k
    x;
1904
1905
611k
  register double
1906
611k
    alpha,
1907
611k
    value;
1908
1909
611k
  long
1910
611k
    number_pixels;
1911
1912
611k
  number_pixels=(long) GetPixelCacheArea(image);
1913
611k
  q=AccessMutablePixels(image);
1914
1915
28.8M
  for (x = number_pixels; x > 0; --x)
1916
28.2M
    {
1917
28.2M
      alpha=((double) MaxRGB-q->opacity)/MaxRGB;
1918
28.2M
      value=(double) q->red*alpha;
1919
28.2M
      q->red=RoundDoubleToQuantum(value);
1920
28.2M
      value=(double) q->green*alpha;
1921
28.2M
      q->green=RoundDoubleToQuantum(value);
1922
28.2M
      value=(double) q->blue*alpha;
1923
28.2M
      q->blue=RoundDoubleToQuantum(value);
1924
28.2M
      q++;
1925
28.2M
    }
1926
611k
}
1927
1928
/*
1929
  Convert associated alpha to internal representation for selected
1930
  pixel area.
1931
*/
1932
static void
1933
DisassociateAlphaRegion(Image *image)
1934
498k
{
1935
498k
  register PixelPacket
1936
498k
    *q;
1937
1938
498k
  register long
1939
498k
    x;
1940
1941
498k
  register double
1942
498k
    alpha,
1943
498k
    value;
1944
1945
498k
  long
1946
498k
    number_pixels;
1947
1948
498k
  number_pixels=(long) GetPixelCacheArea(image);
1949
498k
  q=AccessMutablePixels(image);
1950
1951
11.1M
  for (x = number_pixels; x > 0; --x)
1952
10.6M
    {
1953
10.6M
      if (q->opacity != (Quantum) MaxRGB)
1954
9.83M
        {
1955
9.83M
          alpha=((double) MaxRGB-q->opacity)/MaxRGB;
1956
9.83M
          value=(double) q->red/alpha;
1957
9.83M
          q->red=RoundDoubleToQuantum(value);
1958
9.83M
          value=(double) q->green/alpha;
1959
9.83M
          q->green=RoundDoubleToQuantum(value);
1960
9.83M
          value=(double) q->blue/alpha;
1961
9.83M
          q->blue=RoundDoubleToQuantum(value);
1962
9.83M
        }
1963
10.6M
      q++;
1964
10.6M
    }
1965
498k
}
1966
1967
#if defined(__cplusplus) || defined(c_plusplus)
1968
}
1969
#endif
1970
1971
/*
1972
  Copy a possibly unterminated sized string to an image attribute.
1973
*/
1974
#define CopySizedFieldToAttribute(key,count,text)                       \
1975
34
  do                                                                    \
1976
34
    {                                                                   \
1977
34
      char _attribute[MaxTextExtent];                                   \
1978
34
      (void) memcpy(_attribute,text,Min(sizeof(_attribute),count));     \
1979
34
      _attribute[Min(sizeof(_attribute)-1,count)]='\0';                 \
1980
34
      (void) SetImageAttribute(image,key,_attribute);                   \
1981
34
    } while(0);
1982
1983
1984
typedef enum
1985
{
1986
  ScanLineMethod,            /* Scanline method */
1987
  StrippedMethod,            /* Stripped method */
1988
  TiledMethod,               /* Tiled method */
1989
  RGBAStrippedMethod,        /* RGBA stripped method */
1990
  RGBATiledMethod,           /* RGBA tiled method */
1991
  RGBAPuntMethod             /* RGBA whole-image method (last resort) */
1992
} TIFFMethod;
1993
1994
3.31k
#define ThrowTIFFReaderException(code_,reason_,image_) \
1995
3.31k
{ \
1996
3.31k
  if (tiff != (TIFF *) NULL)                  \
1997
3.31k
    TIFFClose(tiff);                          \
1998
3.31k
  ThrowReaderException(code_,reason_,image_); \
1999
0
}
2000
2001
static Image *
2002
ReadTIFFImage(const ImageInfo *image_info,ExceptionInfo *exception)
2003
899k
{
2004
899k
  char
2005
899k
    *text;
2006
2007
899k
  const char *
2008
899k
    definition_value;
2009
2010
899k
  float
2011
899k
    *chromaticity,
2012
899k
    x_resolution,
2013
899k
    y_resolution;
2014
2015
899k
  Image
2016
899k
    *image;
2017
2018
899k
  unsigned int
2019
899k
    y;
2020
2021
899k
  register unsigned int
2022
899k
    x;
2023
2024
899k
  register PixelPacket
2025
899k
    *q;
2026
2027
899k
  register unsigned int
2028
899k
    i;
2029
2030
899k
  TIFF
2031
899k
    *tiff = (TIFF *) NULL;
2032
2033
899k
  magick_off_t
2034
899k
    file_size,
2035
899k
    max_compress_ratio=1000; /* Maximum compression ratio */
2036
2037
899k
  uint16
2038
899k
    compress_tag,
2039
899k
    bits_per_sample,
2040
899k
    extra_samples,
2041
899k
    fill_order,
2042
899k
    max_sample_value,
2043
899k
    min_sample_value,
2044
899k
    orientation,
2045
899k
    pages,
2046
899k
    photometric,
2047
899k
    planar_config,
2048
899k
    *sample_info,
2049
899k
    sample_format,
2050
899k
    samples_per_pixel,
2051
899k
    units;
2052
2053
899k
  uint32
2054
899k
    count,
2055
899k
    height,
2056
899k
    rows_per_strip,
2057
899k
    width;
2058
2059
899k
  TIFFMethod
2060
899k
    method;
2061
2062
899k
  Magick_TIFF_ClientData
2063
899k
    client_data;
2064
2065
899k
  ImportPixelAreaOptions
2066
899k
    import_options;
2067
2068
899k
  AlphaType
2069
899k
    alpha_type=UnspecifiedAlpha;
2070
2071
899k
  MagickBool
2072
899k
    logging,
2073
899k
    more_frames;
2074
2075
899k
  MagickPassFail
2076
899k
    status;
2077
2078
  /*
2079
    Open image.
2080
  */
2081
899k
  assert(image_info != (const ImageInfo *) NULL);
2082
899k
  assert(image_info->signature == MagickSignature);
2083
899k
  assert(exception != (ExceptionInfo *) NULL);
2084
899k
  assert(exception->signature == MagickSignature);
2085
2086
899k
  logging=IsEventLogged(CoderEvent);
2087
899k
  image=AllocateImage(image_info);
2088
899k
  more_frames=MagickFalse;
2089
899k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2090
899k
  if (status == MagickFail)
2091
899k
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
2092
899k
  file_size = GetBlobSize(image);
2093
899k
  (void) MagickTsdSetSpecific(tsd_key,(void *) exception);
2094
2095
  /*
2096
    Set global thread-specific reader errors and warnings handlers.
2097
  */
2098
899k
  (void) TIFFSetErrorHandler((TIFFErrorHandler) TIFFReadErrorsHandler);
2099
899k
  (void) TIFFSetWarningHandler((TIFFErrorHandler) (CheckThrowWarnings(image_info) ?
2100
0
                                                   TIFFWarningsThrowException :
2101
899k
                                                   TIFFWarningsLogOnly));
2102
899k
  client_data.image=image;
2103
899k
  client_data.image_info=image_info;
2104
899k
#if defined(HAVE_TIFFERROREXTR)
2105
899k
  {
2106
899k
    magick_int64_t
2107
899k
      memory_consumed,
2108
899k
      memory_maximum_limit;
2109
2110
899k
    tmsize_t
2111
899k
      max_single_mem_alloc;
2112
2113
899k
    TIFFOpenOptions *open_options = TIFFOpenOptionsAlloc();
2114
    /*
2115
      TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts,
2116
                                             tmsize_t max_single_mem_alloc);
2117
      TIFFOpenOptionsSetMaxCumulatedMemAlloc(TIFFOpenOptions *opts,
2118
                                             tmsize_t max_cumulated_mem_alloc);
2119
      TIFFOpenOptionsSetWarnAboutUnknownTags(TIFFOpenOptions *opts,
2120
                                             int warn_about_unknown_tags);
2121
      TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions *opts,
2122
                                         TIFFErrorHandlerExtR handler,
2123
                                         void *errorhandler_user_data);
2124
      TIFFOpenOptionsSetWarningHandlerExtR(TIFFOpenOptions *opts,
2125
                                           TIFFErrorHandlerExtR handler,
2126
                                           void *warnhandler_user_data);
2127
    */
2128
899k
    TIFFOpenOptionsSetErrorHandlerExtR(open_options, TIFFReadErrorsHandlerExtR, (void *) exception);
2129
899k
    TIFFOpenOptionsSetWarningHandlerExtR(open_options,
2130
899k
                                         (CheckThrowWarnings(image_info) ?
2131
899k
                                          TIFFReadWarningHandlerExtRThrowException : TIFFReadWarningHandlerExtRLogOnly),
2132
899k
                                         (void *) exception); /* FIXME */
2133
899k
    memory_maximum_limit=GetMagickResourceLimit(MemoryResource);
2134
899k
    memory_consumed=GetMagickResource(MemoryResource);
2135
899k
    max_single_mem_alloc=((memory_maximum_limit-memory_consumed)/8); /* FIXME: Support configuring ratio? */
2136
899k
    TIFFOpenOptionsSetMaxSingleMemAlloc(open_options, max_single_mem_alloc); /* Added in v4.5.0 */
2137
899k
#if defined(HAVE_TIFFOPENOPTIONSSETMAXCUMULATEDMEMALLOC)
2138
899k
    {
2139
899k
      tmsize_t
2140
899k
        max_cumulated_mem_alloc;
2141
2142
899k
      max_cumulated_mem_alloc=((memory_maximum_limit-memory_consumed)/4); /* FIXME: Support configuring ratio? */
2143
899k
      TIFFOpenOptionsSetMaxCumulatedMemAlloc(open_options, max_cumulated_mem_alloc); /* Added in v4.7.0 */
2144
899k
    }
2145
899k
#endif /* if defined(HAVE_TIFFOPENOPTIONSSETMAXCUMULATEDMEMALLOC) */
2146
899k
    tiff=TIFFClientOpenExt(image->filename,"rb",(thandle_t) &client_data,
2147
899k
                           TIFFReadBlob,TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,
2148
899k
                           TIFFGetBlobSize,TIFFMapBlob,TIFFUnmapBlob,
2149
899k
                           open_options);
2150
899k
    TIFFOpenOptionsFree(open_options);
2151
899k
  }
2152
#else
2153
  tiff=TIFFClientOpen(image->filename,"rb",(thandle_t) &client_data,
2154
                      TIFFReadBlob,
2155
                      TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,
2156
                      TIFFGetBlobSize,TIFFMapBlob,TIFFUnmapBlob);
2157
#endif /* if defined(HAVE_TIFFERROREXTR) */
2158
899k
  if (tiff == (TIFF *) NULL)
2159
791k
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
2160
2161
  /*
2162
    Report error if error was reported via TIFFReadErrorsHandler() while in
2163
    TIFFClientOpen().
2164
  */
2165
108k
  if (exception->severity > ErrorException)
2166
51.4k
    {
2167
51.4k
      TIFFClose(tiff);
2168
51.4k
      DestroyImageList(image);
2169
51.4k
      return (Image *) NULL;
2170
51.4k
    }
2171
2172
57.3k
  if (image_info->subrange != 0)
2173
55.0k
    while (image->scene < image_info->subimage)
2174
0
      {
2175
        /*
2176
          Skip to next image.
2177
        */
2178
0
        image->scene++;
2179
0
        status=TIFFReadDirectory(tiff);
2180
0
        if (status == False)
2181
0
          {
2182
0
            ThrowTIFFReaderException(CorruptImageError,UnableToReadSubImageData,
2183
0
                                     image);
2184
0
          }
2185
0
      }
2186
57.3k
  do
2187
57.3k
    {
2188
57.3k
      if (image_info->verbose > 1)
2189
0
        TIFFPrintDirectory(tiff,stdout,False);
2190
2191
      /*
2192
        Read critical tags.  We need a value for these tags in order to proceed.
2193
      */
2194
57.3k
      status = 1;
2195
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_PHOTOMETRIC,&photometric) == 1);
2196
57.3k
      if ((status == 1) &&
2197
56.0k
          ((photometric == PHOTOMETRIC_LOGL) || (photometric == PHOTOMETRIC_LOGLUV)))
2198
1.15k
        status &= (TIFFSetField(tiff,TIFFTAG_SGILOGDATAFMT,SGILOGDATAFMT_FLOAT) == 1);
2199
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_COMPRESSION,&compress_tag) == 1);
2200
57.3k
      status &= (TIFFGetField(tiff,TIFFTAG_IMAGEWIDTH,&width) == 1);
2201
57.3k
      status &= (TIFFGetField(tiff,TIFFTAG_IMAGELENGTH,&height) == 1);
2202
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_PLANARCONFIG,&planar_config) == 1);
2203
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,&samples_per_pixel) == 1);
2204
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,&bits_per_sample) == 1);
2205
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLEFORMAT,&sample_format) == 1);
2206
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_MINSAMPLEVALUE,&min_sample_value) == 1);
2207
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_MAXSAMPLEVALUE,&max_sample_value) == 1);
2208
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_ROWSPERSTRIP,&rows_per_strip) == 1);
2209
57.3k
      status &= (TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&fill_order) == 1);
2210
57.3k
      if (status == 0)
2211
1.32k
        {
2212
          /*
2213
            Promote TIFF warnings to errors for these critical tags.
2214
          */
2215
1.32k
          if ((exception->severity > WarningException) &&
2216
6
              (exception->severity < ErrorException))
2217
0
            exception->severity = (ExceptionType) ((int) exception->severity +
2218
0
                                                   ((int) ErrorException - (int)WarningException));
2219
1.32k
          ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,
2220
0
                                   image);
2221
0
        }
2222
56.0k
      if (TIFFGetField(tiff,TIFFTAG_ORIENTATION,&orientation) == 1)
2223
4.96k
        image->orientation=(OrientationType) orientation;
2224
56.0k
      if (logging)
2225
0
        {
2226
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %ux%u",
2227
0
                                (unsigned int) width,(unsigned int) height);
2228
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),"PlanarConfiguration: %s",
2229
0
                                planar_config == PLANARCONFIG_CONTIG ? "contiguous" :
2230
0
                                planar_config == PLANARCONFIG_SEPARATE ? "separate" :
2231
0
                                "UNKNOWN");
2232
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2233
0
                                "Samples per pixel: %u", samples_per_pixel);
2234
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2235
0
                                "Sample format: %s",
2236
0
                                sample_format == SAMPLEFORMAT_UINT ? "Unsigned integer" :
2237
0
                                sample_format == SAMPLEFORMAT_INT ? "Signed integer" :
2238
0
                                sample_format == SAMPLEFORMAT_IEEEFP ? "IEEE floating point" :
2239
0
                                sample_format == SAMPLEFORMAT_VOID ? "Untyped data" :
2240
0
                                sample_format == SAMPLEFORMAT_COMPLEXINT ? "Complex signed int" :
2241
0
                                sample_format == SAMPLEFORMAT_COMPLEXIEEEFP ? "Complex IEEE floating point" :
2242
0
                                "UNKNOWN");
2243
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2244
0
                                "Bits per sample: %u",bits_per_sample);
2245
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2246
0
                                "Min sample value: %u",min_sample_value);
2247
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2248
0
                                "Max sample value: %u",max_sample_value);
2249
0
          if (sample_format == SAMPLEFORMAT_IEEEFP)
2250
0
            {
2251
0
              double
2252
0
                value;
2253
2254
0
              if (TIFFGetField(tiff,TIFFTAG_SMINSAMPLEVALUE,&value) == 1)
2255
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2256
0
                                      "Special min sample value: %g", value);
2257
0
              if (TIFFGetField(tiff,TIFFTAG_SMAXSAMPLEVALUE,&value) == 1)
2258
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2259
0
                                      "Special max sample value: %g", value);
2260
0
            }
2261
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2262
0
                                "Photometric: %s", PhotometricTagToString(photometric));
2263
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2264
0
                                "Compression: %s", CompressionTagToString(compress_tag));
2265
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2266
0
                                "Byte swapped: %s",TIFFIsByteSwapped(tiff) ?
2267
0
                                "true" : "false");
2268
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2269
0
                                "Bit fill order: %s",
2270
0
                                fill_order == FILLORDER_LSB2MSB ? "LSB2MSB" :
2271
0
                                fill_order == FILLORDER_MSB2LSB ? "MSB2LSB" :
2272
0
                                "unknown");
2273
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2274
0
                                "Rows per strip: %u",(unsigned int) rows_per_strip);
2275
0
        }
2276
56.0k
      ImportPixelAreaOptionsInit(&import_options);
2277
56.0k
      if (photometric == PHOTOMETRIC_CIELAB)
2278
3.58k
        {
2279
3.58k
#if 1
2280
3.58k
          image->colorspace=LABColorspace;
2281
#else
2282
          ThrowTIFFReaderException(CoderError,UnableToReadCIELABImages,image);
2283
#endif
2284
3.58k
        }
2285
56.0k
      if (photometric == PHOTOMETRIC_SEPARATED)
2286
2.65k
        image->colorspace=CMYKColorspace;
2287
56.0k
      if (planar_config == PLANARCONFIG_SEPARATE)
2288
3.66k
        image->interlace=PlaneInterlace;
2289
56.0k
      (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_RESOLUTIONUNIT,&units);
2290
56.0k
      x_resolution=(float) image->x_resolution;
2291
56.0k
      y_resolution=(float) image->y_resolution;
2292
56.0k
      (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_XRESOLUTION,&x_resolution);
2293
56.0k
      (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_YRESOLUTION,&y_resolution);
2294
56.0k
      image->x_resolution=x_resolution;
2295
56.0k
      image->y_resolution=y_resolution;
2296
56.0k
      chromaticity=(float *) NULL;
2297
56.0k
      if (TIFFGetField(tiff,TIFFTAG_WHITEPOINT,&chromaticity) == 1)
2298
402
        {
2299
402
          if (chromaticity != (float *) NULL)
2300
402
            {
2301
402
              if (logging)
2302
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2303
0
                                      "White Point: %gx%g",
2304
0
                                      chromaticity[0] /* white_point.x */,
2305
0
                                      chromaticity[1] /* white_point.y */);
2306
402
              if (MAGICK_ISNAN(chromaticity[0]) || (chromaticity[0] < 0.0) ||
2307
402
                  MAGICK_ISNAN(chromaticity[1]) || (chromaticity[1] < 0.0))
2308
19
                {
2309
19
                  if (logging)
2310
0
                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2311
0
                                          "White Point: Is corrupt!");
2312
19
                }
2313
383
              else
2314
383
                {
2315
383
                  image->chromaticity.white_point.x=chromaticity[0];
2316
383
                  image->chromaticity.white_point.y=chromaticity[1];
2317
383
                }
2318
402
            }
2319
402
        }
2320
56.0k
      chromaticity=(float *) NULL;
2321
56.0k
      if (TIFFGetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,&chromaticity) == 1)
2322
236
        {
2323
236
          if (chromaticity != (float *) NULL)
2324
236
            {
2325
236
              if (logging)
2326
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2327
0
                                      "Primary Chromaticities: "
2328
0
                                      "r=%gx%g g=%gx%g b=%gx%g",
2329
0
                                      chromaticity[0] /* red_primary.x */,
2330
0
                                      chromaticity[1] /* red_primary.y */,
2331
0
                                      chromaticity[2] /* green_primary.x */,
2332
0
                                      chromaticity[3] /* green_primary.y */,
2333
0
                                      chromaticity[4] /* blue_primary.x */,
2334
0
                                      chromaticity[5] /* blue_primary.y */);
2335
236
              if (MAGICK_ISNAN(chromaticity[0]) || (chromaticity[0] < 0.0) ||
2336
236
                  MAGICK_ISNAN(chromaticity[1]) || (chromaticity[1] < 0.0) ||
2337
236
                  MAGICK_ISNAN(chromaticity[2]) || (chromaticity[2] < 0.0) ||
2338
236
                  MAGICK_ISNAN(chromaticity[3]) || (chromaticity[3] < 0.0) ||
2339
236
                  MAGICK_ISNAN(chromaticity[4]) || (chromaticity[4] < 0.0) ||
2340
236
                  MAGICK_ISNAN(chromaticity[5]) || (chromaticity[5] < 0.0))
2341
64
                {
2342
64
                  if (logging)
2343
0
                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2344
0
                                          "Primary Chromaticities: Is corrupt!");
2345
64
                }
2346
172
              else
2347
172
                {
2348
172
                  image->chromaticity.red_primary.x=chromaticity[0];
2349
172
                  image->chromaticity.red_primary.y=chromaticity[1];
2350
172
                  image->chromaticity.green_primary.x=chromaticity[2];
2351
172
                  image->chromaticity.green_primary.y=chromaticity[3];
2352
172
                  image->chromaticity.blue_primary.x=chromaticity[4];
2353
172
                  image->chromaticity.blue_primary.y=chromaticity[5];
2354
172
                }
2355
236
            }
2356
236
        }
2357
56.0k
      {
2358
        /*
2359
          Retrieve embedded profiles.
2360
        */
2361
56.0k
        uint32
2362
56.0k
          length;
2363
        /*
2364
          ICC ICM color profile.
2365
        */
2366
56.0k
#if defined(TIFFTAG_ICCPROFILE)
2367
56.0k
        if (TIFFGetField(tiff,TIFFTAG_ICCPROFILE,&length,&text) == 1)
2368
38
          {
2369
38
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2370
38
                                  "ICC ICM embedded profile with length %lu bytes",
2371
38
                                  (unsigned long)length);
2372
38
            (void) SetImageProfile(image,"ICM",(unsigned char *) text,(size_t) length);
2373
38
          }
2374
56.0k
#endif /* defined(TIFFTAG_ICCPROFILE) */
2375
        /*
2376
          IPTC/Photoshop profile.
2377
        */
2378
56.0k
#if defined(TIFFTAG_PHOTOSHOP)
2379
        /* Photoshop profile (with embedded IPTC profile) */
2380
56.0k
        if (TIFFGetField(tiff,TIFFTAG_PHOTOSHOP,&length,&text) == 1)
2381
98
          {
2382
98
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2383
98
                                  "Photoshop embedded profile with length %lu bytes",
2384
98
                                  (unsigned long) length);
2385
98
            (void) ReadNewsProfile((unsigned char *) text,(long) length,image,TIFFTAG_PHOTOSHOP);
2386
98
          }
2387
#elif defined(TIFFTAG_RICHTIFFIPTC)
2388
        /* IPTC TAG from RichTIFF specifications */
2389
        if (TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC,&length,&text) == 1)
2390
          {
2391
            if (TIFFIsByteSwapped(tiff))
2392
              TIFFSwabArrayOfLong((uint32 *) text,length);
2393
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2394
                                  "IPTC Newsphoto embedded profile with length %u bytes",length);
2395
            ReadNewsProfile((unsigned char *) text,length,image,TIFFTAG_RICHTIFFIPTC);
2396
          }
2397
#endif
2398
        /*
2399
          XML XMP profile.
2400
        */
2401
56.0k
#if defined(TIFFTAG_XMLPACKET)
2402
        /* %XML packet [Adobe XMP Specification, Janary 2004] */
2403
56.0k
        if (TIFFGetField(tiff,TIFFTAG_XMLPACKET,&length,&text) == 1)
2404
34
          {
2405
34
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2406
34
                                  "XMP embedded profile with length %lu bytes",
2407
34
                                  (unsigned long) length);
2408
34
            SetImageProfile(image,"XMP",(unsigned char *) text,(size_t) length);
2409
34
          }
2410
56.0k
#endif
2411
56.0k
      }
2412
      /*
2413
        Map from TIFF compression tags to GraphicsMagick equivalents
2414
        as well as estimate a maximum compression ratio (for
2415
        validating scanline/strip/tile allocation requests).
2416
      */
2417
56.0k
      switch (compress_tag)
2418
56.0k
        {
2419
8.88k
        case COMPRESSION_NONE:
2420
8.88k
          image->compression=NoCompression;
2421
8.88k
          break;
2422
3.87k
        case COMPRESSION_CCITTFAX3:
2423
3.87k
          image->compression=FaxCompression;
2424
3.87k
          break;
2425
4.92k
        case COMPRESSION_CCITTFAX4:
2426
4.92k
          image->compression=Group4Compression;
2427
4.92k
          break;
2428
12.3k
        case COMPRESSION_JPEG:
2429
12.3k
          image->compression=JPEGCompression;
2430
12.3k
          break;
2431
0
        case COMPRESSION_OJPEG:
2432
0
          image->compression=JPEGCompression;
2433
0
          break;
2434
1.70k
        case COMPRESSION_LZW:
2435
1.70k
          image->compression=LZWCompression;
2436
1.70k
          break;
2437
0
#if defined(COMPRESSION_LZMA)
2438
75
        case COMPRESSION_LZMA:
2439
75
          image->compression=LZMACompression;
2440
75
          break;
2441
0
#endif /* defined(COMPRESSION_LZMA) */
2442
863
        case COMPRESSION_DEFLATE:
2443
863
          image->compression=ZipCompression;
2444
863
          break;
2445
4.24k
        case COMPRESSION_ADOBE_DEFLATE:
2446
4.24k
          image->compression=ZipCompression;
2447
4.24k
          break;
2448
0
#if defined(COMPRESSION_ZSTD)
2449
5.60k
        case COMPRESSION_ZSTD:
2450
5.60k
          image->compression=ZSTDCompression;
2451
5.60k
          break;
2452
0
#endif /* defined(COMPRESSION_ZSTD) */
2453
0
#if defined(COMPRESSION_WEBP)
2454
7.43k
        case COMPRESSION_WEBP:
2455
7.43k
          image->compression=WebPCompression;
2456
7.43k
          break;
2457
0
#endif /* if defined(COMPRESSION_WEBP) */
2458
6.13k
        default:
2459
6.13k
          image->compression=NoCompression;
2460
6.13k
          break;
2461
56.0k
        }
2462
56.0k
      image->columns=width;
2463
56.0k
      image->rows=height;
2464
56.0k
      image->depth=bits_per_sample;
2465
2466
56.0k
      if (image->scene != 0)
2467
0
        status=MagickMonitorFormatted(image->scene-1,image->scene,
2468
0
                                      &image->exception,
2469
0
                                      LoadImageText,image->filename,
2470
0
                                      image->columns,image->rows);
2471
2472
      /*
2473
        Obtain information about any extra samples.
2474
        FIXME samples_per_pixel = 4 and 1 extra sample which is 'unspecified'
2475
      */
2476
56.0k
      extra_samples=0;
2477
56.0k
      if (TIFFGetField(tiff,TIFFTAG_EXTRASAMPLES,&extra_samples,
2478
56.0k
                       &sample_info) == 1)
2479
6.96k
        {
2480
6.96k
          int
2481
6.96k
            sample_index;
2482
2483
6.96k
          if (extra_samples != 0)
2484
6.87k
            {
2485
6.87k
              if (sample_info[0] == EXTRASAMPLE_UNSPECIFIED)
2486
303
                {
2487
303
                  alpha_type=UnspecifiedAlpha;
2488
303
                }
2489
6.57k
              else if (sample_info[0] == EXTRASAMPLE_UNASSALPHA)
2490
3.63k
                {
2491
3.63k
                  alpha_type=UnassociatedAlpha;
2492
3.63k
                }
2493
2.93k
              else if (sample_info[0] == EXTRASAMPLE_ASSOCALPHA)
2494
2.93k
                {
2495
2.93k
                  alpha_type=AssociatedAlpha;
2496
2.93k
                }
2497
6.87k
            }
2498
6.96k
          if (image->logging)
2499
793k
            for (sample_index=0 ; sample_index < extra_samples; sample_index++)
2500
786k
              {
2501
786k
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2502
786k
                                      "Extra sample %u contains %s",sample_index+1,
2503
786k
                                      ExtraSampleToString(sample_info[sample_index]));
2504
786k
              }
2505
6.96k
        }
2506
      /*
2507
        Report RGBA images which may be improperly marked.
2508
      */
2509
56.0k
      if ((image->logging) && (extra_samples == 0))
2510
49.1k
        if (((PHOTOMETRIC_RGB == photometric) && (samples_per_pixel == 4)) ||
2511
47.2k
            (((PHOTOMETRIC_MINISWHITE == photometric) || (PHOTOMETRIC_MINISBLACK == photometric)) && (samples_per_pixel == 2)))
2512
2.38k
          {
2513
2.38k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2514
2.38k
                                  "Photometric is %s but %u samples/pixel and %u extra_samples provided!",
2515
2.38k
                                  PhotometricTagToString(photometric),samples_per_pixel, extra_samples);
2516
2.38k
          }
2517
      /*
2518
        Deal with files which are marked as unspecified alpha, but
2519
        they should be unassociated alpha.
2520
      */
2521
56.0k
      if (((extra_samples == 1) && (sample_info[0] == EXTRASAMPLE_UNSPECIFIED)) &&
2522
255
          (
2523
255
           ((samples_per_pixel == 2) && ((PHOTOMETRIC_MINISWHITE == photometric) || (PHOTOMETRIC_MINISBLACK == photometric))) ||
2524
152
           ((samples_per_pixel == 4) && (PHOTOMETRIC_RGB == photometric)) ||
2525
63
           ((samples_per_pixel == 5) && (PHOTOMETRIC_SEPARATED == photometric))
2526
255
           )
2527
56.0k
          )
2528
213
        {
2529
213
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2530
213
                                "Promoting UnspecifiedAlpha to UnassociatedAlpha");
2531
213
          alpha_type=UnassociatedAlpha;
2532
213
          image->matte=True;
2533
213
        }
2534
      /*
2535
        Allow the user to over-ride the alpha channel type.
2536
      */
2537
56.0k
      if (image->matte)
2538
213
        {
2539
213
          if ((definition_value=AccessDefinition(image_info,"tiff","alpha")))
2540
0
            {
2541
0
              if (LocaleCompare(definition_value,"unspecified") == 0)
2542
0
                alpha_type=UnspecifiedAlpha;
2543
0
              else if (LocaleCompare(definition_value,"associated") == 0)
2544
0
                alpha_type=AssociatedAlpha;
2545
0
              else if (LocaleCompare(definition_value,"unassociated") == 0)
2546
0
                alpha_type=UnassociatedAlpha;
2547
0
            }
2548
213
        }
2549
2550
      /*
2551
        Does alpha type deserve a matte channel?
2552
      */
2553
56.0k
      switch (alpha_type)
2554
56.0k
        {
2555
49.2k
        case UnspecifiedAlpha:
2556
49.2k
          break;
2557
3.85k
        case UnassociatedAlpha:
2558
3.85k
          image->matte=True;
2559
3.85k
          break;
2560
2.93k
        case AssociatedAlpha:
2561
2.93k
          image->matte=True;
2562
2.93k
          break;
2563
0
        default:
2564
0
          break;
2565
56.0k
        }
2566
2567
      /*
2568
        Describe how the alpha channel will be treated.
2569
      */
2570
56.0k
      if (image->matte)
2571
6.78k
        {
2572
6.78k
          char
2573
6.78k
            alpha_string[MaxTextExtent];
2574
2575
6.78k
          switch (alpha_type)
2576
6.78k
            {
2577
0
            default:
2578
0
            case UnspecifiedAlpha:
2579
0
              (void) strlcpy(alpha_string,"Unspecified",MaxTextExtent);
2580
0
              break;
2581
3.85k
            case UnassociatedAlpha:
2582
3.85k
              (void) strlcpy(alpha_string,"Unassociated",MaxTextExtent);
2583
3.85k
              break;
2584
2.93k
            case AssociatedAlpha:
2585
2.93k
              (void) strlcpy(alpha_string,"Associated",MaxTextExtent);
2586
2.93k
              break;
2587
6.78k
            }
2588
6.78k
          (void) SetImageAttribute(image,"alpha",alpha_string);
2589
6.78k
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2590
6.78k
                                "Image has a matte channel of type: %s",
2591
6.78k
                                alpha_string);
2592
6.78k
        }
2593
2594
56.0k
      if (units == RESUNIT_INCH)
2595
55.4k
        image->units=PixelsPerInchResolution;
2596
56.0k
      if (units == RESUNIT_CENTIMETER)
2597
93
        image->units=PixelsPerCentimeterResolution;
2598
56.0k
      {
2599
56.0k
        uint16
2600
56.0k
          pagenumber;
2601
2602
56.0k
        pagenumber=(unsigned short) image->scene;
2603
56.0k
        if (TIFFGetFieldDefaulted(tiff,TIFFTAG_PAGENUMBER,&pagenumber,&pages) == 1)
2604
628
          image->scene=pagenumber;
2605
56.0k
      }
2606
2607
      /*
2608
        Convert TIFF tags to text attributes
2609
        https://gitlab.com/libtiff/libtiff/-/issues/575
2610
      */
2611
56.0k
      {
2612
56.0k
        static const struct
2613
56.0k
        {
2614
56.0k
          uint32 tag;
2615
56.0k
          const char name[14];
2616
56.0k
        } text_tags[] =
2617
56.0k
          {
2618
56.0k
            { TIFFTAG_ARTIST, "artist" },
2619
56.0k
            { TIFFTAG_COPYRIGHT, "copyright" },
2620
56.0k
            { TIFFTAG_DATETIME, "timestamp" },
2621
56.0k
            { TIFFTAG_DOCUMENTNAME, "document" },
2622
56.0k
            { TIFFTAG_HOSTCOMPUTER, "hostcomputer" },
2623
56.0k
            { TIFFTAG_IMAGEDESCRIPTION, "comment" },
2624
56.0k
            { TIFFTAG_MAKE, "make" },
2625
56.0k
            { TIFFTAG_MODEL, "model" },
2626
56.0k
            { TIFFTAG_PAGENAME, "label" },
2627
56.0k
            { TIFFTAG_SOFTWARE, "software" },
2628
56.0k
#if 1
2629
            /*
2630
              These three cause TIFFFieldWithTag() to return NULL and
2631
              therefore produce "TIFF Warning: Warning, unknown tag" exceptions
2632
              while reading!
2633
            */
2634
56.0k
            { TIFFTAG_OPIIMAGEID, "imageid" },
2635
56.0k
            { 33423, "kodak-33423" },
2636
56.0k
            { 36867, "kodak-36867" }
2637
56.0k
#endif
2638
56.0k
          };
2639
2640
784k
        for (i = 0; i < ArraySize(text_tags); i++)
2641
728k
          {
2642
728k
            const uint32 tag = text_tags[i].tag;
2643
728k
            const char *tag_name = text_tags[i].name;
2644
728k
            int field_passcount=1; /* "Unsupported" tags return two arguments */
2645
#if TIFFLIB_VERSION <= 20111221
2646
             /*
2647
               Before tiff 4.0.0 (20111221), TIFFFieldWithTag returned
2648
               TIFFFieldInfo * which provides field_passcount
2649
             */
2650
            const TIFFFieldInfo* tiff_field=TIFFFieldWithTag(tiff,tag);
2651
            if (tiff_field != (const TIFFFieldInfo *))
2652
                field_passcount=tiff_field->field_passcount;
2653
            else
2654
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2655
                                    "TIFFFieldWithTag() returns NULL for tag %u \"%s\"", tag, tag_name);
2656
#else
2657
728k
            const TIFFField *tiff_field=TIFFFieldWithTag(tiff,tag);
2658
728k
            if (tiff_field != (const TIFFField *) NULL)
2659
560k
              field_passcount=TIFFFieldPassCount(tiff_field);
2660
168k
            else
2661
168k
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2662
168k
                                    "TIFFFieldWithTag() returns NULL for tag %u \"%s\"", tag, tag_name);
2663
728k
#endif
2664
#if 0
2665
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2666
                                  "Field pass count for tag %u \"%s\" is %d", tag, tag_name, field_passcount);
2667
#endif
2668
728k
            if (field_passcount)
2669
168k
              {
2670
168k
                if ((TIFFGetField(tiff,tag,&count,&text) == 1) && (count) && (text != (const char*) NULL))
2671
34
                  CopySizedFieldToAttribute(tag_name,count,text);
2672
168k
              }
2673
560k
            else
2674
560k
              {
2675
560k
                if ((TIFFGetField(tiff,tag,&text) == 1) && (text != (const char*) NULL))
2676
10.5k
                  (void) SetImageAttribute(image,tag_name,text);
2677
560k
              }
2678
728k
          }
2679
56.0k
      }
2680
2681
56.0k
      if ((photometric == PHOTOMETRIC_PALETTE) ||
2682
53.8k
          ((photometric == PHOTOMETRIC_MINISWHITE ||
2683
37.2k
            photometric == PHOTOMETRIC_MINISBLACK) &&
2684
31.5k
           ((image_info->type == PaletteType) ||
2685
31.5k
            (image_info->type == PaletteMatteType)) &&
2686
0
           (MaxColormapSize > MaxValueGivenBits(bits_per_sample))
2687
53.8k
           )
2688
56.0k
          )
2689
2.25k
        {
2690
          /*
2691
            Palette image
2692
          */
2693
2.25k
          if (MaxColormapSize > MaxValueGivenBits(bits_per_sample))
2694
2.25k
            {
2695
2.25k
              (void) InitializeImageColormap(image,tiff);
2696
2.25k
            }
2697
0
          else
2698
0
            {
2699
0
              ThrowTIFFReaderException(CoderError,ColormapTooLarge,image);
2700
0
            }
2701
2.25k
        }
2702
2703
      /*
2704
        Quit if in "ping" mode and we are outside of requested range,
2705
        otherwise continue to next frame.
2706
      */
2707
56.0k
      if (image_info->ping)
2708
0
        {
2709
0
          if (image_info->subrange != 0)
2710
0
            if (image->scene >= (image_info->subimage+image_info->subrange-1))
2711
0
              break;
2712
2713
0
          goto read_next_frame;
2714
0
        }
2715
2716
56.0k
      if (CheckImagePixelLimits(image, exception) != MagickPass)
2717
1.44k
        {
2718
1.44k
          ThrowTIFFReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
2719
0
        }
2720
2721
      /*
2722
        Verify that the bits per sample, samples per pixel, and
2723
        photometric are suitable for the claimed compressor
2724
      */
2725
54.6k
#if defined(COMPRESSION_CCITTFAX3)
2726
54.6k
      if (COMPRESSION_CCITTFAX3 == compress_tag)
2727
3.85k
        {
2728
3.85k
          if (1 != bits_per_sample)
2729
5
            {
2730
5
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2731
5
                                    "%s compression requires 1 bits per sample!",
2732
5
                                    CompressionTagToString(compress_tag));
2733
5
              ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2734
0
            }
2735
3.85k
          if ((PHOTOMETRIC_MINISBLACK != photometric) && (PHOTOMETRIC_MINISWHITE != photometric))
2736
23
            {
2737
23
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2738
23
                                    "%s compression requires photometric of minisblack or miniswhite!",
2739
23
                                    CompressionTagToString(compress_tag));
2740
23
              ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2741
0
            }
2742
3.85k
        }
2743
54.5k
#endif /* if defined(COMPRESSION_CCITTFAX3) */
2744
54.5k
#if defined(COMPRESSION_CCITTFAX4)
2745
54.5k
      if (COMPRESSION_CCITTFAX4 == compress_tag)
2746
4.78k
        {
2747
4.78k
          if (1 != bits_per_sample)
2748
4
            {
2749
4
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2750
4
                                    "%s compression requires 1 bits per sample!",
2751
4
                                    CompressionTagToString(compress_tag));
2752
4
              ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2753
0
            }
2754
4.77k
          if ((PHOTOMETRIC_MINISBLACK != photometric) && (PHOTOMETRIC_MINISWHITE != photometric))
2755
18
            {
2756
18
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2757
18
                                    "%s compression requires photometric of minisblack or miniswhite!",
2758
18
                                    CompressionTagToString(compress_tag));
2759
18
              ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2760
0
            }
2761
4.77k
        }
2762
54.5k
#endif /* if defined(COMPRESSION_CCITTFAX4) */
2763
54.5k
#if defined(COMPRESSION_JBIG)
2764
54.5k
      if (COMPRESSION_JBIG == compress_tag)
2765
0
        {
2766
0
          if (1 != bits_per_sample)
2767
0
            {
2768
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2769
0
                                    "%s compression requires 1 bits per sample!",
2770
0
                                    CompressionTagToString(compress_tag));
2771
0
              ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2772
0
            }
2773
0
          if ((PHOTOMETRIC_MINISBLACK != photometric) && (PHOTOMETRIC_MINISWHITE != photometric))
2774
0
            {
2775
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2776
0
                                    "%s compression requires photometric of minisblack or miniswhite!",
2777
0
                                    CompressionTagToString(compress_tag));
2778
0
              ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2779
0
            }
2780
0
        }
2781
54.5k
#endif /* if defined(COMPRESSION_JBIG) */
2782
54.5k
#if defined(COMPRESSION_WEBP)
2783
54.5k
      if (COMPRESSION_WEBP == compress_tag)
2784
7.41k
        {
2785
7.41k
          if (8 != bits_per_sample)
2786
10
            {
2787
10
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2788
10
                                    "%s compression requires 8 bits per sample!",
2789
10
                                    CompressionTagToString(compress_tag));
2790
10
              ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2791
0
            }
2792
7.40k
          if ((3 != samples_per_pixel) && (4 != samples_per_pixel))
2793
8
            {
2794
8
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2795
8
                                    "%s compression requires 3 or 4 samples per pixel!",
2796
8
                                    CompressionTagToString(compress_tag));
2797
8
              ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2798
0
            }
2799
7.39k
          if (PHOTOMETRIC_RGB != photometric)
2800
4
            {
2801
4
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2802
4
                                    "%s compression requires photometric RGB!",
2803
4
                                    CompressionTagToString(compress_tag));
2804
4
              ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2805
0
            }
2806
7.39k
        }
2807
54.5k
#endif /* if defined(COMPRESSION_WEBP) */
2808
2809
      /*
2810
        Check if the bits-per-sample value is supported by the
2811
        implementation before proceeding.
2812
2813
        Currently we support a range of 1-32, and 64 bits if the
2814
        samples are float.
2815
      */
2816
54.5k
      if (!((sample_format == SAMPLEFORMAT_IEEEFP && bits_per_sample == 64) ||
2817
53.6k
            ((bits_per_sample > 0) && (bits_per_sample <= 32))))
2818
44
        {
2819
44
          ThrowTIFFReaderException(CoderError,UnsupportedBitsPerSample,image);
2820
0
        }
2821
2822
      /*
2823
        Check for excessive samples per pixel or excessive extra samples.
2824
      */
2825
54.4k
      if ((samples_per_pixel > 8U) || (extra_samples > 8U))
2826
47
        {
2827
47
          ThrowTIFFReaderException(CoderError,UnsupportedSamplesPerPixel,image);
2828
0
        }
2829
2830
      /*
2831
        Determine which method to use for reading pixels.
2832
      */
2833
54.4k
      {
2834
54.4k
        int
2835
54.4k
          quantum_samples;
2836
2837
54.4k
        QuantumType
2838
54.4k
          quantum_type;
2839
2840
54.4k
        if ((samples_per_pixel > 1) &&
2841
21.6k
            (compress_tag == COMPRESSION_JPEG) &&
2842
1.79k
            (photometric == PHOTOMETRIC_YCBCR))
2843
1.29k
          {
2844
            /* Following hack avoids the error message "Application
2845
               transferred too many scanlines. (JPEGLib)." caused by
2846
               YCbCr subsampling, but it returns data in RGB rather
2847
               than YCbCr. */
2848
1.29k
            if (logging)
2849
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2850
0
                                    "Resetting photometric from %s to %s for JPEG RGB",
2851
0
                                    PhotometricTagToString(photometric),
2852
0
                                    PhotometricTagToString(PHOTOMETRIC_RGB));
2853
1.29k
            (void) TIFFSetField( tiff, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB );
2854
1.29k
            photometric=PHOTOMETRIC_RGB;
2855
1.29k
          }
2856
54.4k
        method=RGBAPuntMethod;
2857
54.4k
        quantum_type=UndefinedQuantum;
2858
54.4k
        quantum_samples=0;
2859
54.4k
        if (QuantumTransferMode(image,photometric,compress_tag,sample_format,
2860
54.4k
                                samples_per_pixel,planar_config,0,&quantum_type,
2861
54.4k
                                &quantum_samples,exception)
2862
54.4k
            == MagickPass)
2863
46.9k
          {
2864
46.9k
            method=ScanLineMethod;
2865
46.9k
            if ((compress_tag == COMPRESSION_JPEG) ||
2866
34.8k
                (compress_tag == COMPRESSION_OJPEG))
2867
12.1k
              {
2868
12.1k
                if (TIFFIsTiled(tiff))
2869
486
                  method=TiledMethod;
2870
11.6k
                else
2871
11.6k
                  method=StrippedMethod;
2872
12.1k
              }
2873
34.8k
#if defined(COMPRESSION_JBIG)
2874
34.8k
            else if (compress_tag == COMPRESSION_JBIG)
2875
              /* libtiff jbig coder only handles strips */
2876
0
              method=StrippedMethod;
2877
34.8k
#endif
2878
34.8k
            else if (TIFFIsTiled(tiff))
2879
3.89k
              method=TiledMethod;
2880
30.9k
            else if (TIFFStripSize(tiff) <= 1024*256)
2881
27.1k
              method=StrippedMethod;
2882
46.9k
            if (photometric == PHOTOMETRIC_MINISWHITE)
2883
15.3k
              import_options.grayscale_miniswhite=MagickTrue;
2884
46.9k
          }
2885
7.45k
        else if (exception->severity < ErrorException)
2886
7.41k
          {
2887
7.41k
            if (TIFFIsTiled(tiff))
2888
1.20k
              method=RGBATiledMethod;
2889
6.20k
            else if (TIFFGetField(tiff,TIFFTAG_ROWSPERSTRIP,&rows_per_strip) == 1)
2890
3.70k
              method=RGBAStrippedMethod;
2891
7.41k
          }
2892
39
        else
2893
39
          {
2894
            /*
2895
              QuantumTransferMode reported an error
2896
            */
2897
39
            ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,image);
2898
0
          }
2899
54.4k
      }
2900
2901
      /*
2902
        Set extra import options for floating point.
2903
      */
2904
54.4k
      if (sample_format == SAMPLEFORMAT_IEEEFP)
2905
4.81k
        {
2906
4.81k
          double
2907
4.81k
            value;
2908
2909
4.81k
          import_options.sample_type=FloatQuantumSampleType;
2910
4.81k
          if (TIFFGetField(tiff,TIFFTAG_SMINSAMPLEVALUE,&value) == 1)
2911
58
            import_options.double_minvalue=value;
2912
4.81k
          if (TIFFGetField(tiff,TIFFTAG_SMAXSAMPLEVALUE,&value) == 1)
2913
112
            import_options.double_maxvalue=value;
2914
4.81k
          if ((definition_value=AccessDefinition(image_info,"tiff","min-sample-value")))
2915
0
            import_options.double_minvalue=strtod(definition_value,(char **)NULL);
2916
4.81k
          if ((definition_value=AccessDefinition(image_info,"tiff","max-sample-value")))
2917
0
            import_options.double_maxvalue=strtod(definition_value,(char **)NULL);
2918
4.81k
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2919
4.81k
                                "Using min sample value %g, max sample value %g",
2920
4.81k
                                import_options.double_minvalue,
2921
4.81k
                                import_options.double_maxvalue);
2922
4.81k
        }
2923
2924
      /*
2925
        For sample sizes matching a CPU native word, use native endian
2926
        order for import.
2927
      */
2928
54.4k
      if ((16 == bits_per_sample) || (32 == bits_per_sample) || (64 == bits_per_sample))
2929
7.05k
        import_options.endian=NativeEndian;
2930
2931
54.4k
      switch (method)
2932
54.4k
        {
2933
3.81k
        case ScanLineMethod:
2934
3.81k
          {
2935
            /*
2936
              Read TIFF image as scanlines.
2937
            */
2938
3.81k
            unsigned char
2939
3.81k
              *scanline = (unsigned char *) NULL;
2940
2941
3.81k
            int
2942
3.81k
              max_sample,
2943
3.81k
              quantum_samples,
2944
3.81k
              sample;
2945
2946
3.81k
            tsize_t
2947
3.81k
              scanline_size = 0;
2948
2949
3.81k
            QuantumType
2950
3.81k
              quantum_type;
2951
2952
3.81k
            if (logging)
2953
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2954
0
                                    "Using scanline %s read method with %u bits per sample",
2955
0
                                    PhotometricTagToString(photometric),bits_per_sample);
2956
            /*
2957
              Prepare for separate/contiguous retrieval.
2958
            */
2959
3.81k
            max_sample=1;
2960
3.81k
            if (planar_config == PLANARCONFIG_SEPARATE)
2961
67
              {
2962
67
                if (QuantumTransferMode(image,photometric,compress_tag,
2963
67
                                        sample_format,samples_per_pixel,
2964
67
                                        PLANARCONFIG_CONTIG,0,
2965
67
                                        &quantum_type,&quantum_samples,
2966
67
                                        exception)
2967
67
                    != MagickPass)
2968
3
                  ThrowTIFFReaderException(CorruptImageError,
2969
67
                                           ImproperImageHeader,image);
2970
64
                max_sample=quantum_samples;
2971
64
              }
2972
            /*
2973
              Allocate memory for one scanline.
2974
            */
2975
3.80k
            scanline_size=TIFFScanlineSize(tiff);
2976
3.80k
            if (scanline_size <= 0)
2977
0
              {
2978
0
                status=MagickFail;
2979
0
                break;
2980
0
              }
2981
            /*
2982
              Scale up to size of 32-bit word.
2983
            */
2984
3.80k
            scanline_size=RoundUpToAlignment(scanline_size,sizeof(magick_int32_t));
2985
2986
3.80k
            if (logging)
2987
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2988
0
                                    "Request to allocate scanline buffer of "
2989
0
                                    "%" MAGICK_SIZE_T_F "u bytes",
2990
0
                                    (MAGICK_SIZE_T) scanline_size);
2991
2992
            /*
2993
              Rationalize memory request based on file size
2994
            */
2995
3.80k
            if (scanline_size > file_size*max_compress_ratio)
2996
0
              {
2997
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2998
0
                                      "Unreasonable allocation size "
2999
0
                                      "(ratio of alloc to file size %g)",
3000
0
                                      (double) scanline_size/file_size);
3001
0
                ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile,
3002
0
                                         image);
3003
0
              }
3004
3005
3.80k
            scanline=MagickAllocateResourceLimitedClearedMemory(unsigned char *,(size_t) scanline_size);
3006
3.80k
            if (scanline == (unsigned char *) NULL)
3007
0
              {
3008
0
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3009
0
                                         image);
3010
0
              }
3011
7.61k
            for (sample=0; (status != MagickFail) && (sample < max_sample); sample++)
3012
3.80k
              {
3013
1.55M
                for (y=0; (status != MagickFail) && (y < image->rows); y++)
3014
1.55M
                  {
3015
                    /*
3016
                      Obtain a scanline
3017
                    */
3018
1.55M
                    if (TIFFReadScanline(tiff,(char *) scanline,(uint32) y,sample) == -1)
3019
2.70k
                      {
3020
2.70k
                        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3021
2.70k
                                              "TIFFReadScanline() failed!");
3022
2.70k
                        status=MagickFail;
3023
2.70k
                        break;
3024
2.70k
                      }
3025
1.54M
                    if (image->exception.severity >= ErrorException)
3026
0
                      {
3027
0
                        status=MagickFail;
3028
0
                        break;
3029
0
                      }
3030
1.54M
#if !defined(WORDS_BIGENDIAN)
3031
1.54M
                    if (24 == bits_per_sample)
3032
757
                      SwabDataToBigEndian(bits_per_sample,scanline,scanline_size);
3033
1.54M
#endif
3034
                    /*
3035
                      Determine quantum parse method.
3036
                    */
3037
1.54M
                    if (QuantumTransferMode(image,photometric,compress_tag,
3038
1.54M
                                            sample_format,
3039
1.54M
                                            samples_per_pixel,planar_config,
3040
1.54M
                                            sample,
3041
1.54M
                                            &quantum_type,&quantum_samples,
3042
1.54M
                                            exception)
3043
1.54M
                        == MagickFail)
3044
0
                      {
3045
0
                        status=MagickFail;
3046
0
                        break;
3047
0
                      }
3048
                    /*
3049
                      Compact scanline to only contain raster data.
3050
                    */
3051
1.54M
                    if ((samples_per_pixel > quantum_samples) &&
3052
184k
                        (planar_config == PLANARCONFIG_CONTIG))
3053
184k
                      CompactSamples(image->columns, bits_per_sample,
3054
184k
                                     samples_per_pixel, quantum_samples, scanline);
3055
                    /*
3056
                      Import scanline into image.
3057
                    */
3058
1.54M
                    if (sample == 0)
3059
1.54M
                      q=SetImagePixelsEx(image,0,y,image->columns,1,exception);
3060
0
                    else
3061
0
                      q=GetImagePixelsEx(image,0,y,image->columns,1,exception);
3062
1.54M
                    if (q == (PixelPacket *) NULL)
3063
0
                      {
3064
0
                        status=MagickFail;
3065
0
                        break;
3066
0
                      }
3067
1.54M
                    if ((sample == 0) && (max_sample > 1))
3068
69
                      (void) memset(q,0,image->columns*sizeof(PixelPacket));
3069
1.54M
                    if (ImportImagePixelArea(image,quantum_type,bits_per_sample,scanline,
3070
1.54M
                                             &import_options,0) == MagickFail)
3071
3
                      {
3072
3
                        CopyException(exception,&image->exception);
3073
3
                        status=MagickFail;
3074
3
                        break;
3075
3
                      }
3076
                    /*
3077
                      Disassociate alpha from pixels if necessary.
3078
                    */
3079
1.54M
                    if ((PHOTOMETRIC_RGB == photometric) &&
3080
71.3k
                        (image->matte) && (alpha_type == AssociatedAlpha) &&
3081
12.5k
                        (sample == (max_sample-1)))
3082
12.5k
                      DisassociateAlphaRegion(image);
3083
                    /*
3084
                      Save our updates.
3085
                    */
3086
1.54M
                    if (!SyncImagePixelsEx(image,exception))
3087
0
                      {
3088
0
                        status=MagickFail;
3089
0
                        break;
3090
0
                      }
3091
1.54M
                    if (image->previous == (Image *) NULL)
3092
1.54M
                      if (QuantumTick(y+(magick_int64_t)sample*image->rows, (magick_int64_t)image->rows*max_sample))
3093
137k
                        if (!MagickMonitorFormatted(y+ (magick_int64_t)sample*image->rows,
3094
137k
                                                    (magick_int64_t)image->rows*max_sample,exception,
3095
137k
                                                    LoadImageText,image->filename,
3096
137k
                                                    image->columns,image->rows))
3097
0
                          break;
3098
1.54M
                  }
3099
3.80k
              }
3100
3.80k
            MagickFreeResourceLimitedMemory(unsigned char *,scanline);
3101
3.80k
            break;
3102
3.80k
          }
3103
38.8k
        case StrippedMethod:
3104
38.8k
          {
3105
            /*
3106
              Read TIFF image using multi-row strip storage.
3107
            */
3108
38.8k
            unsigned char
3109
38.8k
              *p,
3110
38.8k
              *strip = (unsigned char *) NULL;
3111
3112
38.8k
            long
3113
              /* pixels_per_strip, */
3114
38.8k
              stride,
3115
38.8k
              rows_remaining;
3116
3117
38.8k
            int
3118
38.8k
              max_sample,
3119
38.8k
              quantum_samples,
3120
38.8k
              sample;
3121
3122
38.8k
            tsize_t
3123
38.8k
              strip_size,
3124
38.8k
              strip_size_max = 0;
3125
3126
38.8k
            tstrip_t
3127
38.8k
              strip_id;
3128
3129
38.8k
            QuantumType
3130
38.8k
              quantum_type;
3131
3132
38.8k
            ImportPixelAreaInfo
3133
38.8k
              import_info;
3134
3135
38.8k
            if (logging)
3136
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3137
0
                                    "Using stripped read method with %u bits per sample",
3138
0
                                    bits_per_sample);
3139
            /*
3140
              Prepare for separate/contiguous retrieval.
3141
            */
3142
38.8k
            max_sample=1;
3143
38.8k
            if (planar_config == PLANARCONFIG_SEPARATE)
3144
2.63k
              {
3145
2.63k
                if (QuantumTransferMode(image,photometric,compress_tag,
3146
2.63k
                                        sample_format,
3147
2.63k
                                        samples_per_pixel,PLANARCONFIG_CONTIG,
3148
2.63k
                                        0,&quantum_type,&quantum_samples,
3149
2.63k
                                        exception)
3150
2.63k
                    != MagickPass)
3151
14
                  ThrowTIFFReaderException(CorruptImageError,
3152
2.63k
                                           ImproperImageHeader,image);
3153
2.61k
                max_sample=quantum_samples;
3154
2.61k
              }
3155
3156
            /* pixels_per_strip=rows_per_strip*image->columns; */
3157
38.7k
            p=0;
3158
38.7k
            strip_size=0;
3159
38.7k
            strip_id=0;
3160
            /*
3161
              Allocate memory for one strip.
3162
            */
3163
38.7k
            strip_size_max=TIFFStripSize(tiff);
3164
38.7k
            if (strip_size_max <= 0)
3165
0
              {
3166
0
                status=MagickFail;
3167
0
                break;
3168
0
              }
3169
            /*
3170
              Scale up to size of 32-bit word.
3171
            */
3172
38.7k
            strip_size_max=RoundUpToAlignment(strip_size_max,sizeof(magick_int32_t));
3173
38.7k
            if (logging)
3174
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3175
0
                                    "Maximum strip size %" MAGICK_SIZE_T_F "u",
3176
0
                                    (MAGICK_SSIZE_T) strip_size_max);
3177
38.7k
            if (strip_size_max <= 0)
3178
0
              {
3179
0
                status=MagickFail;
3180
0
                break;
3181
0
              }
3182
3183
            /*
3184
              Rationalize memory request based on file size
3185
            */
3186
38.7k
            if (strip_size_max > file_size*max_compress_ratio)
3187
75
              {
3188
75
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3189
75
                                      "Unreasonable allocation size "
3190
75
                                      "(ratio of alloc to file size %g)",
3191
75
                                      (double) strip_size_max/file_size);
3192
75
                ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile,
3193
0
                                         image);
3194
0
              }
3195
3196
38.7k
            strip=MagickAllocateResourceLimitedClearedMemory(unsigned char *,(size_t) strip_size_max);
3197
38.7k
            if (strip == (unsigned char *) NULL)
3198
0
              {
3199
0
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3200
0
                                         image);
3201
0
              }
3202
            /*
3203
              Compute per-row stride.
3204
            */
3205
38.7k
            stride=TIFFVStripSize(tiff,1);
3206
            /*
3207
              Process each plane
3208
            */
3209
65.6k
            for (sample=0; (status != MagickFail) && (sample < max_sample); sample++)
3210
41.5k
              {
3211
41.5k
                rows_remaining=0;
3212
                /*
3213
                  Determine quantum parse method.
3214
                */
3215
41.5k
                if (QuantumTransferMode(image,photometric,compress_tag,
3216
41.5k
                                        sample_format,samples_per_pixel,
3217
41.5k
                                        planar_config,sample,
3218
41.5k
                                        &quantum_type,&quantum_samples,
3219
41.5k
                                        exception)
3220
41.5k
                    == MagickFail)
3221
0
                  {
3222
0
                    status=MagickFail;
3223
0
                    break;
3224
0
                  }
3225
11.7M
                for (y=0; (status != MagickFail) && (y < image->rows); y++)
3226
11.7M
                  {
3227
11.7M
                    if (rows_remaining == 0)
3228
124k
                      {
3229
                        /*
3230
                          Obtain a strip
3231
                        */
3232
124k
                        if (((strip_size=TIFFReadEncodedStrip(tiff,strip_id,strip,
3233
124k
                                                              strip_size_max)) == -1))
3234
14.5k
                          {
3235
14.5k
                            status=MagickFail;
3236
14.5k
                            break;
3237
14.5k
                          }
3238
110k
#if !defined(WORDS_BIGENDIAN)
3239
110k
                        if (24 == bits_per_sample)
3240
2.68k
                          SwabDataToBigEndian(bits_per_sample,strip,strip_size);
3241
110k
#endif
3242
110k
                        rows_remaining=rows_per_strip;
3243
110k
                        if (y+rows_per_strip > image->rows)
3244
9.14k
                          rows_remaining=(rows_per_strip-(y+rows_per_strip-image->rows));
3245
110k
                        p=strip;
3246
110k
                        strip_id++;
3247
110k
                      }
3248
                    /*
3249
                      Compact strip row to only contain raster data.
3250
                    */
3251
11.7M
                    if ((samples_per_pixel > quantum_samples) &&
3252
705k
                        (planar_config == PLANARCONFIG_CONTIG))
3253
591k
                      CompactSamples(image->columns, bits_per_sample,
3254
591k
                                     samples_per_pixel, quantum_samples, p);
3255
                    /*
3256
                      Access Magick pixels.
3257
                    */
3258
11.7M
                    if (sample == 0)
3259
11.6M
                      q=SetImagePixelsEx(image,0,y,image->columns,1,exception);
3260
63.8k
                    else
3261
63.8k
                      q=GetImagePixelsEx(image,0,y,image->columns,1,exception);
3262
11.7M
                    if (q == (PixelPacket *) NULL)
3263
11
                      {
3264
11
                        status=MagickFail;
3265
11
                        break;
3266
11
                      }
3267
11.7M
                    if ((sample == 0) && (max_sample > 1))
3268
29.6k
                      (void) memset(q,0,image->columns*sizeof(PixelPacket));
3269
                    /*
3270
                      Import strip row into image.
3271
                    */
3272
11.7M
                    if (ImportImagePixelArea(image,quantum_type,bits_per_sample,p,
3273
11.7M
                                             &import_options,&import_info) == MagickFail)
3274
11
                      {
3275
11
                        CopyException(exception,&image->exception);
3276
11
                        status=MagickFail;
3277
11
                        break;
3278
11
                      }
3279
                    /*
3280
                      Disassociate alpha from pixels if necessary.
3281
                    */
3282
11.7M
                    if ((PHOTOMETRIC_RGB == photometric) &&
3283
2.49M
                        (image->matte) && (alpha_type == AssociatedAlpha)
3284
485k
                        && (sample == (max_sample-1)))
3285
483k
                      DisassociateAlphaRegion(image);
3286
                    /*
3287
                      Save our updates.
3288
                    */
3289
11.7M
                    if (!SyncImagePixelsEx(image,exception))
3290
0
                      {
3291
0
                        status=MagickFail;
3292
0
                        break;
3293
0
                      }
3294
                    /*
3295
                      Advance to next row
3296
                    */
3297
11.7M
                    p += stride;
3298
11.7M
                    rows_remaining--;
3299
3300
11.7M
                    if (image->previous == (Image *) NULL)
3301
11.7M
                      if (QuantumTick(y+(magick_int64_t)image->rows*sample, (magick_int64_t)image->rows*max_sample))
3302
1.59M
                        if (!MagickMonitorFormatted(y+ (magick_int64_t)image->rows*sample, (magick_int64_t)image->rows*max_sample,exception,
3303
1.59M
                                                    LoadImageText,image->filename,
3304
1.59M
                                                    image->columns,image->rows))
3305
0
                          {
3306
0
                            status=MagickFail;
3307
0
                            break;
3308
0
                          }
3309
11.7M
                  }
3310
41.5k
                if (status == MagickFail)
3311
14.5k
                  break;
3312
41.5k
              }
3313
38.7k
            MagickFreeResourceLimitedMemory(unsigned char *,strip);
3314
38.7k
            break;
3315
38.7k
          }
3316
4.38k
        case TiledMethod:
3317
4.38k
          {
3318
            /*
3319
              Read TIFF using tiled storage.
3320
            */
3321
4.38k
            unsigned char
3322
4.38k
              *tile = (unsigned char *) NULL;
3323
3324
4.38k
            uint32
3325
4.38k
              tile_columns,
3326
4.38k
              tile_rows;
3327
3328
4.38k
            tsize_t
3329
4.38k
              stride,
3330
4.38k
              tile_size,
3331
4.38k
              tile_size_max = 0;
3332
3333
4.38k
            int
3334
4.38k
              max_sample,
3335
4.38k
              quantum_samples,
3336
4.38k
              sample;
3337
3338
4.38k
            QuantumType
3339
4.38k
              quantum_type;
3340
3341
4.38k
            size_t
3342
4.38k
              tile_total_pixels,
3343
4.38k
              tile_num=0,
3344
4.38k
              tiles_total;
3345
3346
4.38k
            if (logging)
3347
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3348
0
                                    "Using tiled %s read method with %u bits per sample",
3349
0
                                    PhotometricTagToString(photometric), bits_per_sample);
3350
            /*
3351
              Prepare for separate/contiguous retrieval.
3352
            */
3353
4.38k
            max_sample=1;
3354
4.38k
            if (planar_config == PLANARCONFIG_SEPARATE)
3355
99
              {
3356
99
                if (QuantumTransferMode(image,photometric,compress_tag,
3357
99
                                        sample_format,samples_per_pixel,
3358
99
                                        PLANARCONFIG_CONTIG,0,&quantum_type,
3359
99
                                        &quantum_samples,
3360
99
                                        exception)
3361
99
                    != MagickPass)
3362
4
                  ThrowTIFFReaderException(CorruptImageError,
3363
99
                                           ImproperImageHeader,image);
3364
95
                max_sample=quantum_samples;
3365
95
              }
3366
            /*
3367
              Obtain tile geometry
3368
            */
3369
4.38k
            if (!(TIFFGetField(tiff,TIFFTAG_TILEWIDTH,&tile_columns) == 1) ||
3370
4.38k
               !(TIFFGetField(tiff,TIFFTAG_TILELENGTH,&tile_rows) == 1))
3371
0
              {
3372
0
                ThrowTIFFReaderException(CoderError,ImageIsNotTiled,image);
3373
0
              }
3374
            /*
3375
              Obtain the maximum number of bytes required to contain a tile.
3376
            */
3377
4.38k
            tile_size_max=TIFFTileSize(tiff);
3378
4.38k
            if (tile_size_max <= 0)
3379
1
              {
3380
1
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3381
0
                                         image);
3382
0
              }
3383
            /*
3384
              Scale up to size of 32-bit word.
3385
            */
3386
4.37k
            tile_size_max=RoundUpToAlignment(tile_size_max,sizeof(magick_int32_t));
3387
4.37k
            if (0 == tile_size_max)
3388
0
              {
3389
0
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3390
0
                                         image);
3391
0
              }
3392
            /*
3393
              Compute the total number of pixels in one tile
3394
            */
3395
4.37k
            tile_total_pixels=MagickArraySize(tile_columns,tile_rows);
3396
4.37k
            if (logging)
3397
0
              {
3398
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3399
0
                                      "TIFF tile geometry %ux%u, "
3400
0
                                      "%" MAGICK_SIZE_T_F "u pixels"
3401
0
                                      " (%" MAGICK_SIZE_T_F  "u bytes max)",
3402
0
                                      (unsigned int)tile_columns,
3403
0
                                      (unsigned int)tile_rows,
3404
0
                                      (MAGICK_SIZE_T) tile_total_pixels,
3405
0
                                      (MAGICK_SIZE_T) tile_size_max);
3406
0
              }
3407
3408
            /*
3409
              Rationalize memory request based on file size
3410
            */
3411
4.37k
            if (tile_size_max > file_size*max_compress_ratio)
3412
111
              {
3413
111
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3414
111
                                      "Unreasonable tile allocation size "
3415
111
                                      "(ratio of alloc to file size %g)",
3416
111
                                      (double) tile_size_max/file_size);
3417
111
                ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile,
3418
0
                                         image);
3419
0
              }
3420
3421
4.26k
            if ((tile_columns > 1024) && (tile_columns > image->columns*10))
3422
5
              {
3423
5
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3424
5
                                      "Unreasonable tile columns %u",
3425
5
                                      (unsigned) tile_columns);
3426
5
                ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,
3427
0
                                         image);
3428
0
              }
3429
3430
4.26k
            if ((tile_rows > 1024) && (tile_rows > image->rows*10))
3431
6
              {
3432
6
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3433
6
                                      "Unreasonable tile rows %u",
3434
6
                                      (unsigned) tile_rows);
3435
6
                ThrowTIFFReaderException(CorruptImageError,ImproperImageHeader,
3436
0
                                         image);
3437
0
              }
3438
3439
            /*
3440
              Allocate tile buffer
3441
            */
3442
4.25k
            tile=MagickAllocateResourceLimitedClearedMemory(unsigned char *, (size_t) tile_size_max);
3443
4.25k
            if (tile == (unsigned char *) NULL)
3444
0
              {
3445
0
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3446
0
                                         image);
3447
0
              }
3448
4.25k
            tiles_total=((((size_t) image->columns/tile_columns)+((image->columns % tile_columns) ? 1 : 0))
3449
4.25k
                         *(((size_t) image->rows/tile_rows)+((image->rows % tile_rows) ? 1 : 0)))*max_sample;
3450
            /*
3451
              Compute per-row stride.
3452
            */
3453
4.25k
            stride=TIFFTileRowSize(tiff);
3454
3455
            /*
3456
              Process each plane.
3457
            */
3458
5.81k
            for (sample=0; (status != MagickFail) && (sample < max_sample); sample++)
3459
4.32k
              {
3460
                /*
3461
                  Determine quantum parse method.
3462
                */
3463
4.32k
                if (QuantumTransferMode(image,photometric,compress_tag,
3464
4.32k
                                        sample_format,samples_per_pixel,
3465
4.32k
                                        planar_config,sample,&quantum_type,
3466
4.32k
                                        &quantum_samples,exception)
3467
4.32k
                    == MagickFail)
3468
0
                  {
3469
0
                    status=MagickFail;
3470
0
                    break;
3471
0
                  }
3472
23.6k
                for (y=0; (status != MagickFail) && (y < image->rows); y+=tile_rows)
3473
22.0k
                  {
3474
1.64M
                    for (x=0; (status != MagickFail) && (x < image->columns); x+=tile_columns)
3475
1.62M
                      {
3476
1.62M
                        long
3477
1.62M
                          tile_set_columns,
3478
1.62M
                          tile_set_rows;
3479
3480
1.62M
                        unsigned char
3481
1.62M
                          *p;
3482
3483
1.62M
                        register long
3484
1.62M
                          yy;
3485
3486
                        /*
3487
                          Compute image region corresponding to tile.
3488
                        */
3489
1.62M
                        if (x+tile_columns > image->columns)
3490
11.1k
                          tile_set_columns=(tile_columns-(x+tile_columns-image->columns));
3491
1.61M
                        else
3492
1.61M
                          tile_set_columns=tile_columns;
3493
1.62M
                        if (y+tile_rows > image->rows)
3494
17.8k
                          tile_set_rows=(tile_rows-(y+tile_rows-image->rows));
3495
1.61M
                        else
3496
1.61M
                          tile_set_rows=tile_rows;
3497
3498
                        /*
3499
                          Read a tile.
3500
                        */
3501
1.62M
                        tile_num++;
3502
1.62M
                        if ((tile_size=TIFFReadTile(tiff,tile,x,y,0,sample)) == -1)
3503
2.39k
                          {
3504
2.39k
                            status=MagickFail;
3505
2.39k
                            break;
3506
2.39k
                          }
3507
1.62M
#if !defined(WORDS_BIGENDIAN)
3508
1.62M
                        if (24 == bits_per_sample)
3509
316
                          SwabDataToBigEndian(bits_per_sample,tile,tile_size);
3510
1.62M
#endif
3511
1.62M
                        p=tile;
3512
11.1M
                        for (yy=y; (status != MagickFail) && (yy < (long) y+tile_set_rows); yy++)
3513
9.48M
                          {
3514
                            /*
3515
                              Compact tile row to only contain raster data.
3516
                            */
3517
9.48M
                            if ((samples_per_pixel > quantum_samples) &&
3518
1.79M
                                (planar_config == PLANARCONFIG_CONTIG))
3519
1.79M
                              CompactSamples(tile_set_columns, bits_per_sample,
3520
1.79M
                                             samples_per_pixel, quantum_samples, p);
3521
                            /*
3522
                              Obtain pixel region corresponding to tile row.
3523
                            */
3524
9.48M
                            if (sample == 0)
3525
9.48M
                              q=SetImagePixelsEx(image,x,yy,tile_set_columns,1,exception);
3526
1.67k
                            else
3527
1.67k
                              q=GetImagePixelsEx(image,x,yy,tile_set_columns,1,exception);
3528
9.48M
                            if (q == (PixelPacket *) NULL)
3529
377
                              {
3530
377
                                status=MagickFail;
3531
377
                                break;
3532
377
                              }
3533
9.48M
                            if ((sample == 0) && (max_sample > 1))
3534
1.45k
                              (void) memset(q,0,tile_set_columns*sizeof(PixelPacket));
3535
                            /*
3536
                              Import tile row
3537
                            */
3538
9.48M
                            if (ImportImagePixelArea(image,quantum_type,
3539
9.48M
                                                     bits_per_sample,p,
3540
9.48M
                                                     &import_options,0)
3541
9.48M
                                == MagickFail)
3542
5
                              {
3543
5
                                CopyException(exception,&image->exception);
3544
5
                                status=MagickFail;
3545
5
                                break;
3546
5
                              }
3547
                            /*
3548
                              Disassociate alpha from pixels if necessary.
3549
                            */
3550
9.48M
                            if ((PHOTOMETRIC_RGB == photometric) &&
3551
58.1k
                                (image->matte) && (alpha_type == AssociatedAlpha)
3552
1.45k
                                && (sample == (max_sample-1)))
3553
1.18k
                              DisassociateAlphaRegion(image);
3554
                            /*
3555
                              Save our updates.
3556
                            */
3557
9.48M
                            if (!SyncImagePixelsEx(image,exception))
3558
0
                              {
3559
0
                                status=MagickFail;
3560
0
                                break;
3561
0
                              }
3562
9.48M
                            p += stride;
3563
9.48M
                          }
3564
1.62M
                        if (image->previous == (Image *) NULL)
3565
1.62M
                          if (QuantumTick(tile_num,tiles_total))
3566
21.6k
                            if (!MagickMonitorFormatted(tile_num,
3567
21.6k
                                                        tiles_total,
3568
21.6k
                                                        exception,
3569
21.6k
                                                        LoadImageText,image->filename,
3570
21.6k
                                                        image->columns,image->rows))
3571
0
                              {
3572
0
                                status=MagickFail;
3573
0
                              }
3574
1.62M
                        if (status == MagickFail)
3575
382
                          break;
3576
1.62M
                      }
3577
22.0k
                    if (status == MagickFail)
3578
2.77k
                      break;
3579
22.0k
                  }
3580
4.32k
                if (status == MagickFail)
3581
2.77k
                  break;
3582
4.32k
              }
3583
3584
4.25k
            MagickFreeResourceLimitedMemory(unsigned char *,tile);
3585
4.25k
            break;
3586
4.25k
          }
3587
3.70k
        case RGBAStrippedMethod:
3588
3.70k
          {
3589
3.70k
            size_t
3590
3.70k
              number_pixels,
3591
3.70k
              strip_pixels_size;
3592
3593
3.70k
            uint32
3594
3.70k
              *strip_pixels;
3595
3596
3.70k
            register uint32
3597
3.70k
              *p;
3598
3599
3.70k
            if (logging)
3600
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3601
0
                                    "Using RGB stripped read method with %u bits per sample",
3602
0
                                    bits_per_sample);
3603
            /*
3604
              Convert stripped TIFF image to DirectClass MIFF image.
3605
            */
3606
3.70k
            image->storage_class=DirectClass;
3607
3.70k
            number_pixels=MagickArraySize(image->columns,rows_per_strip);
3608
3.70k
            if (0 == number_pixels)
3609
0
              {
3610
0
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3611
0
                                         image);
3612
0
              }
3613
            /*
3614
              Rationalize memory request based on file size
3615
            */
3616
3.70k
            if ((magick_off_t) (number_pixels*sizeof(uint32)) >
3617
3.70k
                file_size*max_compress_ratio)
3618
49
              {
3619
49
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3620
49
                                      "Unreasonable allocation size "
3621
49
                                      "(ratio of alloc to file size %g)",
3622
49
                                      (double) (number_pixels*sizeof(uint32))/file_size);
3623
49
                ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile,
3624
0
                                         image);
3625
0
              }
3626
3.65k
            strip_pixels_size=MagickArraySize(number_pixels,sizeof(uint32));
3627
3.65k
            if (strip_pixels_size == 0)
3628
0
              ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3629
3.65k
                                       image);
3630
3.65k
            strip_pixels=MagickAllocateResourceLimitedClearedMemory(uint32 *,strip_pixels_size);
3631
3.65k
            if (strip_pixels == (uint32 *) NULL)
3632
3
              {
3633
3
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3634
0
                                         image);
3635
0
              }
3636
3.65k
            if (logging)
3637
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3638
0
                                    "Allocated %" MAGICK_SIZE_T_F "u bytes for RGBA strip",
3639
0
                                    (MAGICK_SIZE_T) number_pixels*sizeof(uint32));
3640
            /*
3641
              Convert image to DirectClass pixel packets.
3642
            */
3643
3.65k
            i=0;
3644
3.65k
            p=0;
3645
458k
            for (y=0; (status != MagickFail) && (y < image->rows); y++)
3646
457k
              {
3647
457k
                q=SetImagePixelsEx(image,0,y,image->columns,1,exception);
3648
457k
                if (q == (PixelPacket *) NULL)
3649
0
                  {
3650
0
                    status=MagickFail;
3651
0
                    break;
3652
0
                  }
3653
457k
                if (0 == i)
3654
68.5k
                  {
3655
68.5k
                    if (!TIFFReadRGBAStrip(tiff,y,strip_pixels))
3656
2.52k
                      {
3657
2.52k
                        if (logging)
3658
0
                          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3659
0
                                                "TIFFReadRGBAStrip reports failure");
3660
2.52k
                        status=MagickFail;
3661
2.52k
                        break;
3662
2.52k
                      }
3663
65.9k
                    i=(long) Min(rows_per_strip,image->rows-y);
3664
65.9k
                  }
3665
454k
                i--;
3666
454k
                p=strip_pixels+(size_t) image->columns*i;
3667
209M
                for (x=0; (status != MagickFail) && (x < image->columns); x++)
3668
208M
                  {
3669
208M
                    q->red=ScaleCharToQuantum(TIFFGetR(*p));
3670
208M
                    q->green=ScaleCharToQuantum(TIFFGetG(*p));
3671
208M
                    q->blue=ScaleCharToQuantum(TIFFGetB(*p));
3672
208M
                    if (image->matte)
3673
1.33M
                      q->opacity=(Quantum) ScaleCharToQuantum(TIFFGetA(*p));
3674
207M
                    else
3675
207M
                      q->opacity=OpaqueOpacity;
3676
208M
                    p++;
3677
208M
                    q++;
3678
208M
                  }
3679
                /*
3680
                  Disassociate alpha from pixels if necessary.
3681
                */
3682
454k
                if ((PHOTOMETRIC_RGB == photometric) &&
3683
19.7k
                    (image->matte) && (alpha_type == AssociatedAlpha))
3684
775
                  DisassociateAlphaRegion(image);
3685
454k
                if (!SyncImagePixelsEx(image,exception))
3686
0
                  {
3687
0
                    status=MagickFail;
3688
0
                    break;
3689
0
                  }
3690
454k
                if (image->previous == (Image *) NULL)
3691
454k
                  if (QuantumTick(y,image->rows))
3692
145k
                    if (!MagickMonitorFormatted(y,image->rows,exception,
3693
145k
                                                LoadImageText,image->filename,
3694
145k
                                                image->columns,image->rows))
3695
0
                      {
3696
0
                        status=MagickFail;
3697
0
                        break;
3698
0
                      }
3699
454k
              }
3700
3.65k
            MagickFreeResourceLimitedMemory(uint32 *,strip_pixels);
3701
3.65k
            break;
3702
3.65k
          }
3703
1.20k
        case RGBATiledMethod:
3704
1.20k
          {
3705
            /*
3706
              Convert tiled TIFF image to DirectClass MIFF image.
3707
            */
3708
1.20k
            register uint32
3709
1.20k
              *p;
3710
3711
1.20k
            uint32
3712
1.20k
              *tile_pixels,
3713
1.20k
              tile_columns,
3714
1.20k
              tile_rows;
3715
3716
1.20k
            tsize_t
3717
1.20k
              tile_size_max;
3718
3719
1.20k
            size_t
3720
1.20k
              tile_pixels_size,
3721
1.20k
              tile_total_pixels,
3722
1.20k
              tile_num=0,
3723
1.20k
              tiles_total;
3724
3725
1.20k
            if (logging)
3726
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3727
0
                                    "Using RGB tiled read method with %u bits per sample",
3728
0
                                    bits_per_sample);
3729
1.20k
            image->storage_class=DirectClass;
3730
            /*
3731
              Obtain tile geometry
3732
            */
3733
1.20k
            if (!(TIFFGetField(tiff,TIFFTAG_TILEWIDTH,&tile_columns) == 1) ||
3734
1.20k
                !(TIFFGetField(tiff,TIFFTAG_TILELENGTH,&tile_rows) == 1))
3735
0
              {
3736
0
                ThrowTIFFReaderException(CoderError,ImageIsNotTiled,image);
3737
0
              }
3738
1.20k
            tile_total_pixels=MagickArraySize(tile_columns,tile_rows);
3739
1.20k
            tiles_total=((((size_t) image->columns/tile_columns)+((image->columns % tile_columns) ? 1 : 0))
3740
1.20k
                         *(((size_t) image->rows/tile_rows)+((image->rows % tile_rows) ? 1 : 0)));
3741
1.20k
            if (logging)
3742
0
              {
3743
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Reading TIFF tiles ...");
3744
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3745
0
                                      "TIFF tile geometry %ux%u, %" MAGICK_SIZE_T_F "u pixels/tile"
3746
0
                                      ", %" MAGICK_SIZE_T_F "u tiles",
3747
0
                                      (unsigned int)tile_columns,
3748
0
                                      (unsigned int)tile_rows,
3749
0
                                      (MAGICK_SIZE_T) tile_total_pixels,
3750
0
                                      (MAGICK_SIZE_T) tiles_total);
3751
0
              }
3752
            /*
3753
              Obtain the maximum number of bytes required to contain a tile.
3754
            */
3755
1.20k
            tile_size_max=TIFFTileSize(tiff);
3756
1.20k
            if (tile_size_max <= 0)
3757
0
              {
3758
0
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3759
0
                                         image);
3760
0
              }
3761
            /*
3762
              Apply image resource limits to tile width, height, and pixels.
3763
            */
3764
1.20k
            errno=0;
3765
1.20k
            if (AcquireMagickResource(WidthResource,tile_columns) != MagickPass)
3766
54
              {
3767
54
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3768
54
                                      "TIFF tile width %u exceeds limit!",tile_columns);
3769
54
                ThrowTIFFReaderException(ResourceLimitError,ImagePixelWidthLimitExceeded,
3770
0
                                         image);
3771
0
              }
3772
1.15k
            if (AcquireMagickResource(HeightResource,tile_rows) != MagickPass)
3773
6
              {
3774
6
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3775
6
                                      "TIFF tile width %u exceeds limit!",tile_rows);
3776
6
                ThrowTIFFReaderException(ResourceLimitError,ImagePixelHeightLimitExceeded,
3777
0
                                         image);
3778
0
              }
3779
1.14k
            if (AcquireMagickResource(PixelsResource,tile_total_pixels) != MagickPass)
3780
0
              {
3781
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3782
0
                                      "TIFF tile pixels %" MAGICK_SIZE_T_F "u exceeds limit!",
3783
0
                                      (MAGICK_SIZE_T) tile_total_pixels);
3784
0
                ThrowTIFFReaderException(ResourceLimitError,ImagePixelLimitExceeded,
3785
0
                                         image);
3786
0
              }
3787
            /*
3788
              Rationalize memory request based on file size
3789
            */
3790
1.14k
            if (tile_size_max > file_size*max_compress_ratio)
3791
5
              {
3792
5
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3793
5
                                      "Unreasonable tile allocation size "
3794
5
                                      "(ratio of alloc to file size %g)",
3795
5
                                      (double) tile_size_max/file_size);
3796
5
                ThrowTIFFReaderException(CorruptImageError,InsufficientImageDataInFile,
3797
0
                                         image);
3798
0
              }
3799
            /*
3800
              Allocate tile buffer
3801
            */
3802
1.14k
            tile_pixels_size=MagickArraySize(MagickArraySize(tile_columns,tile_rows),
3803
1.14k
                                             sizeof (uint32));
3804
1.14k
            if (tile_pixels_size == 0)
3805
0
              ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3806
1.14k
                                       image);
3807
1.14k
            tile_pixels=MagickAllocateResourceLimitedMemory(uint32*,tile_pixels_size);
3808
1.14k
            if (tile_pixels == (uint32 *) NULL)
3809
0
              {
3810
0
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3811
0
                                         image);
3812
0
              }
3813
17.9k
            for (y=0; (status != MagickFail) && (y < image->rows); y+=tile_rows)
3814
17.6k
              {
3815
                /*
3816
                  Retrieve a tile height's worth of rows
3817
                */
3818
17.6k
                PixelPacket
3819
17.6k
                  *strip;
3820
3821
17.6k
                unsigned int
3822
17.6k
                  tile_columns_remaining,
3823
17.6k
                  tile_rows_remaining;
3824
3825
                /* Compute remaining tile rows */
3826
17.6k
                if (y+tile_rows < image->rows)
3827
17.1k
                  tile_rows_remaining=tile_rows;
3828
526
                else
3829
526
                  tile_rows_remaining=image->rows-y;
3830
                /*
3831
                  Obtain a row of pixels
3832
                */
3833
17.6k
                strip=SetImagePixelsEx(image,0,y,image->columns,tile_rows_remaining,exception);
3834
17.6k
                if (strip == (PixelPacket *) NULL)
3835
0
                  {
3836
0
                    status=MagickFail;
3837
0
                    break;
3838
0
                  }
3839
753k
                for (x=0; (status != MagickFail) && (x < image->columns); x+=tile_columns)
3840
736k
                  {
3841
736k
                    register unsigned int
3842
736k
                      tile_column,
3843
736k
                      tile_row;
3844
3845
                    /*
3846
                      Obtain one tile.  Origin is bottom left of tile.
3847
                    */
3848
736k
                    tile_num++;
3849
736k
                    if (!TIFFReadRGBATile(tiff,x,y,tile_pixels))
3850
838
                      {
3851
838
                        status=MagickFail;
3852
838
                        break;
3853
838
                      }
3854
                    /*
3855
                      Compute remaining tile columns
3856
                    */
3857
735k
                    if (x+tile_columns < image->columns)
3858
719k
                      tile_columns_remaining=tile_columns;
3859
16.8k
                    else
3860
16.8k
                      tile_columns_remaining=image->columns-x;
3861
                    /*
3862
                      Transfer tile to image
3863
                    */
3864
735k
                    p=tile_pixels+(size_t)(tile_rows-tile_rows_remaining)*tile_columns;
3865
735k
                    q=strip+(x+(size_t)(tile_rows_remaining-1)*image->columns);
3866
16.2M
                    for ( tile_row=tile_rows_remaining; tile_row != 0; tile_row--)
3867
15.5M
                      {
3868
15.5M
                        if (image->matte)
3869
268k
                          for (tile_column=tile_columns_remaining; tile_column != 0;
3870
262k
                               tile_column--)
3871
262k
                            {
3872
262k
                              q->red=ScaleCharToQuantum(TIFFGetR(*p));
3873
262k
                              q->green=ScaleCharToQuantum(TIFFGetG(*p));
3874
262k
                              q->blue=ScaleCharToQuantum(TIFFGetB(*p));
3875
262k
                              q->opacity=(Quantum) ScaleCharToQuantum(TIFFGetA(*p));
3876
262k
                              q++;
3877
262k
                              p++;
3878
262k
                            }
3879
15.5M
                        else
3880
40.0M
                          for (tile_column=tile_columns_remaining; tile_column != 0;
3881
24.4M
                               tile_column--)
3882
24.4M
                            {
3883
24.4M
                              q->red=ScaleCharToQuantum(TIFFGetR(*p));
3884
24.4M
                              q->green=ScaleCharToQuantum(TIFFGetG(*p));
3885
24.4M
                              q->blue=ScaleCharToQuantum(TIFFGetB(*p));
3886
24.4M
                              q->opacity=OpaqueOpacity;
3887
24.4M
                              q++;
3888
24.4M
                              p++;
3889
24.4M
                            }
3890
15.5M
                        p+=tile_columns-tile_columns_remaining;
3891
15.5M
                        q-=((size_t) image->columns+tile_columns_remaining);
3892
15.5M
                      }
3893
735k
                    if (image->previous == (Image *) NULL)
3894
735k
                      if (QuantumTick(tile_num,tiles_total))
3895
18.6k
                        if (!MagickMonitorFormatted(tile_num,
3896
18.6k
                                                    tiles_total,
3897
18.6k
                                                    exception,
3898
18.6k
                                                    LoadImageText,image->filename,
3899
18.6k
                                                    image->columns,image->rows))
3900
0
                          {
3901
0
                            status=MagickFail;
3902
0
                          }
3903
735k
                    if (status == MagickFail)
3904
0
                      break;
3905
735k
                  }
3906
17.6k
                if (status == MagickFail)
3907
838
                  break;
3908
                /*
3909
                  Disassociate alpha from pixels if necessary.
3910
                */
3911
16.8k
                if ((PHOTOMETRIC_RGB == photometric) &&
3912
253
                    (image->matte) && (alpha_type == AssociatedAlpha))
3913
3
                  DisassociateAlphaRegion(image);
3914
16.8k
                if (!SyncImagePixelsEx(image,exception))
3915
0
                  {
3916
0
                    status=MagickFail;
3917
0
                    break;
3918
0
                  }
3919
16.8k
              }
3920
1.14k
            MagickFreeResourceLimitedMemory(uint32 *,tile_pixels);
3921
1.14k
            break;
3922
1.14k
          }
3923
2.50k
        case RGBAPuntMethod:
3924
2.50k
        default:
3925
2.50k
          {
3926
2.50k
            register uint32
3927
2.50k
              *p;
3928
3929
2.50k
            uint32
3930
2.50k
              *pixels;
3931
3932
2.50k
            size_t
3933
2.50k
              number_pixels,
3934
2.50k
              pixels_size;
3935
3936
2.50k
            if (logging)
3937
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3938
0
                                    "Using RGB punt read method with %u bits per sample",
3939
0
                                    bits_per_sample);
3940
3941
3942
            /*
3943
              TIFFReadRGBAImage() does not handle more than 4 samples per pixel.
3944
            */
3945
2.50k
            if (samples_per_pixel > 4)
3946
10
              {
3947
10
                ThrowTIFFReaderException(CoderError,UnsupportedSamplesPerPixel,image);
3948
0
              }
3949
3950
            /*
3951
              Convert TIFF image to DirectClass MIFF image.
3952
            */
3953
2.49k
            image->storage_class=DirectClass;
3954
2.49k
            number_pixels=MagickArraySize(image->columns,image->rows);
3955
2.49k
            if (number_pixels == 0)
3956
0
              ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3957
2.49k
                                       image);
3958
3959
3960
            /*
3961
              TIFFReadRGBAImage reads a strip- or tile-based image
3962
              into memory, storing the result in the user supplied
3963
              raster.  The raster is assumed to be an array of width
3964
              times height 32-bit entries, where width must be less
3965
              than or equal to the width of the image (height may be
3966
              any non-zero size). If the raster dimensions are smaller
3967
              than the image, the image data is cropped to the raster
3968
              bounds.  If the raster height is greater than that of
3969
              the image, then the image data are placed in the lower
3970
              part of the raster.  (Note that the raster is assumed to
3971
              be organized such that the pixel at location (x,y) is
3972
              raster[y*width+x]; with the raster origin in the
3973
              lower-left hand corner.)
3974
3975
              Please note that this allocation used to be
3976
              (number_pixels+6*image->columns)*sizeof(uint32) for
3977
              unknown reasons.
3978
            */
3979
2.49k
            pixels_size=MagickArraySize(number_pixels,sizeof(uint32));
3980
2.49k
            if (pixels_size == 0)
3981
0
              ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3982
2.49k
                                       image);
3983
2.49k
            pixels=MagickAllocateResourceLimitedMemory(uint32 *,pixels_size);
3984
2.49k
            if (pixels == (uint32 *) NULL)
3985
0
              {
3986
0
                ThrowTIFFReaderException(ResourceLimitError,MemoryAllocationFailed,
3987
0
                                         image);
3988
0
              }
3989
2.49k
            if (logging)
3990
0
                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3991
0
                                        "Dispatching to TIFFReadRGBAImage()");
3992
2.49k
            if (!TIFFReadRGBAImage(tiff,(uint32) image->columns,
3993
2.49k
                                   (uint32) image->rows,
3994
2.49k
                                   pixels,0))
3995
430
              {
3996
430
                if (logging)
3997
0
                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3998
0
                                        "TIFFReadRGBAImage() returns failure!");
3999
430
                MagickFreeResourceLimitedMemory(uint32 *,pixels);
4000
430
                status=MagickFail;
4001
430
                break;
4002
430
              }
4003
            /*
4004
              Convert image to DirectClass pixel packets.
4005
            */
4006
2.06k
            p=pixels+number_pixels-1;
4007
446k
            for (y=0; y < image->rows; y++)
4008
444k
              {
4009
444k
                q=SetImagePixelsEx(image,0,y,image->columns,1,exception);
4010
444k
                if (q == (PixelPacket *) NULL)
4011
0
                  {
4012
0
                    status=MagickFail;
4013
0
                    break;
4014
0
                  }
4015
444k
                q+=image->columns-1;
4016
444k
                if (image->matte)
4017
3.19M
                  for (x=(long) image->columns; x != 0; x--)
4018
3.17M
                    {
4019
3.17M
                      q->red=ScaleCharToQuantum(TIFFGetR(*p));
4020
3.17M
                      q->green=ScaleCharToQuantum(TIFFGetG(*p));
4021
3.17M
                      q->blue=ScaleCharToQuantum(TIFFGetB(*p));
4022
3.17M
                      q->opacity=(Quantum) ScaleCharToQuantum(TIFFGetA(*p));
4023
3.17M
                      p--;
4024
3.17M
                      q--;
4025
3.17M
                    }
4026
428k
                else
4027
297M
                  for (x=(long) image->columns; x != 0; x--)
4028
297M
                    {
4029
297M
                      q->red=ScaleCharToQuantum(TIFFGetR(*p));
4030
297M
                      q->green=ScaleCharToQuantum(TIFFGetG(*p));
4031
297M
                      q->blue=ScaleCharToQuantum(TIFFGetB(*p));
4032
297M
                      q->opacity=OpaqueOpacity;
4033
297M
                      p--;
4034
297M
                      q--;
4035
297M
                    }
4036
                /*
4037
                  Disassociate alpha from pixels if necessary.
4038
                */
4039
444k
                if ((PHOTOMETRIC_RGB == photometric) &&
4040
25.9k
                    (image->matte) && (alpha_type == AssociatedAlpha))
4041
1.26k
                  DisassociateAlphaRegion(image);
4042
444k
                if (!SyncImagePixelsEx(image,exception))
4043
0
                  {
4044
0
                    status=MagickFail;
4045
0
                    break;
4046
0
                  }
4047
444k
                if (image->previous == (Image *) NULL)
4048
444k
                  if (QuantumTick(y,image->rows))
4049
155k
                    if (!MagickMonitorFormatted(y,image->rows,exception,
4050
155k
                                                LoadImageText,image->filename,
4051
155k
                                                image->columns,image->rows))
4052
0
                      {
4053
0
                        status=MagickFail;
4054
0
                        break;
4055
0
                      }
4056
444k
                if (status == MagickFail)
4057
0
                  break;
4058
444k
              }
4059
2.06k
            MagickFreeResourceLimitedMemory(uint32 *,pixels);
4060
2.06k
            break;
4061
2.49k
          }
4062
54.4k
        }
4063
4064
54.0k
    read_next_frame:
4065
54.0k
      if (status == MagickPass)
4066
30.1k
        {
4067
30.1k
          StopTimer(&image->timer);
4068
30.1k
          if (image->depth > QuantumDepth)
4069
3.26k
            image->depth=QuantumDepth;
4070
30.1k
          if ((photometric == PHOTOMETRIC_LOGL) ||
4071
30.1k
              (photometric == PHOTOMETRIC_MINISBLACK) ||
4072
24.1k
              (photometric == PHOTOMETRIC_MINISWHITE))
4073
17.3k
            image->is_grayscale=MagickTrue;
4074
30.1k
          if ((image->is_grayscale == MagickTrue) && (bits_per_sample == 1))
4075
7.64k
            image->is_monochrome=MagickTrue;
4076
          /*
4077
            Proceed to next image.
4078
          */
4079
30.1k
          if (image_info->subrange != 0)
4080
28.3k
            if (image->scene >= (image_info->subimage+image_info->subrange-1))
4081
28.3k
              break;
4082
1.88k
          more_frames=TIFFReadDirectory(tiff);
4083
1.88k
          if (logging)
4084
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
4085
0
                                  "TIFFReadDirectory() returned %d",more_frames);
4086
1.88k
          if ((more_frames == 0) && (exception->severity == CorruptImageError))
4087
212
            {
4088
212
              if (logging)
4089
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
4090
0
                                      "Re-casting 'CorruptImageError' to"
4091
0
                                      " 'CorruptImageWarning' due to"
4092
0
                                      " TIFFReadDirectory() error");
4093
212
              exception->severity=CorruptImageWarning;
4094
212
            }
4095
1.88k
          if (more_frames)
4096
0
            {
4097
              /*
4098
                Allocate next image structure.
4099
              */
4100
0
              AllocateNextImage(image_info,image);
4101
0
              if (image->next == (Image *) NULL)
4102
0
                {
4103
0
                  DestroyImageList(image);
4104
0
                  return((Image *) NULL);
4105
0
                }
4106
0
              image=SyncNextImageInList(image);
4107
0
            }
4108
1.88k
        }
4109
4110
25.7k
      if (status == MagickFail)
4111
23.8k
        break;
4112
4113
25.7k
    } while ((status == MagickPass) && (more_frames));
4114
54.0k
  TIFFClose(tiff);
4115
54.0k
  if (status == MagickFail)
4116
23.8k
    {
4117
23.8k
      if (logging)
4118
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
4119
0
                              "Delete image %ld from list due to error",
4120
0
                              image->scene);
4121
23.8k
      DeleteImageFromList(&image);
4122
23.8k
    }
4123
54.0k
  return GetFirstImageInList(image);
4124
57.3k
}
4125
#endif
4126

4127
/*
4128
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4129
%                                                                             %
4130
%                                                                             %
4131
%                                                                             %
4132
%   R e g i s t e r T I F F I m a g e                                         %
4133
%                                                                             %
4134
%                                                                             %
4135
%                                                                             %
4136
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4137
%
4138
%  Method RegisterTIFFImage adds attributes for the TIFF image format to
4139
%  the list of supported formats.  The attributes include the image format
4140
%  tag, a method to read and/or write the format, whether the format
4141
%  supports the saving of more than one frame to the same file or blob,
4142
%  whether the format supports native in-memory I/O, and a brief
4143
%  description of the format.
4144
%
4145
%  The format of the RegisterTIFFImage method is:
4146
%
4147
%      void RegisterTIFFImage(void)
4148
%
4149
*/
4150
ModuleExport void
4151
RegisterTIFFImage(void)
4152
7
{
4153
7
#define BIGTIFFDescription  "Tagged Image File Format (64-bit offsets)"
4154
7
#define GROUP4RAWDescription "CCITT Group4 RAW"
4155
7
#define PTIFDescription "Pyramid encoded TIFF"
4156
14
#define TIFFDescription  "Tagged Image File Format"
4157
7
#if defined(HasTIFF)
4158
4159
7
  static char
4160
7
    version[32];
4161
4162
7
  MagickInfo
4163
7
    *entry;
4164
4165
7
  static const char
4166
7
    TIFFNote[] =
4167
7
    "Supported Compressions: "
4168
7
#if defined(COMPRESSION_NONE)
4169
7
    "None"
4170
7
#endif
4171
7
#if defined(COMPRESSION_CCITTFAX3)
4172
7
    ", Fax/Group3"
4173
7
#endif
4174
7
#if defined(COMPRESSION_CCITTFAX4)
4175
7
    ", Group4"
4176
7
#endif
4177
7
#if defined(COMPRESSION_JBIG)
4178
7
    ", JBIG"
4179
7
#endif
4180
7
#if defined(COMPRESSION_JPEG)
4181
7
    ", JPEG"
4182
7
#endif
4183
7
#if defined(COMPRESSION_LZW)
4184
7
    ", LZW"
4185
7
#endif
4186
7
#if defined(COMPRESSION_LZMA)
4187
7
    ", LZMA"
4188
7
#endif
4189
7
#if defined(COMPRESSION_PACKBITS)
4190
7
    ", RLE"
4191
7
#endif
4192
7
#if defined(COMPRESSION_ADOBE_DEFLATE)
4193
7
    ", ZIP"
4194
7
#endif
4195
7
#if defined(COMPRESSION_ZSTD)
4196
7
    ", ZSTD"
4197
7
#endif
4198
7
#if defined(COMPRESSION_WEBP)
4199
7
    ", WEBP"
4200
7
#endif
4201
7
    ;
4202
4203
  /*
4204
    Initialize thread specific data key.
4205
  */
4206
7
  if (tsd_key == (MagickTsdKey_t) 0)
4207
7
    (void) MagickTsdKeyCreate(&tsd_key);
4208
4209
7
  version[0]='\0';
4210
7
  {
4211
7
    unsigned int
4212
7
      i;
4213
4214
7
    const char
4215
7
      *p;
4216
4217
    /* TIFFGetVersion() is in libtiff 3.5.3 and later */
4218
7
    for (p=TIFFGetVersion(), i=0;
4219
161
         (i < sizeof(version)-1) && (*p != 0) && (*p != '\n');
4220
154
          p++, i++)
4221
154
      version[i] = *p;
4222
7
    version[i]=0;
4223
7
  }
4224
4225
  /*
4226
    Big TIFF (64-bit offsets)
4227
  */
4228
7
#if defined(HasBigTIFF)
4229
7
  entry=SetMagickInfo("BIGTIFF");
4230
7
  entry->thread_support=MagickFalse; /* libtiff uses libjpeg which is not thread safe */
4231
7
  entry->decoder=(DecoderHandler) ReadTIFFImage;
4232
7
  entry->encoder=(EncoderHandler) WriteTIFFImage;
4233
7
  entry->seekable_stream=MagickTrue;
4234
7
  entry->description=BIGTIFFDescription;
4235
7
  entry->note=TIFFNote;
4236
7
  entry->module="TIFF";
4237
7
  entry->coder_class=PrimaryCoderClass;
4238
7
  (void) RegisterMagickInfo(entry);
4239
7
#endif /* defined(HasBigTIFF) */
4240
4241
  /*
4242
    CCITT Group4 RAW encoded page.
4243
  */
4244
7
  entry=SetMagickInfo("GROUP4RAW");
4245
7
  entry->thread_support=MagickTrue;
4246
  /* entry->decoder=(DecoderHandler) ReadGROUP4RAWImage; */
4247
7
  entry->encoder=(EncoderHandler) WriteGROUP4RAWImage;
4248
7
  entry->raw=MagickTrue;
4249
7
  entry->adjoin=MagickFalse;
4250
7
  entry->seekable_stream=MagickFalse;
4251
7
  entry->extension_treatment=IgnoreExtensionTreatment;
4252
7
  entry->stealth=MagickTrue; /* Don't list in '-list format' output */
4253
7
  entry->description=GROUP4RAWDescription;
4254
7
  entry->module="TIFF";
4255
7
  (void) RegisterMagickInfo(entry);
4256
4257
  /*
4258
    Pyramid TIFF (sequence of successively smaller versions of the same image)
4259
  */
4260
7
  entry=SetMagickInfo("PTIF");
4261
7
  entry->thread_support=MagickFalse; /* libtiff uses libjpeg which is not thread safe */
4262
7
  entry->decoder=(DecoderHandler) ReadTIFFImage;
4263
7
  entry->encoder=(EncoderHandler) WritePTIFImage;
4264
7
  entry->seekable_stream=MagickTrue;
4265
7
  entry->description=PTIFDescription;
4266
7
  entry->note=TIFFNote;
4267
7
  entry->module="TIFF";
4268
7
  (void) RegisterMagickInfo(entry);
4269
4270
  /*
4271
    Another name for 32-bit TIFF
4272
  */
4273
7
  entry=SetMagickInfo("TIF");
4274
7
  entry->thread_support=MagickFalse; /* libtiff uses libjpeg which is not thread safe */
4275
7
  entry->decoder=(DecoderHandler) ReadTIFFImage;
4276
7
  entry->encoder=(EncoderHandler) WriteTIFFImage;
4277
7
  entry->seekable_stream=MagickTrue;
4278
7
  entry->description=TIFFDescription;
4279
7
  if (*version != '\0')
4280
7
    entry->version=version;
4281
7
  entry->note=TIFFNote;
4282
7
  entry->stealth=MagickTrue; /* Don't list in '-list format' output */
4283
7
  entry->module="TIFF";
4284
7
  entry->coder_class=PrimaryCoderClass;
4285
7
  (void) RegisterMagickInfo(entry);
4286
4287
  /*
4288
    Traditional 32-bit TIFF
4289
  */
4290
7
  entry=SetMagickInfo("TIFF");
4291
7
  entry->thread_support=MagickFalse; /* libtiff uses libjpeg which is not thread safe */
4292
7
  entry->decoder=(DecoderHandler) ReadTIFFImage;
4293
7
  entry->encoder=(EncoderHandler) WriteTIFFImage;
4294
7
  entry->magick=(MagickHandler) IsTIFF;
4295
7
  entry->seekable_stream=MagickTrue;
4296
7
  entry->description=TIFFDescription;
4297
7
  if (*version != '\0')
4298
7
    entry->version=version;
4299
7
  entry->note=TIFFNote;
4300
7
  entry->module="TIFF";
4301
7
  entry->coder_class=PrimaryCoderClass;
4302
7
  (void) RegisterMagickInfo(entry);
4303
4304
7
#if defined(EXTEND_TIFF_TAGS)
4305
  /*
4306
    Add our own TIFF tag extensions.
4307
  */
4308
7
  ExtensionTagsInitialize();
4309
7
#endif /* defined(EXTEND_TIFF_TAGS) */
4310
4311
4312
7
#endif /* if defined(HasTIFF) */
4313
7
}
4314

4315
/*
4316
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4317
%                                                                             %
4318
%                                                                             %
4319
%                                                                             %
4320
%   U n r e g i s t e r T I F F I m a g e                                     %
4321
%                                                                             %
4322
%                                                                             %
4323
%                                                                             %
4324
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4325
%
4326
%  Method UnregisterTIFFImage removes format registrations made by the
4327
%  TIFF module from the list of supported formats.
4328
%
4329
%  The format of the UnregisterTIFFImage method is:
4330
%
4331
%      void UnregisterTIFFImage(void)
4332
%
4333
*/
4334
ModuleExport void
4335
UnregisterTIFFImage(void)
4336
0
{
4337
0
#if defined(HasTIFF)
4338
0
#if defined(HasBigTIFF)
4339
0
  (void) UnregisterMagickInfo("BIGTIFF");
4340
0
#endif /* defined(HasBigTIFF) */
4341
0
  (void) UnregisterMagickInfo("GROUP4RAW");
4342
0
  (void) UnregisterMagickInfo("PTIF");
4343
0
  (void) UnregisterMagickInfo("TIF");
4344
0
  (void) UnregisterMagickInfo("TIFF");
4345
4346
  /*
4347
    Destroy thread specific data key.
4348
  */
4349
0
  if (tsd_key != (MagickTsdKey_t) 0)
4350
0
    {
4351
0
      (void) MagickTsdKeyDelete(tsd_key);
4352
0
      tsd_key = (MagickTsdKey_t) 0;
4353
0
    }
4354
0
#endif
4355
0
}
4356

4357
#if defined(HasTIFF)
4358
/*
4359
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4360
%                                                                             %
4361
%                                                                             %
4362
%                                                                             %
4363
%   W r i t e G R O U P 4 R A W I m a g e                                     %
4364
%                                                                             %
4365
%                                                                             %
4366
%                                                                             %
4367
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4368
%
4369
%  Method WriteGROUP4RAWImage writes an image as raw Group4 compressed data.
4370
%
4371
%  The format of the WriteGROUP4RAWImage method is:
4372
%
4373
%      MagickPassFail WriteGROUP4RAWImage(const ImageInfo *image_info,Image *image)
4374
%
4375
%  A description of each parameter follows:
4376
%
4377
%    o status:  Method WriteGROUP4RAWImage return True if the image is written.
4378
%      False is returned is there is of a memory shortage or if the image
4379
%      file cannot be opened for writing.
4380
%
4381
%    o image_info: Specifies a pointer to a ImageInfo structure.
4382
%
4383
%    o image:  A pointer to an Image structure.
4384
%
4385
%
4386
*/
4387
static MagickPassFail
4388
WriteGROUP4RAWImage(const ImageInfo *image_info,Image *image)
4389
1.67k
{
4390
1.67k
  char
4391
1.67k
    temporary_filename[MaxTextExtent];
4392
4393
1.67k
  Image
4394
1.67k
    *huffman_image;
4395
4396
1.67k
  ImageInfo
4397
1.67k
    *clone_info;
4398
4399
1.67k
  TIFF
4400
1.67k
    *tiff;
4401
4402
1.67k
  toff_t
4403
1.67k
    *byte_counts,
4404
1.67k
    count,
4405
1.67k
    strip_size;
4406
4407
1.67k
  unsigned char
4408
1.67k
    *strip;
4409
4410
1.67k
 unsigned int
4411
1.67k
   i;
4412
4413
1.67k
  MagickPassFail
4414
1.67k
    status;
4415
4416
  /*
4417
    Write image as CCITTFax4 TIFF image.
4418
  */
4419
1.67k
  assert(image_info != (ImageInfo *) NULL);
4420
1.67k
  assert(image_info->signature == MagickSignature);
4421
1.67k
  assert(image != (Image *) NULL);
4422
1.67k
  assert(image->signature == MagickSignature);
4423
4424
1.67k
  if (!AcquireTemporaryFileName(temporary_filename))
4425
1.67k
    ThrowWriterException(FileOpenError,UnableToCreateTemporaryFile,image);
4426
4427
1.67k
  huffman_image=CloneImage(image,0,0,True,&image->exception);
4428
1.67k
  if (huffman_image == (Image *) NULL)
4429
0
    return(MagickFail);
4430
4431
1.67k
  if (SetImageType(huffman_image,BilevelType) == MagickFail)
4432
0
    {
4433
0
      CopyException(&image->exception,&huffman_image->exception);
4434
0
      DestroyImage(huffman_image);
4435
0
      return MagickFail;
4436
0
    }
4437
4438
1.67k
  MagickFormatString(huffman_image->filename,sizeof(huffman_image->filename),"tiff:%s",temporary_filename);
4439
1.67k
  clone_info=CloneImageInfo((const ImageInfo *) NULL);
4440
/*   clone_info->blob=0; */
4441
1.67k
  clone_info->compression=Group4Compression;
4442
1.67k
  clone_info->type=BilevelType;
4443
1.67k
  (void) AddDefinitions(clone_info,"tiff:strip-per-page=TRUE",
4444
1.67k
                        &image->exception);
4445
1.67k
  (void) AddDefinitions(clone_info,"tiff:fill-order=msb2lsb",
4446
1.67k
                        &image->exception);
4447
1.67k
  status=WriteImage(clone_info,huffman_image);
4448
1.67k
  if (status == MagickFail)
4449
0
    CopyException(&image->exception,&huffman_image->exception);
4450
1.67k
  DestroyImageInfo(clone_info);
4451
1.67k
  DestroyImage(huffman_image);
4452
1.67k
  if (status == MagickFail)
4453
0
    {
4454
0
      (void) LiberateTemporaryFile(temporary_filename);
4455
0
      return MagickFail;
4456
0
    }
4457
4458
1.67k
  (void) MagickTsdSetSpecific(tsd_key,(void *) (&image->exception));
4459
1.67k
  (void) TIFFSetErrorHandler((TIFFErrorHandler) TIFFWriteErrorsHandler);
4460
1.67k
  (void) TIFFSetWarningHandler((TIFFErrorHandler) (CheckThrowWarnings(image_info) ?
4461
0
                                                   TIFFWarningsThrowException :
4462
1.67k
                                                   TIFFWarningsLogOnly));
4463
4464
1.67k
  tiff=TIFFOpen(temporary_filename,"rb");
4465
1.67k
  if (tiff == (TIFF *) NULL)
4466
0
    {
4467
0
      (void) LiberateTemporaryFile(temporary_filename);
4468
0
      return MagickFail;
4469
0
    }
4470
4471
  /*
4472
    Allocate raw strip buffer.
4473
  */
4474
1.67k
  if (TIFFGetField(tiff,TIFFTAG_STRIPBYTECOUNTS,&byte_counts) != 1)
4475
0
    {
4476
0
      TIFFClose(tiff);
4477
0
      (void) LiberateTemporaryFile(temporary_filename);
4478
0
      return MagickFail;
4479
0
    }
4480
1.67k
  strip_size=byte_counts[0];
4481
1.67k
  for (i=1; i < TIFFNumberOfStrips(tiff); i++)
4482
0
    if (byte_counts[i] > strip_size)
4483
0
      strip_size=byte_counts[i];
4484
1.67k
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
4485
1.67k
                        "Allocating %lu bytes of memory for TIFF strip",
4486
1.67k
                        (unsigned long) strip_size);
4487
1.67k
  strip=MagickAllocateResourceLimitedMemory(unsigned char *,(size_t) strip_size);
4488
1.67k
  if (strip == (unsigned char *) NULL)
4489
0
    {
4490
0
      TIFFClose(tiff);
4491
0
      (void) LiberateTemporaryFile(temporary_filename);
4492
0
      ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
4493
0
                           image);
4494
0
    }
4495
  /*
4496
    Open blob for output
4497
  */
4498
1.67k
  if ((status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception))
4499
1.67k
      == MagickFail)
4500
0
    {
4501
0
      MagickFreeResourceLimitedMemory(unsigned char *,strip);
4502
0
      TIFFClose(tiff);
4503
0
      (void) LiberateTemporaryFile(temporary_filename);
4504
0
      ThrowWriterException(FileOpenError,UnableToOpenFile,image);
4505
0
    }
4506
4507
  /*
4508
    Compress runlength encoded to 2D Huffman pixels.
4509
  */
4510
1.67k
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
4511
1.67k
                        "Output 2D Huffman pixels.");
4512
3.35k
  for (i=0; i < TIFFNumberOfStrips(tiff); i++)
4513
1.67k
  {
4514
1.67k
    count=TIFFReadRawStrip(tiff,(uint32) i,strip,strip_size);
4515
1.67k
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
4516
1.67k
                          "Writing strip %u (%lu bytes) to blob ...",
4517
1.67k
                          i,(unsigned long) count);
4518
1.67k
    if ((toff_t) WriteBlob(image,count,strip) != count)
4519
0
      status=MagickFail;
4520
1.67k
  }
4521
4522
1.67k
  MagickFreeResourceLimitedMemory(unsigned char *,strip);
4523
1.67k
  TIFFClose(tiff);
4524
4525
1.67k
  (void) LiberateTemporaryFile(temporary_filename);
4526
1.67k
  status &= CloseBlob(image);
4527
1.67k
  return status;
4528
1.67k
}
4529
#endif /* if defined(HasTIFF) */
4530

4531
#if defined(HasTIFF)
4532
/*
4533
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4534
%                                                                             %
4535
%                                                                             %
4536
%                                                                             %
4537
%   W r i t e P T I F I m a g e                                               %
4538
%                                                                             %
4539
%                                                                             %
4540
%                                                                             %
4541
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4542
%
4543
%  WritePTIFImage() writes an image in the pyramid-encoded Tagged image file
4544
%  format.
4545
%
4546
%  The format of the WritePTIFImage method is:
4547
%
4548
%      MagickPassFail WritePTIFImage(const ImageInfo *image_info,Image *image)
4549
%
4550
%  A description of each parameter follows:
4551
%
4552
%    o status:  Method WritePTIFImage return MagickPass if the image is written.
4553
%      MagickFail is returned is there is of a memory shortage or if the image
4554
%      file cannot be opened for writing.
4555
%
4556
%    o image_info: Specifies a pointer to a ImageInfo structure.
4557
%
4558
%    o image:  A pointer to an Image structure.
4559
%
4560
%
4561
*/
4562
static MagickPassFail
4563
WritePTIFImage(const ImageInfo *image_info,Image *image)
4564
8.95k
{
4565
8.95k
  Image
4566
8.95k
    *pyramid_image;
4567
4568
8.95k
  ImageInfo
4569
8.95k
    *clone_info;
4570
4571
8.95k
  FilterTypes
4572
8.95k
    filter;
4573
4574
8.95k
  unsigned int
4575
8.95k
    status;
4576
4577
8.95k
  const char
4578
8.95k
    *def;
4579
4580
8.95k
  RectangleInfo
4581
8.95k
    min_geometry;
4582
4583
  /*
4584
    Create pyramid-encoded TIFF image.
4585
  */
4586
8.95k
  assert(image_info != (const ImageInfo *) NULL);
4587
8.95k
  assert(image_info->signature == MagickSignature);
4588
8.95k
  assert(image != (Image *) NULL);
4589
8.95k
  assert(image->signature == MagickSignature);
4590
8.95k
  if (!(((def=AccessDefinition(image_info,"ptif","minimum-geometry")) != NULL) &&
4591
0
        (GetGeometry(def,&min_geometry.x,&min_geometry.y,&min_geometry.width,
4592
0
                     &min_geometry.height) & (WidthValue|HeightValue))))
4593
8.95k
    {
4594
      /*
4595
        Minimum default subresolution frame is 32x32
4596
      */
4597
8.95k
      min_geometry.height=32;
4598
8.95k
      min_geometry.width=32;
4599
8.95k
    }
4600
8.95k
  if (image->logging)
4601
0
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
4602
0
                          "PTIF minimum pyramid dimensions: %lux%lu",
4603
0
                          min_geometry.width, min_geometry.height);
4604
8.95k
  filter=TriangleFilter;
4605
8.95k
  if (image->is_monochrome)
4606
1.40k
    filter=PointFilter;
4607
8.95k
  pyramid_image=CloneImage(image,0,0,True,&image->exception);
4608
8.95k
  if (pyramid_image == (Image *) NULL)
4609
8.95k
    ThrowWriterException2(FileOpenError,image->exception.reason,image);
4610
8.95k
  DestroyBlob(pyramid_image);
4611
8.95k
  pyramid_image->blob=ReferenceBlob(image->blob);
4612
8.95k
  (void) SetImageAttribute(pyramid_image,"subfiletype","NONE");
4613
14.2k
  while(1)
4614
14.2k
    {
4615
14.2k
      if ((pyramid_image->columns/2 < min_geometry.width) ||
4616
7.04k
          (pyramid_image->rows/2 < min_geometry.height))
4617
8.95k
        break;
4618
4619
5.30k
      pyramid_image->next=ResizeImage(image,pyramid_image->columns/2,
4620
5.30k
                                      pyramid_image->rows/2,filter,
4621
5.30k
                                      1.0,&image->exception);
4622
5.30k
      if (pyramid_image->next == (Image *) NULL)
4623
0
        {
4624
0
          DestroyImageList(pyramid_image);
4625
0
          ThrowWriterException2(FileOpenError,image->exception.reason,image);
4626
0
        }
4627
5.30k
      DestroyBlob(pyramid_image->next);
4628
5.30k
        pyramid_image->next->blob=ReferenceBlob(image->blob);
4629
5.30k
      if ((!image->is_monochrome) && (image->storage_class == PseudoClass))
4630
510
        (void) MapImage(pyramid_image->next,image,False);
4631
5.30k
      pyramid_image->next->x_resolution=pyramid_image->x_resolution/2.0;
4632
5.30k
      pyramid_image->next->y_resolution=pyramid_image->y_resolution/2.0;
4633
5.30k
      (void) SetImageAttribute(pyramid_image->next,"subfiletype","REDUCEDIMAGE");
4634
5.30k
      pyramid_image->next->previous=pyramid_image;
4635
5.30k
      pyramid_image=pyramid_image->next;
4636
8.95k
    };
4637
14.2k
  while (pyramid_image->previous != (Image *) NULL)
4638
5.30k
    pyramid_image=pyramid_image->previous;
4639
  /*
4640
    Write pyramid-encoded TIFF image.
4641
  */
4642
8.95k
  clone_info=CloneImageInfo(image_info);
4643
8.95k
  clone_info->adjoin=True;
4644
8.95k
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
4645
8.95k
                        "Invoking \"%.1024s\" encoder, monochrome=%s, grayscale=%s",
4646
8.95k
                        "TIFF",
4647
8.95k
                        MagickBoolToString(image->is_monochrome),
4648
8.95k
                        MagickBoolToString(image->is_grayscale));
4649
8.95k
  status=WriteTIFFImage(clone_info,pyramid_image);
4650
8.95k
  DestroyImageList(pyramid_image);
4651
8.95k
  DestroyImageInfo(clone_info);
4652
8.95k
  return(status);
4653
8.95k
}
4654
#endif /* defined(HasTIFF) */
4655

4656
#if defined(HasTIFF)
4657
4658
#if EXPERIMENTAL_EXIF_TAGS
4659
#if TIFFLIB_VERSION >= 20120922
4660
4661
77
#define FLAG_EXIF       1 /* In (or have handled) EXIF IFD */
4662
420
#define FLAG_GPS        2 /* In (or have handled) GPS IFD */
4663
288
#define FLAG_BASE       4 /* Transfer tags. Used to be set globally, so primary IFD would be updated/trashed */
4664
4665
4666
/*
4667
static TIFFField customFields[] = {
4668
    {544, -1, -1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
4669
     TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Custom1", NULL},
4670
};
4671
4672
static TIFFFieldArray customFieldArray = {tfiatOther, 0, 1, customFields};
4673
*/
4674
4675
/*
4676
  EXIF data-marshalling functions. The "_LO" variants are for reading
4677
  little-endian EXIF and the "_HI" variants are for big-endian
4678
  EXIF. Reading is done in bytes in order to avoid address alignment
4679
  violations.
4680
4681
  The implementations are reversed from what may be intuitively
4682
  expected, since they also perform endian swapping.
4683
*/
4684
static magick_uint32_t LD_UINT32_LO(const unsigned char *Mem)
4685
102
{
4686
#ifdef WORDS_BIGENDIAN
4687
  return (((magick_uint32_t)Mem[0]<<24) | ((magick_uint32_t)Mem[1] << 16) | ((magick_uint32_t)Mem[2] << 8) | ((magick_uint32_t)Mem[3]));
4688
#else
4689
102
  return ((magick_uint32_t)Mem[0] | ((magick_uint32_t)Mem[1] << 8) | ((magick_uint32_t)Mem[2] << 16) | ((magick_uint32_t)Mem[3] << 24));
4690
102
#endif
4691
102
}
4692
4693
static magick_uint32_t LD_UINT32_HI(const unsigned char *Mem)
4694
7.96k
{
4695
#ifdef WORDS_BIGENDIAN
4696
  return ((magick_uint32_t)Mem[0] | ((magick_uint32_t)Mem[1] << 8) | ((magick_uint32_t)Mem[2] << 16) | ((magick_uint32_t)Mem[3] << 24));
4697
#else
4698
7.96k
  return (((magick_uint32_t)Mem[0]<<24) | ((magick_uint32_t)Mem[1] << 16) | ((magick_uint32_t)Mem[2] << 8) | ((magick_uint32_t)Mem[3]));
4699
7.96k
#endif
4700
7.96k
}
4701
4702
4703
static magick_uint16_t LD_UINT16_LO(const unsigned char *Mem)
4704
90
{
4705
#ifdef WORDS_BIGENDIAN
4706
  return (((magick_uint16_t)Mem[0] << 8) | ((magick_uint16_t)Mem[1]));
4707
#else
4708
90
  return ((magick_uint16_t)Mem[0] | ((magick_uint16_t)Mem[1] << 8));
4709
90
#endif
4710
90
}
4711
4712
static magick_uint16_t LD_UINT16_HI(const unsigned char *Mem)
4713
7.89k
{
4714
#ifdef WORDS_BIGENDIAN
4715
  return ((magick_uint16_t)Mem[0] | ((magick_uint16_t)Mem[1] << 8));
4716
#else
4717
7.89k
  return (((magick_uint16_t)Mem[0] << 8) | ((magick_uint16_t)Mem[1]));
4718
7.89k
#endif
4719
7.89k
}
4720
4721
4722
static const char *FipFieldName(const TIFFField *fip)
4723
0
{
4724
0
  if (fip)
4725
0
    {
4726
0
      const char * const FName = TIFFFieldName(fip);
4727
0
      if (FName==NULL)
4728
0
        return "N/A";
4729
0
      return FName;
4730
0
    }
4731
0
  return "UNSUPPORTED";
4732
0
}
4733
4734
static const char *FipFieldTypeToStr(const TIFFDataType data_type)
4735
0
{
4736
0
  const char *str = "UNKNOWN";
4737
0
  switch (data_type)
4738
0
    {
4739
0
    case TIFF_NOTYPE:     /* placeholder */
4740
0
      str = "NOTYPE";
4741
0
      break;
4742
0
    case TIFF_BYTE:       /* 8-bit unsigned integer */
4743
0
      str = "BYTE";
4744
0
      break;
4745
0
    case TIFF_ASCII:      /* 8-bit bytes w/ last byte null */
4746
0
      str = "STRING";     /* vs "ASCII */
4747
0
      break;
4748
0
    case TIFF_SHORT:      /* 16-bit unsigned integer */
4749
0
      str = "USHORT";
4750
0
      break;
4751
0
    case TIFF_LONG:       /* 32-bit unsigned integer */
4752
0
      str = "ULONG";
4753
0
      break;
4754
0
    case TIFF_RATIONAL:   /* 64-bit unsigned fraction */
4755
0
      str = "URATIONAL";
4756
0
      break;
4757
0
    case TIFF_SBYTE:      /* !8-bit signed integer */
4758
0
      str = "SBYTE";
4759
0
      break;
4760
0
    case TIFF_UNDEFINED:  /* !8-bit untyped data */
4761
0
      str = "UNDEFINED";
4762
0
      break;
4763
0
    case TIFF_SSHORT:     /* !16-bit signed integer */
4764
0
      str = "SSHORT";
4765
0
      break;
4766
0
    case TIFF_SLONG:      /* !32-bit signed integer */
4767
0
      str = "SLONG";
4768
0
      break;
4769
0
    case TIFF_SRATIONAL: /* !64-bit signed fraction */
4770
0
      str = "SRATIONAL";
4771
0
      break;
4772
0
    case TIFF_FLOAT:     /* !32-bit IEEE floating point */
4773
0
      str = "FLOAT";
4774
0
      break;
4775
0
    case TIFF_DOUBLE:    /* !64-bit IEEE floating point */
4776
0
      str = "DOUBLE";
4777
0
      break;
4778
0
    case TIFF_IFD:       /* %32-bit unsigned integer (offset) */
4779
0
      str = "IFD";
4780
0
      break;
4781
0
#if defined(HasBigTIFF)
4782
0
    case TIFF_LONG8:     /* BigTIFF 64-bit unsigned integer */
4783
0
      str = "LONG8";
4784
0
      break;
4785
0
    case TIFF_SLONG8:    /* BigTIFF 64-bit signed integer */
4786
0
      str = "SLONG8";
4787
0
      break;
4788
0
    case TIFF_IFD8:       /* BigTIFF 64-bit unsigned integer (offset) */
4789
0
      str = "IFD8";
4790
0
      break;
4791
0
#endif /* if defined(HasBigTIFF) */
4792
0
    }
4793
0
  return str;
4794
0
}
4795
4796
4797
static int CheckAndStoreStr(TIFF *tiff, const magick_uint16_t Tag, const char *String, const magick_uint32_t StrSize)
4798
0
{
4799
0
  magick_uint32_t i = StrSize;
4800
4801
0
  if (Tag == TIFFTAG_INKNAMES)             /* Variant of call is tag dependent, too bad. */
4802
0
    {
4803
0
      if (StrSize > 0xFFFF)
4804
0
        return 0;
4805
      /* TIFFTAG_INKNAMES needs only uint16_t https://libtiff.gitlab.io/libtiff/functions/TIFFSetField.html#c.TIFFSetField */
4806
0
      return TIFFSetField(tiff, Tag, (magick_uint16_t)StrSize, String);
4807
0
    }
4808
4809
  /* Look for zero terminator. */
4810
0
  while (i > 0)
4811
0
    {
4812
0
      i--;
4813
0
      if (String[i] == 0)
4814
0
        {
4815
0
          return TIFFSetField(tiff, Tag, String);
4816
0
        }
4817
0
    }
4818
4819
0
  if (StrSize > 0)
4820
0
    {
4821
      /* Try to duplicate unterminated string. */
4822
0
      char *StringDup = MagickAllocateResourceLimitedMemory(char *, StrSize+1);
4823
0
      if (StringDup != NULL)
4824
0
        {
4825
0
          memcpy(StringDup,String,StrSize);
4826
0
          StringDup[StrSize] = 0;
4827
0
          i = TIFFSetField(tiff, Tag, String);
4828
0
          MagickFreeResourceLimitedMemory(char *,StringDup);
4829
0
          return i;
4830
0
        }
4831
0
    }
4832
0
  return 0;
4833
0
}
4834
4835
4836
static int AddIFDExifFields(TIFF *tiff, unsigned int *ifds_handled,
4837
                            const unsigned char * const profile_data,
4838
                            const unsigned char *IFD_data,
4839
                            const size_t profile_length,
4840
                            MagickBool logging, magick_uint16_t Flags)
4841
245
{
4842
245
  magick_uint32_t(*LD_UINT32)(const unsigned char *Mem);
4843
245
  magick_uint16_t(*LD_UINT16)(const unsigned char *Mem);
4844
245
  const TIFFField *fip;
4845
245
  magick_uint16_t EntryNum;
4846
245
  magick_uint16_t Tag, Field;
4847
245
  magick_uint32_t Long2, Value;
4848
245
  const size_t Max_IFD_data_Loops = 4096;
4849
245
  size_t IFD_data_Loops = 0;
4850
245
  MagickBool continue_looping = MagickTrue;
4851
245
  int FieldCount = 0;
4852
4853
245
  if (*profile_data == 'M')
4854
206
    {
4855
      /* "MM" is big-endian */
4856
206
      if (logging)
4857
0
        (void)LogMagickEvent(CoderEvent,GetMagickModule(),
4858
0
                             "Big-endian IFD");
4859
206
      LD_UINT32 = LD_UINT32_HI;
4860
206
      LD_UINT16 = LD_UINT16_HI;
4861
206
    }
4862
39
  else
4863
39
    {
4864
      /* "II" is little-endian */
4865
39
      if (*profile_data != 'I')
4866
3
        return 0;
4867
36
      if (logging)
4868
0
        (void)LogMagickEvent(CoderEvent,GetMagickModule(),
4869
0
                             "Little-endian IFD");
4870
36
      LD_UINT32 = LD_UINT32_LO;
4871
36
      LD_UINT16 = LD_UINT16_LO;
4872
36
    }
4873
4874
242
  do
4875
272
    {
4876
272
      const unsigned char *Orig_IFD_data
4877
272
        = IFD_data;
4878
4879
272
      if (profile_length < (size_t)(IFD_data-profile_data)+2)
4880
6
        return 0;
4881
266
      if (logging)
4882
0
        (void)LogMagickEvent(CoderEvent,GetMagickModule(),
4883
0
                             "Flags=0x%02x", (unsigned) Flags);
4884
266
      EntryNum = LD_UINT16(IFD_data); /* Number of IFD directory entries */
4885
266
      if (logging /* && (Flags & FLAG_BASE) != 0 */)
4886
0
        (void)LogMagickEvent(CoderEvent,GetMagickModule(),
4887
0
                             "IFD EntryNum %u", (unsigned) EntryNum);
4888
266
      if (profile_length < (size_t)(IFD_data-profile_data)+(EntryNum*12))
4889
97
        return 0;
4890
169
      IFD_data += 2;
4891
4892
4.02k
      while (EntryNum > 0)
4893
3.86k
        {
4894
          /* Directory Entry */
4895
3.86k
          Tag = LD_UINT16(IFD_data);     /* Tag */
4896
3.86k
          Field = LD_UINT16(IFD_data+2); /* Tag Type Code */
4897
3.86k
          Long2 = LD_UINT32(IFD_data+4); /* Count */
4898
3.86k
          Value = LD_UINT32(IFD_data+8); /* Value or Offset */
4899
4900
3.86k
          fip = TIFFFindField(tiff, Tag, TIFF_ANY);
4901
3.86k
          if (logging && (Flags & FLAG_BASE) != 0)
4902
0
            (void)LogMagickEvent(CoderEvent,GetMagickModule(),
4903
0
                                 "Extracted tag from EXIF %xh.H (%u), Field %u (%s), Long2 %u, val %u %s",
4904
0
                                 (unsigned) Tag, (unsigned) Tag, (unsigned) Field,
4905
0
                                 FipFieldTypeToStr((TIFFDataType) Field),
4906
0
                                 (unsigned) Long2, (unsigned) Value, FipFieldName(fip));
4907
4908
          /*
4909
            Skip EXIF tags which are redundant with the main IFD
4910
            (there are many more).
4911
          */
4912
3.86k
          if (Tag == 0 ||
4913
3.44k
              Tag == TIFFTAG_COLORMAP ||        /* 0x0140 */
4914
3.44k
              Tag == TIFFTAG_COMPRESSION ||     /* 0x0103 */
4915
3.43k
              Tag == TIFFTAG_IMAGELENGTH ||     /* 0x0101 */
4916
3.40k
              Tag == TIFFTAG_IMAGEWIDTH ||      /* 0x0100 */
4917
3.32k
              Tag == TIFFTAG_SAMPLESPERPIXEL || /* 0x0115 */
4918
3.32k
              Tag == TIFFTAG_BITSPERSAMPLE ||   /* 0x0102 */
4919
3.31k
              Tag == TIFFTAG_SAMPLEFORMAT ||    /* 0x0153 */
4920
3.31k
              Tag == TIFFTAG_STRIPOFFSETS ||    /* 0x0111 */
4921
3.30k
              Tag == TIFFTAG_ROWSPERSTRIP ||    /* 0x0116 */
4922
3.30k
              Tag == TIFFTAG_STRIPBYTECOUNTS || /* 0x0117 */
4923
3.30k
              Tag == TIFFTAG_ORIENTATION ||     /* 0x0112 */ /* Orientation is handled different way. */
4924
3.30k
              Tag == TIFFTAG_XRESOLUTION ||     /* 0x011A */
4925
3.29k
              Tag == TIFFTAG_YRESOLUTION ||     /* 0x011B */
4926
3.28k
              Tag == TIFFTAG_PLANARCONFIG ||    /* 0x011C */
4927
3.28k
              Tag == TIFFTAG_TRANSFERFUNCTION ||/* 0x012D */ /* Depends on TIFFTAG_BITSPERSAMPLE and TIFFTAG_SAMPLESPERPIXEL (above) */
4928
3.28k
              Tag == TIFFTAG_EXTRASAMPLES       /* 0x0152 */
4929
3.86k
              )
4930
577
            {
4931
577
              if (logging && (Flags & FLAG_BASE) != 0)
4932
0
                (void)LogMagickEvent(CoderEvent,GetMagickModule(),
4933
0
                                     "  Skipping tag from EXIF %xh.H (%u), Field %u (%s), Long2 %u, val %u %s",
4934
0
                                     (unsigned) Tag, (unsigned) Tag, (unsigned) Field,
4935
0
                                     FipFieldTypeToStr((TIFFDataType) Field),
4936
0
                                     (unsigned) Long2, (unsigned) Value, FipFieldName(fip));
4937
577
              goto NextItem;        /* Banned TIFF tags that cannot be copied from EXIF. */
4938
577
            }
4939
4940
3.28k
          if (Tag == TIFFTAG_EXIFIFD)
4941
0
            {
4942
0
              if (Value >= profile_length)
4943
0
                {
4944
0
                  if (logging)
4945
0
                    (void)LogMagickEvent(CoderEvent,GetMagickModule(),
4946
0
                                         "EXIF IFD data length (%u) exceeds profile length (%zu)!",
4947
0
                                         (unsigned) Value, profile_length);
4948
0
                  goto NextItem;
4949
0
                }
4950
0
              if (((Flags & FLAG_EXIF) != 0) && ((*ifds_handled & FLAG_EXIF) == 0))
4951
0
                {
4952
0
                  if (logging)
4953
0
                    (void)LogMagickEvent(CoderEvent,GetMagickModule(),"Recursing into EXIF IFD...");
4954
0
                  *ifds_handled |= FLAG_EXIF;
4955
4956
0
                  FieldCount += AddIFDExifFields(tiff, ifds_handled, profile_data, profile_data+Value,
4957
0
                                                 profile_length, logging, Flags|FLAG_BASE);
4958
0
                  if (logging)
4959
0
                    (void)LogMagickEvent(CoderEvent,GetMagickModule(),"Recursing out of EXIF IFD...");
4960
0
                }
4961
0
              goto NextItem;
4962
0
            }
4963
3.28k
          if (Tag == TIFFTAG_GPSIFD)
4964
342
            {
4965
342
              if (Value >= profile_length)
4966
108
                {
4967
108
                  if (logging)
4968
0
                    (void)LogMagickEvent(CoderEvent,GetMagickModule(),
4969
0
                                         "GPS IFD data length (%u) exceeds profile length (%zu)!",
4970
0
                                         (unsigned) Value, profile_length);
4971
108
                  goto NextItem;
4972
108
                }
4973
234
              if (((Flags & FLAG_GPS) != 0) && ((*ifds_handled & FLAG_GPS) == 0))
4974
29
                {
4975
29
                  if (logging)
4976
0
                    (void)LogMagickEvent(CoderEvent,GetMagickModule(),"Recursing into GPS IFD...");
4977
29
                  *ifds_handled |= FLAG_GPS;
4978
4979
29
                  FieldCount += AddIFDExifFields(tiff, ifds_handled, profile_data, profile_data+Value,
4980
29
                                                 profile_length, logging, Flags|FLAG_BASE);
4981
29
                  if (logging)
4982
0
                    (void)LogMagickEvent(CoderEvent,GetMagickModule(),"Recursing out of GPS IFD...");
4983
29
                }
4984
234
              goto NextItem;
4985
342
            }
4986
4987
2.94k
          if (fip != NULL && (Flags & FLAG_BASE)!=0)           /* libtiff doesn't understand these */
4988
20
            {
4989
20
              const TIFFDataType FDT = TIFFFieldDataType(fip);
4990
20
              const int WriteCount = TIFFFieldWriteCount(fip);
4991
20
              switch (Field)
4992
20
                {
4993
0
                case TIFF_ASCII:
4994
0
                  if (FDT != TIFF_ASCII)
4995
0
                    break;             /* Incompatible recipe.*/
4996
0
                  if (Long2 <= 4)
4997
0
                    {
4998
0
                      if (CheckAndStoreStr(tiff, Tag, (const char *) IFD_data+8, Long2))    /* The short string is inside Value. */
4999
0
                        FieldCount++;
5000
0
                    }
5001
0
                  else
5002
0
                    {
5003
0
                      if ((Value > (Value+Long2)) || (Value+Long2 >= profile_length-1))
5004
0
                        break;             /* String outside EXIF boundary. */
5005
0
                      if (CheckAndStoreStr(tiff, Tag, (const char *) profile_data+Value, Long2))
5006
0
                        FieldCount++;
5007
0
                    }
5008
0
                  break;
5009
5010
0
                case TIFF_SHORT:
5011
0
                  if (WriteCount!=1)
5012
0
                    {
5013
0
                      magick_uint16_t *Array;
5014
0
                      magick_uint32_t i;
5015
0
                      if (FDT != Field)
5016
0
                        break;                        /* Incompatible array type, might be converted in future. */
5017
0
                      if (WriteCount != TIFF_VARIABLE && WriteCount != TIFF_VARIABLE2)
5018
0
                        {
5019
0
                          if (logging && (Flags & FLAG_BASE) != 0)
5020
0
                            (void)LogMagickEvent(CoderEvent,GetMagickModule(),"%s fixed size arrays are not supported yet.",
5021
0
                                                 FipFieldTypeToStr((TIFFDataType) Field));
5022
0
                          break;                      /* Fixed size arrays not handled. */
5023
0
                        }
5024
0
                      if ((Value > (Value+2U*Long2)) || (Value+2U*Long2 >= profile_length-1))
5025
0
                        break;
5026
0
                      if (Long2 == 0)
5027
0
                        break;
5028
0
                      Array = MagickAllocateResourceLimitedMemory(magick_uint16_t *, 2*Long2);
5029
0
                      if (Array == NULL)
5030
0
                        break;
5031
0
                      for (i=0; i < Long2; i++)
5032
0
                        Array[i] = LD_UINT16(profile_data+Value+2*i);
5033
0
                      if (WriteCount == TIFF_VARIABLE)
5034
0
                        {
5035
0
                          if (TIFFSetField(tiff, Tag, (int)Long2, Array))     /* Argument 3 type int, argument 4 uint16_t*. */
5036
0
                            FieldCount++;
5037
0
                        } else if (WriteCount == TIFF_VARIABLE2)
5038
0
                        {
5039
0
                          if (TIFFSetField(tiff, Tag, Long2, Array))          /* Argument 3 type uint32_t, argument 4 uint16_t*.. */
5040
0
                            FieldCount++;
5041
0
                        }
5042
0
                      MagickFreeResourceLimitedMemory(magick_uint16_t *,Array);
5043
0
                      break;
5044
0
                    }
5045
0
                  goto Scalar;
5046
5047
0
                case TIFF_LONG:
5048
0
                  if (WriteCount != 1)
5049
0
                    {
5050
0
                      magick_uint32_t *Array;
5051
0
                      magick_uint32_t i;
5052
0
                      if (FDT != Field)
5053
0
                        break;                        /* Incompatible array type, might be converted in future. */
5054
0
                      if (WriteCount != TIFF_VARIABLE && WriteCount != TIFF_VARIABLE2)
5055
0
                        {
5056
0
                          if (logging && (Flags & FLAG_BASE) != 0)
5057
0
                            (void)LogMagickEvent(CoderEvent,GetMagickModule(),"%s fixed size arrays are not supported yet.",
5058
0
                                                 FipFieldTypeToStr((TIFFDataType) Field));
5059
0
                          break;                      /* Fixed size arrays not handled. */
5060
0
                        }
5061
0
                      if ((Value > (Value+4U*Long2)) || (Value+4U*Long2 >= profile_length-1))
5062
0
                        break;
5063
0
                      if (Long2==0)
5064
0
                        break;
5065
0
                      Array = MagickAllocateResourceLimitedMemory(magick_uint32_t *, 4*Long2);
5066
0
                      if (Array == NULL)
5067
0
                        break;
5068
0
                      for (i=0; i < Long2; i++)
5069
0
                        Array[i] = LD_UINT32(profile_data+Value+4*i);
5070
0
                      if (WriteCount == TIFF_VARIABLE)
5071
0
                        {
5072
0
                          if (TIFFSetField(tiff, Tag, (int)Long2, Array))     /* Argument 3 type int, argument 4 uint32_t*. */
5073
0
                            FieldCount++;
5074
0
                        } else if (WriteCount == TIFF_VARIABLE2)
5075
0
                        {
5076
0
                          if (TIFFSetField(tiff, Tag, Long2, Array))           /* Argument 3 type uint32_t, argument 4 uint32_t*. */
5077
0
                            FieldCount++;
5078
0
                        }
5079
0
                      MagickFreeResourceLimitedMemory(magick_uint32_t *,Array);
5080
0
                      break;
5081
0
                    }
5082
0
                  goto Scalar;
5083
5084
0
                case TIFF_BYTE:
5085
0
                  if (WriteCount != 1)
5086
0
                    {
5087
0
                      if (FDT != Field)
5088
0
                        break;                        /* Incompatible array type, might be converted in future. */
5089
0
                      if (WriteCount != TIFF_VARIABLE && WriteCount != TIFF_VARIABLE2)
5090
0
                        {
5091
0
                          if ((WriteCount <= 0) || (Long2 < (magick_uint32_t)WriteCount))
5092
0
                            break;            /* Too small amount of mandatory items. */
5093
0
                          if (Long2 < (magick_uint32_t)WriteCount)
5094
0
                            break;               /* Too small amount of mandatory items. */
5095
0
                          if (Long2 <= 4)
5096
0
                            {
5097
0
                              if (TIFFSetField(tiff, Tag, IFD_data+8))  /* Argument 3 uint8_t[4]. */
5098
0
                                FieldCount++;
5099
0
                            }
5100
0
                          else
5101
0
                            {
5102
0
                              if ((Value > (Value+Long2)) || (Value+Long2 >= profile_length-1))
5103
0
                                break;
5104
0
                              if (TIFFSetField(tiff, Tag, profile_data+Value))  /* Argument 3 uint8_t[4]. */
5105
0
                                FieldCount++;
5106
0
                            }
5107
0
                          break;                                     /* Fixed size arrays not handled. */
5108
0
                        }
5109
0
                      if ((Value > (Value+Long2)) || (Value+Long2 >= profile_length-1))
5110
0
                        break;
5111
                      /* No need to convert endianity for BYTES. */
5112
0
                      if (WriteCount == TIFF_VARIABLE)
5113
0
                        {
5114
0
                          if (TIFFSetField(tiff, Tag, (int)Long2, profile_data+Value)) /* Argument 3 type int, argument 4 uint8_t*. */
5115
0
                            FieldCount++;
5116
0
                        } else if (WriteCount == TIFF_VARIABLE2)
5117
0
                        {
5118
0
                          if (TIFFSetField(tiff, Tag, Long2, profile_data+Value))     /* Argument 3 type uint32_t, argument 4 uint8_t*. */
5119
0
                            FieldCount++;
5120
0
                        }
5121
0
                      break;
5122
0
                    }
5123
5124
0
                Scalar:
5125
0
                  if (FDT == TIFF_SHORT)
5126
0
                    {
5127
0
                      if (TIFFSetField(tiff, Tag, (unsigned)Value & 0xFFFF))
5128
0
                        FieldCount++;
5129
0
                    }
5130
0
                  if (FDT != TIFF_BYTE && FDT != TIFF_LONG)
5131
0
                    break;
5132
0
                  if (TIFFSetField(tiff, Tag, Value))
5133
0
                    FieldCount++;
5134
0
                  break;
5135
5136
0
                case TIFF_SRATIONAL:
5137
0
                  if (logging && (Flags & FLAG_BASE) != 0)
5138
0
                    (void)LogMagickEvent(CoderEvent,GetMagickModule(),"TIFF_SRATIONAL type is not supported yet.");
5139
0
                  break;
5140
19
                case TIFF_RATIONAL:
5141
19
                  if (FDT != TIFF_RATIONAL)
5142
0
                    break;
5143
19
                  if (WriteCount != 1)
5144
19
                    {
5145
19
                      if (WriteCount > 1)
5146
19
                        {
5147
19
                          if (Long2 < (magick_uint32_t)WriteCount)
5148
16
                            break;       /* Too small amount of mandatory items. */
5149
3
                          if ((Value > (Value+8*WriteCount)) || (Value+8*WriteCount >= profile_length-1))
5150
3
                            break;    /* Array falls over blob boundary. */
5151
0
#if TIFFLIB_VERSION >= 20230609
5152
0
                          {
5153
0
                            int i;
5154
0
                            switch (TIFFFieldSetGetSize(fip))
5155
0
                              {
5156
0
                              case 8:                /* double array is required in input. */
5157
0
                                {
5158
0
                                  double *ArrayD;
5159
0
                                  ArrayD = MagickAllocateResourceLimitedMemory(double *, sizeof(double)*WriteCount);
5160
0
                                  if (ArrayD == NULL)
5161
0
                                    break;
5162
0
                                  for (i=0; i < WriteCount; i++)
5163
0
                                    {
5164
0
                                      const magick_uint32_t val = LD_UINT32(profile_data+Value+4+8*i);
5165
0
                                      ArrayD[i] = (val==0) ? 0.0 : (LD_UINT32(profile_data+Value+8*i) / (double)val);
5166
0
                                    }
5167
0
                                  if (TIFFSetField(tiff, Tag, ArrayD))
5168
0
                                    FieldCount++;
5169
0
                                  MagickFreeResourceLimitedMemory(double *,ArrayD);
5170
0
                                }
5171
0
                                break;
5172
0
                              case 4:                /* float array is required in input. */
5173
0
                                {
5174
0
                                  float *ArrayF;
5175
0
                                  ArrayF = MagickAllocateResourceLimitedMemory(float *, sizeof(float)*WriteCount);
5176
0
                                  if (ArrayF==NULL)
5177
0
                                    break;
5178
0
                                  for (i=0; i < WriteCount; i++)
5179
0
                                    {
5180
0
                                      const magick_uint32_t val = LD_UINT32(profile_data+Value+4+8*i);
5181
0
                                      ArrayF[i] = (val==0) ? 0.0f : (LD_UINT32(profile_data+Value+8*i) / (float)val);
5182
0
                                    }
5183
0
                                  if (TIFFSetField(tiff, Tag, ArrayF))
5184
0
                                    FieldCount++;
5185
0
                                  MagickFreeResourceLimitedMemory(float *,ArrayF);
5186
0
                                }
5187
0
                                break;
5188
0
                              }
5189
0
                          }
5190
0
#endif
5191
0
                          break;
5192
0
                        }
5193
5194
0
                      if (WriteCount == TIFF_VARIABLE || WriteCount == TIFF_VARIABLE2)
5195
0
                        {
5196
0
                          if (logging && (Flags & FLAG_BASE) != 0)
5197
0
                            (void)LogMagickEvent(CoderEvent,GetMagickModule(),"Variable size fractional arrays are not supported yet.");
5198
0
                          break;
5199
0
                        }
5200
0
                      break;
5201
0
                    }
5202
0
                  else           /* Process as scalar. */
5203
0
                    {
5204
0
                      double d;
5205
0
                      if ((Value > (Value+8U)) || (Value+8U >= profile_length))
5206
0
                        break;
5207
0
                      d = LD_UINT32(profile_data+Value+4);
5208
0
                      if (d == 0)
5209
0
                        break;              /* Prevent division by 0. */
5210
0
                      d = LD_UINT32(profile_data+Value) / d;
5211
0
                      if (TIFFSetField(tiff, Tag, d))
5212
0
                        FieldCount++;
5213
0
                    }
5214
0
                  break;
5215
20
                }
5216
20
            }
5217
5218
3.86k
        NextItem:
5219
3.86k
          if (profile_length <= 12)
5220
0
            break;
5221
3.86k
          IFD_data += 12;
5222
3.86k
          EntryNum--;
5223
3.86k
        }
5224
5225
169
      if (profile_length < (size_t)(IFD_data-profile_data)+4)
5226
34
        break;
5227
135
      Value = LD_UINT32(IFD_data);
5228
135
      if (Value >= profile_length)
5229
95
        break;
5230
40
      IFD_data = profile_data+Value;
5231
      /*
5232
        It is possible for the calculated IFD_data to create a
5233
        non-terminal loop by computing the same IFD or one earlier in
5234
        IFD list.  Defend against this by placing a limit on loops, as
5235
        well as detecting the immediate looping case.
5236
      */
5237
40
      IFD_data_Loops++;
5238
40
      if (Orig_IFD_data == IFD_data)
5239
2
        {
5240
2
          (void)LogMagickEvent(CoderEvent,GetMagickModule(),
5241
2
                               "IFD direct loop detected!");
5242
2
          continue_looping = MagickFalse; /* Break looping */
5243
2
        }
5244
40
      if (IFD_data_Loops == Max_IFD_data_Loops)
5245
0
        continue_looping = MagickFalse;
5246
40
    } while ((continue_looping) && (Value > 8));
5247
5248
139
  if ((logging && (Flags & FLAG_BASE) != 0) && (!continue_looping))
5249
0
    (void)LogMagickEvent(CoderEvent,GetMagickModule(),
5250
0
                         "IFD looping detected (%zu loops)!", IFD_data_Loops);
5251
5252
139
  return FieldCount;
5253
242
}
5254
5255
5256
static int AddExifFields(TIFF *tiff, const unsigned char *profile_data,
5257
                         size_t profile_length, MagickBool logging,
5258
                         magick_uint16_t Flags)
5259
231
{
5260
231
  const char EXIF[6]
5261
231
    = {'E','x','i','f',0,0};
5262
5263
231
  unsigned int
5264
231
    ifds_handled = 0;
5265
5266
231
  size_t
5267
231
    profile_data_len;
5268
5269
231
  if (profile_data==NULL || profile_length < 12+8)
5270
3
    return 0;
5271
5272
228
  if (memcmp(EXIF,profile_data,6)==0)
5273
225
    {
5274
225
      profile_data += 6;
5275
225
      profile_length -= 6;
5276
225
      if (profile_length < 12+8)
5277
3
        return 0;
5278
225
    }
5279
5280
225
  if (profile_data[0] != profile_data[1])
5281
9
    return 0;
5282
5283
216
  profile_data_len = (size_t)((profile_data[0]=='M') ?
5284
177
                              LD_UINT32_HI(profile_data+4) :
5285
216
                              LD_UINT32_LO(profile_data+4));
5286
216
  if (logging)
5287
0
    (void)LogMagickEvent(CoderEvent,GetMagickModule(),
5288
0
                         "Profile data length %zu", profile_data_len);
5289
5290
216
  return AddIFDExifFields(tiff, &ifds_handled, profile_data,
5291
216
                          profile_data + profile_data_len,
5292
216
                          profile_length-2, logging, Flags);
5293
225
}
5294
5295
#endif /* if TIFFLIB_VERSION >= 20120922 */
5296
#endif /* if EXPERIMENTAL_EXIF_TAGS */
5297
5298
/*
5299
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5300
%                                                                             %
5301
%                                                                             %
5302
%                                                                             %
5303
%   W r i t e T I F F I m a g e                                               %
5304
%                                                                             %
5305
%                                                                             %
5306
%                                                                             %
5307
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5308
%
5309
%  Method WriteTIFFImage writes an image in the Tagged image file format.
5310
%
5311
%  The format of the WriteTIFFImage method is:
5312
%
5313
%      MagickPassFail WriteTIFFImage(const ImageInfo *image_info,Image *image)
5314
%
5315
%  A description of each parameter follows:
5316
%
5317
%    o status:  Method WriteTIFFImage return True if the image is written.
5318
%      False is returned is there is of a memory shortage or if the image
5319
%      file cannot be opened for writing.
5320
%
5321
%    o image_info: Specifies a pointer to a ImageInfo structure.
5322
%
5323
%    o image:  A pointer to an Image structure.
5324
%
5325
%
5326
*/
5327
5328
static void
5329
WriteNewsProfile(TIFF *tiff,
5330
                 int profile_tag,
5331
                 const unsigned char *profile_data,
5332
                 const size_t profile_length)
5333
370
{
5334
370
  unsigned char
5335
370
    *profile=0;
5336
5337
370
  size_t
5338
370
    length;
5339
5340
370
  assert(tiff != (TIFF *) NULL);
5341
370
  assert(profile_tag != 0);
5342
370
  assert(profile_data != (const unsigned char *) NULL);
5343
5344
370
  length = (uint32) profile_length;
5345
370
  if (length == 0)
5346
0
    return;
5347
5348
370
  if (profile_tag == TIFFTAG_RICHTIFFIPTC)
5349
0
    {
5350
      /*
5351
        Handle TIFFTAG_RICHTIFFIPTC tag.
5352
      */
5353
0
      length += (4-(length & 0x03)); /* Round up for long word alignment */
5354
0
      profile=MagickAllocateResourceLimitedClearedMemory(unsigned char *,length);
5355
0
      if (profile == (unsigned char *) NULL)
5356
0
        return;
5357
0
      (void) memcpy(profile,profile_data,profile_length);
5358
5359
0
      if (TIFFIsByteSwapped(tiff))
5360
0
        TIFFSwabArrayOfLong((uint32 *) profile,length/4);
5361
5362
      /* Tag is type TIFF_LONG so byte length is divided by four */
5363
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5364
0
                            "TIFFSetField(tiff=0x%p,tag=%d,"
5365
0
                            "length=%" MAGICK_SIZE_T_F "u,data=0x%p)",
5366
0
                            tiff,profile_tag,(MAGICK_SIZE_T) length/4,profile);
5367
0
      (void) TIFFSetField(tiff,profile_tag,(uint32) length/4,(void *) profile);
5368
0
    }
5369
370
  else if (profile_tag == TIFFTAG_PHOTOSHOP)
5370
370
    {
5371
      /*
5372
        Handle TIFFTAG_PHOTOSHOP tag.
5373
      */
5374
370
      length += (length & 0x01); /* Round up for Photoshop */
5375
#if defined(GET_ONLY_IPTC_DATA)
5376
      length += 12;              /* Space for 8BIM header */
5377
      profile=MagickAllocateResourceLimitedClearedMemory(unsigned char *,length);
5378
      if (profile == (unsigned char *) NULL)
5379
        return;
5380
      (void) memcpy(profile,"8BIM\04\04\0\0",8);
5381
      profile[8]=(length >> 24) & 0xff;
5382
      profile[9]=(length >> 16) & 0xff;
5383
      profile[10]=(length >> 8) & 0xff;
5384
      profile[11]=length & 0xff;
5385
      (void) memcpy(profile+12,profile_data,profile_length);
5386
#else
5387
370
      profile=MagickAllocateResourceLimitedClearedMemory(unsigned char *,length);
5388
370
      if (profile == (unsigned char *) NULL)
5389
0
        return;
5390
370
      (void) memcpy(profile,profile_data,profile_length);
5391
370
#endif
5392
370
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5393
370
                            "TIFFSetField(tiff=0x%p,tag=%d,"
5394
370
                            "length=%" MAGICK_SIZE_T_F "u,data=0x%p)",
5395
370
                            tiff,profile_tag,(MAGICK_SIZE_T) length,profile);
5396
370
      (void) TIFFSetField(tiff,profile_tag,(uint32) length,(void *) profile);
5397
370
    }
5398
5399
370
  MagickFreeResourceLimitedMemory(unsigned char *,profile);
5400
370
}
5401
5402
0
#define ThrowTIFFWriterException(code_,reason_,image_) \
5403
0
{ \
5404
0
  if (tiff != (TIFF *) NULL)                  \
5405
0
    TIFFClose(tiff);                          \
5406
0
  ThrowWriterException(code_,reason_,image_); \
5407
0
}
5408
5409
static MagickPassFail
5410
WriteTIFFImage(const ImageInfo *image_info,Image *image)
5411
27.4k
{
5412
27.4k
  char
5413
27.4k
    filename[MaxTextExtent],
5414
27.4k
    open_flags[MaxTextExtent];
5415
5416
27.4k
  const ImageAttribute
5417
27.4k
    *attribute;
5418
5419
27.4k
  unsigned int
5420
27.4k
    x,
5421
27.4k
    y;
5422
5423
27.4k
  register unsigned int
5424
27.4k
    i;
5425
5426
27.4k
  TIFF
5427
27.4k
    *tiff = (TIFF *) NULL;
5428
5429
27.4k
  size_t
5430
27.4k
    bytes_per_strip_target = TIFF_BYTES_PER_STRIP;
5431
5432
27.4k
  uint16
5433
27.4k
    bits_per_sample,
5434
27.4k
    compress_tag,
5435
27.4k
    fill_order,
5436
27.4k
    photometric,
5437
27.4k
    planar_config,
5438
27.4k
    predictor,
5439
27.4k
    sample_format,
5440
27.4k
    samples_per_pixel;
5441
5442
27.4k
  uint32
5443
27.4k
    rows_per_strip;
5444
5445
27.4k
  tsize_t
5446
27.4k
    scanline_size;
5447
5448
27.4k
  AlphaType
5449
27.4k
    alpha_type;
5450
5451
27.4k
  CompressionType
5452
27.4k
    compression=UndefinedCompression;
5453
5454
27.4k
  TIFFMethod
5455
27.4k
    method;
5456
5457
27.4k
  Magick_TIFF_ClientData
5458
27.4k
    client_data;
5459
5460
27.4k
  ExportPixelAreaOptions
5461
27.4k
    export_options;
5462
5463
27.4k
  ExportPixelAreaInfo
5464
27.4k
    export_info;
5465
5466
27.4k
  MagickBool
5467
27.4k
    logging=MagickFalse;
5468
5469
27.4k
  MagickPassFail
5470
27.4k
    status;
5471
5472
27.4k
  unsigned long
5473
27.4k
    depth,
5474
27.4k
    scene;
5475
5476
27.4k
  size_t
5477
27.4k
    image_list_length;
5478
5479
5480
5481
  /*
5482
    Open TIFF file.
5483
  */
5484
27.4k
  assert(image_info != (const ImageInfo *) NULL);
5485
27.4k
  assert(image_info->signature == MagickSignature);
5486
27.4k
  assert(image != (Image *) NULL);
5487
27.4k
  assert(image->signature == MagickSignature);
5488
27.4k
  image_list_length=GetImageListLength(image);
5489
27.4k
  logging=IsEventLogged(CoderEvent);
5490
27.4k
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
5491
27.4k
  if (status == MagickFail)
5492
27.4k
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
5493
27.4k
  (void) MagickTsdSetSpecific(tsd_key,(void *) (&image->exception));
5494
27.4k
  (void) TIFFSetErrorHandler((TIFFErrorHandler) TIFFWriteErrorsHandler);
5495
27.4k
  (void) TIFFSetWarningHandler((TIFFErrorHandler) (CheckThrowWarnings(image_info) ?
5496
0
                                                   TIFFWarningsThrowException :
5497
27.4k
                                                   TIFFWarningsLogOnly));
5498
27.4k
  (void) strlcpy(filename,image->filename,MaxTextExtent);
5499
  /*
5500
    Open TIFF file
5501
5502
    'w'  open for write
5503
    'l'  force little-endian byte order
5504
    'b'  force big-endian byte order
5505
    'L'  force LSB to MSB bit order (weird)
5506
    'B'  force MSB to LSB bit order (normal)
5507
    '8'  64-bit offsets (BigTIFF)
5508
  */
5509
27.4k
  (void) strlcpy(open_flags, "w", sizeof(open_flags));
5510
27.4k
  switch (image_info->endian)
5511
27.4k
    {
5512
0
    case LSBEndian:
5513
0
      (void) strlcat(open_flags, "l", sizeof(open_flags));
5514
0
      if (logging)
5515
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5516
0
                              "Using little endian byte order");
5517
0
      break;
5518
0
    case MSBEndian:
5519
0
      (void) strlcat(open_flags, "b", sizeof(open_flags));
5520
0
      if (logging)
5521
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5522
0
                              "Using big endian byte order");
5523
0
      break;
5524
0
    default:
5525
27.4k
    case UndefinedEndian:
5526
27.4k
      {
5527
        /* Default is native byte order */
5528
27.4k
        if (logging)
5529
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5530
0
                                "Using native endian byte order");
5531
27.4k
      }
5532
27.4k
    }
5533
5534
27.4k
#if defined(HasBigTIFF)
5535
27.4k
  if (strcmp(image_info->magick,"BIGTIFF") == 0)
5536
8.07k
    {
5537
8.07k
      (void) strlcat(open_flags, "8", sizeof(open_flags));
5538
8.07k
      if (logging)
5539
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5540
0
                              "Using 64-bit offsets (BigTIFF format)");
5541
8.07k
    }
5542
27.4k
#endif
5543
5544
27.4k
  if (logging)
5545
0
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5546
0
                          "Opening TIFF file \"%s\" using open flags \"%s\".",
5547
0
                          filename,open_flags);
5548
27.4k
  client_data.image=image;
5549
27.4k
  client_data.image_info=image_info;
5550
27.4k
#if defined(HAVE_TIFFERROREXTR)
5551
27.4k
  {
5552
27.4k
    TIFFOpenOptions *open_options = TIFFOpenOptionsAlloc();
5553
27.4k
    TIFFOpenOptionsSetErrorHandlerExtR(open_options, TIFFWriteErrorsHandlerExtR, (void *) &image->exception);
5554
27.4k
    TIFFOpenOptionsSetWarningHandlerExtR(open_options, TIFFWriteErrorsHandlerExtR, (void *) &image->exception); /* FIXME */
5555
27.4k
    tiff=TIFFClientOpenExt(filename,open_flags,(thandle_t) &client_data,
5556
27.4k
                           TIFFReadBlob,TIFFWriteBlob,TIFFSeekBlob,
5557
27.4k
                           TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
5558
27.4k
                           TIFFUnmapBlob,
5559
27.4k
                           open_options);
5560
27.4k
    TIFFOpenOptionsFree(open_options);
5561
27.4k
  }
5562
#else
5563
  {
5564
    tiff=TIFFClientOpen(filename,open_flags,(thandle_t) &client_data,
5565
                        TIFFReadBlob,TIFFWriteBlob,TIFFSeekBlob,
5566
                        TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
5567
                        TIFFUnmapBlob);
5568
  }
5569
#endif /* if defined(HAVE_TIFFERROREXTR) */
5570
27.4k
  if (tiff == (TIFF *) NULL)
5571
0
    {
5572
0
      if (GetBlobIsOpen(image))
5573
0
        CloseBlob(image);
5574
0
      return(MagickFail);
5575
0
    }
5576
27.4k
  scene=0;
5577
27.4k
  do
5578
34.3k
    {
5579
34.3k
      ImageCharacteristics
5580
34.3k
        characteristics;
5581
5582
34.3k
      if ((image->columns == 0) || (image->rows == 0) || !GetPixelCachePresent(image))
5583
0
        {
5584
0
          if (logging)
5585
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5586
0
                                  "Image columns=%lu, rows=%lu, pixel-cache=%s",
5587
0
                                  image->columns, image->rows,
5588
0
                                  GetPixelCachePresent(image) ? "Present" : "Missing!");
5589
0
          ThrowException(&(image->exception),CoderError,ImageColumnOrRowSizeIsNotSupported,image->filename);
5590
0
          break;
5591
0
        }
5592
5593
      /*
5594
        Initialize TIFF fields.
5595
      */
5596
34.3k
      (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,
5597
34.3k
                                   &samples_per_pixel);
5598
34.3k
      (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
5599
34.3k
                                   &bits_per_sample);
5600
34.3k
      (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLEFORMAT,&sample_format);
5601
34.3k
      (void) TIFFSetField(tiff,TIFFTAG_IMAGELENGTH,(uint32) image->rows);
5602
34.3k
      (void) TIFFSetField(tiff,TIFFTAG_IMAGEWIDTH,(uint32) image->columns);
5603
5604
34.3k
      ExportPixelAreaOptionsInit(&export_options);
5605
34.3k
      depth=image->depth;
5606
34.3k
      bits_per_sample=8;
5607
34.3k
      predictor=0U;
5608
34.3k
      method=ScanLineMethod;
5609
34.3k
      if ((AccessDefinition(image_info,"tiff","tile")) ||
5610
34.3k
          (AccessDefinition(image_info,"tiff","tile-geometry")) ||
5611
34.3k
          (AccessDefinition(image_info,"tiff","tile-width")) ||
5612
34.3k
          (AccessDefinition(image_info,"tiff","tile-height")))
5613
0
        method=TiledMethod;
5614
5615
      /*
5616
        Decide how to compress the image.
5617
      */
5618
34.3k
      compression=image->compression;
5619
34.3k
      if (image_info->compression != UndefinedCompression)
5620
1.67k
        compression=image_info->compression;
5621
34.3k
      if (UndefinedCompression == compression)
5622
2.78k
        compression=NoCompression;
5623
5624
      /*
5625
        Ensure that only supported compression types are requested.
5626
      */
5627
34.3k
      {
5628
34.3k
        char
5629
34.3k
          compression_name[MaxTextExtent];
5630
5631
34.3k
        if (CompressionSupported(compression,compression_name,sizeof(compression_name)) != MagickTrue)
5632
0
          {
5633
0
            compression=NoCompression;
5634
0
            if (logging)
5635
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5636
0
                                    "%s compression not supported.  "
5637
0
                                    "Compression request removed",
5638
0
                                    compression_name);
5639
0
          }
5640
34.3k
      }
5641
5642
      /*
5643
        Determine libtiff compression settings.
5644
      */
5645
34.3k
      compress_tag=COMPRESSION_NONE;
5646
34.3k
      fill_order=FILLORDER_MSB2LSB;
5647
34.3k
      switch (compression)
5648
34.3k
        {
5649
          /*
5650
            Note that RFC 2301 recommends using LSB2MSB fill order for FAX
5651
            since it is the transmission order used on the wire for FAX.
5652
            However, it also states that all conforming readers should be
5653
            able to read data in both bit orders.
5654
          */
5655
1.58k
        case FaxCompression:
5656
1.58k
          {
5657
1.58k
            compress_tag=COMPRESSION_CCITTFAX3;
5658
1.58k
            fill_order=FILLORDER_LSB2MSB;
5659
1.58k
            break;
5660
0
          }
5661
4.95k
        case Group4Compression:
5662
4.95k
          {
5663
4.95k
            compress_tag=COMPRESSION_CCITTFAX4;
5664
4.95k
            fill_order=FILLORDER_LSB2MSB;
5665
4.95k
            break;
5666
0
          }
5667
0
#if defined(COMPRESSION_JBIG)
5668
0
        case JBIG1Compression:
5669
0
          {
5670
0
            compress_tag=COMPRESSION_JBIG;
5671
0
            fill_order=FILLORDER_LSB2MSB;
5672
0
            break;
5673
0
          }
5674
0
#endif /* defined(COMPRESSION_JBIG) */
5675
8.15k
        case JPEGCompression:
5676
8.15k
          {
5677
8.15k
            compress_tag=COMPRESSION_JPEG;
5678
8.15k
            break;
5679
0
          }
5680
750
        case LZWCompression:
5681
750
          {
5682
750
            compress_tag=COMPRESSION_LZW;
5683
750
            break;
5684
0
          }
5685
0
#if defined(COMPRESSION_LZMA)
5686
0
        case LZMACompression:
5687
0
          {
5688
0
            compress_tag=COMPRESSION_LZMA;
5689
0
            break;
5690
0
          }
5691
0
#endif /* defined(COMPRESSION_LZMA) */
5692
0
        case RLECompression:
5693
0
          {
5694
0
            compress_tag=COMPRESSION_PACKBITS;
5695
0
            break;
5696
0
          }
5697
3.52k
        case ZipCompression:
5698
3.52k
          {
5699
3.52k
            compress_tag=COMPRESSION_ADOBE_DEFLATE;
5700
3.52k
            break;
5701
0
          }
5702
0
#if defined(COMPRESSION_ZSTD)
5703
2.42k
        case ZSTDCompression:
5704
2.42k
          {
5705
2.42k
            compress_tag=COMPRESSION_ZSTD;
5706
2.42k
            break;
5707
0
          }
5708
0
#endif /* defined(COMPRESSION_ZSTD) */
5709
0
#if defined(COMPRESSION_WEBP)
5710
3.12k
        case WebPCompression:
5711
3.12k
          {
5712
3.12k
            compress_tag=COMPRESSION_WEBP;
5713
3.12k
            break;
5714
0
          }
5715
0
#endif /* defined(COMPRESSION_WEBP) */
5716
0
#if defined(COMPRESSION_LERC)
5717
0
        case LERCCompression:
5718
0
          {
5719
0
            compress_tag=COMPRESSION_LERC;
5720
0
            break;
5721
0
          }
5722
0
#endif /* defined(COMPRESSION_LERC) */
5723
9.85k
        default:
5724
9.85k
          {
5725
9.85k
            compress_tag=COMPRESSION_NONE;
5726
9.85k
            break;
5727
0
          }
5728
34.3k
        }
5729
5730
      /*
5731
        Ensure that image is in desired output space
5732
      */
5733
34.3k
      if ((image_info->type != UndefinedType) &&
5734
1.67k
          (image_info->type != OptimizeType))
5735
1.67k
        {
5736
1.67k
          if (SetImageType(image,image_info->type) == MagickFail)
5737
0
            {
5738
0
              ThrowException(&image->exception,CoderError,UnableToSetImageType,
5739
0
                             image->filename);
5740
0
              status=MagickFail;
5741
0
              break;
5742
0
            }
5743
1.67k
        }
5744
32.7k
      else if (!IsCMYKColorspace(image->colorspace) &&
5745
29.9k
               (!IsRGBColorspace(image->colorspace)))
5746
3.01k
        {
5747
3.01k
          if (TransformColorspace(image,RGBColorspace) == MagickFail)
5748
0
            {
5749
0
              ThrowException(&image->exception,CoderError,UnableToTransformColorspace,
5750
0
                             image->filename);
5751
0
              status=MagickFail;
5752
0
              break;
5753
0
            }
5754
3.01k
        }
5755
5756
      /*
5757
        Analyze image to be written.
5758
      */
5759
34.3k
      if (!GetImageCharacteristics(image,&characteristics,
5760
34.3k
                                   (OptimizeType == image_info->type),
5761
34.3k
                                   &image->exception))
5762
0
        {
5763
0
          ThrowException(&image->exception,CoderError,UnableToGetImageCharacteristics,
5764
0
                         image->filename);
5765
0
          status=MagickFail;
5766
0
          break;
5767
0
        }
5768
5769
34.3k
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5770
34.3k
                            "Image characteristics: cmyk=%c, gray=%c, mono=%c,"
5771
34.3k
                            " opaque=%c, palette=%c",
5772
34.3k
                            (characteristics.cmyk ? 'y' : 'n'),
5773
34.3k
                            (characteristics.grayscale ? 'y' : 'n'),
5774
34.3k
                            (characteristics.monochrome ? 'y' : 'n'),
5775
34.3k
                            (characteristics.opaque ? 'y' : 'n'),
5776
34.3k
                            (characteristics.palette ? 'y' : 'n'));
5777
5778
5779
      /*
5780
        Some compression types do not work with a matte channel.
5781
        Disable matte channel for these types.
5782
      */
5783
34.3k
      if (image->matte)
5784
5.23k
        {
5785
5.23k
          switch (compress_tag)
5786
5.23k
            {
5787
4
            case COMPRESSION_CCITTFAX3:
5788
16
            case COMPRESSION_CCITTFAX4:
5789
16
            case COMPRESSION_JBIG:
5790
74
            case COMPRESSION_JPEG:
5791
74
              {
5792
74
                if (logging)
5793
0
                  {
5794
0
                    const char *
5795
0
                      compress_type;
5796
5797
0
                    compress_type=CompressionTagToString(compress_tag);
5798
0
                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5799
0
                                          "Disabled image matte channel since "
5800
0
                                          "%s compression not supported with "
5801
0
                                          "alpha channel.",
5802
0
                                          compress_type);
5803
0
                  }
5804
74
                image->matte=MagickFalse;
5805
74
                break;
5806
16
              }
5807
5.16k
            default:
5808
5.16k
              {
5809
5.16k
              }
5810
5.23k
            }
5811
5.23k
        }
5812
5813
      /*
5814
        Choose best photometric based on image properties.
5815
      */
5816
34.3k
      if (characteristics.cmyk)
5817
2.74k
        {
5818
2.74k
          photometric=PHOTOMETRIC_SEPARATED;
5819
2.74k
        }
5820
31.6k
      else if (characteristics.monochrome)
5821
6.53k
        {
5822
6.53k
          photometric=PHOTOMETRIC_MINISWHITE;
5823
6.53k
          depth=1;
5824
6.53k
        }
5825
25.1k
      else if (characteristics.palette)
5826
1.27k
        {
5827
1.27k
          photometric=PHOTOMETRIC_PALETTE;
5828
1.27k
        }
5829
23.8k
      else if (characteristics.grayscale)
5830
12.3k
        {
5831
12.3k
          photometric=PHOTOMETRIC_MINISBLACK;
5832
12.3k
        }
5833
11.4k
      else
5834
11.4k
        {
5835
11.4k
          photometric=PHOTOMETRIC_RGB;
5836
11.4k
        }
5837
5838
      /*
5839
        If optimization is requested, disable matte channel if image
5840
        is opaque.
5841
      */
5842
34.3k
      if ((OptimizeType == image_info->type) &&
5843
0
          (characteristics.opaque && image->matte))
5844
0
        {
5845
0
          image->matte=MagickFalse;
5846
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5847
0
                                "Disabled image matte channel since image is "
5848
0
                                "opaque.");
5849
0
        }
5850
5851
      /*
5852
        Currently we only support JPEG compression with MINISWHITE,
5853
        MINISBLACK, and RGB.  FAX compression types require
5854
        MINISWHITE.  CMYK takes precedence over JPEG compression.
5855
      */
5856
34.3k
      if ((compress_tag == COMPRESSION_JPEG) &&
5857
8.15k
          (photometric == PHOTOMETRIC_PALETTE))
5858
3
        {
5859
3
          photometric=PHOTOMETRIC_RGB;
5860
3
          if (logging)
5861
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5862
0
                                  "Using RGB photometric due to request for"
5863
0
                                  " JPEG compression.");
5864
3
        }
5865
34.3k
      else if (compress_tag == COMPRESSION_CCITTFAX3)
5866
1.58k
        {
5867
1.58k
          photometric=PHOTOMETRIC_MINISWHITE;
5868
1.58k
          depth=1;
5869
1.58k
          if (logging)
5870
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5871
0
                                  "Using MINISWHITE photometric due to request"
5872
0
                                  " for Group3 FAX compression.");
5873
1.58k
        }
5874
32.7k
      else if (compress_tag == COMPRESSION_CCITTFAX4)
5875
4.95k
        {
5876
4.95k
          photometric=PHOTOMETRIC_MINISWHITE;
5877
4.95k
          depth=1;
5878
4.95k
          if (logging)
5879
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5880
0
                                  "Using MINISWHITE photometric due to request"
5881
0
                                  " for Group4 FAX compression.");
5882
4.95k
        }
5883
27.8k
#if defined(COMPRESSION_JBIG)
5884
27.8k
      else if (compress_tag == COMPRESSION_JBIG)
5885
0
        {
5886
0
          photometric=PHOTOMETRIC_MINISWHITE;
5887
0
          depth=1;
5888
0
          if (logging)
5889
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5890
0
                                  "Using MINISWHITE photometric due to request"
5891
0
                                  " for JBIG compression.");
5892
0
        }
5893
27.8k
#endif /* defined(COMPRESSION_JBIG) */
5894
27.8k
#if defined(COMPRESSION_WEBP)
5895
27.8k
      else if (compress_tag == COMPRESSION_WEBP)
5896
3.12k
        {
5897
3.12k
          photometric=PHOTOMETRIC_RGB;
5898
3.12k
          if (logging)
5899
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
5900
0
                                  "Using RGB photometric due to request for"
5901
0
                                  " WebP compression.");
5902
3.12k
        }
5903
34.3k
#endif /* defined(COMPRESSION_WEBP) */
5904
5905
      /*
5906
        Allow user to override the photometric.
5907
      */
5908
34.3k
      switch (image_info->type)
5909
34.3k
        {
5910
1.67k
        case BilevelType:
5911
1.67k
          {
5912
1.67k
            photometric=PHOTOMETRIC_MINISWHITE;
5913
1.67k
            depth=1;
5914
1.67k
            break;
5915
0
          }
5916
0
        case GrayscaleType:
5917
0
          {
5918
0
            photometric=PHOTOMETRIC_MINISBLACK;
5919
0
            break;
5920
0
          }
5921
0
        case GrayscaleMatteType:
5922
0
          {
5923
0
            photometric=PHOTOMETRIC_MINISBLACK;
5924
0
            if (!image->matte)
5925
0
              SetImageOpacity(image,OpaqueOpacity);
5926
0
            break;
5927
0
          }
5928
0
        case PaletteType:
5929
0
          {
5930
0
            photometric=PHOTOMETRIC_PALETTE;
5931
0
            break;
5932
0
          }
5933
0
        case PaletteMatteType:
5934
0
          {
5935
0
            photometric=PHOTOMETRIC_PALETTE;
5936
0
            if (!image->matte)
5937
0
              SetImageOpacity(image,OpaqueOpacity);
5938
0
            break;
5939
0
          }
5940
0
        case TrueColorType:
5941
0
          {
5942
0
            photometric=PHOTOMETRIC_RGB;
5943
0
            break;
5944
0
          }
5945
0
        case TrueColorMatteType:
5946
0
          {
5947
0
            photometric=PHOTOMETRIC_RGB;
5948
0
            if (!image->matte)
5949
0
              SetImageOpacity(image,OpaqueOpacity);
5950
0
            break;
5951
0
          }
5952
0
        case ColorSeparationType:
5953
0
          {
5954
0
            photometric=PHOTOMETRIC_SEPARATED;
5955
0
            break;
5956
0
          }
5957
0
        case ColorSeparationMatteType:
5958
0
          {
5959
0
            photometric=PHOTOMETRIC_SEPARATED;
5960
0
            if (!image->matte)
5961
0
              SetImageOpacity(image,OpaqueOpacity);
5962
0
            break;
5963
0
          }
5964
32.7k
        case UndefinedType:
5965
32.7k
        case OptimizeType:
5966
32.7k
          {
5967
            /* No special handling */
5968
32.7k
          }
5969
34.3k
        }
5970
5971
      /*
5972
        Allow the user to over-ride the photometric for bilevel and
5973
        gray images since 'type' is insufficient for this.
5974
      */
5975
34.3k
      if ((PHOTOMETRIC_MINISWHITE == photometric) ||
5976
25.5k
          (PHOTOMETRIC_MINISBLACK == photometric))
5977
18.9k
      {
5978
18.9k
        const char *
5979
18.9k
          value;
5980
5981
        /*
5982
          Photometric
5983
        */
5984
18.9k
        value=AccessDefinition(image_info,"tiff","photometric");
5985
18.9k
        if (value)
5986
0
          {
5987
0
            if (LocaleCompare(value,"miniswhite") == 0)
5988
0
              photometric=PHOTOMETRIC_MINISWHITE;
5989
0
            else if (LocaleCompare(value,"minisblack") == 0)
5990
0
              photometric=PHOTOMETRIC_MINISBLACK;
5991
0
          }
5992
18.9k
      }
5993
5994
      /*
5995
        If the user has selected something other than MINISWHITE,
5996
        MINISBLACK, or RGB, then remove JPEG compression.  Also remove
5997
        fax compression if photometric is not compatible.
5998
      */
5999
34.3k
      if ((compress_tag == COMPRESSION_JPEG) &&
6000
8.15k
          ((photometric != PHOTOMETRIC_MINISWHITE) &&
6001
8.15k
           (photometric != PHOTOMETRIC_MINISBLACK) &&
6002
1.62k
           (photometric != PHOTOMETRIC_RGB) &&
6003
25
           (photometric != PHOTOMETRIC_YCBCR)))
6004
25
        {
6005
25
          compress_tag=COMPRESSION_NONE;
6006
25
          if (logging)
6007
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6008
0
                                  "Ignoring request for JPEG compression due "
6009
0
                                  "to incompatible photometric.");
6010
25
        }
6011
34.3k
      else if (((compress_tag == COMPRESSION_CCITTFAX3) ||
6012
32.7k
                (compress_tag == COMPRESSION_CCITTFAX4)) &&
6013
6.54k
               ((photometric != PHOTOMETRIC_MINISWHITE) &&
6014
0
                (photometric != PHOTOMETRIC_MINISBLACK)))
6015
0
        {
6016
0
          compress_tag=COMPRESSION_NONE;
6017
0
          fill_order=FILLORDER_MSB2LSB;
6018
0
          if (logging)
6019
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6020
0
                                  "Ignoring request for FAX compression"
6021
0
                                  " due to incompatible photometric.");
6022
0
        }
6023
34.3k
#if defined(COMPRESSION_JBIG)
6024
34.3k
      else if ((compress_tag == COMPRESSION_JBIG) &&
6025
0
               (photometric != PHOTOMETRIC_MINISWHITE))
6026
0
        {
6027
0
          compress_tag=COMPRESSION_NONE;
6028
0
          fill_order=FILLORDER_MSB2LSB;
6029
0
          if (logging)
6030
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6031
0
                                  "Ignoring request for JBIG compression"
6032
0
                                  " due to incompatible photometric.");
6033
0
        }
6034
34.3k
#endif /* defined(COMPRESSION_JBIG) */
6035
6036
      /*
6037
        Support writing bits per sample of 8, 16, & 32 by default.
6038
      */
6039
46.7k
      for (bits_per_sample=8; bits_per_sample < depth; )
6040
12.3k
        bits_per_sample*=2;
6041
6042
      /*
6043
        Now choose appropriate settings for the photometric.
6044
      */
6045
34.3k
      switch (photometric)
6046
34.3k
        {
6047
8.84k
        case PHOTOMETRIC_MINISWHITE:
6048
18.9k
        case PHOTOMETRIC_MINISBLACK:
6049
18.9k
          {
6050
18.9k
            samples_per_pixel=1;
6051
18.9k
            if (depth == 1)
6052
9.29k
              bits_per_sample=1;
6053
18.9k
            break;
6054
8.84k
          }
6055
11.4k
        case PHOTOMETRIC_RGB:
6056
11.4k
          {
6057
11.4k
            samples_per_pixel=3;
6058
11.4k
            break;
6059
8.84k
          }
6060
1.26k
        case PHOTOMETRIC_PALETTE:
6061
1.26k
          {
6062
1.26k
            samples_per_pixel=1;
6063
1.26k
            bits_per_sample=1;
6064
            /*
6065
              Support colormap indexes of 1, 2, 4, 8, and 16 by default.
6066
            */
6067
3.39k
            while ((1UL << bits_per_sample) < image->colors)
6068
2.12k
              bits_per_sample*=2;
6069
1.26k
            break;
6070
8.84k
          }
6071
2.74k
        case PHOTOMETRIC_SEPARATED:
6072
2.74k
          {
6073
2.74k
            samples_per_pixel=4; /* CMYK */
6074
6075
2.74k
            (void) TIFFSetField(tiff,TIFFTAG_INKSET,INKSET_CMYK);
6076
2.74k
            if (logging)
6077
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6078
0
                                    "Using INKSET_CMYK");
6079
2.74k
            break;
6080
8.84k
          }
6081
0
        case PHOTOMETRIC_YCBCR:
6082
0
          {
6083
            /* This is here to support JPEGCOLORMODE_RGB*/
6084
0
            samples_per_pixel=3;
6085
0
            break;
6086
8.84k
          }
6087
34.3k
        }
6088
6089
34.3k
      if (COMPRESSION_JPEG == compress_tag)
6090
8.13k
        {
6091
          /*
6092
            JPEG compression can only use size specified by
6093
            BITS_IN_JSAMPLE (except for MK1 JPEG) which supports two
6094
            sizes.
6095
6096
            Maybe there is a tricky way to obtain this value from
6097
            libtiff or libtiff can be extended?
6098
6099
            FIXME
6100
          */
6101
8.13k
#if defined(BITS_IN_JSAMPLE)
6102
8.13k
          depth=BITS_IN_JSAMPLE;
6103
8.13k
          bits_per_sample=BITS_IN_JSAMPLE;
6104
#else
6105
          depth=8;
6106
          bits_per_sample=8;
6107
#endif
6108
8.13k
        }
6109
6110
34.3k
#if defined(COMPRESSION_WEBP)
6111
34.3k
      if (COMPRESSION_WEBP == compress_tag)
6112
3.12k
        {
6113
          /*
6114
            WebP compression only supports a depth of 8.
6115
          */
6116
3.12k
          depth=8;
6117
3.12k
          bits_per_sample=8;
6118
3.12k
        }
6119
34.3k
#endif /* if defined(COMPRESSION_WEBP) */
6120
6121
34.3k
      alpha_type=UnspecifiedAlpha;
6122
34.3k
      if (image->matte)
6123
5.16k
        {
6124
          /*
6125
            Image has a matte channel.  Mark it correctly.
6126
          */
6127
5.16k
          uint16
6128
5.16k
            extra_samples,
6129
5.16k
            sample_info[1];
6130
6131
5.16k
          const char *
6132
5.16k
            value;
6133
6134
5.16k
          alpha_type=UnassociatedAlpha;
6135
6136
5.16k
          if ((value=AccessDefinition(image_info,"tiff","alpha")))
6137
0
            {
6138
0
              if (LocaleCompare(value,"unspecified") == 0)
6139
0
                alpha_type=UnspecifiedAlpha;
6140
0
              else if (LocaleCompare(value,"associated") == 0)
6141
0
                alpha_type=AssociatedAlpha;
6142
0
              else if (LocaleCompare(value,"unassociated") == 0)
6143
0
                alpha_type=UnassociatedAlpha;
6144
0
            }
6145
5.16k
          else if ((attribute=GetImageAttribute(image,"alpha")))
6146
5.08k
            {
6147
5.08k
              if (LocaleCompare(attribute->value,"unspecified") == 0)
6148
0
                alpha_type=UnspecifiedAlpha;
6149
5.08k
              else if (LocaleCompare(attribute->value,"associated") == 0)
6150
1.96k
                alpha_type=AssociatedAlpha;
6151
3.11k
              else if (LocaleCompare(attribute->value,"unassociated") == 0)
6152
3.11k
                alpha_type=UnassociatedAlpha;
6153
5.08k
            }
6154
6155
5.16k
          samples_per_pixel += 1;
6156
5.16k
          extra_samples=1;
6157
5.16k
          sample_info[0]=EXTRASAMPLE_ASSOCALPHA;
6158
5.16k
          switch (alpha_type)
6159
5.16k
            {
6160
0
            case UnspecifiedAlpha:
6161
0
              {
6162
0
                sample_info[0]=EXTRASAMPLE_UNSPECIFIED;
6163
0
                break;
6164
0
              }
6165
1.96k
            case AssociatedAlpha:
6166
1.96k
              {
6167
1.96k
                sample_info[0]=EXTRASAMPLE_ASSOCALPHA;
6168
1.96k
                break;
6169
0
              }
6170
3.19k
            case UnassociatedAlpha:
6171
3.19k
              {
6172
3.19k
                sample_info[0]=EXTRASAMPLE_UNASSALPHA;
6173
3.19k
                break;
6174
0
              }
6175
5.16k
            }
6176
6177
5.16k
          (void) TIFFSetField(tiff,TIFFTAG_EXTRASAMPLES,extra_samples,
6178
5.16k
                              &sample_info);
6179
5.16k
        }
6180
6181
      /*
6182
        Allow the advanced user to over-ride some TIFF write options
6183
      */
6184
34.3k
      {
6185
34.3k
        const char *
6186
34.3k
          value;
6187
6188
34.3k
        unsigned int
6189
34.3k
          old_value;
6190
6191
        /*
6192
          Fill order
6193
        */
6194
34.3k
        value=AccessDefinition(image_info,"tiff","fill-order");
6195
34.3k
        if (value)
6196
1.67k
          {
6197
1.67k
            if (LocaleNCompare(value,"msb2lsb",3) == 0)
6198
1.67k
              fill_order=FILLORDER_MSB2LSB;
6199
0
            else if (LocaleNCompare(value,"lsb2msb",3) == 0)
6200
0
              fill_order=FILLORDER_LSB2MSB;
6201
1.67k
          }
6202
6203
        /*
6204
          Sample format
6205
        */
6206
34.3k
        value=AccessDefinition(image_info,"tiff","sample-format");
6207
34.3k
        if (value)
6208
0
          {
6209
0
            if (LocaleCompare(value,"unsigned") == 0)
6210
0
              sample_format=SAMPLEFORMAT_UINT;
6211
0
            else if (LocaleCompare(value,"ieeefp") == 0)
6212
0
              sample_format=SAMPLEFORMAT_IEEEFP;
6213
0
          }
6214
6215
        /*
6216
          Bits per sample (needs to be after sample format)
6217
        */
6218
34.3k
        value=AccessDefinition(image_info,"tiff","bits-per-sample");
6219
34.3k
        if (value)
6220
0
          {
6221
0
            old_value=bits_per_sample;
6222
0
            bits_per_sample=MagickAtoI(value);
6223
0
            if (sample_format == SAMPLEFORMAT_IEEEFP)
6224
0
              {
6225
                /*
6226
                  If floating point is selected, ensure that valid
6227
                  bits-per-sample values are specified.
6228
                */
6229
0
                if ((bits_per_sample != 16) &&
6230
0
                    (bits_per_sample != 24) &&
6231
0
                    (bits_per_sample != 32) &&
6232
0
                    (bits_per_sample != 64))
6233
0
                  bits_per_sample=32;
6234
0
              }
6235
0
            else
6236
0
              {
6237
                /* Clamp maximum unsigned bits per sample to 32 bits */
6238
0
                if ((bits_per_sample < 1) ||
6239
0
                    ((bits_per_sample > 32) && (bits_per_sample != 64)))
6240
0
                  bits_per_sample=old_value;
6241
0
              }
6242
0
            if ((logging) && (old_value != bits_per_sample))
6243
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6244
0
                                    "User override (bits-per-sample): %u bits "
6245
0
                                    "per sample (was %u)",
6246
0
                                    (unsigned int) bits_per_sample, old_value);
6247
0
          }
6248
6249
        /*
6250
          Samples per pixel
6251
        */
6252
34.3k
        value=AccessDefinition(image_info,"tiff","samples-per-pixel");
6253
34.3k
        if (value)
6254
0
          {
6255
0
            old_value=samples_per_pixel;
6256
0
            samples_per_pixel=MagickAtoI(value);
6257
0
            if (logging)
6258
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6259
0
                                    "User override (samples-per-pixel): %u "
6260
0
                                    "samples per pixel (was %u)",
6261
0
                                    (unsigned int) samples_per_pixel, old_value);
6262
0
          }
6263
34.3k
      }
6264
6265
      /*
6266
        Determine planar configuration.
6267
      */
6268
34.3k
      planar_config=PLANARCONFIG_CONTIG;
6269
34.3k
      if (samples_per_pixel > 1)
6270
15.6k
        {
6271
15.6k
          switch (image->interlace)
6272
15.6k
            {
6273
13.5k
            case UndefinedInterlace:
6274
13.5k
              break;
6275
5
            case NoInterlace:
6276
14
            case LineInterlace:
6277
14
            case PartitionInterlace:
6278
14
              planar_config=PLANARCONFIG_CONTIG;
6279
14
              break;
6280
2.06k
            case PlaneInterlace:
6281
2.06k
              planar_config=PLANARCONFIG_SEPARATE;
6282
2.06k
              break;
6283
15.6k
            }
6284
6285
15.6k
          switch (image_info->interlace)
6286
15.6k
            {
6287
15.6k
            case UndefinedInterlace:
6288
15.6k
              break;
6289
0
            case NoInterlace:
6290
0
            case LineInterlace:
6291
0
            case PartitionInterlace:
6292
0
              planar_config=PLANARCONFIG_CONTIG;
6293
0
              break;
6294
0
            case PlaneInterlace:
6295
0
              planar_config=PLANARCONFIG_SEPARATE;
6296
0
              break;
6297
15.6k
            }
6298
15.6k
        }
6299
6300
      /*
6301
        YCbCr encoding compresses much better than RGB.  Use YCbCr
6302
        encoding for JPEG (normal for JPEG files).
6303
6304
        FIXME: Need to find a way to select between RGB or YCbCr
6305
        encoding with JPEG compression.  Testing shows that YCbCr is
6306
        over 2.5X smaller than RGB but the PSNR is a bit lower,
6307
        particularly in red and blue channels.  Someone might want to
6308
        use RGB to minimize color loss.
6309
      */
6310
34.3k
      if ((compress_tag == COMPRESSION_JPEG) &&
6311
8.13k
          (planar_config == PLANARCONFIG_CONTIG) &&
6312
8.05k
          (photometric == PHOTOMETRIC_RGB))
6313
1.51k
        photometric=PHOTOMETRIC_YCBCR;
6314
6315
34.3k
      if (logging)
6316
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6317
0
                              "Using %s photometric, %u samples per pixel, "
6318
0
                              "%u bits per sample, format %s",
6319
0
                              PhotometricTagToString(photometric),
6320
0
                              (unsigned int) samples_per_pixel,
6321
0
                              (unsigned int) bits_per_sample,
6322
0
                              sample_format == SAMPLEFORMAT_UINT ? "Unsigned" :
6323
0
                              sample_format == SAMPLEFORMAT_IEEEFP ? "IEEEFP" :
6324
0
                              "unknown");
6325
6326
      /*
6327
        Only set fill order if the setting is not the default.
6328
      */
6329
34.3k
      if (FILLORDER_MSB2LSB != fill_order)
6330
4.86k
        (void) TIFFSetField(tiff,TIFFTAG_FILLORDER,fill_order);
6331
34.3k
      if (logging)
6332
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6333
0
                              "Using %s bit fill order",
6334
0
                              (fill_order == FILLORDER_MSB2LSB ? "MSB2LSB" :
6335
0
                               (fill_order == FILLORDER_LSB2MSB ? "LSB2MSB" :
6336
0
                                "undefined")));
6337
34.3k
      if (image->orientation != UndefinedOrientation)
6338
3.11k
        (void) TIFFSetField(tiff,TIFFTAG_ORIENTATION,(uint16) image->orientation);
6339
34.3k
      (void) TIFFSetField(tiff,TIFFTAG_PHOTOMETRIC,photometric);
6340
34.3k
      (void) TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,bits_per_sample);
6341
34.3k
      (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,samples_per_pixel);
6342
34.3k
      (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,sample_format);
6343
34.3k
      (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,planar_config);
6344
34.3k
      if (logging)
6345
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6346
0
                              "%s image planes",
6347
0
                              (planar_config == PLANARCONFIG_SEPARATE ?
6348
0
                               "Separate" : "Contiguous"));
6349
34.3k
      (void) TIFFSetField(tiff,TIFFTAG_COMPRESSION,compress_tag);
6350
6351
      /*
6352
        Determine rows per strip given current image width, bits per
6353
        sample, samples per pixel, tags, and compression specific
6354
        requirements.  Tries to create strips with
6355
        TARGET_BYTES_PER_STRIP of uncompressed data.
6356
      */
6357
34.3k
      switch (compress_tag)
6358
34.3k
        {
6359
8.13k
        case COMPRESSION_JPEG:
6360
8.13k
          {
6361
            /*
6362
              Set JPEG RGB mode since we don't have a suitable YCbCR encoder.
6363
            */
6364
8.13k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6365
8.13k
                                  "JPEG Quality: %u", (unsigned) image_info->quality);
6366
8.13k
            (void) TIFFSetField(tiff,TIFFTAG_JPEGQUALITY,image_info->quality);
6367
8.13k
            if (IsRGBColorspace(image->colorspace))
6368
8.13k
              {
6369
8.13k
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6370
8.13k
                                      "TIFFTAG_JPEGCOLORMODE: JPEGCOLORMODE_RGB");
6371
8.13k
                (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RGB);
6372
8.13k
              }
6373
8.13k
            if (bits_per_sample == 12)
6374
0
              {
6375
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6376
0
                                      "TIFFTAG_JPEGTABLESMODE: JPEGTABLESMODE_QUANT");
6377
0
                (void) TIFFSetField(tiff,TIFFTAG_JPEGTABLESMODE,JPEGTABLESMODE_QUANT);
6378
0
              }
6379
8.13k
            break;
6380
0
          }
6381
3.52k
        case COMPRESSION_ADOBE_DEFLATE:
6382
3.52k
          {
6383
            /*
6384
              Use horizontal differencing (type 2) for images which are
6385
              likely to be continuous tone.  The TIFF spec says that this
6386
              usually leads to better compression.
6387
            */
6388
3.52k
            if (((photometric == PHOTOMETRIC_RGB) ||
6389
2.74k
                 (photometric == PHOTOMETRIC_MINISBLACK)) &&
6390
1.93k
                ((bits_per_sample == 8) || (bits_per_sample == 16)))
6391
1.68k
              predictor=PREDICTOR_HORIZONTAL;
6392
3.52k
            {
6393
              /*
6394
                Zip quality has a useful range of 1-9.
6395
              */
6396
3.52k
              unsigned int zip_quality=image_info->quality / 10;
6397
3.52k
              if (zip_quality < 1)
6398
0
                zip_quality=1;
6399
3.52k
              if (zip_quality > 9)
6400
0
                zip_quality=9;
6401
6402
3.52k
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6403
3.52k
                                    "TIFFTAG_ZIPQUALITY: %u", zip_quality);
6404
3.52k
              (void) TIFFSetField(tiff,TIFFTAG_ZIPQUALITY,zip_quality);
6405
3.52k
            }
6406
3.52k
            break;
6407
0
          }
6408
1.58k
        case COMPRESSION_CCITTFAX3:
6409
1.58k
          {
6410
            /*
6411
              Set Group 3 Options.  Group 3 options are arranged as 32 flag bits.
6412
              Specify byte-aligned EOL padding option.
6413
6414
              Group3Options = 4,5. LONG. Data may be one- or
6415
              two-dimensional, but EOLs must be
6416
              byte-aligned. Uncompressed data is not allowed.
6417
6418
              bit 0 = 0 for 1-Dimensional, 1 for 2-Dimensional
6419
6420
              bit 1 = must be 0 (uncompressed data not allowed)
6421
6422
              bit 2 = 1 for byte-aligned EOLs
6423
6424
            */
6425
1.58k
            uint32
6426
1.58k
              group_three_options = 4;
6427
6428
1.58k
            const char *
6429
1.58k
              value;
6430
6431
1.58k
            if ((value=AccessDefinition(image_info,"tiff","group-three-options")))
6432
0
              {
6433
0
                group_three_options=(uint32) strtol(value,(char **)NULL, 10);
6434
0
              }
6435
1.58k
            (void) TIFFSetField(tiff,TIFFTAG_GROUP3OPTIONS,group_three_options);
6436
1.58k
            break;
6437
0
          }
6438
4.95k
        case COMPRESSION_CCITTFAX4:
6439
4.95k
          {
6440
4.95k
            break;
6441
0
          }
6442
0
#if defined(COMPRESSION_LZMA)
6443
0
        case COMPRESSION_LZMA:
6444
0
          {
6445
0
            unsigned int
6446
0
              lzma_preset;
6447
6448
0
            const char *
6449
0
              lzma_preset_str;
6450
6451
            /*
6452
              Lzma preset has a useful range of 1-9.
6453
6454
              We default to 1 since testing does not show much benefit
6455
              from use of larger values.  However, we allow the
6456
              power-user who wants to experiment to change the preset
6457
              value via syntax like '-define tiff:lzmapreset=7'.  This
6458
              ability is intentionally not documented other than here.
6459
            */
6460
6461
0
            lzma_preset=1;
6462
0
            if ((lzma_preset_str=AccessDefinition(image_info,"tiff","lzmapreset")))
6463
0
              lzma_preset=(unsigned short) MagickAtoI(lzma_preset_str);
6464
6465
0
            if (lzma_preset < 1)
6466
0
              lzma_preset=1;
6467
0
            if (lzma_preset > 9)
6468
0
              lzma_preset=9;
6469
0
            (void) TIFFSetField(tiff,TIFFTAG_LZMAPRESET,lzma_preset);
6470
0
            if (logging)
6471
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6472
0
                                    "LZMA PRESET set to %u", lzma_preset);
6473
6474
            /*
6475
              Use horizontal differencing (type 2) for images which are
6476
              likely to be continuous tone.  The TIFF spec says that this
6477
              usually leads to better compression.
6478
            */
6479
0
            if (((photometric == PHOTOMETRIC_RGB) ||
6480
0
                 (photometric == PHOTOMETRIC_MINISBLACK)) &&
6481
0
                ((bits_per_sample == 8) || (bits_per_sample == 16)))
6482
0
              predictor=PREDICTOR_HORIZONTAL;
6483
0
            break;
6484
0
          }
6485
0
#endif /* COMPRESSION_LZMA */
6486
0
#if defined(COMPRESSION_JBIG)
6487
0
        case COMPRESSION_JBIG:
6488
0
          {
6489
0
            break;
6490
0
          }
6491
0
#endif /* COMPRESSION_JBIG */
6492
750
        case COMPRESSION_LZW:
6493
750
          {
6494
            /*
6495
              Use horizontal differencing (type 2) for images which are
6496
              likely to be continuous tone.  The TIFF spec says that this
6497
              usually leads to better compression.
6498
            */
6499
750
            if (((photometric == PHOTOMETRIC_RGB) ||
6500
438
                 (photometric == PHOTOMETRIC_MINISBLACK)) &&
6501
664
                ((bits_per_sample == 8) || (bits_per_sample == 16)))
6502
659
              predictor=PREDICTOR_HORIZONTAL;
6503
750
            break;
6504
0
          }
6505
0
#if defined(COMPRESSION_ZSTD)
6506
2.42k
        case COMPRESSION_ZSTD:
6507
2.42k
          {
6508
            /*
6509
              Use horizontal differencing (type 2) for images which are
6510
              likely to be continuous tone.  The TIFF spec says that this
6511
              usually leads to better compression.
6512
            */
6513
2.42k
            if (((photometric == PHOTOMETRIC_RGB) ||
6514
925
                 (photometric == PHOTOMETRIC_MINISBLACK)) &&
6515
1.69k
                ((bits_per_sample == 8) || (bits_per_sample == 16)))
6516
1.67k
              predictor=PREDICTOR_HORIZONTAL;
6517
2.42k
            {
6518
              /*
6519
                Zstd level has a useful range of 1-19 (or even 22).
6520
6521
                Libtiff uses a default level of 9.
6522
6523
                Default for ImageInfo 'quality' is 75, which is translated to 9.
6524
6525
                Use -define tiff:zstd-compress-level=<value> to specify a value.
6526
              */
6527
2.42k
              const char *value;
6528
2.42k
              int compress_level = (image_info->quality*9)/75;
6529
2.42k
#if defined(HasZSTD)
6530
2.42k
              int max_compression = ZSTD_maxCLevel();
6531
#else
6532
              int max_compression = 19;
6533
#endif
6534
2.42k
              if ((value=AccessDefinition(image_info,"tiff","zstd-compress-level")))
6535
0
                compress_level=MagickAtoI(value);
6536
2.42k
              if (compress_level < 1)
6537
0
                compress_level=1;
6538
2.42k
              if (compress_level > max_compression)
6539
0
                compress_level=max_compression;
6540
2.42k
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6541
2.42k
                                    "TIFFTAG_ZSTD_LEVEL: %u", compress_level);
6542
2.42k
              (void) TIFFSetField(tiff,TIFFTAG_ZSTD_LEVEL,compress_level);
6543
2.42k
            }
6544
2.42k
            break;
6545
0
          }
6546
0
#endif /* defined(COMPRESSION_ZSTD) */
6547
0
#if defined(COMPRESSION_WEBP)
6548
3.12k
        case COMPRESSION_WEBP:
6549
3.12k
          {
6550
            /* TIFFTAG_WEBP_LEVEL */
6551
3.12k
            if (image_info->quality != DefaultCompressionQuality)
6552
0
              {
6553
0
                int quality = (int) image_info->quality;
6554
0
                if (quality < 1)
6555
0
                  quality=1;
6556
0
                else if (quality > 100)
6557
0
                  quality=100;
6558
6559
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6560
0
                                      "TIFFTAG_WEBP_LEVEL: %d", quality);
6561
0
                (void) TIFFSetField(tiff,TIFFTAG_WEBP_LEVEL,quality);
6562
0
              }
6563
6564
            /* TIFFTAG_WEBP_LOSSLESS */
6565
3.12k
            {
6566
3.12k
              const char *value;
6567
3.12k
              if (((value=AccessDefinition(image_info,"tiff","webp-lossless")) != NULL) ||
6568
3.12k
                  ((value=AccessDefinition(image_info,"webp","lossless")) != NULL))
6569
0
                {
6570
0
                  int lossless=(LocaleCompare(value,"TRUE") == 0 ? 1 : 0);
6571
0
                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6572
0
                                        "TIFFTAG_WEBP_LOSSLESS: %d", lossless);
6573
0
                  (void) TIFFSetField(tiff,TIFFTAG_WEBP_LOSSLESS,lossless);
6574
0
                }
6575
3.12k
            }
6576
3.12k
            break;
6577
0
          }
6578
0
#endif /* defined(COMPRESSION_WEBP) */
6579
0
#if defined(COMPRESSION_LERC)
6580
0
        case COMPRESSION_LERC:
6581
0
          {
6582
            /*
6583
              TIFFTAG_LERC_MAXZERROR is used to define the maximum
6584
              allowed error (precision loss) when compressing data
6585
              using LERC. It specifies the maximum absolute difference
6586
              allowed between the original and compressed pixel
6587
              values.
6588
             */
6589
0
            {
6590
0
              const char *str_value;
6591
0
              if ((str_value=AccessDefinition(image_info,"tiff","lerc-maxzerror")) != NULL)
6592
0
                {
6593
0
                  double max_z_error;
6594
0
                  if (MagickAtoFChk(str_value,&max_z_error) != MagickFail)
6595
0
                    {
6596
0
                      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6597
0
                                            "TIFFTAG_LERC_MAXZERROR: %f", max_z_error);
6598
0
                      (void) TIFFSetField(tiff,TIFFTAG_LERC_MAXZERROR,max_z_error);
6599
0
                    }
6600
0
                }
6601
0
            }
6602
6603
            /*
6604
              TIFFTAG_LERC_ADD_COMPRESSION adds a secondary (followup)
6605
              compression algorithm for LERC.
6606
            */
6607
0
            {
6608
0
              const char *str_value;
6609
0
              if ((str_value=AccessDefinition(image_info,"tiff","lerc-compression")) != NULL)
6610
0
                {
6611
0
                  if ((LocaleCompare(str_value,"NONE") == 0) ||
6612
0
                      (LocaleCompare(str_value,"0") == 0))
6613
0
                    {
6614
0
                      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6615
0
                                            "TIFFTAG_LERC_ADD_COMPRESSION: none");
6616
0
                      (void) TIFFSetField(tiff,TIFFTAG_LERC_ADD_COMPRESSION,LERC_ADD_COMPRESSION_NONE);
6617
0
                    }
6618
0
                  else if ((LocaleCompare(str_value,"DEFLATE") == 0) ||
6619
0
                           (LocaleCompare(str_value,"ZIP") == 0) ||
6620
0
                           (LocaleCompare(str_value,"1") == 0))
6621
0
                    {
6622
0
                      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6623
0
                                            "TIFFTAG_LERC_ADD_COMPRESSION: deflate");
6624
0
                      (void) TIFFSetField(tiff,TIFFTAG_LERC_ADD_COMPRESSION,LERC_ADD_COMPRESSION_DEFLATE);
6625
                      /* TIFFTAG_ZIPQUALITY (-1 or 1-12) */
6626
0
                      if ((str_value=AccessDefinition(image_info,"tiff","lerc-zip-quality")) != NULL)
6627
0
                        {
6628
0
                          int int_value = -1;
6629
0
                          if ((MagickAtoIChk(str_value,&int_value) != MagickFail) &&
6630
0
                              ((-1 == int_value) || (int_value <= 12 && int_value >= 0)))
6631
0
                            {
6632
0
                              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6633
0
                                                    "TIFFTAG_ZIPQUALITY: %d", int_value);
6634
0
                              (void) TIFFSetField(tiff,TIFFTAG_ZIPQUALITY,int_value);
6635
0
                            }
6636
0
                        }
6637
0
                    }
6638
0
                  else if ((LocaleCompare(str_value,"ZSTD") == 0) ||
6639
0
                           (LocaleCompare(str_value,"2") == 0))
6640
0
                    {
6641
0
                      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6642
0
                                            "TIFFTAG_LERC_ADD_COMPRESSION: zstd");
6643
0
                      (void) TIFFSetField(tiff,TIFFTAG_LERC_ADD_COMPRESSION,LERC_ADD_COMPRESSION_ZSTD);
6644
                      /* TIFFTAG_ZSTD_LEVEL (1-22) */
6645
0
                      if ((str_value=AccessDefinition(image_info,"tiff","lerc-zstd-level")) != NULL)
6646
0
                        {
6647
0
                          int int_value = -1;
6648
0
                          if ((MagickAtoIChk(str_value,&int_value) != MagickFail) &&
6649
0
                              (int_value <= 22 && int_value >= 1))
6650
0
                            {
6651
0
                              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6652
0
                                                    "TIFFTAG_ZSTD_LEVEL: %d", int_value);
6653
0
                              (void) TIFFSetField(tiff,TIFFTAG_ZSTD_LEVEL,int_value);
6654
0
                            }
6655
0
                        }
6656
0
                    }
6657
0
                }
6658
0
            }
6659
0
            break;
6660
0
          }
6661
0
#endif /* defined(COMPRESSION_WEBP) */
6662
9.87k
        default:
6663
9.87k
          {
6664
9.87k
            break;
6665
0
          }
6666
34.3k
        }
6667
6668
34.3k
      scanline_size=TIFFScanlineSize(tiff);
6669
      /* (void) LogMagickEvent(CoderEvent,GetMagickModule(),"TIFFScanlineSize(): %lu", (unsigned long) scanline_size); */
6670
34.3k
      rows_per_strip=TIFFDefaultStripSize(tiff,0);
6671
      /* (void) LogMagickEvent(CoderEvent,GetMagickModule(),"TIFFDefaultStripSize(): %lu", (unsigned long) rows_per_strip); */
6672
6673
34.3k
      switch (compress_tag)
6674
34.3k
        {
6675
1.58k
        case COMPRESSION_CCITTFAX3:
6676
6.54k
        case COMPRESSION_CCITTFAX4:
6677
6.54k
#if defined(COMPRESSION_JBIG)
6678
6.54k
        case COMPRESSION_JBIG:
6679
6.54k
#endif /* COMPRESSION_JBIG */
6680
6.54k
          {
6681
            /*
6682
              It is recommended (but not required) to output FAX/JBIG
6683
              as one strip. We will limit strip size to 32 megapixels
6684
              (4MiB) by default.
6685
            */
6686
6.54k
            bytes_per_strip_target = 4*TIFF_BYTES_PER_STRIP;
6687
6.54k
            break;
6688
6.54k
          }
6689
0
#if defined(COMPRESSION_LZMA)
6690
0
        case COMPRESSION_LZMA:
6691
0
          {
6692
0
            uint32
6693
0
              lzma_preset = 0;
6694
6695
            /*
6696
              Strip memory target for various compression preset levels.
6697
              Values are arbitrary.  LZMA is a memory and CPU pig.
6698
            */
6699
0
            static const unsigned int
6700
0
              lzma_memory_mb[] =
6701
0
              {       /* Level  Compress  Decompress */
6702
0
                1U,  /*   1       2 MB      1 MB    */
6703
0
                4U,  /*   2      12 MB      2 MB    */
6704
0
                4U,  /*   3      12 MB      1 MB    */
6705
0
                4U,  /*   4      16 MB      2 MB    */
6706
0
                6U,  /*   5      26 MB      3 MB    */
6707
0
                10U, /*   6      45 MB      5 MB    */
6708
0
                18U, /*   7      83 MB      9 MB    */
6709
0
                34U, /*   8     159 MB     17 MB    */
6710
0
                66U  /*   9     311 MB     33 MB    */
6711
0
              };
6712
6713
0
            (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_LZMAPRESET,&lzma_preset);
6714
0
            bytes_per_strip_target = (size_t) lzma_memory_mb[lzma_preset-1]*1024*1024;
6715
0
            break;
6716
6.54k
          }
6717
0
#endif /* COMPRESSION_LZMA */
6718
27.8k
        default:
6719
27.8k
          {
6720
27.8k
          }
6721
34.3k
        }
6722
6723
34.3k
      if (rows_per_strip==0 || scanline_size==0)
6724
0
        rows_per_strip=1;
6725
34.3k
      else
6726
34.3k
      {
6727
34.3k
        if (scanline_size < (tsize_t) bytes_per_strip_target)
6728
34.3k
          rows_per_strip *= (uint32) ((size_t) bytes_per_strip_target / ((size_t) rows_per_strip*scanline_size));
6729
34.3k
        if (rows_per_strip > image->rows)
6730
33.8k
          rows_per_strip=image->rows;
6731
34.3k
        if (rows_per_strip < 1)
6732
0
          rows_per_strip=1;
6733
34.3k
      }
6734
6735
      /*
6736
        It seems that some programs fail to handle more than 32K or
6737
        64K strips in an image due to using a 16-bit strip counter.
6738
        The solution is to use a larger strip size.  This approach
6739
        might cause excessively large strips for mega-sized images and
6740
        someday we may remove the solution since the problematic
6741
        readers will have expired.
6742
      */
6743
34.3k
      if ((image->rows/rows_per_strip) > 32767)
6744
0
        rows_per_strip=image->rows/32768;
6745
34.3k
      if (rows_per_strip < 1)
6746
0
        rows_per_strip=1;
6747
6748
      /*
6749
        Allow the user to specify the predictor (at their own peril)
6750
      */
6751
34.3k
      {
6752
34.3k
        const char *
6753
34.3k
          value;
6754
6755
34.3k
        if ((value=AccessDefinition(image_info,"tiff","predictor")))
6756
0
          predictor=(unsigned short) MagickAtoI(value);
6757
34.3k
      }
6758
6759
34.3k
      if (predictor != 0)
6760
4.01k
        {
6761
4.01k
          if (logging)
6762
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6763
0
                                  "Requesting predictor %u",
6764
0
                                  (unsigned int) predictor);
6765
4.01k
          (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,predictor);
6766
4.01k
        }
6767
6768
      /*
6769
        Allow the user to override rows-per-strip settings.
6770
      */
6771
34.3k
      if (method != TiledMethod)
6772
34.3k
        {
6773
34.3k
          const char *
6774
34.3k
            value;
6775
6776
34.3k
          if ((value=AccessDefinition(image_info,"tiff","rows-per-strip")))
6777
0
            {
6778
0
              unsigned int
6779
0
                old_value;
6780
6781
0
              old_value=rows_per_strip;
6782
0
              rows_per_strip=MagickAtoI(value);
6783
0
              if (logging)
6784
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6785
0
                                      "User override (rows_per_strip): %u rows"
6786
0
                                      " per strip (was %u)",
6787
0
                                      (unsigned int) rows_per_strip, old_value);
6788
0
            }
6789
34.3k
          if ((value=AccessDefinition(image_info,"tiff","strip-per-page")))
6790
1.67k
            {
6791
1.67k
              if (LocaleCompare("TRUE",value) == 0)
6792
1.67k
                {
6793
1.67k
                  rows_per_strip=(uint32) image->rows;
6794
6795
1.67k
                  if (logging)
6796
0
                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6797
0
                                          "User requested a single strip per "
6798
0
                                          "page (strip-per-page)");
6799
1.67k
                }
6800
1.67k
            }
6801
34.3k
        }
6802
6803
34.3k
      if (COMPRESSION_JPEG == compress_tag)
6804
8.13k
        {
6805
          /*
6806
            RowsPerStrip must be multiple of 16 for JPEG.
6807
          */
6808
8.13k
          rows_per_strip=(((rows_per_strip < 16 ? 16 : rows_per_strip)+1)/16)*16;
6809
8.13k
        }
6810
6811
34.3k
      if (logging)
6812
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6813
0
                              "Using %s compression",
6814
0
                              CompressionTagToString(compress_tag));
6815
34.3k
      if (logging)
6816
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6817
0
                              "Image depth %lu bits",depth);
6818
34.3k
      if (method != TiledMethod)
6819
34.3k
        {
6820
34.3k
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6821
34.3k
                                "Rows per strip: %u (%lu bytes/strip)",
6822
34.3k
                                (unsigned int) rows_per_strip,
6823
34.3k
                                (unsigned long) scanline_size*rows_per_strip);
6824
34.3k
          (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
6825
34.3k
        }
6826
6827
6828
34.3k
      if ((image->x_resolution != 0) && (image->y_resolution != 0))
6829
2.43k
        {
6830
2.43k
          unsigned short
6831
2.43k
            units;
6832
6833
          /*
6834
            Set image resolution.
6835
          */
6836
2.43k
          units=RESUNIT_NONE;
6837
2.43k
          if (image->units == PixelsPerInchResolution)
6838
2.20k
            units=RESUNIT_INCH;
6839
2.43k
          if (image->units == PixelsPerCentimeterResolution)
6840
84
            units=RESUNIT_CENTIMETER;
6841
2.43k
          if (logging)
6842
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6843
0
                                  "Resolution %gx%g pixels%s",
6844
0
                                  image->x_resolution, image->y_resolution,
6845
0
                                  (units == RESUNIT_NONE ? " (undefined units)" :
6846
0
                                   (units == RESUNIT_INCH ? " per inch" :
6847
0
                                    (units == RESUNIT_CENTIMETER ? " per centimeter"
6848
0
                                     : "BAD VALUE"))));
6849
2.43k
          (void) TIFFSetField(tiff,TIFFTAG_RESOLUTIONUNIT,(uint16) units);
6850
2.43k
          (void) TIFFSetField(tiff,TIFFTAG_XRESOLUTION,image->x_resolution);
6851
2.43k
          (void) TIFFSetField(tiff,TIFFTAG_YRESOLUTION,image->y_resolution);
6852
2.43k
        }
6853
6854
34.3k
#if EXPERIMENTAL_EXIF_TAGS
6855
34.3k
#if TIFFLIB_VERSION >= 20120922
6856
34.3k
        if (status!=MagickFail)
6857
34.3k
        {
6858
34.3k
          const unsigned char *profile_data;
6859
34.3k
          size_t profile_length;
6860
34.3k
          if ((profile_data=GetImageProfile(image,"Exif",&profile_length)) != 0)
6861
77
          {
6862
77
            AddExifFields(tiff,profile_data,profile_length,logging, 0/* FLAG_BASE */);
6863
77
          }
6864
34.3k
        }
6865
34.3k
#endif /* TIFFLIB_VERSION >= 20120922 */
6866
34.3k
#endif /* defined(EXPERIMENTAL_EXIF_TAGS) */
6867
6868
34.3k
      if (image->chromaticity.white_point.x != 0.0)
6869
336
        {
6870
336
          float
6871
336
            chromaticity[6];
6872
6873
          /*
6874
            Set image primary chromaticities (x,y coordinates of RGB
6875
            colorants and white point).
6876
          */
6877
336
          chromaticity[0]=(float) image->chromaticity.red_primary.x;
6878
336
          chromaticity[1]=(float) image->chromaticity.red_primary.y;
6879
336
          chromaticity[2]=(float) image->chromaticity.green_primary.x;
6880
336
          chromaticity[3]=(float) image->chromaticity.green_primary.y;
6881
336
          chromaticity[4]=(float) image->chromaticity.blue_primary.x;
6882
336
          chromaticity[5]=(float) image->chromaticity.blue_primary.y;
6883
336
          if (logging)
6884
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6885
0
                                  "Primary Chromaticities: "
6886
0
                                  "r=%gx%g g=%gx%g b=%gx%g",
6887
0
                                  chromaticity[0] /* red_primary.x */,
6888
0
                                  chromaticity[1] /* red_primary.y */,
6889
0
                                  chromaticity[2] /* green_primary.x */,
6890
0
                                  chromaticity[3] /* green_primary.y */,
6891
0
                                  chromaticity[4] /* blue_primary.x */,
6892
0
                                  chromaticity[5] /* blue_primary.y */);
6893
336
          (void) TIFFSetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,chromaticity);
6894
336
          chromaticity[0]=(float) image->chromaticity.white_point.x;
6895
336
          chromaticity[1]=(float) image->chromaticity.white_point.y;
6896
336
          if (logging)
6897
0
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6898
0
                                  "White Point: %gx%g",
6899
0
                                  chromaticity[0] /* white_point.x */,
6900
0
                                  chromaticity[1] /* white_point.y */);
6901
336
          (void) TIFFSetField(tiff,TIFFTAG_WHITEPOINT,chromaticity);
6902
336
        }
6903
34.3k
      {
6904
        /*
6905
          Copy any embedded profiles to TIFF.
6906
        */
6907
34.3k
        size_t
6908
34.3k
          profile_length=0;
6909
6910
34.3k
        const unsigned char
6911
34.3k
          *profile_data=0;
6912
6913
34.3k
#if defined(TIFFTAG_XMLPACKET)
6914
        /*
6915
          XML XMP profile.
6916
        */
6917
34.3k
        if ((profile_data=GetImageProfile(image,"XMP",&profile_length)) != 0)
6918
18
          {
6919
18
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6920
18
                                  "XMP embedded profile with length %lu bytes",
6921
18
                                  (unsigned long) profile_length);
6922
18
            (void) TIFFSetField(tiff,TIFFTAG_XMLPACKET,(uint32) profile_length,
6923
18
                                profile_data);
6924
18
          }
6925
34.3k
#endif /* defined(TIFFTAG_XMLPACKET) */
6926
6927
34.3k
#if defined(TIFFTAG_ICCPROFILE)
6928
        /*
6929
          ICC color profile.
6930
        */
6931
34.3k
        if ((profile_data=GetImageProfile(image,"ICM",&profile_length)) != 0)
6932
158
          {
6933
158
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6934
158
                                  "ICC ICM embedded profile with length %lu bytes",
6935
158
                                  (unsigned long) profile_length);
6936
158
            (void) TIFFSetField(tiff,TIFFTAG_ICCPROFILE,(uint32)profile_length,
6937
158
                                profile_data);
6938
158
          }
6939
34.3k
#endif /* defined(ICC_SUPPORT) */
6940
6941
        /*
6942
          IPTC NewsPhoto profile.
6943
        */
6944
34.3k
        if ((profile_data=GetImageProfile(image,"IPTC",&profile_length)) != 0)
6945
370
          {
6946
370
            int
6947
370
              profile_tag=0;
6948
370
#if defined(TIFFTAG_PHOTOSHOP)
6949
            /* Photoshop profile (with embedded IPTC profile). */
6950
370
            profile_tag=TIFFTAG_PHOTOSHOP;
6951
370
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6952
370
                                  "Photoshop embedded profile with length %lu"
6953
370
                                  " bytes",
6954
370
                                  (unsigned long) profile_length);
6955
#else
6956
            /* IPTC TAG from RichTIFF specifications */
6957
            profile_tag=TIFFTAG_RICHTIFFIPTC;
6958
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
6959
                                  "IPTC Newsphoto embedded profile with length"
6960
                                  " %lu bytes",
6961
                                  (unsigned long) profile_length);
6962
6963
#endif /* defined(PHOTOSHOP_SUPPORT) */
6964
370
            WriteNewsProfile(tiff,profile_tag,profile_data,profile_length);
6965
370
          }
6966
34.3k
      }
6967
34.3k
      attribute=GetImageAttribute(image,"subfiletype");
6968
34.3k
      if (attribute != (const ImageAttribute *) NULL)
6969
14.1k
        {
6970
          /*
6971
            Support "REDUCEDIMAGE", "PAGE", and "MASK".  Any other
6972
            value results in no subfile type tag applied.
6973
          */
6974
14.1k
          if (LocaleCompare(attribute->value,"REDUCEDIMAGE") == 0)
6975
5.15k
            {
6976
5.15k
              (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_REDUCEDIMAGE);
6977
5.15k
            }
6978
8.95k
          else if (LocaleCompare(attribute->value,"PAGE") == 0)
6979
0
            {
6980
0
              (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
6981
0
            }
6982
8.95k
          else if (LocaleCompare(attribute->value,"MASK") == 0)
6983
0
            {
6984
0
              (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_MASK);
6985
0
            }
6986
14.1k
        }
6987
20.2k
      else
6988
20.2k
        {
6989
          /*
6990
            Page and Page number tags.  Page is the current page number
6991
            (0 based) and pages is the total number of pages.
6992
          */
6993
6994
20.2k
          uint16
6995
20.2k
            page,
6996
20.2k
            pages;
6997
6998
20.2k
          page=(uint16) scene;
6999
20.2k
          pages=(uint16) image_list_length;
7000
7001
20.2k
          if (image_info->adjoin && pages > 1)
7002
1.87k
            {
7003
              /*
7004
                SubFileType = 2. LONG. The value 2 identifies a single
7005
                page of a multi-page image.
7006
              */
7007
1.87k
              (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
7008
1.87k
            }
7009
7010
20.2k
          (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,page,pages);
7011
20.2k
        }
7012
34.3k
      attribute=GetImageAttribute(image,"artist");
7013
34.3k
      if (attribute != (const ImageAttribute *) NULL)
7014
291
        (void) TIFFSetField(tiff,TIFFTAG_ARTIST,attribute->value);
7015
7016
34.3k
      attribute=GetImageAttribute(image,"copyright");
7017
34.3k
      if (attribute != (const ImageAttribute *) NULL)
7018
385
        (void) TIFFSetField(tiff,33432,attribute->value);  /* TIFFTAG_COPYRIGHT */
7019
7020
34.3k
      attribute=GetImageAttribute(image,"timestamp");
7021
34.3k
      if (attribute != (const ImageAttribute *) NULL)
7022
680
        (void) TIFFSetField(tiff,TIFFTAG_DATETIME,attribute->value);
7023
7024
34.3k
      (void) TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,image->filename);
7025
7026
34.3k
      attribute=GetImageAttribute(image,"hostcomputer");
7027
34.3k
      if (attribute != (const ImageAttribute *) NULL)
7028
3.08k
        (void) TIFFSetField(tiff,TIFFTAG_HOSTCOMPUTER,attribute->value);
7029
7030
34.3k
      attribute=GetImageAttribute(image,"comment");
7031
34.3k
      if (attribute != (const ImageAttribute *) NULL)
7032
183
        (void) TIFFSetField(tiff,TIFFTAG_IMAGEDESCRIPTION,attribute->value);
7033
7034
34.3k
      attribute=GetImageAttribute(image,"make");
7035
34.3k
      if (attribute != (const ImageAttribute *) NULL)
7036
434
        (void) TIFFSetField(tiff,TIFFTAG_MAKE,attribute->value);
7037
7038
34.3k
      attribute=GetImageAttribute(image,"model");
7039
34.3k
      if (attribute != (const ImageAttribute *) NULL)
7040
479
        (void) TIFFSetField(tiff,TIFFTAG_MODEL,attribute->value);
7041
7042
34.3k
      attribute=GetImageAttribute(image,"label");
7043
34.3k
      if (attribute != (const ImageAttribute *) NULL)
7044
187
        (void) TIFFSetField(tiff,TIFFTAG_PAGENAME,attribute->value);
7045
7046
34.3k
      attribute=GetImageAttribute(image,"software");
7047
34.3k
      if (attribute != (const ImageAttribute *) NULL)
7048
625
        {
7049
          /*
7050
            Allow skipping software tag if attribute exists but is empty.
7051
          */
7052
625
          if (strlen(attribute->value))
7053
360
            (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,attribute->value);
7054
625
        }
7055
33.7k
      else
7056
33.7k
        {
7057
33.7k
          (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,
7058
33.7k
                              GetMagickVersion((unsigned long *) NULL));
7059
33.7k
        }
7060
7061
#if 0
7062
      /*
7063
        This tag is not supported by libtiff so the tag extension
7064
        mechanism would need to be used to add support for it.
7065
      */
7066
      attribute=GetImageAttribute(image,"imageid");
7067
      if (attribute != (const ImageAttribute *) NULL)
7068
        (void) TIFFSetField(tiff,TIFFTAG_OPIIMAGEID,attribute->value);
7069
#endif
7070
7071
34.3k
      if (photometric == PHOTOMETRIC_PALETTE)
7072
1.26k
        {
7073
1.26k
          uint16
7074
1.26k
            *blue,
7075
1.26k
            *green,
7076
1.26k
            *red;
7077
7078
          /*
7079
            Initialize TIFF colormap.
7080
          */
7081
1.26k
          blue=MagickAllocateResourceLimitedClearedArray(unsigned short *,
7082
1.26k
                                                         65536L,sizeof(unsigned short));
7083
1.26k
          green=MagickAllocateResourceLimitedClearedArray(unsigned short *,
7084
1.26k
                                                          65536L,sizeof(unsigned short));
7085
1.26k
          red=MagickAllocateResourceLimitedClearedArray(unsigned short *,
7086
1.26k
                                                        65536L,sizeof(unsigned short));
7087
1.26k
          if ((blue == (unsigned short *) NULL) ||
7088
1.26k
              (green == (unsigned short *) NULL) ||
7089
1.26k
              (red == (unsigned short *) NULL))
7090
0
            {
7091
0
              MagickFreeResourceLimitedMemory(unsigned short *,blue);
7092
0
              MagickFreeResourceLimitedMemory(unsigned short *,green);
7093
0
              MagickFreeResourceLimitedMemory(unsigned short *,red);
7094
0
              ThrowTIFFWriterException(ResourceLimitError,MemoryAllocationFailed,
7095
0
                                       image);
7096
0
            }
7097
169k
          for (i=0; i < image->colors; i++)
7098
168k
            {
7099
168k
              red[i]=ScaleQuantumToShort(image->colormap[i].red);
7100
168k
              green[i]=ScaleQuantumToShort(image->colormap[i].green);
7101
168k
              blue[i]=ScaleQuantumToShort(image->colormap[i].blue);
7102
168k
            }
7103
1.26k
          (void) TIFFSetField(tiff,TIFFTAG_COLORMAP,red,green,blue);
7104
1.26k
          MagickFreeResourceLimitedMemory(unsigned short *,red);
7105
1.26k
          MagickFreeResourceLimitedMemory(unsigned short *,green);
7106
1.26k
          MagickFreeResourceLimitedMemory(unsigned short *,blue);
7107
1.26k
        }
7108
      /*
7109
        Set extra export options for grayscale.
7110
      */
7111
34.3k
      if (photometric == PHOTOMETRIC_MINISWHITE)
7112
8.84k
        export_options.grayscale_miniswhite=MagickTrue;
7113
25.5k
      else if (photometric == PHOTOMETRIC_MINISBLACK)
7114
10.0k
         export_options.grayscale_miniswhite=MagickFalse;
7115
      /*
7116
        Set extra export options for floating point.
7117
      */
7118
34.3k
      if (sample_format == SAMPLEFORMAT_IEEEFP)
7119
0
        {
7120
0
          const char *
7121
0
            definition_value;
7122
7123
0
          export_options.sample_type=FloatQuantumSampleType;
7124
0
          if ((definition_value=AccessDefinition(image_info,"tiff","min-sample-value")))
7125
0
            export_options.double_minvalue=strtod(definition_value,(char **)NULL);
7126
0
          if ((definition_value=AccessDefinition(image_info,"tiff","max-sample-value")))
7127
0
            export_options.double_maxvalue=strtod(definition_value,(char **)NULL);
7128
0
          (void) TIFFSetField(tiff,TIFFTAG_SMINSAMPLEVALUE,
7129
0
                              export_options.double_minvalue);
7130
0
          (void) TIFFSetField(tiff,TIFFTAG_SMAXSAMPLEVALUE,
7131
0
                              export_options.double_maxvalue);
7132
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7133
0
                                "Using min sample value %g, max sample value %g",
7134
0
                                export_options.double_minvalue,
7135
0
                                export_options.double_maxvalue);
7136
0
        }
7137
7138
      /*
7139
        For sample sizes matching a CPU native word, use native endian
7140
        order for import.
7141
      */
7142
34.3k
      if ((16 == bits_per_sample) || (32 == bits_per_sample) || (64 == bits_per_sample))
7143
6.34k
        export_options.endian=NativeEndian;
7144
7145
      /*
7146
        Export pixels to TIFF.
7147
7148
        FIXME: JBIG needs a Strip writer.
7149
      */
7150
34.3k
      switch (method)
7151
34.3k
        {
7152
0
        default:
7153
34.3k
        case ScanLineMethod:
7154
34.3k
          {
7155
            /*
7156
              Write TIFF image as scanlines
7157
            */
7158
34.3k
            unsigned char
7159
34.3k
              *scanline;
7160
7161
34.3k
            const PixelPacket
7162
34.3k
              *p;
7163
7164
34.3k
            int
7165
34.3k
              max_sample,
7166
34.3k
              quantum_samples,
7167
34.3k
              sample;
7168
7169
34.3k
            QuantumType
7170
34.3k
              quantum_type;
7171
7172
            /*
7173
              Allocate memory for one scanline.
7174
            */
7175
34.3k
            scanline_size=TIFFScanlineSize(tiff);
7176
7177
34.3k
            if (logging)
7178
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7179
0
                                    "Using scanline %s write method with %u "
7180
0
                                    "bits per sample (%lu bytes/scanline)",
7181
0
                                    PhotometricTagToString(photometric),
7182
0
                                    bits_per_sample, (unsigned long) scanline_size);
7183
            /*
7184
              Prepare for separate/contiguous retrieval.
7185
            */
7186
34.3k
            max_sample=1;
7187
34.3k
            if (planar_config == PLANARCONFIG_SEPARATE)
7188
2.06k
              {
7189
2.06k
                if (QuantumTransferMode(image,photometric,compress_tag,
7190
2.06k
                                        sample_format,samples_per_pixel,
7191
2.06k
                                        PLANARCONFIG_CONTIG,0,&quantum_type,
7192
2.06k
                                        &quantum_samples,&image->exception)
7193
2.06k
                    == MagickPass)
7194
2.06k
                  max_sample=quantum_samples;
7195
2.06k
              }
7196
7197
34.3k
            scanline=MagickAllocateResourceLimitedMemory(unsigned char *,(size_t) scanline_size);
7198
34.3k
            if (scanline == (unsigned char *) NULL)
7199
34.3k
              ThrowTIFFWriterException(ResourceLimitError,MemoryAllocationFailed,image);
7200
            /*
7201
              For each plane
7202
            */
7203
73.3k
            for (sample=0; (status != MagickFail) && (sample < max_sample); sample++)
7204
38.9k
              {
7205
                /*
7206
                  Determine quantum parse method.
7207
                */
7208
38.9k
                if (QuantumTransferMode(image,photometric,compress_tag,
7209
38.9k
                                        sample_format,samples_per_pixel,
7210
38.9k
                                        planar_config,sample,&quantum_type,
7211
38.9k
                                        &quantum_samples,&image->exception)
7212
38.9k
                    == MagickFail)
7213
0
                  {
7214
0
                    status=MagickFail;
7215
0
                    break;
7216
0
                  }
7217
13.9M
                for (y=0; (status != MagickFail) && (y < image->rows); y++)
7218
13.8M
                  {
7219
13.8M
                    if ((image->matte) && (alpha_type == AssociatedAlpha))
7220
619k
                      p=GetImagePixels(image,0,y,image->columns,1);
7221
13.2M
                    else
7222
13.2M
                      p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
7223
13.8M
                    if (p == (const PixelPacket *) NULL)
7224
0
                      {
7225
0
                        status=MagickFail;
7226
0
                        break;
7227
0
                      }
7228
                    /*
7229
                      Convert to associated alpha if necessary.
7230
                    */
7231
13.8M
                    if ((sample == 0) && (image->matte) &&
7232
684k
                        (alpha_type == AssociatedAlpha))
7233
611k
                      AssociateAlphaRegion(image);
7234
                    /*
7235
                      Export pixels to scanline.
7236
                    */
7237
13.8M
                    if (ExportImagePixelArea(image,quantum_type,bits_per_sample,
7238
13.8M
                                             scanline,&export_options,&export_info)
7239
13.8M
                        == MagickFail)
7240
0
                      {
7241
0
                        status=MagickFail;
7242
0
                        break;
7243
0
                      }
7244
                    /*
7245
                      Write scanline.
7246
                    */
7247
13.8M
#if !defined(WORDS_BIGENDIAN)
7248
13.8M
                    if (24 == bits_per_sample)
7249
0
                      SwabDataToNativeEndian(bits_per_sample,scanline,scanline_size);
7250
13.8M
#endif
7251
13.8M
                    if (TIFFWriteScanline(tiff, scanline,y,sample) == -1)
7252
31
                      {
7253
31
                        status=MagickFail;
7254
31
                        break;
7255
31
                      }
7256
7257
13.8M
                    if (image->previous == (Image *) NULL)
7258
12.7M
                      if (QuantumTick(y+(magick_int64_t)sample*image->rows, (magick_int64_t)image->rows*max_sample))
7259
1.74M
                        if (!MagickMonitorFormatted(y+ (magick_int64_t)sample*image->rows,
7260
1.74M
                                                    (magick_int64_t)image->rows*max_sample,&image->exception,
7261
1.74M
                                                    SaveImageText,image->filename,
7262
1.74M
                                                    image->columns,image->rows))
7263
0
                          {
7264
0
                            status=MagickFail;
7265
0
                            break;
7266
0
                          }
7267
7268
13.8M
                  }
7269
38.9k
                if (status == MagickFail)
7270
31
                  break;
7271
38.9k
              }
7272
34.3k
            MagickFreeResourceLimitedMemory(unsigned char *,scanline);
7273
34.3k
            break;
7274
34.3k
          }
7275
0
        case TiledMethod:
7276
0
          {
7277
            /*
7278
              Write TIFF image as tiles
7279
            */
7280
0
            unsigned char
7281
0
              *tile;
7282
7283
0
            uint32
7284
0
              tile_columns,
7285
0
              tile_rows;
7286
7287
0
            tsize_t
7288
0
              stride,
7289
0
              tile_size,
7290
0
              tile_size_max;
7291
7292
0
            int
7293
0
              max_sample,
7294
0
              quantum_samples,
7295
0
              sample;
7296
7297
0
            QuantumType
7298
0
              quantum_type;
7299
7300
0
            unsigned long
7301
0
              tile_total_pixels;
7302
7303
0
            if (logging)
7304
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7305
0
                                    "Using tiled %s write method with %u bits "
7306
0
                                    "per sample",
7307
0
                                    PhotometricTagToString(photometric),
7308
0
                                    bits_per_sample);
7309
7310
            /*
7311
              Determine tile size
7312
            */
7313
0
            {
7314
0
              const char *
7315
0
                value;
7316
7317
0
              tile_columns=0;
7318
0
              tile_rows=0;
7319
7320
              /*
7321
                Enable tiled output (with default size, or specified separately)
7322
                -define tiff:tile
7323
7324
                Use an exact tile size in rows & columns
7325
                -define tiff:tile-geometry=128x128
7326
7327
                Use a specific tile width (pixels)
7328
                -define tiff:tile-width=128
7329
7330
                Use a specific tile height (pixels)
7331
                -define tiff:tile-height=128
7332
              */
7333
0
              if ((value=AccessDefinition(image_info,"tiff","tile-geometry")))
7334
0
                {
7335
0
                  double
7336
0
                    width,
7337
0
                    height;
7338
7339
0
                  if (GetMagickDimension(value,&width,&height,NULL,NULL) == 2)
7340
0
                    {
7341
0
                      tile_rows=(uint32) height;
7342
0
                      tile_columns=(uint32) width;
7343
0
                    }
7344
0
                }
7345
0
              if ((value=AccessDefinition(image_info,"tiff","tile-width")))
7346
0
                {
7347
0
                  tile_columns=MagickAtoL(value);
7348
0
                }
7349
0
              if ((value=AccessDefinition(image_info,"tiff","tile-height")))
7350
0
                {
7351
0
                  tile_rows=MagickAtoL(value);
7352
0
                }
7353
7354
0
              TIFFDefaultTileSize(tiff,&tile_columns,&tile_rows);
7355
0
            }
7356
7357
0
            if (!TIFFSetField(tiff,TIFFTAG_TILEWIDTH,tile_columns))
7358
0
              status=MagickFail;
7359
0
            if (!TIFFSetField(tiff,TIFFTAG_TILELENGTH,tile_rows))
7360
0
              status=MagickFail;
7361
            /*
7362
              Obtain the maximum number of bytes required to contain a tile.
7363
            */
7364
0
            tile_size_max=TIFFTileSize(tiff);
7365
            /*
7366
              Compute the total number of pixels in one tile
7367
            */
7368
0
            tile_total_pixels=tile_columns*tile_rows;
7369
0
            if (logging)
7370
0
              {
7371
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7372
0
                                      "TIFF tile geometry %ux%u, %lu pixels",
7373
0
                                      (unsigned int)tile_columns,
7374
0
                                      (unsigned int)tile_rows,
7375
0
                                      tile_total_pixels);
7376
0
              }
7377
            /*
7378
              Allocate tile buffer
7379
            */
7380
0
            tile=MagickAllocateResourceLimitedMemory(unsigned char *, (size_t) tile_size_max);
7381
0
            if (tile == (unsigned char *) NULL)
7382
0
              ThrowTIFFWriterException(ResourceLimitError,MemoryAllocationFailed,image);
7383
            /*
7384
              Prepare for separate/contiguous retrieval.
7385
            */
7386
0
            max_sample=1;
7387
0
            if (planar_config == PLANARCONFIG_SEPARATE)
7388
0
              {
7389
0
                if (QuantumTransferMode(image,photometric,compress_tag,
7390
0
                                        sample_format,samples_per_pixel,
7391
0
                                        PLANARCONFIG_CONTIG,0,&quantum_type,
7392
0
                                        &quantum_samples,&image->exception)
7393
0
                    == MagickPass)
7394
0
                  max_sample=quantum_samples;
7395
0
              }
7396
            /*
7397
              Obtain per-row stride.
7398
            */
7399
0
            stride=TIFFTileRowSize(tiff);
7400
7401
            /*
7402
              Process each plane.
7403
            */
7404
0
            for (sample=0; (status != MagickFail) && (sample < max_sample); sample++)
7405
0
              {
7406
                /*
7407
                  Determine quantum parse method.
7408
                */
7409
0
                if (QuantumTransferMode(image,photometric,compress_tag,
7410
0
                                        sample_format,samples_per_pixel,
7411
0
                                        planar_config,sample,&quantum_type,
7412
0
                                        &quantum_samples,&image->exception)
7413
0
                    == MagickFail)
7414
0
                  {
7415
0
                    status=MagickFail;
7416
0
                    break;
7417
0
                  }
7418
0
                for (y=0; (status != MagickFail) && (y < image->rows); y+=tile_rows)
7419
0
                  {
7420
0
                    for (x=0; (status != MagickFail) && (x < image->columns); x+=tile_columns)
7421
0
                      {
7422
0
                        const PixelPacket
7423
0
                          *p;
7424
7425
0
                        long
7426
0
                          tile_set_columns,
7427
0
                          tile_set_rows;
7428
7429
0
                        unsigned char
7430
0
                          *q;
7431
7432
0
                        register long
7433
0
                          yy;
7434
7435
                        /*
7436
                          Compute image region corresponding to tile.
7437
                        */
7438
0
                        if (x+tile_columns > image->columns)
7439
0
                          tile_set_columns=(tile_columns-(x+tile_columns-image->columns));
7440
0
                        else
7441
0
                          tile_set_columns=tile_columns;
7442
0
                        if (y+tile_rows > image->rows)
7443
0
                          tile_set_rows=(tile_rows-(y+tile_rows-image->rows));
7444
0
                        else
7445
0
                          tile_set_rows=tile_rows;
7446
7447
0
                        q=tile;
7448
0
                        for (yy=y; (status != MagickFail) && (yy < (long) y+tile_set_rows); yy++)
7449
0
                          {
7450
                            /*
7451
                              Obtain pixel region corresponding to tile row.
7452
                            */
7453
0
                            if ((image->matte) && (alpha_type == AssociatedAlpha))
7454
0
                              p=GetImagePixels(image,x,yy,tile_set_columns,1);
7455
0
                            else
7456
0
                              p=AcquireImagePixels(image,x,yy,tile_set_columns,
7457
0
                                                   1,&image->exception);
7458
0
                            if (p == (const PixelPacket *) NULL)
7459
0
                              {
7460
0
                                status=MagickFail;
7461
0
                                break;
7462
0
                              }
7463
                            /*
7464
                              Convert to associated alpha if necessary.
7465
                            */
7466
0
                            if ((sample == 0) && (image->matte) &&
7467
0
                                (alpha_type == AssociatedAlpha))
7468
0
                              AssociateAlphaRegion(image);
7469
                            /*
7470
                              Export tile row
7471
                            */
7472
0
                            if (ExportImagePixelArea(image,quantum_type,
7473
0
                                                     bits_per_sample,q,
7474
0
                                                     &export_options,&export_info)
7475
0
                                == MagickFail)
7476
0
                              {
7477
0
                                status=MagickFail;
7478
0
                                break;
7479
0
                              }
7480
                            /*
7481
                              Enforce that we did not overrun our buffer.
7482
                            */
7483
0
                            assert(export_info.bytes_exported <= (size_t) scanline_size);
7484
0
                            q += stride;
7485
0
                          } /* for yy */
7486
0
                        if (status == MagickFail)
7487
0
                          break;
7488
                        /*
7489
                          Write tile.
7490
                        */
7491
0
#if !defined(WORDS_BIGENDIAN)
7492
0
                        if (24 == bits_per_sample)
7493
0
                          SwabDataToNativeEndian(bits_per_sample,tile,tile_size_max);
7494
0
#endif
7495
0
                        if ((tile_size=TIFFWriteTile(tiff,tile,x,y,0,sample)) == -1)
7496
0
                          {
7497
0
                            status=MagickFail;
7498
0
                          }
7499
0
                        if (status == MagickFail)
7500
0
                          break;
7501
0
                      } /* for x */
7502
                    /*
7503
                      Progress indicator.
7504
                    */
7505
0
                    if (image->previous == (Image *) NULL)
7506
0
                      if (QuantumTick((y+sample*image->rows)/tile_rows,
7507
0
                                      (image->rows*max_sample)/tile_rows))
7508
0
                        if (!MagickMonitorFormatted((y+sample*image->rows)/tile_rows,
7509
0
                                                    (image->rows*max_sample)/tile_rows,
7510
0
                                                    &image->exception,
7511
0
                                                    SaveImageText,image->filename,
7512
0
                                                    image->columns,image->rows))
7513
0
                          status=MagickFail;
7514
7515
0
                    if (status == MagickFail)
7516
0
                      break;
7517
0
                  } /* for y */
7518
0
              } /* for sample */
7519
0
            MagickFreeResourceLimitedMemory(unsigned char *,tile);
7520
0
            break;
7521
0
          }
7522
34.3k
        }
7523
34.3k
      if (image_info->verbose > 1)
7524
0
        TIFFPrintDirectory(tiff,stdout,MagickFalse);
7525
34.3k
      if (!TIFFWriteDirectory(tiff))
7526
93
        {
7527
93
          status=MagickFail;
7528
93
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7529
93
                                "TIFFWriteDirectory returns failed status!");
7530
93
        }
7531
7532
34.3k
#if EXPERIMENTAL_EXIF_TAGS
7533
34.3k
#if TIFFLIB_VERSION >= 20120922
7534
7535
34.3k
        if (status!=MagickFail)
7536
34.2k
        {
7537
34.2k
          const unsigned char *profile_data;
7538
34.2k
          size_t profile_length;
7539
34.2k
          if ((profile_data=GetImageProfile(image,"Exif",&profile_length)) != 0)
7540
77
          {
7541
77
            magick_uint64_t dir_EXIF_offset = 0;
7542
77
            magick_uint64_t dir_GPS_offset = 0;
7543
         /*
7544
          * Unfortunately it depends on the prehistory, what number TIFFCurrentDirectory() will get back.
7545
          * Therefore, the current main IFD number has to be adapted. However, this is an inconsistency in LibTIFF which should be
7546
          * corrected. This means that the provided code to determine/handle current directory number here is just a current work around.
7547
          */
7548
77
            tdir_t current_mainifd = TIFFCurrentDirectory(tiff);
7549
77
            if (TIFFCurrentDirOffset(tiff) > 0 && current_mainifd > 0) current_mainifd--;
7550
7551
77
            TIFFFreeDirectory(tiff);
7552
77
            if (TIFFCreateEXIFDirectory(tiff) == 0)
7553
77
            {
7554
77
              if (AddExifFields(tiff,profile_data,profile_length,logging, FLAG_EXIF) > 0)
7555
0
                {             /* Now write the directory of Exif data */
7556
7557
0
                if (!TIFFWriteCustomDirectory(tiff, &dir_EXIF_offset))
7558
0
                {
7559
0
                  LogMagickEvent(CoderEvent,GetMagickModule(),"Failed TIFFWriteCustomDirectory() of the Exif data");
7560
0
                }
7561
0
              }
7562
77
            }
7563
7564
77
#if TIFFLIB_VERSION >= 20230609
7565
77
            if (TIFFCreateGPSDirectory(tiff) == 0)
7566
77
            {
7567
77
              if (AddExifFields(tiff,profile_data,profile_length,logging, FLAG_GPS) > 0)
7568
0
                {             /* Now write the directory of Exif data */
7569
0
                if (!TIFFWriteCustomDirectory(tiff, &dir_GPS_offset))
7570
0
                {
7571
0
                  LogMagickEvent(CoderEvent,GetMagickModule(),"Failed TIFFWriteCustomDirectory() of the ExifGPS data");
7572
0
                }
7573
0
              }
7574
77
              else
7575
77
                TIFFSetDirectory(tiff, 0);
7576
77
            }
7577
77
#endif
7578
7579
77
            if (dir_EXIF_offset>0 || dir_GPS_offset>0)
7580
0
              {          /* Go back to the first directory, and add the EXIFIFD pointer. */
7581
0
              TIFFSetDirectory(tiff, 0);
7582
0
              if (dir_EXIF_offset>0)
7583
0
                  TIFFSetField(tiff, TIFFTAG_EXIFIFD, dir_EXIF_offset);
7584
0
              if (dir_GPS_offset>0)
7585
0
                  TIFFSetField(tiff, TIFFTAG_GPSIFD, dir_GPS_offset);
7586
0
            }
7587
7588
                /* Save changed tiff-directory to file */
7589
77
            if (image->next != (Image *)NULL)
7590
0
            {
7591
0
              if (!TIFFWriteDirectory(tiff))
7592
0
              {
7593
0
                (void)LogMagickEvent(CoderEvent, GetMagickModule(), "TIFFWriteDirectory returns failed status!");
7594
0
              }
7595
              /* Re configure directory status for next image. Reset current IFD number. */
7596
0
              if (!TIFFSetDirectory(tiff, current_mainifd))
7597
0
              {
7598
0
                if (logging)
7599
0
                  LogMagickEvent(CoderEvent,GetMagickModule(),"TIFFSetDirectory() failed.\n");
7600
0
              }
7601
0
              TIFFFreeDirectory(tiff);
7602
0
              if (!TIFFCreateDirectory(tiff))
7603
0
              {
7604
0
                if (logging)
7605
0
                  LogMagickEvent(CoderEvent,GetMagickModule(),"TIFFCreateDirectory() failed.\n");
7606
0
              }
7607
0
            }
7608
77
          }
7609
34.2k
        }
7610
34.3k
#endif /* TIFFLIB_VERSION >= 20120922 */
7611
34.3k
#endif /* if EXPERIMENTAL_EXIF_TAGS */
7612
7613
34.3k
      if (image->next == (Image *) NULL)
7614
27.4k
        break;
7615
6.93k
      image=SyncNextImageInList(image);
7616
6.93k
      if ((status &= MagickMonitorFormatted(scene++,
7617
6.93k
                                            image_list_length,
7618
6.93k
                                            &image->exception,
7619
6.93k
                                            SaveImagesText,
7620
6.93k
                                            image->filename)) == MagickFail)
7621
44
        break;
7622
6.93k
    } while (image_info->adjoin);
7623
34.4k
  while (image->previous != (Image *) NULL)
7624
6.93k
    image=image->previous;
7625
27.4k
  if (TIFFFlush(tiff) != 1) /* Flush pending writes, check status */
7626
93
    status=MagickFail;
7627
27.4k
  TIFFClose(tiff); /* Should implicity invoke CloseBlob(image) */
7628
7629
27.4k
  if (status == MagickFail)
7630
93
    {
7631
      /*
7632
        Handle write failure.
7633
      */
7634
7635
93
      if (unlink(filename) != -1)
7636
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
7637
0
                              "Removed broken output file \"%s\"",filename);
7638
93
    }
7639
7640
27.4k
  return(status);
7641
27.4k
}
7642
#endif