Coverage Report

Created: 2026-01-20 07:37

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