Coverage Report

Created: 2026-05-16 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/tiff.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                        TTTTT  IIIII  FFFFF  FFFFF                           %
7
%                          T      I    F      F                               %
8
%                          T      I    FFF    FFF                             %
9
%                          T      I    F      F                               %
10
%                          T    IIIII  F      F                               %
11
%                                                                             %
12
%                                                                             %
13
%                        Read/Write TIFF Image Format                         %
14
%                                                                             %
15
%                              Software Design                                %
16
%                                   Cristy                                    %
17
%                                 July 1992                                   %
18
%                                                                             %
19
%                                                                             %
20
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
21
%  dedicated to making software imaging solutions freely available.           %
22
%                                                                             %
23
%  You may not use this file except in compliance with the License.  You may  %
24
%  obtain a copy of the License at                                            %
25
%                                                                             %
26
%    https://imagemagick.org/license/                                         %
27
%                                                                             %
28
%  Unless required by applicable law or agreed to in writing, software        %
29
%  distributed under the License is distributed on an "AS IS" BASIS,          %
30
%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31
%  See the License for the specific language governing permissions and        %
32
%  limitations under the License.                                             %
33
%                                                                             %
34
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
%
36
%
37
*/
38

39
/*
40
  Include declarations.
41
*/
42
#ifdef __VMS
43
#define JPEG_SUPPORT 1
44
#endif
45
#include "MagickCore/studio.h"
46
#include "MagickCore/artifact.h"
47
#include "MagickCore/attribute.h"
48
#include "MagickCore/blob.h"
49
#include "MagickCore/blob-private.h"
50
#include "MagickCore/cache.h"
51
#include "MagickCore/channel.h"
52
#include "MagickCore/color.h"
53
#include "MagickCore/color-private.h"
54
#include "MagickCore/colormap.h"
55
#include "MagickCore/colorspace.h"
56
#include "MagickCore/colorspace-private.h"
57
#include "MagickCore/constitute.h"
58
#include "MagickCore/enhance.h"
59
#include "MagickCore/exception.h"
60
#include "MagickCore/exception-private.h"
61
#include "MagickCore/geometry.h"
62
#include "MagickCore/image.h"
63
#include "MagickCore/image-private.h"
64
#include "MagickCore/list.h"
65
#include "MagickCore/locale_.h"
66
#include "MagickCore/log.h"
67
#include "MagickCore/magick.h"
68
#include "MagickCore/memory_.h"
69
#include "MagickCore/memory-private.h"
70
#include "MagickCore/method-attribute.h"
71
#include "MagickCore/module.h"
72
#include "MagickCore/monitor.h"
73
#include "MagickCore/monitor-private.h"
74
#include "MagickCore/nt-base-private.h"
75
#include "MagickCore/option.h"
76
#include "MagickCore/pixel-accessor.h"
77
#include "MagickCore/property.h"
78
#include "MagickCore/quantum.h"
79
#include "MagickCore/quantum-private.h"
80
#include "MagickCore/profile-private.h"
81
#include "MagickCore/resize.h"
82
#include "MagickCore/resource_.h"
83
#include "MagickCore/semaphore.h"
84
#include "MagickCore/splay-tree.h"
85
#include "MagickCore/static.h"
86
#include "MagickCore/statistic.h"
87
#include "MagickCore/string_.h"
88
#include "MagickCore/string-private.h"
89
#include "MagickCore/thread_.h"
90
#include "MagickCore/token.h"
91
#include "MagickCore/utility.h"
92
#include "MagickCore/utility-private.h"
93
#include "coders/coders-private.h"
94
#include "coders/psd-private.h"
95
#if defined(MAGICKCORE_TIFF_DELEGATE)
96
# include <tiff.h>
97
# include <tiffio.h>
98
# if !defined(COMPRESSION_ADOBE_DEFLATE)
99
#  define COMPRESSION_ADOBE_DEFLATE  8
100
# endif
101
# if !defined(PREDICTOR_HORIZONTAL)
102
# define PREDICTOR_HORIZONTAL  2
103
# endif
104
# if !defined(TIFFTAG_COPYRIGHT)
105
#  define TIFFTAG_COPYRIGHT  33432
106
# endif
107
# if !defined(TIFFTAG_OPIIMAGEID)
108
#  define TIFFTAG_OPIIMAGEID  32781
109
# endif
110
# if defined(COMPRESSION_ZSTD) && defined(MAGICKCORE_ZSTD_DELEGATE)
111
#   include <zstd.h>
112
# endif
113
114
#if (TIFFLIB_VERSION >= 20201219)
115
#if defined(MAGICKCORE_HAVE_STDINT_H) || defined(MAGICKCORE_WINDOWS_SUPPORT)
116
#  undef uint16
117
159k
#  define uint16  uint16_t
118
#  undef uint32
119
348k
#  define uint32  uint32_t
120
#  undef uint64
121
293k
#  define uint64  uint64_t
122
#endif
123
#endif
124
125
/*
126
  Typedef declarations.
127
*/
128
typedef enum
129
{
130
  ReadYCCKMethod,
131
  ReadStripMethod,
132
  ReadTileMethod,
133
  ReadGenericMethod
134
} TIFFMethodType;
135
136
typedef struct _PhotoshopProfile
137
{
138
  StringInfo
139
    *data;
140
141
  MagickOffsetType
142
    offset;
143
144
  size_t
145
    length,
146
    extent,
147
    quantum;
148
} PhotoshopProfile;
149

150
/*
151
  Global declarations.
152
*/
153
static MagickThreadKey
154
  tiff_exception;
155
156
static SemaphoreInfo
157
  *tiff_semaphore = (SemaphoreInfo *) NULL;
158
159
static TIFFErrorHandler
160
  error_handler,
161
  warning_handler;
162
163
static volatile MagickBooleanType
164
  instantiate_key = MagickFalse;
165

166
/*
167
  Forward declarations.
168
*/
169
static Image *
170
  ReadTIFFImage(const ImageInfo *,ExceptionInfo *);
171
172
static MagickBooleanType
173
  WriteGROUP4Image(const ImageInfo *,Image *,ExceptionInfo *),
174
  WritePTIFImage(const ImageInfo *,Image *,ExceptionInfo *),
175
  WriteTIFFImage(const ImageInfo *,Image *,ExceptionInfo *);
176
177
static MagickOffsetType TIFFSeekCustomStream(const MagickOffsetType offset,
178
  const int whence,void *user_data)
179
10.3k
{
180
10.3k
  PhotoshopProfile
181
10.3k
    *profile;
182
183
10.3k
  profile=(PhotoshopProfile *) user_data;
184
10.3k
  switch (whence)
185
10.3k
  {
186
6.07k
    case SEEK_SET:
187
6.07k
    default:
188
6.07k
    {
189
6.07k
      if (offset < 0)
190
0
        return(-1);
191
6.07k
      profile->offset=offset;
192
6.07k
      break;
193
6.07k
    }
194
1.83k
    case SEEK_CUR:
195
1.83k
    {
196
1.83k
      if (((offset > 0) && (profile->offset > (MAGICK_SSIZE_MAX-offset))) ||
197
1.83k
          ((offset < 0) && (profile->offset < (MAGICK_SSIZE_MIN-offset))))
198
0
        {
199
0
          errno=EOVERFLOW;
200
0
          return(-1);
201
0
        }
202
1.83k
      if ((profile->offset+offset) < 0)
203
0
        return(-1);
204
1.83k
      profile->offset+=offset;
205
1.83k
      break;
206
1.83k
    }
207
2.44k
    case SEEK_END:
208
2.44k
    {
209
2.44k
      if (((MagickOffsetType) profile->length+offset) < 0)
210
0
        return(-1);
211
2.44k
      profile->offset=(MagickOffsetType) profile->length+offset;
212
2.44k
      break;
213
2.44k
    }
214
10.3k
  }
215
216
10.3k
  return(profile->offset);
217
10.3k
}
218
219
static MagickOffsetType TIFFTellCustomStream(void *user_data)
220
5.00k
{
221
5.00k
  PhotoshopProfile
222
5.00k
    *profile;
223
224
5.00k
  profile=(PhotoshopProfile *) user_data;
225
5.00k
  return(profile->offset);
226
5.00k
}
227
228
static void InitPSDInfo(const Image *image,PSDInfo *info)
229
1.07k
{
230
1.07k
  (void) memset(info,0,sizeof(*info));
231
1.07k
  info->version=1;
232
1.07k
  info->columns=image->columns;
233
1.07k
  info->rows=image->rows;
234
1.07k
  info->mode=10; /* Set the mode to a value that won't change the colorspace */
235
1.07k
  info->channels=1U;
236
1.07k
  info->min_channels=1U;
237
1.07k
  info->has_merged_image=MagickFalse;
238
1.07k
  if (image->storage_class == PseudoClass)
239
0
    info->mode=2; /* indexed mode */
240
1.07k
  else
241
1.07k
    {
242
1.07k
      info->channels=(unsigned short) image->number_channels;
243
1.07k
      info->min_channels=info->channels;
244
1.07k
      if ((image->alpha_trait & BlendPixelTrait) != 0)
245
57
        info->min_channels--;
246
1.07k
      if (image->colorspace == CMYColorspace)
247
0
        info->min_channels=MagickMin(4,info->min_channels);
248
1.07k
      else
249
1.07k
        info->min_channels=MagickMin(3,info->min_channels);
250
1.07k
    }
251
1.07k
}
252
#endif
253

254
/*
255
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256
%                                                                             %
257
%                                                                             %
258
%                                                                             %
259
%   I s T I F F                                                               %
260
%                                                                             %
261
%                                                                             %
262
%                                                                             %
263
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
264
%
265
%  IsTIFF() returns MagickTrue if the image format type, identified by the
266
%  magick string, is TIFF.
267
%
268
%  The format of the IsTIFF method is:
269
%
270
%      MagickBooleanType IsTIFF(const unsigned char *magick,const size_t length)
271
%
272
%  A description of each parameter follows:
273
%
274
%    o magick: compare image format pattern against these bytes.
275
%
276
%    o length: Specifies the length of the magick string.
277
%
278
*/
279
static MagickBooleanType IsTIFF(const unsigned char *magick,const size_t length)
280
0
{
281
0
  if (length < 4)
282
0
    return(MagickFalse);
283
0
  if (memcmp(magick,"\115\115\000\052",4) == 0)
284
0
    return(MagickTrue);
285
0
  if (memcmp(magick,"\111\111\052\000",4) == 0)
286
0
    return(MagickTrue);
287
0
#if defined(TIFF_VERSION_BIG)
288
0
  if (length < 8)
289
0
    return(MagickFalse);
290
0
  if (memcmp(magick,"\115\115\000\053\000\010\000\000",8) == 0)
291
0
    return(MagickTrue);
292
0
  if (memcmp(magick,"\111\111\053\000\010\000\000\000",8) == 0)
293
0
    return(MagickTrue);
294
0
#endif
295
0
  return(MagickFalse);
296
0
}
297

298
#if defined(MAGICKCORE_TIFF_DELEGATE)
299
/*
300
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301
%                                                                             %
302
%                                                                             %
303
%                                                                             %
304
%   R e a d G R O U P 4 I m a g e                                             %
305
%                                                                             %
306
%                                                                             %
307
%                                                                             %
308
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309
%
310
%  ReadGROUP4Image() reads a raw CCITT Group 4 image file and returns it.  It
311
%  allocates the memory necessary for the new Image structure and returns a
312
%  pointer to the new image.
313
%
314
%  The format of the ReadGROUP4Image method is:
315
%
316
%      Image *ReadGROUP4Image(const ImageInfo *image_info,
317
%        ExceptionInfo *exception)
318
%
319
%  A description of each parameter follows:
320
%
321
%    o image_info: the image info.
322
%
323
%    o exception: return any errors or warnings in this structure.
324
%
325
*/
326
static Image *ReadGROUP4Image(const ImageInfo *image_info,
327
  ExceptionInfo *exception)
328
2.81k
{
329
2.81k
  char
330
2.81k
    filename[MagickPathExtent];
331
332
2.81k
  Image
333
2.81k
    *image;
334
335
2.81k
  ImageInfo
336
2.81k
    *read_info;
337
338
2.81k
  int
339
2.81k
    c,
340
2.81k
    unique_file;
341
342
2.81k
  MagickBooleanType
343
2.81k
    status;
344
345
2.81k
  TIFF
346
2.81k
    *tiff;
347
348
  /*
349
    Open image file.
350
  */
351
2.81k
  assert(image_info != (const ImageInfo *) NULL);
352
2.81k
  assert(image_info->signature == MagickCoreSignature);
353
2.81k
  assert(exception != (ExceptionInfo *) NULL);
354
2.81k
  assert(exception->signature == MagickCoreSignature);
355
2.81k
  if (IsEventLogging() != MagickFalse)
356
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
357
0
      image_info->filename);
358
2.81k
  image=AcquireImage(image_info,exception);
359
2.81k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
360
2.81k
  if (status == MagickFalse)
361
0
    {
362
0
      image=DestroyImageList(image);
363
0
      return((Image *) NULL);
364
0
    }
365
2.81k
  (void) SetMagickThreadValue(tiff_exception,exception);
366
  /*
367
    Write raw CCITT Group 4 wrapped as a TIFF image file.
368
  */
369
2.81k
  unique_file=AcquireUniqueFileResource(filename);
370
2.81k
  if (unique_file == -1)
371
2.81k
    ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile");
372
2.81k
  (void) close_utf8(unique_file);
373
2.81k
  tiff=TIFFOpen(filename,"w");
374
2.81k
  if (tiff == (TIFF *) NULL)
375
0
    {
376
0
      (void) RelinquishUniqueFileResource(filename);
377
0
      ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile");
378
0
    }
379
2.81k
  TIFFSetField(tiff,TIFFTAG_IMAGEWIDTH,(uint32) image->columns);
380
2.81k
  TIFFSetField(tiff,TIFFTAG_IMAGELENGTH,(uint32) image->rows);
381
2.81k
  TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,1);
382
2.81k
  TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
383
2.81k
  TIFFSetField(tiff,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_MINISBLACK);
384
2.81k
  TIFFSetField(tiff,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
385
2.81k
  TIFFSetField(tiff,TIFFTAG_COMPRESSION,COMPRESSION_CCITTFAX4);
386
2.81k
  TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,(uint32) image->rows);
387
2.81k
  if ((image->resolution.x > 0.0) && (image->resolution.y > 0.0))
388
75
    {
389
75
      if (image->units == PixelsPerCentimeterResolution)
390
0
        TIFFSetField(tiff,TIFFTAG_RESOLUTIONUNIT,RESUNIT_CENTIMETER);
391
75
      else
392
75
        TIFFSetField(tiff,TIFFTAG_RESOLUTIONUNIT,RESUNIT_INCH);
393
75
      TIFFSetField(tiff,TIFFTAG_XRESOLUTION,(uint32) image->resolution.x);
394
75
      TIFFSetField(tiff,TIFFTAG_YRESOLUTION,(uint32) image->resolution.y);
395
75
    }
396
2.81k
  status=MagickTrue;
397
2.81k
  c=ReadBlobByte(image);
398
331k
  while (c != EOF)
399
328k
  {
400
328k
    unsigned char byte = (unsigned char) c;
401
328k
    if (TIFFWriteRawStrip(tiff,0,&byte,1) < 0)
402
80
      {
403
80
        status=MagickFalse;
404
80
        break;
405
80
      }
406
328k
    c=ReadBlobByte(image);
407
328k
  }
408
2.81k
  TIFFClose(tiff);
409
2.81k
  (void) CloseBlob(image);
410
2.81k
  image=DestroyImage(image);
411
2.81k
  if (status == MagickFalse)
412
80
    {
413
80
      (void) RelinquishUniqueFileResource(filename);
414
80
      return((Image*) NULL);
415
80
    }
416
  /*
417
    Read TIFF image.
418
  */
419
2.73k
  read_info=CloneImageInfo((ImageInfo *) NULL);
420
2.73k
  (void) FormatLocaleString(read_info->filename,MagickPathExtent,"%s",filename);
421
2.73k
  image=ReadTIFFImage(read_info,exception);
422
2.73k
  read_info=DestroyImageInfo(read_info);
423
2.73k
  if (image != (Image *) NULL)
424
2.16k
    {
425
2.16k
      (void) CopyMagickString(image->filename,image_info->filename,
426
2.16k
        MagickPathExtent);
427
2.16k
      (void) CopyMagickString(image->magick_filename,image_info->filename,
428
2.16k
        MagickPathExtent);
429
2.16k
      (void) CopyMagickString(image->magick,"GROUP4",MagickPathExtent);
430
2.16k
    }
431
2.73k
  (void) RelinquishUniqueFileResource(filename);
432
2.73k
  return(image);
433
2.81k
}
434
#endif
435

436
#if defined(MAGICKCORE_TIFF_DELEGATE)
437
/*
438
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439
%                                                                             %
440
%                                                                             %
441
%                                                                             %
442
%   R e a d T I F F I m a g e                                                 %
443
%                                                                             %
444
%                                                                             %
445
%                                                                             %
446
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447
%
448
%  ReadTIFFImage() reads a Tagged image file and returns it.  It allocates the
449
%  memory necessary for the new Image structure and returns a pointer to the
450
%  new image.
451
%
452
%  The format of the ReadTIFFImage method is:
453
%
454
%      Image *ReadTIFFImage(const ImageInfo *image_info,
455
%        ExceptionInfo *exception)
456
%
457
%  A description of each parameter follows:
458
%
459
%    o image_info: the image info.
460
%
461
%    o exception: return any errors or warnings in this structure.
462
%
463
*/
464
465
static inline unsigned char ClampYCC(double value)
466
0
{
467
0
  value=255.0-value;
468
0
  if (value < 0.0)
469
0
    return((unsigned char)0);
470
0
  if (value > 255.0)
471
0
    return((unsigned char)255);
472
0
  return((unsigned char)(value));
473
0
}
474
475
static MagickBooleanType DecodeLabImage(Image *image,ExceptionInfo *exception)
476
1.75k
{
477
1.75k
  CacheView
478
1.75k
    *image_view;
479
480
1.75k
  MagickBooleanType
481
1.75k
    status;
482
483
1.75k
  ssize_t
484
1.75k
    y;
485
486
1.75k
  status=MagickTrue;
487
1.75k
  image_view=AcquireAuthenticCacheView(image,exception);
488
216k
  for (y=0; y < (ssize_t) image->rows; y++)
489
214k
  {
490
214k
    Quantum
491
214k
      *magick_restrict q;
492
493
214k
    ssize_t
494
214k
      x;
495
496
214k
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
497
214k
    if (q == (Quantum *) NULL)
498
2
      {
499
2
        status=MagickFalse;
500
2
        break;
501
2
      }
502
46.6M
    for (x=0; x < (ssize_t) image->columns; x++)
503
46.4M
    {
504
46.4M
      double
505
46.4M
        a,
506
46.4M
        b;
507
508
46.4M
      a=QuantumScale*(double) GetPixela(image,q)+0.5;
509
46.4M
      if (a > 1.0)
510
366k
        a-=1.0;
511
46.4M
      b=QuantumScale*(double) GetPixelb(image,q)+0.5;
512
46.4M
      if (b > 1.0)
513
367k
        b-=1.0;
514
46.4M
      SetPixela(image,(Quantum) (QuantumRange*a),q);
515
46.4M
      SetPixelb(image,(Quantum) (QuantumRange*b),q);
516
46.4M
      q+=(ptrdiff_t) GetPixelChannels(image);
517
46.4M
    }
518
214k
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
519
0
      {
520
0
        status=MagickFalse;
521
0
        break;
522
0
      }
523
214k
  }
524
1.75k
  image_view=DestroyCacheView(image_view);
525
1.75k
  return(status);
526
1.75k
}
527
528
static void ReadProfile(Image *image,const char *name,
529
  const unsigned char *datum,uint32 length,ExceptionInfo *exception)
530
6.32k
{
531
6.32k
  StringInfo
532
6.32k
    *profile;
533
534
6.32k
  if (length < 4)
535
376
    return;
536
5.94k
  profile=BlobToProfileStringInfo(name,datum,(size_t) length,
537
5.94k
    exception);
538
5.94k
  (void) SetImageProfilePrivate(image,profile,exception);
539
5.94k
}
540
541
#if defined(__cplusplus) || defined(c_plusplus)
542
extern "C" {
543
#endif
544
545
static int TIFFCloseBlob(thandle_t image)
546
85.5k
{
547
85.5k
  (void) CloseBlob((Image *) image);
548
85.5k
  return(0);
549
85.5k
}
550
551
static void TIFFErrors(const char *,const char *,va_list)
552
  magick_attribute((__format__ (__printf__,2,0)));
553
554
static void TIFFErrors(const char *module,const char *format,va_list error)
555
6.65M
{
556
6.65M
  char
557
6.65M
    message[MagickPathExtent];
558
559
6.65M
  ExceptionInfo
560
6.65M
    *exception;
561
562
6.65M
#if defined(MAGICKCORE_HAVE_VSNPRINTF)
563
6.65M
  (void) vsnprintf(message,MagickPathExtent-2,format,error);
564
#else
565
  (void) vsprintf(message,format,error);
566
#endif
567
6.65M
  message[MagickPathExtent-2]='\0';
568
6.65M
  (void) ConcatenateMagickString(message,".",MagickPathExtent);
569
6.65M
  exception=(ExceptionInfo *) GetMagickThreadValue(tiff_exception);
570
6.65M
  if (exception != (ExceptionInfo *) NULL)
571
6.65M
    (void) ThrowMagickException(exception,GetMagickModule(),CoderError,message,
572
6.65M
      "`%s'",module);
573
6.65M
}
574
575
static toff_t TIFFGetBlobSize(thandle_t image)
576
362k
{
577
362k
  return((toff_t) GetBlobSize((Image *) image));
578
362k
}
579
580
static void TIFFGetProfiles(TIFF *tiff,Image *image,
581
  ExceptionInfo *exception)
582
84.2k
{
583
84.2k
  uint32
584
84.2k
    length = 0;
585
586
84.2k
  unsigned char
587
84.2k
    *profile = (unsigned char *) NULL;
588
589
84.2k
#if defined(TIFFTAG_ICCPROFILE)
590
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_ICCPROFILE,&length,&profile) == 1) &&
591
774
      (profile != (unsigned char *) NULL))
592
724
    ReadProfile(image,"icc",profile,length,exception);
593
84.2k
#endif
594
84.2k
#if defined(TIFFTAG_PHOTOSHOP)
595
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_PHOTOSHOP,&length,&profile) == 1) &&
596
3.46k
      (profile != (unsigned char *) NULL))
597
3.39k
    ReadProfile(image,"8bim",profile,length,exception);
598
84.2k
#endif
599
84.2k
#if defined(TIFFTAG_RICHTIFFIPTC) && (TIFFLIB_VERSION >= 20191103)
600
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC,&length,&profile) == 1) &&
601
803
      (profile != (unsigned char *) NULL))
602
707
    {
603
707
      const TIFFField
604
707
        *field;
605
606
707
      field=TIFFFieldWithTag(tiff,TIFFTAG_RICHTIFFIPTC);
607
707
      if ((field != (const TIFFField *) NULL) &&
608
707
          (TIFFFieldDataType(field) == TIFF_LONG))
609
0
        {
610
0
          if (TIFFIsByteSwapped(tiff) != 0)
611
0
            TIFFSwabArrayOfLong((uint32 *) profile,(tmsize_t) length);
612
0
          ReadProfile(image,"iptc",profile,4L*length,exception);
613
0
        }
614
707
      else
615
707
        ReadProfile(image,"iptc",profile,length,exception);
616
707
    }
617
84.2k
#endif
618
84.2k
#if defined(TIFFTAG_XMLPACKET)
619
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_XMLPACKET,&length,&profile) == 1) &&
620
208
      (profile != (unsigned char *) NULL))
621
134
    {
622
134
      StringInfo
623
134
        *dng;
624
625
134
      ReadProfile(image,"xmp",profile,length,exception);
626
134
      dng=BlobToStringInfo(profile,length);
627
134
      if (dng != (StringInfo *) NULL)
628
134
        {
629
134
          const char
630
134
            *target = "dc:format=\"image/dng\"";
631
632
134
          if (strstr((char *) GetStringInfoDatum(dng),target) != (char *) NULL)
633
10
            (void) CopyMagickString(image->magick,"DNG",MagickPathExtent);
634
134
          dng=DestroyStringInfo(dng);
635
134
        }
636
134
    }
637
84.2k
#endif
638
84.2k
  if ((TIFFGetField(tiff,34118,&length,&profile) == 1) &&
639
60
      (profile != (unsigned char *) NULL))
640
36
    ReadProfile(image,"tiff:34118",profile,length,exception);
641
84.2k
  if ((TIFFGetField(tiff,37724,&length,&profile) == 1) &&
642
1.38k
      (profile != (unsigned char *) NULL))
643
1.33k
    ReadProfile(image,"tiff:37724",profile,length,exception);
644
84.2k
}
645
646
static MagickBooleanType TIFFGetProperties(TIFF *tiff,Image *image,
647
  ExceptionInfo *exception)
648
84.2k
{
649
84.2k
  char
650
84.2k
    message[MagickPathExtent],
651
84.2k
    *text = (char *) NULL;
652
653
84.2k
  MagickBooleanType
654
84.2k
    status;
655
656
84.2k
  uint32
657
84.2k
    count = 0,
658
84.2k
    type;
659
660
84.2k
  void
661
84.2k
    *sans[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
662
663
84.2k
  status=MagickTrue;
664
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_ARTIST,&text,sans) == 1) &&
665
764
      (text != (char *) NULL))
666
764
    status=SetImageProperty(image,"tiff:artist",text,exception);
667
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_COPYRIGHT,&text,sans) == 1) &&
668
587
      (text != (char *) NULL))
669
587
    status=SetImageProperty(image,"tiff:copyright",text,exception);
670
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_DATETIME,&text,sans) == 1) &&
671
1.19k
      (text != (char *) NULL))
672
1.19k
    status=SetImageProperty(image,"tiff:timestamp",text,exception);
673
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_DOCUMENTNAME,&text,sans) == 1) &&
674
925
      (text != (char *) NULL))
675
925
    status=SetImageProperty(image,"tiff:document",text,exception);
676
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_HOSTCOMPUTER,&text,sans) == 1) &&
677
285
      (text != (char *) NULL))
678
285
    status=SetImageProperty(image,"tiff:hostcomputer",text,exception);
679
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_IMAGEDESCRIPTION,&text,sans) == 1) &&
680
583
      (text != (char *) NULL))
681
583
    status=SetImageProperty(image,"comment",text,exception);
682
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_MAKE,&text,sans) == 1) &&
683
761
      (text != (char *) NULL))
684
761
    status=SetImageProperty(image,"tiff:make",text,exception);
685
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_MODEL,&text,sans) == 1) &&
686
827
      (text != (char *) NULL))
687
827
    status=SetImageProperty(image,"tiff:model",text,exception);
688
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_OPIIMAGEID,&count,&text,sans) == 1) &&
689
128
      (count != 0) && (text != (char *) NULL))
690
90
    {
691
90
      if (count >= MagickPathExtent)
692
0
        count=MagickPathExtent-1;
693
90
      (void) CopyMagickString(message,text,count+1);
694
90
      status=SetImageProperty(image,"tiff:image-id",message,exception);
695
90
    }
696
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_PAGENAME,&text,sans) == 1) &&
697
878
      (count != 0) && (text != (char *) NULL))
698
55
    status=SetImageProperty(image,"label",text,exception);
699
84.2k
  if ((TIFFGetField(tiff,TIFFTAG_SOFTWARE,&text) == 1) &&
700
1.37k
      (text != (char *) NULL))
701
1.37k
    status=SetImageProperty(image,"tiff:software",text,exception);
702
84.2k
  if ((TIFFGetField(tiff,33423,&count,&text,sans) == 1) &&
703
101
      (count != 0) && (text != (char *) NULL))
704
58
    {
705
58
      if (count >= MagickPathExtent)
706
0
        count=MagickPathExtent-1;
707
58
      (void) CopyMagickString(message,text,count+1);
708
58
      status=SetImageProperty(image,"tiff:kodak-33423",message,exception);
709
58
    }
710
84.2k
  if ((TIFFGetField(tiff,36867,&count,&text,sans) == 1) &&
711
403
      (count != 0) && (text != (char *) NULL))
712
234
    {
713
234
      if (count >= MagickPathExtent)
714
7
        count=MagickPathExtent-1;
715
234
      (void) CopyMagickString(message,text,count+1);
716
234
      status=SetImageProperty(image,"tiff:kodak-36867",message,exception);
717
234
    }
718
84.2k
  if (TIFFGetField(tiff,TIFFTAG_SUBFILETYPE,&type,sans) == 1)
719
1.78k
    switch (type)
720
1.78k
    {
721
253
      case 0x01:
722
253
      {
723
253
        status=SetImageProperty(image,"tiff:subfiletype","REDUCEDIMAGE",
724
253
          exception);
725
253
        break;
726
0
      }
727
95
      case 0x02:
728
95
      {
729
95
        status=SetImageProperty(image,"tiff:subfiletype","PAGE",exception);
730
95
        break;
731
0
      }
732
126
      case 0x04:
733
126
      {
734
126
        status=SetImageProperty(image,"tiff:subfiletype","MASK",exception);
735
126
        break;
736
0
      }
737
1.31k
      default:
738
1.31k
        break;
739
1.78k
    }
740
84.2k
  return(status);
741
84.2k
}
742
743
static void TIFFSetImageProperties(TIFF *tiff,Image *image,const char *tag,
744
  ExceptionInfo *exception)
745
17.4k
{
746
17.4k
  char
747
17.4k
    buffer[MagickPathExtent],
748
17.4k
    filename[MagickPathExtent];
749
750
17.4k
  FILE
751
17.4k
    *file;
752
753
17.4k
  int
754
17.4k
    unique_file;
755
756
  /*
757
    Set EXIF or GPS image properties.
758
  */
759
17.4k
  unique_file=AcquireUniqueFileResource(filename);
760
17.4k
  file=(FILE *) NULL;
761
17.4k
  if (unique_file != -1)
762
17.4k
    file=fdopen(unique_file,"rb+");
763
17.4k
  if ((unique_file == -1) || (file == (FILE *) NULL))
764
0
    {
765
0
      (void) RelinquishUniqueFileResource(filename);
766
0
      (void) ThrowMagickException(exception,GetMagickModule(),WandError,
767
0
        "UnableToCreateTemporaryFile","`%s'",filename);
768
0
      return;
769
0
    }
770
17.4k
  TIFFPrintDirectory(tiff,file,0);
771
17.4k
  (void) fseek(file,0,SEEK_SET);
772
225k
  while (fgets(buffer,(int) sizeof(buffer),file) != NULL)
773
208k
  {
774
208k
    char
775
208k
      *p,
776
208k
      property[MagickPathExtent],
777
208k
      value[MagickPathExtent];
778
779
208k
    (void) StripMagickString(buffer);
780
208k
    p=strchr(buffer,':');
781
208k
    if (p == (char *) NULL)
782
39.3k
      continue;
783
169k
    *p='\0';
784
169k
    (void) FormatLocaleString(property,MagickPathExtent,"%s%s",tag,buffer);
785
169k
    (void) FormatLocaleString(value,MagickPathExtent,"%s",p+1);
786
169k
    (void) StripMagickString(value);
787
169k
    (void) SetImageProperty(image,property,value,exception);
788
169k
  }
789
17.4k
  (void) fclose(file);
790
17.4k
  (void) RelinquishUniqueFileResource(filename);
791
17.4k
}
792
793
static void TIFFGetEXIFProperties(TIFF *tiff,Image *image,
794
  const ImageInfo* image_info,ExceptionInfo *exception)
795
84.2k
{
796
84.2k
  const char
797
84.2k
    *option;
798
799
84.2k
  tdir_t
800
84.2k
    directory;
801
802
84.2k
#if defined(TIFF_VERSION_BIG)
803
84.2k
  uint64
804
#else
805
  uint32
806
#endif
807
84.2k
    offset;
808
809
  /*
810
    Read EXIF properties.
811
  */
812
84.2k
  option=GetImageOption(image_info,"tiff:exif-properties");
813
84.2k
  if (IsStringFalse(option) != MagickFalse)
814
0
    return;
815
84.2k
  offset=0;
816
84.2k
  if (TIFFGetField(tiff,TIFFTAG_EXIFIFD,&offset) != 1)
817
63.5k
    return;
818
20.6k
  directory=TIFFCurrentDirectory(tiff);
819
20.6k
  if (TIFFReadEXIFDirectory(tiff,offset) == 1)
820
10.5k
    TIFFSetImageProperties(tiff,image,"exif:",exception);
821
20.6k
  TIFFSetDirectory(tiff,directory);
822
20.6k
}
823
824
static void TIFFGetGPSProperties(TIFF *tiff,Image *image,
825
  const ImageInfo* image_info,ExceptionInfo *exception)
826
84.2k
{
827
84.2k
#if (TIFFLIB_VERSION >= 20210416)
828
84.2k
  const char
829
84.2k
    *option;
830
831
84.2k
  tdir_t
832
84.2k
    directory;
833
834
84.2k
#if defined(TIFF_VERSION_BIG)
835
84.2k
  uint64
836
#else
837
  uint32
838
#endif
839
84.2k
    offset;
840
841
  /*
842
    Read GPS properties.
843
  */
844
84.2k
  option=GetImageOption(image_info,"tiff:gps-properties");
845
84.2k
  if (IsStringFalse(option) != MagickFalse)
846
0
    return;
847
84.2k
  offset=0;
848
84.2k
  if (TIFFGetField(tiff,TIFFTAG_GPSIFD,&offset) != 1)
849
71.8k
    return;
850
12.3k
  directory=TIFFCurrentDirectory(tiff);
851
12.3k
  if (TIFFReadGPSDirectory(tiff,offset) == 1)
852
6.89k
    TIFFSetImageProperties(tiff,image,"exif:GPS",exception);
853
12.3k
  TIFFSetDirectory(tiff,directory);
854
#else
855
  magick_unreferenced(tiff);
856
  magick_unreferenced(image);
857
  magick_unreferenced(image_info);
858
  magick_unreferenced(exception);
859
#endif
860
12.3k
}
861
862
static int TIFFMapBlob(thandle_t image,tdata_t *base,toff_t *size)
863
121k
{
864
121k
  *base=(tdata_t *) GetBlobStreamData((Image *) image);
865
121k
  if (*base != (tdata_t *) NULL)
866
118k
    *size=(toff_t) GetBlobSize((Image *) image);
867
121k
  if (*base != (tdata_t *) NULL)
868
118k
    return(1);
869
2.75k
  return(0);
870
121k
}
871
872
static tsize_t TIFFReadBlob(thandle_t image,tdata_t data,tsize_t size)
873
200k
{
874
200k
  tsize_t
875
200k
    count;
876
877
200k
  count=(tsize_t) ReadBlob((Image *) image,(size_t) size,(unsigned char *)
878
200k
    data);
879
200k
  return(count);
880
200k
}
881
882
static int TIFFReadPixels(TIFF *tiff,const tsample_t sample,
883
  const ssize_t row,tdata_t scanline)
884
0
{
885
0
  int
886
0
    status;
887
888
0
  status=TIFFReadScanline(tiff,scanline,(uint32) row,sample);
889
0
  return(status);
890
0
}
891
892
static toff_t TIFFSeekBlob(thandle_t image,toff_t offset,int whence)
893
113k
{
894
113k
  return((toff_t) SeekBlob((Image *) image,(MagickOffsetType) offset,whence));
895
113k
}
896
897
static void TIFFUnmapBlob(thandle_t image,tdata_t base,toff_t size)
898
120k
{
899
120k
  (void) image;
900
120k
  (void) base;
901
120k
  (void) size;
902
120k
}
903
904
static void TIFFWarnings(const char *,const char *,va_list)
905
  magick_attribute((__format__ (__printf__,2,0)));
906
907
static void TIFFWarnings(const char *module,const char *format,va_list warning)
908
8.85M
{
909
8.85M
  char
910
8.85M
    message[MagickPathExtent];
911
912
8.85M
  ExceptionInfo
913
8.85M
    *exception;
914
915
8.85M
#if defined(MAGICKCORE_HAVE_VSNPRINTF)
916
8.85M
  (void) vsnprintf(message,MagickPathExtent-2,format,warning);
917
#else
918
  (void) vsprintf(message,format,warning);
919
#endif
920
8.85M
  message[MagickPathExtent-2]='\0';
921
8.85M
  (void) ConcatenateMagickString(message,".",MagickPathExtent);
922
8.85M
  exception=(ExceptionInfo *) GetMagickThreadValue(tiff_exception);
923
8.85M
  if (exception != (ExceptionInfo *) NULL)
924
8.85M
    (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning,
925
8.85M
      message,"`%s'",module);
926
8.85M
}
927
928
static tsize_t TIFFWriteBlob(thandle_t image,tdata_t data,tsize_t size)
929
50.2k
{
930
50.2k
  tsize_t
931
50.2k
    count;
932
933
50.2k
  count=(tsize_t) WriteBlob((Image *) image,(size_t) size,(unsigned char *)
934
50.2k
    data);
935
50.2k
  return(count);
936
50.2k
}
937
938
static TIFFMethodType GetJPEGMethod(Image* image,TIFF *tiff,
939
  uint16 bits_per_sample,uint16 samples_per_pixel)
940
2.15k
{
941
2.15k
#define BUFFER_SIZE 2048
942
943
2.15k
  MagickOffsetType
944
2.15k
    position,
945
2.15k
    offset;
946
947
2.15k
  size_t
948
2.15k
    i;
949
950
2.15k
  TIFFMethodType
951
2.15k
    method;
952
953
2.15k
#if defined(TIFF_VERSION_BIG)
954
2.15k
  uint64
955
2.15k
    *value = (uint64 *) NULL;
956
#else
957
  uint32
958
    *value = (uint32 *) NULL;
959
#endif
960
961
2.15k
  unsigned char
962
2.15k
    buffer[BUFFER_SIZE+32];
963
964
2.15k
  unsigned short
965
2.15k
    length;
966
967
  /* Only 8-bit and 4-sample are supported for the APP14 marker probe */
968
2.15k
  if ((bits_per_sample != 8) || (samples_per_pixel != 4))
969
2.15k
    return(ReadStripMethod);
970
0
  if (!TIFFGetField(tiff,TIFFTAG_STRIPOFFSETS,&value) || (value == NULL))
971
0
    return(ReadStripMethod);
972
0
  position=TellBlob(image);
973
0
  offset=(MagickOffsetType) (value[0]);
974
0
  if (SeekBlob(image,offset,SEEK_SET) != offset)
975
0
    return(ReadStripMethod);
976
0
  method=ReadStripMethod;
977
0
  if (ReadBlob(image,BUFFER_SIZE,buffer) == BUFFER_SIZE)
978
0
    {
979
0
      for (i=0; i < BUFFER_SIZE; i++)
980
0
      {
981
0
        while (i < BUFFER_SIZE)
982
0
        {
983
0
          if (buffer[i++] == 255)
984
0
           break;
985
0
        }
986
0
        while (i < BUFFER_SIZE)
987
0
        {
988
0
          if (buffer[++i] != 255)
989
0
           break;
990
0
        }
991
0
        if (buffer[i++] == 216) /* JPEG_MARKER_SOI */
992
0
          continue;
993
0
        length=(unsigned short) (((unsigned int) (buffer[i] << 8) |
994
0
          (unsigned int) buffer[i+1]) & 0xffff);
995
0
        if (i+(size_t) length >= BUFFER_SIZE)
996
0
          break;
997
0
        if (buffer[i-1] == 238) /* JPEG_MARKER_APP0+14 */
998
0
          {
999
0
            if (length != 14)
1000
0
              break;
1001
            /* 0 == CMYK, 1 == YCbCr, 2 = YCCK */
1002
0
            if (buffer[i+13] == 2)
1003
0
              method=ReadYCCKMethod;
1004
0
            break;
1005
0
          }
1006
0
        i+=(size_t) length;
1007
0
      }
1008
0
    }
1009
0
  (void) SeekBlob(image,position,SEEK_SET);
1010
0
  return(method);
1011
0
}
1012
1013
static ssize_t TIFFReadCustomStream(unsigned char *data,const size_t count,
1014
  void *user_data)
1015
82.3k
{
1016
82.3k
  PhotoshopProfile
1017
82.3k
    *profile;
1018
1019
82.3k
  size_t
1020
82.3k
    total;
1021
1022
82.3k
  MagickOffsetType
1023
82.3k
    remaining;
1024
1025
82.3k
  if (count == 0)
1026
0
    return(0);
1027
82.3k
  profile=(PhotoshopProfile *) user_data;
1028
82.3k
  remaining=(MagickOffsetType) profile->length-profile->offset;
1029
82.3k
  if (remaining <= 0)
1030
2.92k
    return(-1);
1031
79.4k
  total=MagickMin(count, (size_t) remaining);
1032
79.4k
  (void) memcpy(data,profile->data->datum+profile->offset,total);
1033
79.4k
  profile->offset+=(MagickOffsetType) total;
1034
79.4k
  return((ssize_t) total);
1035
82.3k
}
1036
1037
static CustomStreamInfo *TIFFAcquireCustomStreamForReading(
1038
  PhotoshopProfile *profile,ExceptionInfo *exception)
1039
1.07k
{
1040
1.07k
  CustomStreamInfo
1041
1.07k
    *custom_stream;
1042
1043
1.07k
  custom_stream=AcquireCustomStreamInfo(exception);
1044
1.07k
  if (custom_stream == (CustomStreamInfo *) NULL)
1045
0
    return(custom_stream);
1046
1.07k
  SetCustomStreamData(custom_stream,(void *) profile);
1047
1.07k
  SetCustomStreamReader(custom_stream,TIFFReadCustomStream);
1048
1.07k
  SetCustomStreamSeeker(custom_stream,TIFFSeekCustomStream);
1049
1.07k
  SetCustomStreamTeller(custom_stream,TIFFTellCustomStream);
1050
1.07k
  return(custom_stream);
1051
1.07k
}
1052
1053
static void TIFFReadPhotoshopLayers(const ImageInfo *image_info,Image *image,
1054
  ExceptionInfo *exception)
1055
64.2k
{
1056
64.2k
  const char
1057
64.2k
    *option;
1058
1059
64.2k
  const StringInfo
1060
64.2k
    *profile;
1061
1062
64.2k
  ExceptionInfo
1063
64.2k
    *sans_exception;
1064
1065
64.2k
  CustomStreamInfo
1066
64.2k
    *custom_stream;
1067
1068
64.2k
  Image
1069
64.2k
    *layers;
1070
1071
64.2k
  ImageInfo
1072
64.2k
    *clone_info;
1073
1074
64.2k
  PhotoshopProfile
1075
64.2k
    photoshop_profile;
1076
1077
64.2k
  PSDInfo
1078
64.2k
    info;
1079
1080
64.2k
  ssize_t
1081
64.2k
    i;
1082
1083
64.2k
  if (GetImageListLength(image) != 1)
1084
6.65k
    return;
1085
57.5k
  if ((image_info->number_scenes == 1) && (image_info->scene == 0))
1086
15.0k
    return;
1087
42.5k
  option=GetImageOption(image_info,"tiff:ignore-layers");
1088
42.5k
  if (option != (const char * ) NULL)
1089
0
    return;
1090
42.5k
  profile=GetImageProfile(image,"tiff:37724");
1091
42.5k
  if (profile == (const StringInfo *) NULL)
1092
41.4k
    return;
1093
432k
  for (i=0; i < (ssize_t) profile->length-8; i++)
1094
432k
  {
1095
432k
    if (LocaleNCompare((const char *) (profile->datum+i),
1096
432k
        image->endian == MSBEndian ? "8BIM" : "MIB8",4) != 0)
1097
430k
      continue;
1098
1.35k
    i+=4;
1099
1.35k
    if ((LocaleNCompare((const char *) (profile->datum+i),
1100
1.35k
         image->endian == MSBEndian ? "Layr" : "ryaL",4) == 0) ||
1101
283
        (LocaleNCompare((const char *) (profile->datum+i),
1102
283
         image->endian == MSBEndian ? "LMsk" : "ksML",4) == 0) ||
1103
283
        (LocaleNCompare((const char *) (profile->datum+i),
1104
283
         image->endian == MSBEndian ? "Lr16" : "61rL",4) == 0) ||
1105
283
        (LocaleNCompare((const char *) (profile->datum+i),
1106
283
         image->endian == MSBEndian ? "Lr32" : "23rL",4) == 0))
1107
1.07k
      break;
1108
1.35k
  }
1109
1.12k
  i+=4;
1110
1.12k
  if (i >= (ssize_t) (profile->length-8))
1111
54
    return;
1112
1.07k
  photoshop_profile.data=(StringInfo *) profile;
1113
1.07k
  photoshop_profile.length=profile->length;
1114
1.07k
  custom_stream=TIFFAcquireCustomStreamForReading(&photoshop_profile,exception);
1115
1.07k
  if (custom_stream == (CustomStreamInfo *) NULL)
1116
0
    return;
1117
1.07k
  layers=CloneImage(image,0,0,MagickTrue,exception);
1118
1.07k
  if (layers == (Image *) NULL)
1119
0
    {
1120
0
      custom_stream=DestroyCustomStreamInfo(custom_stream);
1121
0
      return;
1122
0
    }
1123
1.07k
  (void) DeleteImageProfile(layers,"tiff:37724");
1124
1.07k
  AttachCustomStream(layers->blob,custom_stream);
1125
1.07k
  SeekBlob(layers,(MagickOffsetType) i,SEEK_SET);
1126
1.07k
  InitPSDInfo(layers,&info);
1127
1.07k
  clone_info=CloneImageInfo(image_info);
1128
1.07k
  clone_info->number_scenes=0;
1129
1.07k
  sans_exception=AcquireExceptionInfo();
1130
1.07k
  (void) ReadPSDLayers(layers,clone_info,&info,sans_exception);
1131
1.07k
  sans_exception=DestroyExceptionInfo(sans_exception);
1132
1.07k
  clone_info=DestroyImageInfo(clone_info);
1133
1.07k
  DeleteImageFromList(&layers);
1134
1.07k
  if (layers != (Image *) NULL)
1135
153
    {
1136
153
      SetImageArtifact(image,"tiff:has-layers","true");
1137
153
      AppendImageToList(&image,layers);
1138
306
      while (layers != (Image *) NULL)
1139
153
      {
1140
153
        SetImageArtifact(layers,"tiff:has-layers","true");
1141
153
        DetachBlob(layers->blob);
1142
153
        layers=GetNextImageInList(layers);
1143
153
      }
1144
153
    }
1145
1.07k
  custom_stream=DestroyCustomStreamInfo(custom_stream);
1146
1.07k
}
1147
1148
#if defined(__cplusplus) || defined(c_plusplus)
1149
}
1150
#endif
1151
1152
static Image *ReadTIFFImage(const ImageInfo *image_info,
1153
  ExceptionInfo *exception)
1154
123k
{
1155
123k
#define ThrowTIFFException(severity,message) \
1156
415
{ \
1157
415
  if (pixel_info != (MemoryInfo *) NULL) \
1158
415
    pixel_info=RelinquishVirtualMemory(pixel_info); \
1159
415
  if (quantum_info != (QuantumInfo *) NULL) \
1160
415
    quantum_info=DestroyQuantumInfo(quantum_info); \
1161
415
  TIFFClose(tiff); \
1162
415
  ThrowReaderException(severity,message); \
1163
0
}
1164
1165
123k
  float
1166
123k
    *chromaticity = (float *) NULL,
1167
123k
    x_position,
1168
123k
    y_position,
1169
123k
    x_resolution,
1170
123k
    y_resolution;
1171
1172
123k
  Image
1173
123k
    *image;
1174
1175
123k
  int
1176
123k
    tiff_status = 0;
1177
1178
123k
  MagickBooleanType
1179
123k
    more_frames;
1180
1181
123k
  MagickSizeType
1182
123k
    number_pixels;
1183
1184
123k
  MagickStatusType
1185
123k
    status;
1186
1187
123k
  MemoryInfo
1188
123k
    *pixel_info = (MemoryInfo *) NULL;
1189
1190
123k
  QuantumInfo
1191
123k
    *quantum_info;
1192
1193
123k
  QuantumType
1194
123k
    image_quantum_type;
1195
1196
123k
  ssize_t
1197
123k
    i,
1198
123k
    scanline_size,
1199
123k
    y;
1200
1201
123k
  TIFF
1202
123k
    *tiff;
1203
1204
123k
  TIFFMethodType
1205
123k
    method;
1206
1207
123k
  uint16
1208
123k
    compress_tag = 0,
1209
123k
    bits_per_sample = 0,
1210
123k
    endian = 0,
1211
123k
    extra_samples = 0,
1212
123k
    interlace = 0,
1213
123k
    max_sample_value = 0,
1214
123k
    min_sample_value = 0,
1215
123k
    orientation = 0,
1216
123k
    page = 0,
1217
123k
    pages = 0,
1218
123k
    photometric = 0,
1219
123k
    *sample_info = NULL,
1220
123k
    sample_format = 0,
1221
123k
    samples_per_pixel = 0,
1222
123k
    units = 0;
1223
1224
123k
  uint32
1225
123k
    height,
1226
123k
    rows_per_strip,
1227
123k
    width;
1228
1229
123k
  uint64
1230
123k
    dng_version;
1231
1232
123k
  unsigned char
1233
123k
    *pixels;
1234
1235
123k
  void
1236
123k
    *sans[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
1237
1238
  /*
1239
    Open image.
1240
  */
1241
123k
  assert(image_info != (const ImageInfo *) NULL);
1242
123k
  assert(image_info->signature == MagickCoreSignature);
1243
123k
  assert(exception != (ExceptionInfo *) NULL);
1244
123k
  assert(exception->signature == MagickCoreSignature);
1245
123k
  if (IsEventLogging() != MagickFalse)
1246
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1247
0
      image_info->filename);
1248
123k
  image=AcquireImage(image_info,exception);
1249
123k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1250
123k
  if (status == MagickFalse)
1251
0
    {
1252
0
      image=DestroyImageList(image);
1253
0
      return((Image *) NULL);
1254
0
    }
1255
123k
  (void) SetMagickThreadValue(tiff_exception,exception);
1256
123k
  tiff=TIFFClientOpen(image->filename,"rb",(thandle_t) image,TIFFReadBlob,
1257
123k
    TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
1258
123k
    TIFFUnmapBlob);
1259
123k
  if (tiff == (TIFF *) NULL)
1260
45.0k
    {
1261
45.0k
      if (exception->severity == UndefinedException)
1262
44.9k
        ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1263
44.9k
      image=DestroyImageList(image);
1264
44.9k
      return((Image *) NULL);
1265
45.0k
    }
1266
78.0k
  if (exception->severity > ErrorException)
1267
5.57k
    {
1268
5.57k
      TIFFClose(tiff);
1269
5.57k
      image=DestroyImageList(image);
1270
5.57k
      return((Image *) NULL);
1271
5.57k
    }
1272
72.4k
  if (TIFFGetField(tiff,TIFFTAG_DNGVERSION,&dng_version) == 1)
1273
182
    {
1274
182
      ImageInfo
1275
182
        *read_info;
1276
1277
182
      TIFFClose(tiff);
1278
182
      image=DestroyImageList(image);
1279
182
      read_info=CloneImageInfo(image_info);
1280
182
      (void) CopyMagickString(read_info->magick,"DNG",MagickPathExtent);
1281
182
      image=ReadImage(read_info,exception);
1282
182
      read_info=DestroyImageInfo(read_info);
1283
182
      return(image);
1284
182
    }
1285
72.2k
  if (image_info->number_scenes != 0)
1286
20.1k
    {
1287
      /*
1288
        Generate blank images for subimage specification (e.g. image.tif[4].
1289
        We need to check the number of directories because it is possible that
1290
        the subimage(s) are stored in the photoshop profile.
1291
      */
1292
20.1k
      if (image_info->scene < (size_t) TIFFNumberOfDirectories(tiff))
1293
19.5k
        {
1294
19.5k
          for (i=0; i < (ssize_t) image_info->scene; i++)
1295
0
          {
1296
0
            status=TIFFReadDirectory(tiff) != 0 ? MagickTrue : MagickFalse;
1297
0
            if (status == MagickFalse)
1298
0
              {
1299
0
                TIFFClose(tiff);
1300
0
                image=DestroyImageList(image);
1301
0
                return((Image *) NULL);
1302
0
              }
1303
0
            AcquireNextImage(image_info,image,exception);
1304
0
            if (GetNextImageInList(image) == (Image *) NULL)
1305
0
              {
1306
0
                TIFFClose(tiff);
1307
0
                image=DestroyImageList(image);
1308
0
                return((Image *) NULL);
1309
0
              }
1310
0
            image=SyncNextImageInList(image);
1311
0
          }
1312
19.5k
      }
1313
20.1k
  }
1314
72.2k
  more_frames=MagickTrue;
1315
72.2k
  do
1316
86.1k
  {
1317
    /* TIFFPrintDirectory(tiff,stdout,MagickFalse); */
1318
86.1k
    if ((TIFFGetField(tiff,TIFFTAG_IMAGEWIDTH,&width) != 1) ||
1319
86.1k
        (TIFFGetField(tiff,TIFFTAG_IMAGELENGTH,&height) != 1) ||
1320
86.1k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_PHOTOMETRIC,&photometric,sans) != 1) ||
1321
84.4k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_COMPRESSION,&compress_tag,sans) != 1) ||
1322
84.4k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian,sans) != 1) ||
1323
84.4k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_PLANARCONFIG,&interlace,sans) != 1) ||
1324
84.4k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,&samples_per_pixel,sans) != 1) ||
1325
84.4k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,&bits_per_sample,sans) != 1) ||
1326
84.4k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLEFORMAT,&sample_format,sans) != 1) ||
1327
84.4k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_MINSAMPLEVALUE,&min_sample_value,sans) != 1) ||
1328
84.4k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_MAXSAMPLEVALUE,&max_sample_value,sans) != 1))
1329
1.77k
      {
1330
1.77k
        TIFFClose(tiff);
1331
1.77k
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1332
0
      }
1333
84.4k
    if (((sample_format != SAMPLEFORMAT_IEEEFP) || (bits_per_sample != 64)) &&
1334
83.2k
        ((bits_per_sample <= 0) || (bits_per_sample > 32)))
1335
158
      {
1336
158
        TIFFClose(tiff);
1337
158
        ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
1338
0
      }
1339
84.2k
    if (samples_per_pixel > MaxPixelChannels)
1340
55
      {
1341
55
        TIFFClose(tiff);
1342
55
        ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
1343
0
      }
1344
84.2k
    if (sample_format == SAMPLEFORMAT_IEEEFP)
1345
8.54k
      (void) SetImageProperty(image,"quantum:format","floating-point",
1346
8.54k
        exception);
1347
84.2k
    if (TIFFGetField(tiff,TIFFTAG_PHOTOMETRIC,&photometric) != 1)
1348
0
      photometric=PHOTOMETRIC_RGB;
1349
84.2k
    switch (photometric)
1350
84.2k
    {
1351
10.7k
      case PHOTOMETRIC_MINISBLACK:
1352
10.7k
      {
1353
10.7k
        (void) SetImageProperty(image,"tiff:photometric","min-is-black",
1354
10.7k
          exception);
1355
10.7k
        break;
1356
0
      }
1357
15.0k
      case PHOTOMETRIC_MINISWHITE:
1358
15.0k
      {
1359
15.0k
        (void) SetImageProperty(image,"tiff:photometric","min-is-white",
1360
15.0k
          exception);
1361
15.0k
        break;
1362
0
      }
1363
1.78k
      case PHOTOMETRIC_PALETTE:
1364
1.78k
      {
1365
1.78k
        (void) SetImageProperty(image,"tiff:photometric","palette",exception);
1366
1.78k
        break;
1367
0
      }
1368
6.39k
      case PHOTOMETRIC_RGB:
1369
6.39k
      {
1370
6.39k
        (void) SetImageProperty(image,"tiff:photometric","RGB",exception);
1371
6.39k
        break;
1372
0
      }
1373
1.48k
      case PHOTOMETRIC_CIELAB:
1374
1.48k
      {
1375
1.48k
        (void) SetImageProperty(image,"tiff:photometric","CIELAB",exception);
1376
1.48k
        break;
1377
0
      }
1378
1.09k
      case PHOTOMETRIC_LOGL:
1379
1.09k
      {
1380
1.09k
        (void) SetImageProperty(image,"tiff:photometric","CIE Log2(L)",
1381
1.09k
          exception);
1382
1.09k
        break;
1383
0
      }
1384
1.12k
      case PHOTOMETRIC_LOGLUV:
1385
1.12k
      {
1386
1.12k
        (void) SetImageProperty(image,"tiff:photometric","LOGLUV",exception);
1387
1.12k
        break;
1388
0
      }
1389
0
#if defined(PHOTOMETRIC_MASK)
1390
717
      case PHOTOMETRIC_MASK:
1391
717
      {
1392
717
        (void) SetImageProperty(image,"tiff:photometric","MASK",exception);
1393
717
        break;
1394
0
      }
1395
0
#endif
1396
8.27k
      case PHOTOMETRIC_SEPARATED:
1397
8.27k
      {
1398
8.27k
        (void) SetImageProperty(image,"tiff:photometric","separated",exception);
1399
8.27k
        break;
1400
0
      }
1401
13.9k
      case PHOTOMETRIC_YCBCR:
1402
13.9k
      {
1403
13.9k
        (void) SetImageProperty(image,"tiff:photometric","YCBCR",exception);
1404
13.9k
        break;
1405
0
      }
1406
23.6k
      default:
1407
23.6k
      {
1408
23.6k
        (void) SetImageProperty(image,"tiff:photometric","unknown",exception);
1409
23.6k
        break;
1410
0
      }
1411
84.2k
    }
1412
84.2k
    if (image->debug != MagickFalse)
1413
0
      {
1414
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %ux%u",
1415
0
          (unsigned int) width,(unsigned int) height);
1416
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Interlace: %u",
1417
0
          interlace);
1418
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1419
0
          "Bits per sample: %u",bits_per_sample);
1420
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1421
0
          "Min sample value: %u",min_sample_value);
1422
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1423
0
          "Max sample value: %u",max_sample_value);
1424
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Photometric "
1425
0
          "interpretation: %s",GetImageProperty(image,"tiff:photometric",
1426
0
          exception));
1427
0
      }
1428
84.2k
    image->columns=(size_t) width;
1429
84.2k
    image->rows=(size_t) height;
1430
84.2k
    image->depth=(size_t) bits_per_sample;
1431
84.2k
    if (image->debug != MagickFalse)
1432
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Image depth: %.20g",
1433
0
        (double) image->depth);
1434
84.2k
    image->endian=MSBEndian;
1435
84.2k
    if (endian == FILLORDER_LSB2MSB)
1436
553
      image->endian=LSBEndian;
1437
84.2k
    if (TIFFIsBigEndian(tiff) == 0)
1438
52.4k
      {
1439
52.4k
        (void) SetImageProperty(image,"tiff:endian","lsb",exception);
1440
52.4k
        image->endian=LSBEndian;
1441
52.4k
      }
1442
31.7k
    else
1443
31.7k
      {
1444
31.7k
        (void) SetImageProperty(image,"tiff:endian","msb",exception);
1445
31.7k
        image->endian=MSBEndian;
1446
31.7k
      }
1447
84.2k
    if ((photometric == PHOTOMETRIC_MINISBLACK) ||
1448
73.4k
        (photometric == PHOTOMETRIC_MINISWHITE))
1449
25.8k
      (void) SetImageColorspace(image,GRAYColorspace,exception);
1450
84.2k
    if (photometric == PHOTOMETRIC_SEPARATED)
1451
8.27k
      (void) SetImageColorspace(image,CMYKColorspace,exception);
1452
84.2k
    if (photometric == PHOTOMETRIC_CIELAB)
1453
1.48k
      (void) SetImageColorspace(image,LabColorspace,exception);
1454
84.2k
    if ((photometric == PHOTOMETRIC_YCBCR) &&
1455
13.9k
        (compress_tag != COMPRESSION_OJPEG) &&
1456
4.74k
        (compress_tag != COMPRESSION_JPEG))
1457
1.92k
      (void) SetImageColorspace(image,YCbCrColorspace,exception);
1458
84.2k
    TIFFGetProfiles(tiff,image,exception);
1459
84.2k
    status=TIFFGetProperties(tiff,image,exception);
1460
84.2k
    if (status == MagickFalse)
1461
0
      {
1462
0
        TIFFClose(tiff);
1463
0
        return(DestroyImageList(image));
1464
0
      }
1465
84.2k
    TIFFGetEXIFProperties(tiff,image,image_info,exception);
1466
84.2k
    TIFFGetGPSProperties(tiff,image,image_info,exception);
1467
84.2k
    if ((TIFFGetFieldDefaulted(tiff,TIFFTAG_XRESOLUTION,&x_resolution,sans) == 1) &&
1468
5.09k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_YRESOLUTION,&y_resolution,sans) == 1))
1469
5.09k
      {
1470
5.09k
        image->resolution.x=x_resolution;
1471
5.09k
        image->resolution.y=y_resolution;
1472
5.09k
      }
1473
84.2k
    if (TIFFGetFieldDefaulted(tiff,TIFFTAG_RESOLUTIONUNIT,&units,sans,sans) == 1)
1474
84.2k
      {
1475
84.2k
        if (units == RESUNIT_INCH)
1476
82.7k
          image->units=PixelsPerInchResolution;
1477
84.2k
        if (units == RESUNIT_CENTIMETER)
1478
119
          image->units=PixelsPerCentimeterResolution;
1479
84.2k
      }
1480
84.2k
    if ((TIFFGetFieldDefaulted(tiff,TIFFTAG_XPOSITION,&x_position,sans) == 1) &&
1481
2.03k
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_YPOSITION,&y_position,sans) == 1))
1482
2.03k
      {
1483
2.03k
        image->page.x=CastDoubleToSsizeT(ceil((double) x_position*
1484
2.03k
          image->resolution.x-0.5));
1485
2.03k
        image->page.y=CastDoubleToSsizeT(ceil((double) y_position*
1486
2.03k
          image->resolution.y-0.5));
1487
2.03k
      }
1488
84.2k
    if (TIFFGetFieldDefaulted(tiff,TIFFTAG_ORIENTATION,&orientation,sans) == 1)
1489
84.2k
      image->orientation=(OrientationType) orientation;
1490
84.2k
    if (TIFFGetField(tiff,TIFFTAG_WHITEPOINT,&chromaticity) == 1)
1491
1.64k
      {
1492
1.64k
        if ((chromaticity != (float *) NULL) && (*chromaticity != 0.0f))
1493
1.42k
          {
1494
1.42k
            image->chromaticity.white_point.x=chromaticity[0];
1495
1.42k
            image->chromaticity.white_point.y=chromaticity[1];
1496
1.42k
          }
1497
1.64k
      }
1498
84.2k
    if (TIFFGetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,&chromaticity) == 1)
1499
383
      {
1500
383
        if ((chromaticity != (float *) NULL) && (*chromaticity != 0.0f))
1501
316
          {
1502
316
            image->chromaticity.red_primary.x=chromaticity[0];
1503
316
            image->chromaticity.red_primary.y=chromaticity[1];
1504
316
            image->chromaticity.green_primary.x=chromaticity[2];
1505
316
            image->chromaticity.green_primary.y=chromaticity[3];
1506
316
            image->chromaticity.blue_primary.x=chromaticity[4];
1507
316
            image->chromaticity.blue_primary.y=chromaticity[5];
1508
316
          }
1509
383
      }
1510
84.2k
    if ((compress_tag != COMPRESSION_NONE) &&
1511
46.8k
        (TIFFIsCODECConfigured(compress_tag) == 0))
1512
219
      {
1513
219
        TIFFClose(tiff);
1514
219
        ThrowReaderException(CoderError,"CompressNotSupported");
1515
0
      }
1516
83.9k
    switch (compress_tag)
1517
83.9k
    {
1518
37.3k
      case COMPRESSION_NONE: image->compression=NoCompression; break;
1519
6.64k
      case COMPRESSION_CCITTFAX3: image->compression=FaxCompression; break;
1520
4.71k
      case COMPRESSION_CCITTFAX4: image->compression=Group4Compression; break;
1521
9.12k
      case COMPRESSION_JPEG:
1522
9.12k
      {
1523
9.12k
         image->compression=JPEGCompression;
1524
9.12k
#if defined(JPEG_SUPPORT)
1525
9.12k
         {
1526
9.12k
           char
1527
9.12k
             sampling_factor[MagickPathExtent];
1528
1529
9.12k
           uint16
1530
9.12k
             horizontal,
1531
9.12k
             vertical;
1532
1533
9.12k
           tiff_status=TIFFGetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,&horizontal,
1534
9.12k
             &vertical);
1535
9.12k
           if (tiff_status == 1)
1536
236
             {
1537
236
               (void) FormatLocaleString(sampling_factor,MagickPathExtent,
1538
236
                 "%dx%d",horizontal,vertical);
1539
236
               (void) SetImageProperty(image,"jpeg:sampling-factor",
1540
236
                 sampling_factor,exception);
1541
236
               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1542
236
                 "Sampling Factors: %s",sampling_factor);
1543
236
             }
1544
9.12k
         }
1545
9.12k
#endif
1546
9.12k
        break;
1547
0
      }
1548
12.6k
      case COMPRESSION_OJPEG: image->compression=JPEGCompression; break;
1549
0
#if defined(COMPRESSION_LERC)
1550
0
      case COMPRESSION_LERC: image->compression=LERCCompression; break;
1551
0
#endif
1552
0
#if defined(COMPRESSION_LZMA)
1553
1.37k
      case COMPRESSION_LZMA: image->compression=LZMACompression; break;
1554
0
#endif
1555
2.28k
      case COMPRESSION_LZW: image->compression=LZWCompression; break;
1556
148
      case COMPRESSION_DEFLATE: image->compression=ZipCompression; break;
1557
2.28k
      case COMPRESSION_ADOBE_DEFLATE: image->compression=ZipCompression; break;
1558
0
#if defined(COMPRESSION_WEBP)
1559
0
      case COMPRESSION_WEBP: image->compression=WebPCompression; break;
1560
0
#endif
1561
0
#if defined(COMPRESSION_ZSTD)
1562
0
      case COMPRESSION_ZSTD: image->compression=ZstdCompression; break;
1563
0
#endif
1564
7.37k
      default: image->compression=RLECompression; break;
1565
83.9k
    }
1566
83.9k
    quantum_info=(QuantumInfo *) NULL;
1567
83.9k
    if ((photometric == PHOTOMETRIC_PALETTE) &&
1568
1.78k
        (pow(2.0,1.0*bits_per_sample) <= MaxColormapSize))
1569
1.78k
      {
1570
1.78k
        size_t
1571
1.78k
          colors;
1572
1573
1.78k
        colors=(size_t) GetQuantumRange(bits_per_sample)+1;
1574
1.78k
        if (AcquireImageColormap(image,colors,exception) == MagickFalse)
1575
0
          {
1576
0
            TIFFClose(tiff);
1577
0
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1578
0
          }
1579
1.78k
      }
1580
83.9k
    if ((TIFFGetFieldDefaulted(tiff,TIFFTAG_PAGENUMBER,&page,&pages,sans) == 1) &&
1581
827
        (page >= (unsigned short) image->scene))
1582
592
      image->scene=(size_t) page;
1583
83.9k
    if (image->storage_class == PseudoClass)
1584
1.78k
      {
1585
1.78k
        size_t
1586
1.78k
          range;
1587
1588
1.78k
        uint16
1589
1.78k
          *blue_colormap = (uint16 *) NULL,
1590
1.78k
          *green_colormap = (uint16 *) NULL,
1591
1.78k
          *red_colormap = (uint16 *) NULL;
1592
1593
        /*
1594
          Initialize colormap.
1595
        */
1596
1.78k
        tiff_status=TIFFGetField(tiff,TIFFTAG_COLORMAP,&red_colormap,
1597
1.78k
          &green_colormap,&blue_colormap);
1598
1.78k
        if (tiff_status == 1)
1599
1.78k
          {
1600
1.78k
            if ((red_colormap != (uint16 *) NULL) &&
1601
1.78k
                (green_colormap != (uint16 *) NULL) &&
1602
1.78k
                (blue_colormap != (uint16 *) NULL))
1603
1.78k
              {
1604
1.78k
                range=255;  /* might be old style 8-bit colormap */
1605
25.2k
                for (i=0; i < (ssize_t) image->colors; i++)
1606
24.8k
                  if ((red_colormap[i] >= 256) || (green_colormap[i] >= 256) ||
1607
23.6k
                      (blue_colormap[i] >= 256))
1608
1.39k
                    {
1609
1.39k
                      range=65535;
1610
1.39k
                      break;
1611
1.39k
                    }
1612
61.7k
                for (i=0; i < (ssize_t) image->colors; i++)
1613
59.9k
                {
1614
59.9k
                  image->colormap[i].red=ClampToQuantum(((double)
1615
59.9k
                    QuantumRange*red_colormap[i])/range);
1616
59.9k
                  image->colormap[i].green=ClampToQuantum(((double)
1617
59.9k
                    QuantumRange*green_colormap[i])/range);
1618
59.9k
                  image->colormap[i].blue=ClampToQuantum(((double)
1619
59.9k
                    QuantumRange*blue_colormap[i])/range);
1620
59.9k
                }
1621
1.78k
              }
1622
1.78k
          }
1623
1.78k
      }
1624
83.9k
    if (image_info->ping != MagickFalse)
1625
967
      {
1626
967
        if (image_info->number_scenes != 0)
1627
123
          if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1628
123
            break;
1629
844
        goto next_tiff_frame;
1630
967
      }
1631
83.0k
    status=SetImageExtent(image,image->columns,image->rows,exception);
1632
83.0k
    if (status == MagickFalse)
1633
5.40k
      {
1634
5.40k
        TIFFClose(tiff);
1635
5.40k
        return(DestroyImageList(image));
1636
5.40k
      }
1637
77.6k
    status=SetImageColorspace(image,image->colorspace,exception);
1638
77.6k
    status&=(MagickStatusType) ResetImagePixels(image,exception);
1639
77.6k
    if (status == MagickFalse)
1640
0
      {
1641
0
        TIFFClose(tiff);
1642
0
        return(DestroyImageList(image));
1643
0
      }
1644
    /*
1645
      Allocate memory for the image and pixel buffer.
1646
    */
1647
77.6k
    quantum_info=AcquireQuantumInfo(image_info,image);
1648
77.6k
    if (quantum_info == (QuantumInfo *) NULL)
1649
77.6k
      ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
1650
77.6k
    if (sample_format == SAMPLEFORMAT_UINT)
1651
67.4k
      status=SetQuantumFormat(image,quantum_info,UnsignedQuantumFormat);
1652
77.6k
    if (sample_format == SAMPLEFORMAT_INT)
1653
889
      status=SetQuantumFormat(image,quantum_info,SignedQuantumFormat);
1654
77.6k
    if (sample_format == SAMPLEFORMAT_IEEEFP)
1655
8.48k
      status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1656
77.6k
    if (status == MagickFalse)
1657
77.6k
      ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
1658
77.6k
    status=MagickTrue;
1659
77.6k
    switch (photometric)
1660
77.6k
    {
1661
10.2k
      case PHOTOMETRIC_MINISBLACK:
1662
10.2k
      {
1663
10.2k
        SetQuantumMinIsWhite(quantum_info,MagickFalse);
1664
10.2k
        break;
1665
0
      }
1666
14.2k
      case PHOTOMETRIC_MINISWHITE:
1667
14.2k
      {
1668
14.2k
        SetQuantumMinIsWhite(quantum_info,MagickTrue);
1669
14.2k
        break;
1670
0
      }
1671
53.0k
      default:
1672
53.0k
        break;
1673
77.6k
    }
1674
77.6k
    tiff_status=TIFFGetFieldDefaulted(tiff,TIFFTAG_EXTRASAMPLES,&extra_samples,
1675
77.6k
      &sample_info,sans);
1676
77.6k
    if (extra_samples == 0)
1677
62.4k
      {
1678
62.4k
        if ((samples_per_pixel == 4) && (photometric == PHOTOMETRIC_RGB))
1679
0
          image->alpha_trait=BlendPixelTrait;
1680
62.4k
      }
1681
15.2k
    else
1682
15.2k
      {
1683
86.5k
        for (i=0; i < extra_samples; i++)
1684
79.9k
        {
1685
79.9k
          if (sample_info[i] == EXTRASAMPLE_ASSOCALPHA)
1686
5.37k
            {
1687
5.37k
              image->alpha_trait=BlendPixelTrait;
1688
5.37k
              SetQuantumAlphaType(quantum_info,AssociatedQuantumAlpha);
1689
5.37k
              (void) SetImageProperty(image,"tiff:alpha","associated",
1690
5.37k
                exception);
1691
5.37k
              break;
1692
5.37k
            }
1693
74.5k
          else
1694
74.5k
            if (sample_info[i] == EXTRASAMPLE_UNASSALPHA)
1695
3.18k
              {
1696
3.18k
                image->alpha_trait=BlendPixelTrait;
1697
3.18k
                SetQuantumAlphaType(quantum_info,DisassociatedQuantumAlpha);
1698
3.18k
                (void) SetImageProperty(image,"tiff:alpha","unassociated",
1699
3.18k
                  exception);
1700
3.18k
                break;
1701
3.18k
              }
1702
79.9k
        }
1703
15.2k
        if ((image->alpha_trait == UndefinedPixelTrait) && (extra_samples >= 1))
1704
6.65k
          {
1705
6.65k
            const char
1706
6.65k
              *option;
1707
1708
6.65k
            option=GetImageOption(image_info,"tiff:assume-alpha");
1709
6.65k
            if (IsStringTrue(option) != MagickFalse)
1710
0
              image->alpha_trait=BlendPixelTrait;
1711
6.65k
          }
1712
15.2k
        if (image->alpha_trait != UndefinedPixelTrait)
1713
8.55k
          extra_samples--;
1714
15.2k
        if (extra_samples > 0)
1715
7.32k
          {
1716
7.32k
            if (SetPixelMetaChannels(image,extra_samples,exception) == MagickFalse)
1717
7.26k
              ThrowTIFFException(OptionError,"SetPixelMetaChannelsFailure");
1718
7.26k
          }
1719
15.2k
      }
1720
77.5k
    if (image->alpha_trait != UndefinedPixelTrait)
1721
8.54k
      {
1722
8.54k
        if (quantum_info->alpha_type == UndefinedQuantumAlpha)
1723
0
          (void) SetImageProperty(image,"tiff:alpha","unspecified",exception);
1724
8.54k
        (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1725
8.54k
      }
1726
77.5k
    method=ReadGenericMethod;
1727
77.5k
    rows_per_strip=(uint32) image->rows;
1728
77.5k
    if (TIFFGetField(tiff,TIFFTAG_ROWSPERSTRIP,&rows_per_strip) == 1)
1729
32.6k
      {
1730
32.6k
        char
1731
32.6k
          buffer[MagickPathExtent];
1732
1733
32.6k
        (void) FormatLocaleString(buffer,MagickPathExtent,"%u",
1734
32.6k
          (unsigned int) rows_per_strip);
1735
32.6k
        (void) SetImageProperty(image,"tiff:rows-per-strip",buffer,exception);
1736
32.6k
        method=ReadStripMethod;
1737
32.6k
        if (rows_per_strip > (uint32) image->rows)
1738
21.7k
          rows_per_strip=(uint32) image->rows;
1739
32.6k
      }
1740
44.9k
    else if (image->depth > 8)
1741
6.75k
      method=ReadStripMethod;
1742
77.5k
    if (TIFFIsTiled(tiff) != MagickFalse)
1743
11.0k
      {
1744
11.0k
        uint32
1745
11.0k
          columns,
1746
11.0k
          rows;
1747
1748
11.0k
        if ((TIFFGetField(tiff,TIFFTAG_TILEWIDTH,&columns) != 1) ||
1749
11.0k
            (TIFFGetField(tiff,TIFFTAG_TILELENGTH,&rows) != 1))
1750
11.0k
          ThrowTIFFException(CoderError,"ImageIsNotTiled");
1751
11.0k
        if ((AcquireMagickResource(WidthResource,columns) == MagickFalse) ||
1752
10.9k
            (AcquireMagickResource(HeightResource,rows) == MagickFalse))
1753
10.7k
          ThrowTIFFException(ImageError,"WidthOrHeightExceedsLimit");
1754
10.7k
        method=ReadTileMethod;
1755
10.7k
      }
1756
77.2k
    if ((photometric == PHOTOMETRIC_LOGLUV) ||
1757
76.1k
        (compress_tag == COMPRESSION_CCITTFAX3))
1758
7.50k
      method=ReadGenericMethod;
1759
77.2k
    if (image->compression == JPEGCompression)
1760
19.5k
      {
1761
19.5k
        if (photometric == PHOTOMETRIC_SEPARATED)
1762
2.15k
          method=GetJPEGMethod(image,tiff,photometric,bits_per_sample);
1763
17.3k
        else if ((method != ReadStripMethod) ||
1764
3.89k
                 (compress_tag == COMPRESSION_OJPEG) ||
1765
1.11k
                 (photometric == PHOTOMETRIC_YCBCR))
1766
16.8k
          method=ReadGenericMethod;
1767
19.5k
      }
1768
#if defined(WORDS_BIGENDIAN)
1769
    (void) SetQuantumEndian(image,quantum_info,MSBEndian);
1770
#else
1771
77.2k
    (void) SetQuantumEndian(image,quantum_info,LSBEndian);
1772
77.2k
#endif
1773
77.2k
    scanline_size=TIFFScanlineSize(tiff);
1774
77.2k
    if (scanline_size <= 0)
1775
77.2k
      ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
1776
77.2k
    number_pixels=MagickMax((MagickSizeType) (image->columns*samples_per_pixel*
1777
77.2k
      pow(2.0,ceil(log(bits_per_sample)/log(2.0)))),image->columns*
1778
77.2k
      rows_per_strip);
1779
77.2k
    if ((double) scanline_size > 1.5*number_pixels)
1780
77.2k
      ThrowTIFFException(CorruptImageError,"CorruptImage");
1781
77.2k
    number_pixels=MagickMax((MagickSizeType) scanline_size,number_pixels);
1782
77.2k
    pixel_info=AcquireVirtualMemory((size_t) number_pixels,sizeof(uint32));
1783
77.2k
    if (pixel_info == (MemoryInfo *) NULL)
1784
77.2k
      ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
1785
77.2k
    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
1786
77.2k
    (void) memset(pixels,0,(size_t) number_pixels*sizeof(uint32));
1787
77.2k
    image_quantum_type=GrayQuantum;
1788
77.2k
    if (image->storage_class == PseudoClass)
1789
1.76k
      image_quantum_type=IndexQuantum;
1790
77.2k
    if (image->number_meta_channels != 0)
1791
7.24k
      {
1792
7.24k
        image_quantum_type=MultispectralQuantum;
1793
7.24k
        (void) SetQuantumPad(image,quantum_info,0);
1794
7.24k
      }
1795
70.0k
    else
1796
70.0k
      if (interlace != PLANARCONFIG_SEPARATE)
1797
64.3k
        {
1798
64.3k
          ssize_t
1799
64.3k
            pad;
1800
1801
64.3k
          pad=(ssize_t) samples_per_pixel;
1802
64.3k
          if (samples_per_pixel > 2)
1803
25.4k
            {
1804
25.4k
              if (image->colorspace == CMYKColorspace)
1805
4.93k
                {
1806
4.93k
                  pad-=4;
1807
4.93k
                  image_quantum_type=CMYKQuantum;
1808
4.93k
                  if (image->alpha_trait != UndefinedPixelTrait)
1809
1.48k
                    {
1810
1.48k
                      pad--;
1811
1.48k
                      image_quantum_type=CMYKAQuantum;
1812
1.48k
                    }
1813
4.93k
                }
1814
20.4k
              else
1815
20.4k
                {
1816
20.4k
                  pad-=3;
1817
20.4k
                  image_quantum_type=RGBQuantum;
1818
20.4k
                  if (image->alpha_trait != UndefinedPixelTrait)
1819
2.12k
                    {
1820
2.12k
                      pad--;
1821
2.12k
                      image_quantum_type=RGBAQuantum;
1822
2.12k
                    }
1823
20.4k
                }
1824
25.4k
            }
1825
38.8k
          else
1826
38.8k
            {
1827
38.8k
              pad--;
1828
38.8k
              if (image->alpha_trait != UndefinedPixelTrait)
1829
3.51k
                {
1830
3.51k
                  if (samples_per_pixel == 1)
1831
1.58k
                    image_quantum_type=AlphaQuantum;
1832
1.93k
                  else
1833
1.93k
                    {
1834
1.93k
                      pad--;
1835
1.93k
                      if (image->storage_class == PseudoClass)
1836
161
                        image_quantum_type=IndexAlphaQuantum;
1837
1.77k
                      else
1838
1.77k
                        image_quantum_type=GrayAlphaQuantum;
1839
1.93k
                    }
1840
3.51k
                }
1841
38.8k
            }
1842
64.3k
          if (pad < 0)
1843
64.2k
            ThrowTIFFException(CorruptImageError,"CorruptImage");
1844
64.2k
          if (pad > 0)
1845
5.33k
            {
1846
5.33k
              status=SetQuantumPad(image,quantum_info,(size_t) pad*
1847
5.33k
                ((bits_per_sample+7) >> 3));
1848
5.33k
              if (status == MagickFalse)
1849
5.33k
                ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
1850
5.33k
            }
1851
64.2k
        }
1852
77.2k
    if (exception->severity < ErrorException)
1853
58.2k
      switch (method)
1854
58.2k
      {
1855
0
        case ReadYCCKMethod:
1856
0
        {
1857
          /*
1858
            Convert YCC TIFF image.
1859
          */
1860
0
          for (y=0; y < (ssize_t) image->rows; y++)
1861
0
          {
1862
0
            Quantum
1863
0
              *magick_restrict q;
1864
1865
0
            ssize_t
1866
0
              x;
1867
1868
0
            unsigned char
1869
0
              *p;
1870
1871
0
            tiff_status=TIFFReadPixels(tiff,0,y,(char *) pixels);
1872
0
            if (tiff_status == -1)
1873
0
              break;
1874
0
            q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1875
0
            if (q == (Quantum *) NULL)
1876
0
              break;
1877
0
            p=pixels;
1878
0
            for (x=0; x < (ssize_t) image->columns; x++)
1879
0
            {
1880
0
              SetPixelCyan(image,ScaleCharToQuantum(ClampYCC((double) *p+
1881
0
                (1.402*(double) *(p+2))-179.456)),q);
1882
0
              SetPixelMagenta(image,ScaleCharToQuantum(ClampYCC((double) *p-
1883
0
                (0.34414*(double) *(p+1))-(0.71414*(double ) *(p+2))+
1884
0
                135.45984)),q);
1885
0
              SetPixelYellow(image,ScaleCharToQuantum(ClampYCC((double) *p+
1886
0
                (1.772*(double) *(p+1))-226.816)),q);
1887
0
              SetPixelBlack(image,ScaleCharToQuantum((unsigned char) *(p+3)),q);
1888
0
              q+=(ptrdiff_t) GetPixelChannels(image);
1889
0
              p+=(ptrdiff_t) 4;
1890
0
            }
1891
0
            if (SyncAuthenticPixels(image,exception) == MagickFalse)
1892
0
              break;
1893
0
            if (image->previous == (Image *) NULL)
1894
0
              {
1895
0
                status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1896
0
                  image->rows);
1897
0
                if (status == MagickFalse)
1898
0
                  break;
1899
0
              }
1900
0
          }
1901
0
          break;
1902
0
        }
1903
26.8k
        case ReadStripMethod:
1904
26.8k
        {
1905
26.8k
          size_t
1906
26.8k
            count,
1907
26.8k
            extent,
1908
26.8k
            length,
1909
26.8k
            stride,
1910
26.8k
            strip_size;
1911
1912
26.8k
          uint32_t
1913
26.8k
            strip_id;
1914
1915
26.8k
          unsigned char
1916
26.8k
            *p,
1917
26.8k
            *strip_pixels;
1918
1919
          /*
1920
            Convert stripped TIFF image.
1921
          */
1922
26.8k
          strip_size=(size_t) TIFFStripSize(tiff);
1923
26.8k
          stride=(ssize_t) TIFFVStripSize(tiff,1);
1924
26.8k
          length=GetQuantumExtent(image,quantum_info,image_quantum_type);
1925
26.8k
          if (HeapOverflowSanityCheckGetSize(rows_per_strip,MagickMax(stride,length),&count) != MagickFalse)
1926
26.8k
            ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
1927
26.8k
          extent=MagickMax(strip_size,count);
1928
26.8k
          strip_pixels=(unsigned char *) AcquireQuantumMemory(extent,
1929
26.8k
            sizeof(*strip_pixels));
1930
26.8k
          if (strip_pixels == (unsigned char *) NULL)
1931
26.8k
            ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
1932
26.8k
          (void) memset(strip_pixels,0,extent*sizeof(*strip_pixels));
1933
26.8k
          strip_id=0;
1934
26.8k
          p=strip_pixels;
1935
47.1k
          for (i=0; i < (ssize_t) samples_per_pixel; i++)
1936
38.6k
          {
1937
38.6k
            QuantumType
1938
38.6k
              quantum_type = image_quantum_type;
1939
1940
38.6k
            size_t
1941
38.6k
              rows_remaining;
1942
1943
38.6k
            tmsize_t
1944
38.6k
              size = 0;
1945
1946
38.6k
            switch (i)
1947
38.6k
            {
1948
26.8k
              case 0:
1949
26.8k
              {
1950
26.8k
                if (interlace == PLANARCONFIG_SEPARATE)
1951
1.84k
                  quantum_type=RedQuantum;
1952
26.8k
                break;
1953
0
              }
1954
549
              case 1: quantum_type=GreenQuantum; break;
1955
509
              case 2: quantum_type=BlueQuantum; break;
1956
479
              case 3:
1957
479
              {
1958
479
                quantum_type=AlphaQuantum;
1959
479
                if (image->colorspace == CMYKColorspace)
1960
116
                  quantum_type=BlackQuantum;
1961
479
                break;
1962
0
              }
1963
465
              case 4:
1964
465
              {
1965
465
                if (image->colorspace == CMYKColorspace)
1966
112
                  {
1967
112
                    quantum_type=AlphaQuantum;
1968
112
                    break;
1969
112
                  }
1970
353
                magick_fallthrough;
1971
353
              }
1972
10.1k
              default:
1973
10.1k
              {
1974
10.1k
                if (quantum_type == MultispectralQuantum)
1975
4.42k
                  {
1976
4.42k
                    if (image->colorspace == CMYKColorspace)
1977
2.39k
                      (void) SetQuantumMetaChannel(image,quantum_info,i-5);
1978
2.03k
                    else
1979
2.03k
                      (void) SetQuantumMetaChannel(image,quantum_info,i-4);
1980
4.42k
                  }
1981
10.1k
                break;
1982
353
              }
1983
38.6k
            }
1984
38.6k
            rows_remaining=0;
1985
1.71M
            for (y=0; y < (ssize_t) image->rows; y++)
1986
1.68M
            {
1987
1.68M
              Quantum
1988
1.68M
                *magick_restrict q;
1989
1990
1.68M
              q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
1991
1.68M
              if (q == (Quantum *) NULL)
1992
0
                break;
1993
1.68M
              if (rows_remaining == 0)
1994
53.2k
                {
1995
53.2k
                  size=TIFFReadEncodedStrip(tiff,strip_id,strip_pixels,
1996
53.2k
                    strip_size);
1997
53.2k
                  if (size == -1)
1998
6.71k
                    break;
1999
46.5k
                  rows_remaining=rows_per_strip;
2000
46.5k
                  p=strip_pixels;
2001
46.5k
                  strip_id++;
2002
46.5k
                }
2003
1.67M
              (void) ImportQuantumPixels(image,(CacheView *) NULL,
2004
1.67M
                quantum_info,quantum_type,p,exception);
2005
1.67M
              p+=(ptrdiff_t) stride;
2006
1.67M
              rows_remaining--;
2007
1.67M
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
2008
0
                break;
2009
1.67M
              if (image->previous == (Image *) NULL)
2010
1.67M
                {
2011
1.67M
                  status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
2012
1.67M
                    y,image->rows);
2013
1.67M
                  if (status == MagickFalse)
2014
0
                    break;
2015
1.67M
                }
2016
1.67M
            }
2017
38.6k
            if ((size == -1) || ((samples_per_pixel > 1) &&
2018
23.9k
                (interlace != PLANARCONFIG_SEPARATE)))
2019
18.3k
              break;
2020
38.6k
          }
2021
26.8k
          (void) SetQuantumMetaChannel(image,quantum_info,-1);
2022
26.8k
          strip_pixels=(unsigned char *) RelinquishMagickMemory(strip_pixels);
2023
26.8k
          break;
2024
26.8k
        }
2025
3.96k
        case ReadTileMethod:
2026
3.96k
        {
2027
3.96k
          size_t
2028
3.96k
            count,
2029
3.96k
            extent,
2030
3.96k
            length,
2031
3.96k
            stride,
2032
3.96k
            tile_size;
2033
2034
3.96k
          uint32
2035
3.96k
            columns,
2036
3.96k
            rows;
2037
2038
3.96k
          unsigned char
2039
3.96k
            *p,
2040
3.96k
            *tile_pixels;
2041
2042
          /*
2043
            Convert tiled TIFF image.
2044
          */
2045
3.96k
          if ((TIFFGetField(tiff,TIFFTAG_TILEWIDTH,&columns) != 1) ||
2046
3.96k
              (TIFFGetField(tiff,TIFFTAG_TILELENGTH,&rows) != 1))
2047
3.96k
            ThrowTIFFException(CoderError,"ImageIsNotTiled");
2048
3.96k
          if (HeapOverflowSanityCheckGetSize(columns,rows,&count) != MagickFalse)
2049
3.96k
            ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
2050
3.96k
          number_pixels=(MagickSizeType) count;
2051
3.96k
          if (HeapOverflowSanityCheck(rows,sizeof(*tile_pixels)) != MagickFalse)
2052
3.96k
            ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
2053
3.96k
          tile_size=(size_t) TIFFTileSize(tiff);
2054
3.96k
          stride=(size_t) TIFFTileRowSize(tiff);
2055
3.96k
          length=GetQuantumExtent(image,quantum_info,image_quantum_type);
2056
3.96k
          if (HeapOverflowSanityCheckGetSize(rows,MagickMax(stride,length),&count) != MagickFalse)
2057
3.96k
            ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
2058
3.96k
          extent=MagickMax(tile_size,count);
2059
3.96k
          tile_pixels=(unsigned char *) AcquireQuantumMemory(extent,
2060
3.96k
            sizeof(*tile_pixels));
2061
3.96k
          if (tile_pixels == (unsigned char *) NULL)
2062
3.96k
            ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
2063
3.96k
          (void) memset(tile_pixels,0,extent*sizeof(*tile_pixels));
2064
8.89k
          for (i=0; i < (ssize_t) samples_per_pixel; i++)
2065
8.23k
          {
2066
8.23k
            QuantumType
2067
8.23k
              quantum_type = image_quantum_type;
2068
2069
8.23k
            tmsize_t
2070
8.23k
              size = 0;
2071
2072
8.23k
            switch (i)
2073
8.23k
            {
2074
3.96k
              case 0:
2075
3.96k
              {
2076
3.96k
                if (interlace == PLANARCONFIG_SEPARATE)
2077
823
                  quantum_type=RedQuantum;
2078
3.96k
                break;
2079
0
              }
2080
345
              case 1: quantum_type=GreenQuantum; break;
2081
284
              case 2: quantum_type=BlueQuantum; break;
2082
213
              case 3:
2083
213
              {
2084
213
                quantum_type=AlphaQuantum;
2085
213
                if (image->colorspace == CMYKColorspace)
2086
48
                  quantum_type=BlackQuantum;
2087
213
                break;
2088
0
              }
2089
200
              case 4:
2090
200
              {
2091
200
                if (image->colorspace == CMYKColorspace)
2092
45
                  {
2093
45
                    quantum_type=AlphaQuantum;
2094
45
                    break;
2095
45
                  }
2096
155
                magick_fallthrough;
2097
155
              }
2098
3.38k
              default:
2099
3.38k
              {
2100
3.38k
                if (quantum_type == MultispectralQuantum)
2101
1.34k
                  {
2102
1.34k
                    if (image->colorspace == CMYKColorspace)
2103
506
                      (void) SetQuantumMetaChannel(image,quantum_info,i-5);
2104
838
                    else
2105
838
                      (void) SetQuantumMetaChannel(image,quantum_info,i-4);
2106
1.34k
                  }
2107
3.38k
                break;
2108
155
              }
2109
8.23k
            }
2110
23.2k
            for (y=0; y < (ssize_t) image->rows; y+=rows)
2111
18.2k
            {
2112
18.2k
              ssize_t
2113
18.2k
                x;
2114
2115
18.2k
              size_t
2116
18.2k
                rows_remaining;
2117
2118
18.2k
              rows_remaining=image->rows-(size_t) y;
2119
18.2k
              if ((ssize_t) (y+rows) < (ssize_t) image->rows)
2120
11.9k
                rows_remaining=rows;
2121
908k
              for (x=0; x < (ssize_t) image->columns; x+=columns)
2122
893k
              {
2123
893k
                size_t
2124
893k
                  columns_remaining,
2125
893k
                  row;
2126
2127
893k
                columns_remaining=image->columns-(size_t) x;
2128
893k
                if ((x+(ssize_t) columns) < (ssize_t) image->columns)
2129
877k
                  columns_remaining=columns;
2130
893k
                size=TIFFReadTile(tiff,tile_pixels,(uint32_t) x,(uint32_t) y,
2131
893k
                  0,(uint16_t) i);
2132
893k
                if (size == -1)
2133
3.25k
                  break;
2134
890k
                p=tile_pixels;
2135
7.01M
                for (row=0; row < rows_remaining; row++)
2136
6.12M
                {
2137
6.12M
                  Quantum
2138
6.12M
                    *magick_restrict q;
2139
2140
6.12M
                  q=GetAuthenticPixels(image,x,y+(ssize_t) row,
2141
6.12M
                    columns_remaining,1,exception);
2142
6.12M
                  if (q == (Quantum *) NULL)
2143
0
                    break;
2144
6.12M
                  (void) ImportQuantumPixels(image,(CacheView *) NULL,
2145
6.12M
                    quantum_info,quantum_type,p,exception);
2146
6.12M
                  p+=(ptrdiff_t) stride;
2147
6.12M
                  if (SyncAuthenticPixels(image,exception) == MagickFalse)
2148
0
                    break;
2149
6.12M
                }
2150
890k
              }
2151
18.2k
              if (size == -1)
2152
3.25k
                break;
2153
18.2k
            }
2154
8.23k
            if ((size == -1) || ((samples_per_pixel > 1) &&
2155
4.53k
                (interlace != PLANARCONFIG_SEPARATE)))
2156
3.30k
              break;
2157
4.93k
            if (image->previous == (Image *) NULL)
2158
4.92k
              {
2159
4.92k
                status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) i,
2160
4.92k
                  samples_per_pixel);
2161
4.92k
                if (status == MagickFalse)
2162
0
                  break;
2163
4.92k
              }
2164
4.93k
          }
2165
3.96k
          (void) SetQuantumMetaChannel(image,quantum_info,-1);
2166
3.96k
          tile_pixels=(unsigned char *) RelinquishMagickMemory(tile_pixels);
2167
3.96k
          break;
2168
3.96k
        }
2169
27.4k
        case ReadGenericMethod:
2170
27.4k
        default:
2171
27.4k
        {
2172
27.4k
          MemoryInfo
2173
27.4k
            *generic_info = (MemoryInfo * ) NULL;
2174
2175
27.4k
          size_t
2176
27.4k
            count;
2177
2178
27.4k
          uint32
2179
27.4k
            *p;
2180
2181
          /*
2182
            Convert generic TIFF image.
2183
          */
2184
27.4k
          (void) SetImageStorageClass(image,DirectClass,exception);
2185
27.4k
          if (HeapOverflowSanityCheckGetSize(image->rows,image->columns,&count) != MagickFalse)
2186
27.4k
            ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
2187
27.4k
          number_pixels=(MagickSizeType) count;
2188
27.4k
          generic_info=AcquireVirtualMemory(count,sizeof(*p));
2189
27.4k
          if (generic_info == (MemoryInfo *) NULL)
2190
27.4k
            ThrowTIFFException(ResourceLimitError,"MemoryAllocationFailed");
2191
27.4k
          p=(uint32 *) GetVirtualMemoryBlob(generic_info);
2192
27.4k
          (void) memset(p,0,count*sizeof(*p));
2193
27.4k
          tiff_status=TIFFReadRGBAImage(tiff,(uint32) image->columns,(uint32)
2194
27.4k
            image->rows,p,0);
2195
27.4k
          if (tiff_status == -1)
2196
0
            {
2197
0
              generic_info=RelinquishVirtualMemory(generic_info);
2198
0
              break;
2199
0
            }
2200
27.4k
          p+=(ptrdiff_t) (image->columns*image->rows)-1;
2201
10.2M
          for (y=0; y < (ssize_t) image->rows; y++)
2202
10.2M
          {
2203
10.2M
            ssize_t
2204
10.2M
              x;
2205
2206
10.2M
            Quantum
2207
10.2M
              *magick_restrict q;
2208
2209
10.2M
            q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
2210
10.2M
            if (q == (Quantum *) NULL)
2211
0
              break;
2212
10.2M
            q+=(ptrdiff_t) GetPixelChannels(image)*(image->columns-1);
2213
4.35G
            for (x=0; x < (ssize_t) image->columns; x++)
2214
4.34G
            {
2215
4.34G
              SetPixelRed(image,ScaleCharToQuantum((unsigned char)
2216
4.34G
                TIFFGetR(*p)),q);
2217
4.34G
              SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
2218
4.34G
                TIFFGetG(*p)),q);
2219
4.34G
              SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
2220
4.34G
                TIFFGetB(*p)),q);
2221
4.34G
              if (image->alpha_trait != UndefinedPixelTrait)
2222
6.15M
                SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
2223
6.15M
                  TIFFGetA(*p)),q);
2224
4.34G
              p--;
2225
4.34G
              q-=GetPixelChannels(image);
2226
4.34G
            }
2227
10.2M
            if (SyncAuthenticPixels(image,exception) == MagickFalse)
2228
0
              break;
2229
10.2M
            if (image->previous == (Image *) NULL)
2230
10.0M
              {
2231
10.0M
                status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
2232
10.0M
                  image->rows);
2233
10.0M
                if (status == MagickFalse)
2234
0
                  break;
2235
10.0M
              }
2236
10.2M
          }
2237
27.4k
          generic_info=RelinquishVirtualMemory(generic_info);
2238
27.4k
          break;
2239
27.4k
        }
2240
58.2k
      }
2241
77.2k
    pixel_info=RelinquishVirtualMemory(pixel_info);
2242
77.2k
    SetQuantumImageType(image,image_quantum_type);
2243
78.0k
  next_tiff_frame:
2244
78.0k
    if (quantum_info != (QuantumInfo *) NULL)
2245
77.2k
      quantum_info=DestroyQuantumInfo(quantum_info);
2246
78.0k
    if (tiff_status == -1)
2247
0
      {
2248
0
        status=MagickFalse;
2249
0
        break;
2250
0
      }
2251
78.0k
    if (photometric == PHOTOMETRIC_CIELAB)
2252
1.40k
      DecodeLabImage(image,exception);
2253
78.0k
    if ((photometric == PHOTOMETRIC_LOGL) ||
2254
76.9k
        (photometric == PHOTOMETRIC_MINISBLACK) ||
2255
66.7k
        (photometric == PHOTOMETRIC_MINISWHITE))
2256
25.6k
      {
2257
25.6k
        image->type=GrayscaleType;
2258
25.6k
        if (bits_per_sample == 1)
2259
16.3k
          image->type=BilevelType;
2260
25.6k
      }
2261
    /*
2262
      Proceed to next image.
2263
    */
2264
78.0k
    if (image_info->number_scenes != 0)
2265
14.9k
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
2266
14.9k
        break;
2267
63.1k
    more_frames=TIFFReadDirectory(tiff) != 0 ? MagickTrue : MagickFalse;
2268
63.1k
    if (more_frames != MagickFalse)
2269
13.9k
      {
2270
        /*
2271
          Allocate next image structure.
2272
        */
2273
13.9k
        AcquireNextImage(image_info,image,exception);
2274
13.9k
        if (GetNextImageInList(image) == (Image *) NULL)
2275
0
          {
2276
0
            status=MagickFalse;
2277
0
            break;
2278
0
          }
2279
13.9k
        image=SyncNextImageInList(image);
2280
13.9k
        status=SetImageProgress(image,LoadImagesTag,(MagickOffsetType)
2281
13.9k
          image->scene-1,image->scene);
2282
13.9k
        if (status == MagickFalse)
2283
0
          break;
2284
13.9k
      }
2285
63.1k
  } while ((status != MagickFalse) && (more_frames != MagickFalse));
2286
64.2k
  TIFFClose(tiff);
2287
64.2k
  if (status != MagickFalse)
2288
64.2k
    TIFFReadPhotoshopLayers(image_info,image,exception);
2289
64.2k
  if ((image_info->number_scenes != 0) &&
2290
15.0k
      (image_info->scene >= GetImageListLength(image)))
2291
16
    status=MagickFalse;
2292
64.2k
  if (status == MagickFalse)
2293
16
    return(DestroyImageList(image));
2294
64.2k
  return(GetFirstImageInList(image));
2295
64.2k
}
2296
#endif
2297

2298
/*
2299
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2300
%                                                                             %
2301
%                                                                             %
2302
%                                                                             %
2303
%   R e g i s t e r T I F F I m a g e                                         %
2304
%                                                                             %
2305
%                                                                             %
2306
%                                                                             %
2307
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2308
%
2309
%  RegisterTIFFImage() adds properties for the TIFF image format to
2310
%  the list of supported formats.  The properties include the image format
2311
%  tag, a method to read and/or write the format, whether the format
2312
%  supports the saving of more than one frame to the same file or blob,
2313
%  whether the format supports native in-memory I/O, and a brief
2314
%  description of the format.
2315
%
2316
%  The format of the RegisterTIFFImage method is:
2317
%
2318
%      size_t RegisterTIFFImage(void)
2319
%
2320
*/
2321
2322
#if defined(MAGICKCORE_TIFF_DELEGATE)
2323
static TIFFExtendProc
2324
  tag_extender = (TIFFExtendProc) NULL;
2325
2326
static void TIFFIgnoreTags(TIFF *tiff)
2327
206k
{
2328
206k
  char
2329
206k
    *q;
2330
2331
206k
  const char
2332
206k
    *p,
2333
206k
    *tags;
2334
2335
206k
  Image
2336
206k
   *image;
2337
2338
206k
  size_t
2339
206k
    count;
2340
2341
206k
  ssize_t
2342
206k
    i;
2343
2344
206k
  static const
2345
206k
    char *dummy_name = "";
2346
2347
206k
  TIFFFieldInfo
2348
206k
    *ignore;
2349
2350
206k
  if (TIFFGetReadProc(tiff) != TIFFReadBlob)
2351
6.89k
    return;
2352
199k
  image=(Image *)TIFFClientdata(tiff);
2353
199k
  tags=GetImageArtifact(image,"tiff:ignore-tags");
2354
199k
  if (tags == (const char *) NULL)
2355
199k
    return;
2356
0
  count=0;
2357
0
  p=tags;
2358
0
  while (*p != '\0')
2359
0
  {
2360
0
    while ((isspace((int) ((unsigned char) *p)) != 0))
2361
0
      p++;
2362
2363
0
    (void) strtol(p,&q,10);
2364
0
    if (p == q)
2365
0
      return;
2366
2367
0
    p=q;
2368
0
    count++;
2369
2370
0
    while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
2371
0
      p++;
2372
0
  }
2373
0
  if (count == 0)
2374
0
    return;
2375
0
  i=0;
2376
0
  p=tags;
2377
0
  ignore=(TIFFFieldInfo *) AcquireQuantumMemory(count,sizeof(*ignore));
2378
0
  if (ignore == (TIFFFieldInfo *) NULL)
2379
0
    return;
2380
  /*
2381
    This also sets field_bit to 0 (FIELD_IGNORE).
2382
  */
2383
0
  (void) memset(ignore,0,count*sizeof(*ignore));
2384
0
  while (*p != '\0')
2385
0
  {
2386
0
    while ((isspace((int) ((unsigned char) *p)) != 0))
2387
0
      p++;
2388
2389
0
    ignore[i].field_tag=(ttag_t) strtol(p,&q,10);
2390
0
    ignore[i].field_name=(char *) dummy_name;
2391
2392
0
    p=q;
2393
0
    i++;
2394
2395
0
    while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
2396
0
      p++;
2397
0
  }
2398
0
  (void) TIFFMergeFieldInfo(tiff,ignore,(uint32) count);
2399
0
  ignore=(TIFFFieldInfo *) RelinquishMagickMemory(ignore);
2400
0
}
2401
2402
static void TIFFTagExtender(TIFF *tiff)
2403
206k
{
2404
206k
  static const TIFFFieldInfo
2405
206k
    TIFFExtensions[] =
2406
206k
    {
2407
206k
      { 37724, -3, -3, TIFF_UNDEFINED, FIELD_CUSTOM, 1, 1,
2408
206k
        (char *) "PhotoshopLayerData" },
2409
206k
      { 34118, -3, -3, TIFF_UNDEFINED, FIELD_CUSTOM, 1, 1,
2410
206k
        (char *) "Microscope" }
2411
206k
    };
2412
2413
206k
  TIFFMergeFieldInfo(tiff,TIFFExtensions,sizeof(TIFFExtensions)/
2414
206k
    sizeof(*TIFFExtensions));
2415
206k
  if (tag_extender != (TIFFExtendProc) NULL)
2416
0
    (*tag_extender)(tiff);
2417
206k
  TIFFIgnoreTags(tiff);
2418
206k
}
2419
#endif
2420
2421
ModuleExport size_t RegisterTIFFImage(void)
2422
16
{
2423
32
#define TIFFDescription  "Tagged Image File Format"
2424
2425
16
  char
2426
16
    version[MagickPathExtent];
2427
2428
16
  MagickInfo
2429
16
    *entry;
2430
2431
16
  static const char
2432
16
    TIFFNote[] =
2433
16
      "Compression options: "
2434
16
#if defined(COMPRESSION_NONE)
2435
16
      "None"
2436
16
#endif
2437
16
#if defined(COMPRESSION_CCITTFAX3)
2438
16
      ", Fax/Group3"
2439
16
#endif
2440
16
#if defined(COMPRESSION_CCITTFAX4)
2441
16
      ", Group4"
2442
16
#endif
2443
16
#if defined(COMPRESSION_JBIG)
2444
16
      ", JBIG"
2445
16
#endif
2446
16
#if defined(COMPRESSION_JPEG)
2447
16
      ", JPEG"
2448
16
#endif
2449
16
#if defined(COMPRESSION_LERC)
2450
16
      ", LERC"
2451
16
#endif
2452
16
#if defined(COMPRESSION_LZW)
2453
16
      ", LZW"
2454
16
#endif
2455
16
#if defined(COMPRESSION_LZMA)
2456
16
      ", LZMA"
2457
16
#endif
2458
16
#if defined(COMPRESSION_PACKBITS)
2459
16
      ", RLE"
2460
16
#endif
2461
16
#if defined(COMPRESSION_ADOBE_DEFLATE)
2462
16
      ", ZIP"
2463
16
#endif
2464
16
#if defined(COMPRESSION_ZSTD)
2465
16
      ", ZSTD"
2466
16
#endif
2467
16
#if defined(COMPRESSION_WEBP)
2468
16
      ", WEBP"
2469
16
#endif
2470
16
    ;
2471
2472
16
#if defined(MAGICKCORE_TIFF_DELEGATE)
2473
16
  if (tiff_semaphore == (SemaphoreInfo *) NULL)
2474
16
    ActivateSemaphoreInfo(&tiff_semaphore);
2475
16
  LockSemaphoreInfo(tiff_semaphore);
2476
16
  if (instantiate_key == MagickFalse)
2477
16
    {
2478
16
      if (CreateMagickThreadKey(&tiff_exception,NULL) == MagickFalse)
2479
16
        ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
2480
16
      error_handler=TIFFSetErrorHandler(TIFFErrors);
2481
16
      warning_handler=TIFFSetWarningHandler(TIFFWarnings);
2482
16
      if (tag_extender == (TIFFExtendProc) NULL)
2483
16
        tag_extender=TIFFSetTagExtender(TIFFTagExtender);
2484
16
      instantiate_key=MagickTrue;
2485
16
    }
2486
16
  UnlockSemaphoreInfo(tiff_semaphore);
2487
16
#endif
2488
16
  *version='\0';
2489
#if defined(TIFF_VERSION)
2490
  (void) FormatLocaleString(version,MagickPathExtent,"%d",TIFF_VERSION);
2491
#endif
2492
16
#if defined(MAGICKCORE_TIFF_DELEGATE)
2493
16
  {
2494
16
    const char
2495
16
      *p;
2496
2497
16
    ssize_t
2498
16
      i;
2499
2500
16
    p=TIFFGetVersion();
2501
368
    for (i=0; (i < (MagickPathExtent-1)) && (*p != 0) && (*p != '\n'); i++)
2502
352
      version[i]=(*p++);
2503
16
    version[i]='\0';
2504
16
  }
2505
16
#endif
2506
2507
16
  entry=AcquireMagickInfo("TIFF","GROUP4","Raw CCITT Group4");
2508
16
#if defined(MAGICKCORE_TIFF_DELEGATE)
2509
16
  entry->decoder=(DecodeImageHandler *) ReadGROUP4Image;
2510
16
  entry->encoder=(EncodeImageHandler *) WriteGROUP4Image;
2511
16
#endif
2512
16
  entry->flags|=CoderRawSupportFlag;
2513
16
  entry->flags|=CoderEndianSupportFlag;
2514
16
  entry->flags|=CoderDecoderSeekableStreamFlag;
2515
16
  entry->flags|=CoderEncoderSeekableStreamFlag;
2516
16
  entry->flags^=CoderAdjoinFlag;
2517
16
  entry->flags^=CoderUseExtensionFlag;
2518
16
  entry->format_type=ImplicitFormatType;
2519
16
  entry->mime_type=ConstantString("image/tiff");
2520
16
  entry->note=ConstantString(TIFFNote);
2521
16
  (void) RegisterMagickInfo(entry);
2522
16
  entry=AcquireMagickInfo("TIFF","PTIF","Pyramid encoded TIFF");
2523
16
#if defined(MAGICKCORE_TIFF_DELEGATE)
2524
16
  entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
2525
16
  entry->encoder=(EncodeImageHandler *) WritePTIFImage;
2526
16
#endif
2527
16
  entry->flags|=CoderEndianSupportFlag;
2528
16
  entry->flags|=CoderDecoderSeekableStreamFlag;
2529
16
  entry->flags|=CoderEncoderSeekableStreamFlag;
2530
16
  entry->flags^=CoderUseExtensionFlag;
2531
16
  entry->mime_type=ConstantString("image/tiff");
2532
16
  entry->note=ConstantString(TIFFNote);
2533
16
  (void) RegisterMagickInfo(entry);
2534
16
  entry=AcquireMagickInfo("TIFF","TIF",TIFFDescription);
2535
16
#if defined(MAGICKCORE_TIFF_DELEGATE)
2536
16
  entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
2537
16
  entry->encoder=(EncodeImageHandler *) WriteTIFFImage;
2538
16
#endif
2539
16
  entry->flags|=CoderEndianSupportFlag;
2540
16
  entry->flags|=CoderDecoderSeekableStreamFlag;
2541
16
  entry->flags|=CoderEncoderSeekableStreamFlag;
2542
16
  entry->flags|=CoderStealthFlag;
2543
16
  entry->flags^=CoderUseExtensionFlag;
2544
16
  if (*version != '\0')
2545
16
    entry->version=ConstantString(version);
2546
16
  entry->mime_type=ConstantString("image/tiff");
2547
16
  entry->note=ConstantString(TIFFNote);
2548
16
  (void) RegisterMagickInfo(entry);
2549
16
  entry=AcquireMagickInfo("TIFF","TIFF",TIFFDescription);
2550
16
#if defined(MAGICKCORE_TIFF_DELEGATE)
2551
16
  entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
2552
16
  entry->encoder=(EncodeImageHandler *) WriteTIFFImage;
2553
16
#endif
2554
16
  entry->magick=(IsImageFormatHandler *) IsTIFF;
2555
16
  entry->flags|=CoderEndianSupportFlag;
2556
16
  entry->flags|=CoderDecoderSeekableStreamFlag;
2557
16
  entry->flags|=CoderEncoderSeekableStreamFlag;
2558
16
  entry->flags^=CoderUseExtensionFlag;
2559
16
  if (*version != '\0')
2560
16
    entry->version=ConstantString(version);
2561
16
  entry->mime_type=ConstantString("image/tiff");
2562
16
  entry->note=ConstantString(TIFFNote);
2563
16
  (void) RegisterMagickInfo(entry);
2564
16
  entry=AcquireMagickInfo("TIFF","TIFF64","Tagged Image File Format (64-bit)");
2565
16
#if defined(TIFF_VERSION_BIG)
2566
16
  entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
2567
16
  entry->encoder=(EncodeImageHandler *) WriteTIFFImage;
2568
16
#endif
2569
16
  entry->flags|=CoderEndianSupportFlag;
2570
16
  entry->flags|=CoderDecoderSeekableStreamFlag;
2571
16
  entry->flags|=CoderEncoderSeekableStreamFlag;
2572
16
  entry->flags^=CoderUseExtensionFlag;
2573
16
  if (*version != '\0')
2574
16
    entry->version=ConstantString(version);
2575
16
  entry->mime_type=ConstantString("image/tiff");
2576
16
  entry->note=ConstantString(TIFFNote);
2577
16
  (void) RegisterMagickInfo(entry);
2578
16
  return(MagickImageCoderSignature);
2579
16
}
2580

2581
/*
2582
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2583
%                                                                             %
2584
%                                                                             %
2585
%                                                                             %
2586
%   U n r e g i s t e r T I F F I m a g e                                     %
2587
%                                                                             %
2588
%                                                                             %
2589
%                                                                             %
2590
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2591
%
2592
%  UnregisterTIFFImage() removes format registrations made by the TIFF module
2593
%  from the list of supported formats.
2594
%
2595
%  The format of the UnregisterTIFFImage method is:
2596
%
2597
%      UnregisterTIFFImage(void)
2598
%
2599
*/
2600
ModuleExport void UnregisterTIFFImage(void)
2601
0
{
2602
0
  (void) UnregisterMagickInfo("TIFF64");
2603
0
  (void) UnregisterMagickInfo("TIFF");
2604
0
  (void) UnregisterMagickInfo("TIF");
2605
0
  (void) UnregisterMagickInfo("PTIF");
2606
0
#if defined(MAGICKCORE_TIFF_DELEGATE)
2607
0
  if (tiff_semaphore == (SemaphoreInfo *) NULL)
2608
0
    ActivateSemaphoreInfo(&tiff_semaphore);
2609
0
  LockSemaphoreInfo(tiff_semaphore);
2610
0
  if (instantiate_key != MagickFalse)
2611
0
    {
2612
0
      if (tag_extender == (TIFFExtendProc) NULL)
2613
0
        (void) TIFFSetTagExtender(tag_extender);
2614
0
      if (DeleteMagickThreadKey(tiff_exception) == MagickFalse)
2615
0
        ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
2616
0
      (void) TIFFSetWarningHandler(warning_handler);
2617
0
      (void) TIFFSetErrorHandler(error_handler);
2618
0
      instantiate_key=MagickFalse;
2619
0
    }
2620
0
  UnlockSemaphoreInfo(tiff_semaphore);
2621
0
  RelinquishSemaphoreInfo(&tiff_semaphore);
2622
0
#endif
2623
0
}
2624

2625
#if defined(MAGICKCORE_TIFF_DELEGATE)
2626
/*
2627
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2628
%                                                                             %
2629
%                                                                             %
2630
%                                                                             %
2631
%   W r i t e G R O U P 4 I m a g e                                           %
2632
%                                                                             %
2633
%                                                                             %
2634
%                                                                             %
2635
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2636
%
2637
%  WriteGROUP4Image() writes an image in the raw CCITT Group 4 image format.
2638
%
2639
%  The format of the WriteGROUP4Image method is:
2640
%
2641
%      MagickBooleanType WriteGROUP4Image(const ImageInfo *image_info,
2642
%        Image *image,ExceptionInfo *)
2643
%
2644
%  A description of each parameter follows:
2645
%
2646
%    o image_info: the image info.
2647
%
2648
%    o image:  The image.
2649
%
2650
%    o exception: return any errors or warnings in this structure.
2651
%
2652
*/
2653
static MagickBooleanType WriteGROUP4Image(const ImageInfo *image_info,
2654
  Image *image,ExceptionInfo *exception)
2655
1.26k
{
2656
1.26k
  char
2657
1.26k
    filename[MagickPathExtent];
2658
2659
1.26k
  FILE
2660
1.26k
    *file;
2661
2662
1.26k
  Image
2663
1.26k
    *huffman_image;
2664
2665
1.26k
  ImageInfo
2666
1.26k
    *write_info;
2667
2668
1.26k
  int
2669
1.26k
    unique_file;
2670
2671
1.26k
  MagickBooleanType
2672
1.26k
    status;
2673
2674
1.26k
  ssize_t
2675
1.26k
    i;
2676
2677
1.26k
  ssize_t
2678
1.26k
    count;
2679
2680
1.26k
  TIFF
2681
1.26k
    *tiff;
2682
2683
1.26k
  toff_t
2684
1.26k
    *byte_count,
2685
1.26k
    strip_size;
2686
2687
1.26k
  unsigned char
2688
1.26k
    *buffer;
2689
2690
  /*
2691
    Write image as CCITT Group4 TIFF image to a temporary file.
2692
  */
2693
1.26k
  assert(image_info != (const ImageInfo *) NULL);
2694
1.26k
  assert(image_info->signature == MagickCoreSignature);
2695
1.26k
  assert(image != (Image *) NULL);
2696
1.26k
  assert(image->signature == MagickCoreSignature);
2697
1.26k
  assert(exception != (ExceptionInfo *) NULL);
2698
1.26k
  assert(exception->signature == MagickCoreSignature);
2699
1.26k
  if (IsEventLogging() != MagickFalse)
2700
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2701
1.26k
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2702
1.26k
  if (status == MagickFalse)
2703
0
    return(status);
2704
1.26k
  huffman_image=CloneImage(image,0,0,MagickTrue,exception);
2705
1.26k
  if (huffman_image == (Image *) NULL)
2706
0
    {
2707
0
      (void) CloseBlob(image);
2708
0
      return(MagickFalse);
2709
0
    }
2710
1.26k
  huffman_image->endian=MSBEndian;
2711
1.26k
  file=(FILE *) NULL;
2712
1.26k
  unique_file=AcquireUniqueFileResource(filename);
2713
1.26k
  if (unique_file != -1)
2714
1.26k
    file=fdopen(unique_file,"wb");
2715
1.26k
  if ((unique_file == -1) || (file == (FILE *) NULL))
2716
0
    {
2717
0
      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2718
0
        filename);
2719
0
      return(MagickFalse);
2720
0
    }
2721
1.26k
  (void) FormatLocaleString(huffman_image->filename,MagickPathExtent,"tiff:%s",
2722
1.26k
    filename);
2723
1.26k
  if (IsImageMonochrome(huffman_image) == MagickFalse)
2724
0
    (void) SetImageType(huffman_image,BilevelType,exception);
2725
1.26k
  write_info=CloneImageInfo((ImageInfo *) NULL);
2726
1.26k
  SetImageInfoFile(write_info,file);
2727
1.26k
  if (IsImageMonochrome(image) == MagickFalse)
2728
0
    (void) SetImageType(image,BilevelType,exception);
2729
1.26k
  (void) SetImageDepth(image,1,exception);
2730
1.26k
  write_info->compression=Group4Compression;
2731
1.26k
  write_info->type=BilevelType;
2732
1.26k
  status=WriteTIFFImage(write_info,huffman_image,exception);
2733
1.26k
  (void) fflush(file);
2734
1.26k
  write_info=DestroyImageInfo(write_info);
2735
1.26k
  if (status == MagickFalse)
2736
0
    {
2737
0
      huffman_image=DestroyImage(huffman_image);
2738
0
      (void) fclose(file);
2739
0
      (void) RelinquishUniqueFileResource(filename);
2740
0
      return(MagickFalse);
2741
0
    }
2742
1.26k
  tiff=TIFFOpen(filename,"rb");
2743
1.26k
  if (tiff == (TIFF *) NULL)
2744
0
    {
2745
0
      huffman_image=DestroyImage(huffman_image);
2746
0
      (void) fclose(file);
2747
0
      (void) RelinquishUniqueFileResource(filename);
2748
0
      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2749
0
        image_info->filename);
2750
0
      return(MagickFalse);
2751
0
    }
2752
  /*
2753
    Allocate raw strip buffer.
2754
  */
2755
1.26k
  if (TIFFGetField(tiff,TIFFTAG_STRIPBYTECOUNTS,&byte_count) != 1)
2756
0
    {
2757
0
      TIFFClose(tiff);
2758
0
      huffman_image=DestroyImage(huffman_image);
2759
0
      (void) fclose(file);
2760
0
      (void) RelinquishUniqueFileResource(filename);
2761
0
      return(MagickFalse);
2762
0
    }
2763
1.26k
  strip_size=byte_count[0];
2764
1.26k
  for (i=1; i < (ssize_t) TIFFNumberOfStrips(tiff); i++)
2765
0
    if (byte_count[i] > strip_size)
2766
0
      strip_size=byte_count[i];
2767
1.26k
  buffer=(unsigned char *) AcquireQuantumMemory((size_t) strip_size,
2768
1.26k
    sizeof(*buffer));
2769
1.26k
  if (buffer == (unsigned char *) NULL)
2770
0
    {
2771
0
      TIFFClose(tiff);
2772
0
      huffman_image=DestroyImage(huffman_image);
2773
0
      (void) fclose(file);
2774
0
      (void) RelinquishUniqueFileResource(filename);
2775
0
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2776
0
        image_info->filename);
2777
0
    }
2778
  /*
2779
    Compress runlength encoded to 2D Huffman pixels.
2780
  */
2781
2.53k
  for (i=0; i < (ssize_t) TIFFNumberOfStrips(tiff); i++)
2782
1.26k
  {
2783
1.26k
    count=(ssize_t) TIFFReadRawStrip(tiff,(uint32) i,buffer,(tmsize_t)
2784
1.26k
      strip_size);
2785
1.26k
    if (WriteBlob(image,(size_t) count,buffer) != count)
2786
0
      status=MagickFalse;
2787
1.26k
  }
2788
1.26k
  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2789
1.26k
  TIFFClose(tiff);
2790
1.26k
  huffman_image=DestroyImage(huffman_image);
2791
1.26k
  (void) fclose(file);
2792
1.26k
  (void) RelinquishUniqueFileResource(filename);
2793
1.26k
  if (CloseBlob(image) == MagickFalse)
2794
0
    status=MagickFalse;
2795
1.26k
  return(status);
2796
1.26k
}
2797
#endif
2798

2799
#if defined(MAGICKCORE_TIFF_DELEGATE)
2800
/*
2801
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2802
%                                                                             %
2803
%                                                                             %
2804
%                                                                             %
2805
%   W r i t e P T I F I m a g e                                               %
2806
%                                                                             %
2807
%                                                                             %
2808
%                                                                             %
2809
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2810
%
2811
%  WritePTIFImage() writes an image in the pyramid-encoded Tagged image file
2812
%  format.
2813
%
2814
%  The format of the WritePTIFImage method is:
2815
%
2816
%      MagickBooleanType WritePTIFImage(const ImageInfo *image_info,
2817
%        Image *image,ExceptionInfo *exception)
2818
%
2819
%  A description of each parameter follows:
2820
%
2821
%    o image_info: the image info.
2822
%
2823
%    o image:  The image.
2824
%
2825
%    o exception: return any errors or warnings in this structure.
2826
%
2827
*/
2828
static MagickBooleanType WritePTIFImage(const ImageInfo *image_info,
2829
  Image *image,ExceptionInfo *exception)
2830
2.04k
{
2831
2.04k
  const char
2832
2.04k
    *option;
2833
2834
2.04k
  Image
2835
2.04k
    *images,
2836
2.04k
    *next,
2837
2.04k
    *pyramid_image;
2838
2839
2.04k
  ImageInfo
2840
2.04k
    *write_info;
2841
2842
2.04k
  MagickBooleanType
2843
2.04k
    status;
2844
2845
2.04k
  PointInfo
2846
2.04k
    resolution;
2847
2848
2.04k
  size_t
2849
2.04k
    columns,
2850
2.04k
    min_base = 64,
2851
2.04k
    max_levels = ~0UL,
2852
2.04k
    rows;
2853
2854
  /*
2855
    Create pyramid-encoded TIFF image.
2856
  */
2857
2.04k
  option=GetImageOption(image_info,"ptif:pyramid");
2858
2.04k
  if (option != (const char *) NULL)
2859
0
    {
2860
      /*
2861
        Property ptif:min-base[x][max-levels].
2862
      */
2863
0
      RectangleInfo
2864
0
        pyramid_geometry = { 0, 0, 0, 0 };
2865
2866
0
      MagickStatusType flags =
2867
0
        ParseAbsoluteGeometry(option,&pyramid_geometry);
2868
0
      if ((flags & WidthValue) != 0)
2869
0
        min_base=pyramid_geometry.width;
2870
0
      if ((flags & HeightValue) != 0)
2871
0
        max_levels=pyramid_geometry.height;
2872
0
    }
2873
2.04k
  images=NewImageList();
2874
4.09k
  for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
2875
2.04k
  {
2876
2.04k
    Image
2877
2.04k
      *clone_image;
2878
2879
2.04k
    ssize_t
2880
2.04k
      i;
2881
2882
2.04k
    clone_image=CloneImage(next,0,0,MagickFalse,exception);
2883
2.04k
    if (clone_image == (Image *) NULL)
2884
0
      break;
2885
2.04k
    clone_image->previous=NewImageList();
2886
2.04k
    clone_image->next=NewImageList();
2887
2.04k
    (void) SetImageProperty(clone_image,"tiff:subfiletype","none",exception);
2888
2.04k
    AppendImageToList(&images,clone_image);
2889
2.04k
    columns=next->columns;
2890
2.04k
    rows=next->rows;
2891
2.04k
    resolution=next->resolution;
2892
2.04k
    for (i=0; (columns > min_base) && (rows > min_base); i++)
2893
14
    {
2894
14
      if (i > (ssize_t) max_levels)
2895
14
        break;
2896
0
      columns/=2;
2897
0
      rows/=2;
2898
0
      resolution.x/=2;
2899
0
      resolution.y/=2;
2900
0
      pyramid_image=ResizeImage(next,columns,rows,image->filter,exception);
2901
0
      if (pyramid_image == (Image *) NULL)
2902
0
        break;
2903
0
      DestroyBlob(pyramid_image);
2904
0
      pyramid_image->blob=ReferenceBlob(next->blob);
2905
0
      pyramid_image->resolution=resolution;
2906
0
      (void) SetImageProperty(pyramid_image,"tiff:subfiletype","REDUCEDIMAGE",
2907
0
        exception);
2908
0
      AppendImageToList(&images,pyramid_image);
2909
0
    }
2910
2.04k
  }
2911
2.04k
  status=MagickFalse;
2912
2.04k
  if (images != (Image *) NULL)
2913
2.04k
    {
2914
      /*
2915
        Write pyramid-encoded TIFF image.
2916
      */
2917
2.04k
      images=GetFirstImageInList(images);
2918
2.04k
      write_info=CloneImageInfo(image_info);
2919
2.04k
      write_info->adjoin=MagickTrue;
2920
2.04k
      (void) CopyMagickString(write_info->magick,"TIFF",MagickPathExtent);
2921
2.04k
      (void) CopyMagickString(images->magick,"TIFF",MagickPathExtent);
2922
2.04k
      status=WriteTIFFImage(write_info,images,exception);
2923
2.04k
      images=DestroyImageList(images);
2924
2.04k
      write_info=DestroyImageInfo(write_info);
2925
2.04k
    }
2926
2.04k
  return(status);
2927
2.04k
}
2928
#endif
2929

2930
#if defined(MAGICKCORE_TIFF_DELEGATE)
2931
/*
2932
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2933
%                                                                             %
2934
%                                                                             %
2935
%                                                                             %
2936
%   W r i t e T I F F I m a g e                                               %
2937
%                                                                             %
2938
%                                                                             %
2939
%                                                                             %
2940
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2941
%
2942
%  WriteTIFFImage() writes an image in the Tagged image file format.
2943
%
2944
%  The format of the WriteTIFFImage method is:
2945
%
2946
%      MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
2947
%        Image *image,ExceptionInfo *exception)
2948
%
2949
%  A description of each parameter follows:
2950
%
2951
%    o image_info: the image info.
2952
%
2953
%    o image:  The image.
2954
%
2955
%    o exception: return any errors or warnings in this structure.
2956
%
2957
*/
2958
2959
typedef struct _TIFFInfo
2960
{
2961
  RectangleInfo
2962
    tile_geometry;
2963
2964
  unsigned char
2965
    *scanline,
2966
    *scanlines,
2967
    *pixels;
2968
} TIFFInfo;
2969
2970
static void DestroyTIFFInfo(TIFFInfo *tiff_info)
2971
7.56k
{
2972
7.56k
  assert(tiff_info != (TIFFInfo *) NULL);
2973
7.56k
  if (tiff_info->scanlines != (unsigned char *) NULL)
2974
0
    tiff_info->scanlines=(unsigned char *) RelinquishMagickMemory(
2975
0
      tiff_info->scanlines);
2976
7.56k
  if (tiff_info->pixels != (unsigned char *) NULL)
2977
0
    tiff_info->pixels=(unsigned char *) RelinquishMagickMemory(
2978
0
      tiff_info->pixels);
2979
7.56k
}
2980
2981
static MagickBooleanType EncodeLabImage(Image *image,ExceptionInfo *exception)
2982
350
{
2983
350
  CacheView
2984
350
    *image_view;
2985
2986
350
  MagickBooleanType
2987
350
    status;
2988
2989
350
  ssize_t
2990
350
    y;
2991
2992
350
  status=MagickTrue;
2993
350
  image_view=AcquireAuthenticCacheView(image,exception);
2994
13.8k
  for (y=0; y < (ssize_t) image->rows; y++)
2995
13.4k
  {
2996
13.4k
    Quantum
2997
13.4k
      *magick_restrict q;
2998
2999
13.4k
    ssize_t
3000
13.4k
      x;
3001
3002
13.4k
    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3003
13.4k
    if (q == (Quantum *) NULL)
3004
0
      {
3005
0
        status=MagickFalse;
3006
0
        break;
3007
0
      }
3008
412k
    for (x=0; x < (ssize_t) image->columns; x++)
3009
399k
    {
3010
399k
      double
3011
399k
        a,
3012
399k
        b;
3013
3014
399k
      a=QuantumScale*(double) GetPixela(image,q)-0.5;
3015
399k
      if (a < 0.0)
3016
1.41k
        a+=1.0;
3017
399k
      b=QuantumScale*(double) GetPixelb(image,q)-0.5;
3018
399k
      if (b < 0.0)
3019
1.43k
        b+=1.0;
3020
399k
      SetPixela(image,(Quantum) (QuantumRange*a),q);
3021
399k
      SetPixelb(image,(Quantum) (QuantumRange*b),q);
3022
399k
      q+=(ptrdiff_t) GetPixelChannels(image);
3023
399k
    }
3024
13.4k
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3025
0
      {
3026
0
        status=MagickFalse;
3027
0
        break;
3028
0
      }
3029
13.4k
  }
3030
350
  image_view=DestroyCacheView(image_view);
3031
350
  return(status);
3032
350
}
3033
3034
static MagickBooleanType GetTIFFInfo(const ImageInfo *image_info,
3035
  TIFF *tiff,TIFFInfo *tiff_info)
3036
7.56k
{
3037
7.56k
#define TIFFStripSizeDefault  1048576
3038
3039
7.56k
  const char
3040
7.56k
    *option;
3041
3042
7.56k
  MagickStatusType
3043
7.56k
    flags;
3044
3045
7.56k
  uint32
3046
7.56k
    tile_columns,
3047
7.56k
    tile_rows;
3048
3049
7.56k
  assert(tiff_info != (TIFFInfo *) NULL);
3050
7.56k
  (void) memset(tiff_info,0,sizeof(*tiff_info));
3051
7.56k
  option=GetImageOption(image_info,"tiff:tile-geometry");
3052
7.56k
  if (option == (const char *) NULL)
3053
7.56k
    {
3054
7.56k
      size_t
3055
7.56k
        extent;
3056
3057
7.56k
      uint32
3058
7.56k
        rows,
3059
7.56k
        rows_per_strip;
3060
3061
7.56k
      extent=(size_t) TIFFScanlineSize(tiff);
3062
7.56k
      rows_per_strip=TIFFStripSizeDefault/(extent == 0 ? 1 : (uint32) extent);
3063
7.56k
      rows_per_strip=16*(((rows_per_strip < 16 ? 16 : rows_per_strip)+1)/16);
3064
7.56k
      if ((TIFFGetField(tiff,TIFFTAG_IMAGELENGTH,&rows) == 1) &&
3065
7.56k
          (rows_per_strip > rows))
3066
7.54k
        rows_per_strip=rows;
3067
7.56k
      option=GetImageOption(image_info,"tiff:rows-per-strip");
3068
7.56k
      if (option != (const char *) NULL)
3069
0
        rows_per_strip=(uint32) strtoul(option,(char **) NULL,10);
3070
7.56k
      rows_per_strip=TIFFDefaultStripSize(tiff,rows_per_strip);
3071
7.56k
      (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
3072
7.56k
      return(MagickTrue);
3073
7.56k
    }
3074
  /*
3075
    Create tiled TIFF, ignore "tiff:rows-per-strip".
3076
  */
3077
0
  flags=ParseAbsoluteGeometry(option,&tiff_info->tile_geometry);
3078
0
  if ((flags & HeightValue) == 0)
3079
0
    tiff_info->tile_geometry.height=tiff_info->tile_geometry.width;
3080
0
  tile_columns=(uint32) tiff_info->tile_geometry.width;
3081
0
  tile_rows=(uint32) tiff_info->tile_geometry.height;
3082
0
  TIFFDefaultTileSize(tiff,&tile_columns,&tile_rows);
3083
0
  (void) TIFFSetField(tiff,TIFFTAG_TILEWIDTH,tile_columns);
3084
0
  (void) TIFFSetField(tiff,TIFFTAG_TILELENGTH,tile_rows);
3085
0
  tiff_info->tile_geometry.width=tile_columns;
3086
0
  tiff_info->tile_geometry.height=tile_rows;
3087
0
  if ((TIFFScanlineSize(tiff) <= 0) || (TIFFTileSize(tiff) <= 0))
3088
0
    {
3089
0
      DestroyTIFFInfo(tiff_info);
3090
0
      return(MagickFalse);
3091
0
    }
3092
0
  tiff_info->scanlines=(unsigned char *) AcquireQuantumMemory((size_t)
3093
0
    tile_rows*(size_t) TIFFScanlineSize(tiff),sizeof(*tiff_info->scanlines));
3094
0
  tiff_info->pixels=(unsigned char *) AcquireQuantumMemory((size_t)
3095
0
    tile_rows*(size_t) TIFFTileSize(tiff),sizeof(*tiff_info->scanlines));
3096
0
  if ((tiff_info->scanlines == (unsigned char *) NULL) ||
3097
0
      (tiff_info->pixels == (unsigned char *) NULL))
3098
0
    {
3099
0
      DestroyTIFFInfo(tiff_info);
3100
0
      return(MagickFalse);
3101
0
    }
3102
0
  return(MagickTrue);
3103
0
}
3104
3105
static int TIFFWritePixels(TIFF *tiff,TIFFInfo *tiff_info,ssize_t row,
3106
  tsample_t sample,Image *image)
3107
289k
{
3108
289k
  tmsize_t
3109
289k
    status;
3110
3111
289k
  size_t
3112
289k
    number_tiles,
3113
289k
    tile_width;
3114
3115
289k
  ssize_t
3116
289k
    bytes_per_pixel,
3117
289k
    i = 0,
3118
289k
    j,
3119
289k
    k,
3120
289k
    l;
3121
3122
289k
  unsigned char
3123
289k
    *p,
3124
289k
    *q;
3125
3126
289k
  if ((TIFFIsTiled(tiff) == 0) || (tiff_info->tile_geometry.height == 0))
3127
289k
    return(TIFFWriteScanline(tiff,tiff_info->scanline,(uint32) row,sample));
3128
0
  if (tiff_info->scanline != NULL)
3129
0
    {
3130
      /*
3131
        Fill scanlines to tile height.
3132
      */
3133
0
      i=(ssize_t) (row % (ssize_t) tiff_info->tile_geometry.height)*
3134
0
        TIFFScanlineSize(tiff);
3135
0
      (void) memcpy(tiff_info->scanlines+i,(char *) tiff_info->scanline,
3136
0
        (size_t) TIFFScanlineSize(tiff));
3137
0
      if ((((size_t) row % tiff_info->tile_geometry.height) != (tiff_info->tile_geometry.height-1)) &&
3138
0
          (row != (ssize_t) (image->rows-1)))
3139
0
        return(0);
3140
0
    }
3141
  /*
3142
    Write tile to TIFF image.
3143
  */
3144
0
  status=0;
3145
0
  bytes_per_pixel=TIFFTileSize(tiff)/(ssize_t) (
3146
0
    tiff_info->tile_geometry.height*tiff_info->tile_geometry.width);
3147
0
  number_tiles=(image->columns+tiff_info->tile_geometry.width)/
3148
0
    tiff_info->tile_geometry.width;
3149
0
  for (i=0; i < (ssize_t) number_tiles; i++)
3150
0
  {
3151
0
    tile_width=(size_t) ((i == (ssize_t) (number_tiles-1)) ? (ssize_t)
3152
0
      image->columns-(i*(ssize_t) tiff_info->tile_geometry.width) :
3153
0
      (ssize_t) tiff_info->tile_geometry.width);
3154
0
    for (j=0; j < ((row % (ssize_t) tiff_info->tile_geometry.height)+1); j++)
3155
0
      for (k=0; k < (ssize_t) tile_width; k++)
3156
0
      {
3157
0
        if (bytes_per_pixel == 0)
3158
0
          {
3159
0
            p=tiff_info->scanlines+(j*TIFFScanlineSize(tiff)+(i*
3160
0
              (ssize_t) tiff_info->tile_geometry.width+k)/8);
3161
0
            q=tiff_info->pixels+(j*TIFFTileRowSize(tiff)+k/8);
3162
0
            *q++=(*p++);
3163
0
            continue;
3164
0
          }
3165
0
        p=tiff_info->scanlines+(j*TIFFScanlineSize(tiff)+(i*
3166
0
          (ssize_t) tiff_info->tile_geometry.width+k)*bytes_per_pixel);
3167
0
        q=tiff_info->pixels+(j*TIFFTileRowSize(tiff)+k*bytes_per_pixel);
3168
0
        for (l=0; l < bytes_per_pixel; l++)
3169
0
          *q++=(*p++);
3170
0
      }
3171
0
    if (((size_t) i*tiff_info->tile_geometry.width) != image->columns)
3172
0
      status=TIFFWriteTile(tiff,tiff_info->pixels,(uint32) ((size_t) i*
3173
0
        tiff_info->tile_geometry.width),(uint32) (((size_t) row/
3174
0
        tiff_info->tile_geometry.height)*tiff_info->tile_geometry.height),0,
3175
0
        sample);
3176
0
    if (status < 0)
3177
0
      break;
3178
0
  }
3179
0
  return((int) status);
3180
0
}
3181
3182
static ssize_t TIFFWriteCustomStream(unsigned char *data,const size_t count,
3183
  void *user_data)
3184
0
{
3185
0
  PhotoshopProfile
3186
0
    *profile;
3187
3188
0
  if (count == 0)
3189
0
    return(0);
3190
0
  profile=(PhotoshopProfile *) user_data;
3191
0
  if ((profile->offset+(MagickOffsetType) count) >=
3192
0
        (MagickOffsetType) profile->extent)
3193
0
    {
3194
0
      profile->extent+=count+profile->quantum;
3195
0
      profile->quantum<<=1;
3196
0
      SetStringInfoLength(profile->data,profile->extent);
3197
0
    }
3198
0
  (void) memcpy(profile->data->datum+profile->offset,data,count);
3199
0
  profile->offset+=(MagickOffsetType) count;
3200
0
  return((ssize_t) count);
3201
0
}
3202
3203
static CustomStreamInfo *TIFFAcquireCustomStreamForWriting(
3204
  PhotoshopProfile *profile,ExceptionInfo *exception)
3205
0
{
3206
0
  CustomStreamInfo
3207
0
    *custom_stream;
3208
3209
0
  custom_stream=AcquireCustomStreamInfo(exception);
3210
0
  if (custom_stream == (CustomStreamInfo *) NULL)
3211
0
    return(custom_stream);
3212
0
  SetCustomStreamData(custom_stream,(void *) profile);
3213
0
  SetCustomStreamWriter(custom_stream,TIFFWriteCustomStream);
3214
0
  SetCustomStreamSeeker(custom_stream,TIFFSeekCustomStream);
3215
0
  SetCustomStreamTeller(custom_stream,TIFFTellCustomStream);
3216
0
  return(custom_stream);
3217
0
}
3218
3219
static MagickBooleanType TIFFWritePhotoshopLayers(Image* image,
3220
  const ImageInfo *image_info,EndianType endian,ExceptionInfo *exception)
3221
0
{
3222
0
  BlobInfo
3223
0
    *blob;
3224
3225
0
  CustomStreamInfo
3226
0
    *custom_stream;
3227
3228
0
  Image
3229
0
    *base_image,
3230
0
    *next;
3231
3232
0
  ImageInfo
3233
0
    *clone_info;
3234
3235
0
  MagickBooleanType
3236
0
    status;
3237
3238
0
  PhotoshopProfile
3239
0
    profile;
3240
3241
0
  PSDInfo
3242
0
    info;
3243
3244
0
  StringInfo
3245
0
    *layers;
3246
3247
0
  base_image=CloneImage(image,0,0,MagickFalse,exception);
3248
0
  if (base_image == (Image *) NULL)
3249
0
    return(MagickTrue);
3250
0
  clone_info=CloneImageInfo(image_info);
3251
0
  if (clone_info == (ImageInfo *) NULL)
3252
0
    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3253
0
      image->filename);
3254
0
  profile.offset=0;
3255
0
  profile.quantum=MagickMinBlobExtent;
3256
0
  layers=AcquireProfileStringInfo("tiff:37724",profile.quantum,
3257
0
    exception);
3258
0
  if (layers == (StringInfo *) NULL)
3259
0
    {
3260
0
      base_image=DestroyImage(base_image);
3261
0
      clone_info=DestroyImageInfo(clone_info);
3262
0
      return(MagickTrue);
3263
0
    }
3264
0
  profile.data=layers;
3265
0
  profile.extent=layers->length;
3266
0
  custom_stream=TIFFAcquireCustomStreamForWriting(&profile,exception);
3267
0
  if (custom_stream == (CustomStreamInfo *) NULL)
3268
0
    {
3269
0
      base_image=DestroyImage(base_image);
3270
0
      clone_info=DestroyImageInfo(clone_info);
3271
0
      layers=DestroyStringInfo(layers);
3272
0
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3273
0
        image->filename);
3274
0
    }
3275
0
  blob=CloneBlobInfo((BlobInfo *) NULL);
3276
0
  if (blob == (BlobInfo *) NULL)
3277
0
    {
3278
0
      base_image=DestroyImage(base_image);
3279
0
      clone_info=DestroyImageInfo(clone_info);
3280
0
      layers=DestroyStringInfo(layers);
3281
0
      custom_stream=DestroyCustomStreamInfo(custom_stream);
3282
0
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3283
0
        image->filename);
3284
0
    }
3285
0
  DestroyBlob(base_image);
3286
0
  base_image->blob=blob;
3287
0
  next=base_image;
3288
0
  while (next != (Image *) NULL)
3289
0
    next=SyncNextImageInList(next);
3290
0
  AttachCustomStream(base_image->blob,custom_stream);
3291
0
  InitPSDInfo(image,&info);
3292
0
  base_image->endian=endian;
3293
0
  WriteBlobString(base_image,"Adobe Photoshop Document Data Block");
3294
0
  WriteBlobByte(base_image,0);
3295
0
  WriteBlobString(base_image,base_image->endian == LSBEndian ? "MIB8ryaL" :
3296
0
    "8BIMLayr");
3297
0
  status=WritePSDLayers(base_image,clone_info,&info,exception);
3298
0
  if (status != MagickFalse)
3299
0
    {
3300
0
      SetStringInfoLength(layers,(size_t) profile.offset);
3301
0
      (void) SetImageProfilePrivate(image,layers,exception);
3302
0
    }
3303
0
  else
3304
0
    layers=DestroyStringInfo(layers);
3305
0
  next=base_image;
3306
0
  while (next != (Image *) NULL)
3307
0
  {
3308
0
    CloseBlob(next);
3309
0
    next=next->next;
3310
0
  }
3311
0
  clone_info=DestroyImageInfo(clone_info);
3312
0
  custom_stream=DestroyCustomStreamInfo(custom_stream);
3313
0
  return(status);
3314
0
}
3315
3316
static void TIFFSetProfiles(TIFF *tiff,Image *image)
3317
7.56k
{
3318
7.56k
  const char
3319
7.56k
    *name;
3320
3321
7.56k
  const StringInfo
3322
7.56k
    *profile;
3323
3324
7.56k
  if (image->profiles == (void *) NULL)
3325
6.70k
    return;
3326
861
  ResetImageProfileIterator(image);
3327
1.91k
  for (name=GetNextImageProfile(image); name != (const char *) NULL; )
3328
1.05k
  {
3329
1.05k
    profile=GetImageProfile(image,name);
3330
1.05k
    if (GetStringInfoLength(profile) == 0)
3331
0
      {
3332
0
        name=GetNextImageProfile(image);
3333
0
        continue;
3334
0
      }
3335
1.05k
#if defined(TIFFTAG_XMLPACKET)
3336
1.05k
    if (LocaleCompare(name,"xmp") == 0)
3337
0
      (void) TIFFSetField(tiff,TIFFTAG_XMLPACKET,(uint32) GetStringInfoLength(
3338
0
        profile),GetStringInfoDatum(profile));
3339
1.05k
#endif
3340
1.05k
#if defined(TIFFTAG_ICCPROFILE)
3341
1.05k
    if (LocaleCompare(name,"icc") == 0)
3342
4
      (void) TIFFSetField(tiff,TIFFTAG_ICCPROFILE,(uint32) GetStringInfoLength(
3343
4
        profile),GetStringInfoDatum(profile));
3344
1.05k
#endif
3345
1.05k
    if (LocaleCompare(name,"iptc") == 0)
3346
54
      {
3347
54
        const TIFFField
3348
54
          *field;
3349
3350
54
        size_t
3351
54
          length;
3352
3353
54
        StringInfo
3354
54
          *iptc_profile;
3355
3356
54
        iptc_profile=CloneStringInfo(profile);
3357
54
        length=GetStringInfoLength(profile)+4-(GetStringInfoLength(profile) &
3358
54
          0x03);
3359
54
        SetStringInfoLength(iptc_profile,length);
3360
54
        field=TIFFFieldWithTag(tiff,TIFFTAG_RICHTIFFIPTC);
3361
54
        if ((field != (const TIFFField *) NULL) &&
3362
54
            (TIFFFieldDataType(field) == TIFF_LONG))
3363
0
          {
3364
0
            if (TIFFIsByteSwapped(tiff))
3365
0
              TIFFSwabArrayOfLong((uint32 *) GetStringInfoDatum(iptc_profile),
3366
0
                (tmsize_t) (length/4));
3367
0
            (void) TIFFSetField(tiff,TIFFTAG_RICHTIFFIPTC,(uint32)
3368
0
              GetStringInfoLength(iptc_profile)/4,GetStringInfoDatum(
3369
0
                iptc_profile));
3370
0
          }
3371
54
        else
3372
54
          (void) TIFFSetField(tiff,TIFFTAG_RICHTIFFIPTC,(uint32)
3373
54
            GetStringInfoLength(iptc_profile),GetStringInfoDatum(
3374
54
              iptc_profile));
3375
54
        iptc_profile=DestroyStringInfo(iptc_profile);
3376
54
      }
3377
1.05k
#if defined(TIFFTAG_PHOTOSHOP)
3378
1.05k
    if (LocaleCompare(name,"8bim") == 0)
3379
860
      (void) TIFFSetField(tiff,TIFFTAG_PHOTOSHOP,(uint32)
3380
860
        GetStringInfoLength(profile),GetStringInfoDatum(profile));
3381
1.05k
#endif
3382
1.05k
    if (LocaleCompare(name,"tiff:37724") == 0)
3383
0
      (void) TIFFSetField(tiff,37724,(uint32) GetStringInfoLength(profile),
3384
0
        GetStringInfoDatum(profile));
3385
1.05k
    if (LocaleCompare(name,"tiff:34118") == 0)
3386
0
      (void) TIFFSetField(tiff,34118,(uint32) GetStringInfoLength(profile),
3387
0
        GetStringInfoDatum(profile));
3388
1.05k
    name=GetNextImageProfile(image);
3389
1.05k
  }
3390
861
}
3391
3392
static void TIFFSetProperties(TIFF *tiff,const MagickBooleanType adjoin,
3393
  Image *image,ExceptionInfo *exception)
3394
7.56k
{
3395
7.56k
  const char
3396
7.56k
    *value;
3397
3398
7.56k
  value=GetImageArtifact(image,"tiff:document");
3399
7.56k
  if (value != (const char *) NULL)
3400
0
    (void) TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,value);
3401
7.56k
  value=GetImageArtifact(image,"tiff:hostcomputer");
3402
7.56k
  if (value != (const char *) NULL)
3403
0
    (void) TIFFSetField(tiff,TIFFTAG_HOSTCOMPUTER,value);
3404
7.56k
  value=GetImageArtifact(image,"tiff:artist");
3405
7.56k
  if (value != (const char *) NULL)
3406
0
    (void) TIFFSetField(tiff,TIFFTAG_ARTIST,value);
3407
7.56k
  value=GetImageArtifact(image,"tiff:timestamp");
3408
7.56k
  if (value != (const char *) NULL)
3409
0
    (void) TIFFSetField(tiff,TIFFTAG_DATETIME,value);
3410
7.56k
  value=GetImageArtifact(image,"tiff:make");
3411
7.56k
  if (value != (const char *) NULL)
3412
0
    (void) TIFFSetField(tiff,TIFFTAG_MAKE,value);
3413
7.56k
  value=GetImageArtifact(image,"tiff:model");
3414
7.56k
  if (value != (const char *) NULL)
3415
0
    (void) TIFFSetField(tiff,TIFFTAG_MODEL,value);
3416
7.56k
  value=GetImageArtifact(image,"tiff:software");
3417
7.56k
  if (value != (const char *) NULL)
3418
0
    (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,value);
3419
7.56k
  value=GetImageArtifact(image,"tiff:copyright");
3420
7.56k
  if (value != (const char *) NULL)
3421
0
    (void) TIFFSetField(tiff,TIFFTAG_COPYRIGHT,value);
3422
7.56k
  value=GetImageArtifact(image,"kodak-33423");
3423
7.56k
  if (value != (const char *) NULL)
3424
0
    (void) TIFFSetField(tiff,33423,value);
3425
7.56k
  value=GetImageArtifact(image,"kodak-36867");
3426
7.56k
  if (value != (const char *) NULL)
3427
0
    (void) TIFFSetField(tiff,36867,value);
3428
7.56k
  value=GetImageProperty(image,"label",exception);
3429
7.56k
  if (value != (const char *) NULL)
3430
0
    (void) TIFFSetField(tiff,TIFFTAG_PAGENAME,value);
3431
7.56k
  value=GetImageProperty(image,"comment",exception);
3432
7.56k
  if (value != (const char *) NULL)
3433
55
    (void) TIFFSetField(tiff,TIFFTAG_IMAGEDESCRIPTION,value);
3434
7.56k
  value=GetImageArtifact(image,"tiff:subfiletype");
3435
7.56k
  if (value != (const char *) NULL)
3436
0
    {
3437
0
      if (LocaleCompare(value,"REDUCEDIMAGE") == 0)
3438
0
        (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_REDUCEDIMAGE);
3439
0
      else
3440
0
        if (LocaleCompare(value,"PAGE") == 0)
3441
0
          (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
3442
0
        else
3443
0
          if (LocaleCompare(value,"MASK") == 0)
3444
0
            (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_MASK);
3445
0
    }
3446
7.56k
  else
3447
7.56k
    {
3448
7.56k
      uint16
3449
7.56k
        page,
3450
7.56k
        pages;
3451
3452
7.56k
      page=(uint16) image->scene;
3453
7.56k
      pages=(uint16) GetImageListLength(image);
3454
7.56k
      if ((adjoin != MagickFalse) && (pages > 1))
3455
0
        (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
3456
7.56k
      (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,page,pages);
3457
7.56k
    }
3458
7.56k
}
3459
3460
static MagickBooleanType WriteTIFFChannels(Image *image,TIFF *tiff,
3461
  TIFFInfo tiff_info,QuantumInfo *quantum_info,QuantumType quantum_type,
3462
  tsample_t sample,unsigned char *pixels,ExceptionInfo *exception)
3463
7.56k
{
3464
7.56k
  ssize_t
3465
7.56k
    y;
3466
3467
297k
  for (y=0; y < (ssize_t) image->rows; y++)
3468
289k
  {
3469
289k
    const Quantum
3470
289k
      *magick_restrict p;
3471
3472
289k
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3473
289k
    if (p == (const Quantum *) NULL)
3474
0
      break;
3475
289k
    (void) ExportQuantumPixels(image,(CacheView*)NULL,quantum_info,
3476
289k
      quantum_type,pixels,exception);
3477
289k
    if (TIFFWritePixels(tiff,&tiff_info,y,sample,image) == -1)
3478
0
      return(MagickFalse);
3479
289k
  }
3480
7.56k
  return(MagickTrue);
3481
7.56k
}
3482
3483
static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
3484
  Image *image,ExceptionInfo *exception)
3485
7.56k
{
3486
7.56k
  const char
3487
7.56k
    *mode,
3488
7.56k
    *option;
3489
3490
7.56k
  CompressionType
3491
7.56k
    compression;
3492
3493
7.56k
  EndianType
3494
7.56k
    endian_type;
3495
3496
7.56k
  MagickBooleanType
3497
7.56k
    adjoin,
3498
7.56k
    preserve_compression,
3499
7.56k
    status;
3500
3501
7.56k
  MagickOffsetType
3502
7.56k
    scene;
3503
3504
7.56k
  QuantumInfo
3505
7.56k
    *quantum_info;
3506
3507
7.56k
  QuantumType
3508
7.56k
    quantum_type;
3509
3510
7.56k
  size_t
3511
7.56k
    extra_samples,
3512
7.56k
    number_scenes;
3513
3514
7.56k
  ssize_t
3515
7.56k
    i;
3516
3517
7.56k
  TIFF
3518
7.56k
    *tiff;
3519
3520
7.56k
  TIFFInfo
3521
7.56k
    tiff_info;
3522
3523
7.56k
  uint16
3524
7.56k
    bits_per_sample,
3525
7.56k
    compress_tag,
3526
7.56k
    endian,
3527
7.56k
    photometric,
3528
7.56k
    predictor;
3529
3530
7.56k
  unsigned char
3531
7.56k
    *pixels;
3532
3533
7.56k
  void
3534
7.56k
    *sans[2] = { NULL, NULL };
3535
3536
  /*
3537
    Open TIFF file.
3538
  */
3539
7.56k
  assert(image_info != (const ImageInfo *) NULL);
3540
7.56k
  assert(image_info->signature == MagickCoreSignature);
3541
7.56k
  assert(image != (Image *) NULL);
3542
7.56k
  assert(image->signature == MagickCoreSignature);
3543
7.56k
  assert(exception != (ExceptionInfo *) NULL);
3544
7.56k
  assert(exception->signature == MagickCoreSignature);
3545
7.56k
  if (IsEventLogging() != MagickFalse)
3546
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3547
7.56k
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
3548
7.56k
  if (status == MagickFalse)
3549
0
    return(status);
3550
7.56k
  (void) SetMagickThreadValue(tiff_exception,exception);
3551
7.56k
  endian_type=LSBEndian;
3552
7.56k
  if (image_info->endian != UndefinedEndian)
3553
0
    endian_type=image_info->endian;
3554
7.56k
  option=GetImageOption(image_info,"tiff:endian");
3555
7.56k
  if (option != (const char *) NULL)
3556
0
    {
3557
0
      if (LocaleNCompare(option,"msb",3) == 0)
3558
0
        endian_type=MSBEndian;
3559
0
      if (LocaleNCompare(option,"lsb",3) == 0)
3560
0
        endian_type=LSBEndian;
3561
0
    }
3562
7.56k
#if defined(TIFF_VERSION_BIG)
3563
7.56k
  if (LocaleCompare(image_info->magick,"TIFF64") == 0)
3564
1.86k
    mode=endian_type == LSBEndian ? "wl8" : "wb8";
3565
5.70k
  else
3566
5.70k
#endif
3567
5.70k
    mode=endian_type == LSBEndian ? "wl" : "wb";
3568
7.56k
  tiff=TIFFClientOpen(image->filename,mode,(thandle_t) image,TIFFReadBlob,
3569
7.56k
    TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
3570
7.56k
    TIFFUnmapBlob);
3571
7.56k
  if (tiff == (TIFF *) NULL)
3572
0
    return(MagickFalse);
3573
7.56k
  if (exception->severity > ErrorException)
3574
0
    {
3575
0
      TIFFClose(tiff);
3576
0
      return(MagickFalse);
3577
0
    }
3578
7.56k
  (void) DeleteImageProfile(image,"tiff:37724");
3579
7.56k
  scene=0;
3580
7.56k
  adjoin=image_info->adjoin;
3581
7.56k
  number_scenes=GetImageListLength(image);
3582
7.56k
  option=GetImageOption(image_info,"tiff:preserve-compression");
3583
7.56k
  preserve_compression=IsStringTrue(option);
3584
7.56k
  do
3585
7.56k
  {
3586
    /*
3587
      Initialize TIFF fields.
3588
    */
3589
7.56k
    if ((image_info->type != UndefinedType) &&
3590
1.26k
        (image_info->type != OptimizeType) &&
3591
1.26k
        (image_info->type != image->type))
3592
0
      (void) SetImageType(image,image_info->type,exception);
3593
7.56k
    compression=image_info->compression;
3594
7.56k
    if (preserve_compression != MagickFalse)
3595
0
      compression=image->compression;
3596
7.56k
    switch (compression)
3597
7.56k
    {
3598
0
      case FaxCompression:
3599
1.26k
      case Group4Compression:
3600
1.26k
      {
3601
1.26k
        if (IsImageMonochrome(image) == MagickFalse)
3602
0
          {
3603
0
            if (IsImageGray(image) == MagickFalse)
3604
0
              (void) SetImageType(image,BilevelType,exception);
3605
0
            else
3606
0
              (void) SetImageDepth(image,1,exception);
3607
0
          }
3608
1.26k
        image->depth=1;
3609
1.26k
        image->number_meta_channels=0;
3610
1.26k
        break;
3611
0
      }
3612
0
      case JPEGCompression:
3613
0
      {
3614
0
        (void) SetImageStorageClass(image,DirectClass,exception);
3615
0
        (void) SetImageDepth(image,8,exception);
3616
0
        break;
3617
0
      }
3618
6.29k
      default:
3619
6.29k
        break;
3620
7.56k
    }
3621
7.56k
    quantum_info=AcquireQuantumInfo(image_info,image);
3622
7.56k
    if (quantum_info == (QuantumInfo *) NULL)
3623
7.56k
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
3624
7.56k
    if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
3625
1.74k
        (quantum_info->format == UndefinedQuantumFormat) &&
3626
1.74k
        (IsHighDynamicRangeImage(image,exception) != MagickFalse))
3627
1.09k
      {
3628
1.09k
        status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
3629
1.09k
        if (status == MagickFalse)
3630
0
          {
3631
0
            quantum_info=DestroyQuantumInfo(quantum_info);
3632
0
            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
3633
0
          }
3634
1.09k
      }
3635
7.56k
    option=GetImageOption(image_info,"quantum:polarity");
3636
7.56k
    if (option == (const char *) NULL)
3637
7.56k
      option=GetImageArtifact(image,"tiff:photometric");
3638
7.56k
    if (option != (const char *) NULL)
3639
0
      {
3640
0
        if (LocaleCompare(option,"min-is-black") == 0)
3641
0
          SetQuantumMinIsWhite(quantum_info,MagickFalse);
3642
0
        if (LocaleCompare(option,"min-is-white") == 0)
3643
0
          SetQuantumMinIsWhite(quantum_info,MagickTrue);
3644
0
      }
3645
7.56k
    if ((LocaleCompare(image_info->magick,"PTIF") == 0) &&
3646
0
        (GetPreviousImageInList(image) != (Image *) NULL))
3647
0
      (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_REDUCEDIMAGE);
3648
7.56k
    if ((image->columns != (uint32) image->columns) ||
3649
7.56k
        (image->rows != (uint32) image->rows))
3650
7.56k
      ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
3651
7.56k
    (void) TIFFSetField(tiff,TIFFTAG_IMAGELENGTH,(uint32) image->rows);
3652
7.56k
    (void) TIFFSetField(tiff,TIFFTAG_IMAGEWIDTH,(uint32) image->columns);
3653
7.56k
    switch (compression)
3654
7.56k
    {
3655
0
      case FaxCompression:
3656
0
      {
3657
0
        compress_tag=COMPRESSION_CCITTFAX3;
3658
0
        break;
3659
0
      }
3660
1.26k
      case Group4Compression:
3661
1.26k
      {
3662
1.26k
        compress_tag=COMPRESSION_CCITTFAX4;
3663
1.26k
        break;
3664
0
      }
3665
0
#if defined(COMPRESSION_JBIG)
3666
0
      case JBIG1Compression:
3667
0
      {
3668
0
        compress_tag=COMPRESSION_JBIG;
3669
0
        break;
3670
0
      }
3671
0
#endif
3672
0
      case JPEGCompression:
3673
0
      {
3674
0
        compress_tag=COMPRESSION_JPEG;
3675
0
        break;
3676
0
      }
3677
0
#if defined(COMPRESSION_LERC)
3678
0
      case LERCCompression:
3679
0
      {
3680
0
        compress_tag=COMPRESSION_LERC;
3681
0
        break;
3682
0
      }
3683
0
#endif
3684
0
#if defined(COMPRESSION_LZMA)
3685
0
      case LZMACompression:
3686
0
      {
3687
0
        compress_tag=COMPRESSION_LZMA;
3688
0
        break;
3689
0
      }
3690
0
#endif
3691
0
      case LZWCompression:
3692
0
      {
3693
0
        compress_tag=COMPRESSION_LZW;
3694
0
        break;
3695
0
      }
3696
0
      case RLECompression:
3697
0
      {
3698
0
        compress_tag=COMPRESSION_PACKBITS;
3699
0
        break;
3700
0
      }
3701
0
      case ZipCompression:
3702
0
      {
3703
0
        compress_tag=COMPRESSION_ADOBE_DEFLATE;
3704
0
        break;
3705
0
      }
3706
0
#if defined(COMPRESSION_ZSTD)
3707
0
      case ZstdCompression:
3708
0
      {
3709
0
        compress_tag=COMPRESSION_ZSTD;
3710
0
        break;
3711
0
      }
3712
0
#endif
3713
0
      case NoCompression:
3714
6.29k
      default:
3715
6.29k
      {
3716
6.29k
        compress_tag=COMPRESSION_NONE;
3717
6.29k
        break;
3718
0
      }
3719
7.56k
    }
3720
7.56k
    if ((compress_tag != COMPRESSION_NONE) &&
3721
1.26k
        (TIFFIsCODECConfigured(compress_tag) == 0))
3722
0
      {
3723
0
        (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
3724
0
          "CompressionNotSupported","`%s'",CommandOptionToMnemonic(
3725
0
          MagickCompressOptions,(ssize_t) compression));
3726
0
        compress_tag=COMPRESSION_NONE;
3727
0
        compression=NoCompression;
3728
0
      }
3729
7.56k
    if (image->colorspace == CMYKColorspace)
3730
1.35k
      {
3731
1.35k
        photometric=PHOTOMETRIC_SEPARATED;
3732
1.35k
        (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,4);
3733
1.35k
        (void) TIFFSetField(tiff,TIFFTAG_INKSET,INKSET_CMYK);
3734
1.35k
      }
3735
6.21k
    else
3736
6.21k
      {
3737
        /*
3738
          Full color TIFF raster.
3739
        */
3740
6.21k
        if (image->colorspace == LabColorspace)
3741
350
          {
3742
350
            photometric=PHOTOMETRIC_CIELAB;
3743
350
            EncodeLabImage(image,exception);
3744
350
          }
3745
5.86k
        else
3746
5.86k
          if (IsYCbCrCompatibleColorspace(image->colorspace) != MagickFalse)
3747
507
            {
3748
507
              photometric=PHOTOMETRIC_YCBCR;
3749
507
              (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,1,1);
3750
507
              (void) SetImageStorageClass(image,DirectClass,exception);
3751
507
              status=SetQuantumDepth(image,quantum_info,8);
3752
507
              if (status == MagickFalse)
3753
0
                ThrowWriterException(ResourceLimitError,
3754
507
                  "MemoryAllocationFailed");
3755
507
            }
3756
5.35k
          else
3757
5.35k
            photometric=PHOTOMETRIC_RGB;
3758
6.21k
        (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,3);
3759
6.21k
        if ((image_info->type != TrueColorType) &&
3760
6.21k
            (image_info->type != TrueColorAlphaType))
3761
6.21k
          {
3762
6.21k
            if ((image_info->type != PaletteType) &&
3763
6.21k
                (IdentifyImageCoderGray(image,exception) != MagickFalse))
3764
3.58k
              {
3765
3.58k
                photometric=(uint16) (quantum_info->min_is_white !=
3766
3.58k
                  MagickFalse ? PHOTOMETRIC_MINISWHITE :
3767
3.58k
                  PHOTOMETRIC_MINISBLACK);
3768
3.58k
                (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
3769
3.58k
              }
3770
2.62k
            else
3771
2.62k
              if ((image->storage_class == PseudoClass) &&
3772
176
                  ((image->alpha_trait & BlendPixelTrait) == 0))
3773
176
                {
3774
176
                  size_t
3775
176
                    depth;
3776
3777
                  /*
3778
                    Colormapped TIFF raster.
3779
                  */
3780
176
                  (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
3781
176
                  photometric=PHOTOMETRIC_PALETTE;
3782
176
                  depth=1;
3783
522
                  while ((GetQuantumRange(depth)+1) < image->colors)
3784
346
                    depth<<=1;
3785
176
                  status=SetQuantumDepth(image,quantum_info,depth);
3786
176
                  if (status == MagickFalse)
3787
0
                    ThrowWriterException(ResourceLimitError,
3788
176
                      "MemoryAllocationFailed");
3789
176
                }
3790
6.21k
          }
3791
6.21k
      }
3792
7.56k
    (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian,sans);
3793
7.56k
    if ((compress_tag == COMPRESSION_CCITTFAX3) ||
3794
7.56k
        (compress_tag == COMPRESSION_CCITTFAX4))
3795
1.26k
      {
3796
1.26k
         if ((photometric != PHOTOMETRIC_MINISWHITE) &&
3797
1.26k
             (photometric != PHOTOMETRIC_MINISBLACK))
3798
0
          {
3799
0
            compress_tag=COMPRESSION_NONE;
3800
0
            endian=FILLORDER_MSB2LSB;
3801
0
          }
3802
1.26k
      }
3803
7.56k
    option=GetImageOption(image_info,"tiff:fill-order");
3804
7.56k
    if (option != (const char *) NULL)
3805
0
      {
3806
0
        if (LocaleNCompare(option,"msb",3) == 0)
3807
0
          endian=FILLORDER_MSB2LSB;
3808
0
        if (LocaleNCompare(option,"lsb",3) == 0)
3809
0
          endian=FILLORDER_LSB2MSB;
3810
0
      }
3811
7.56k
    (void) TIFFSetField(tiff,TIFFTAG_COMPRESSION,compress_tag);
3812
7.56k
    (void) TIFFSetField(tiff,TIFFTAG_FILLORDER,endian);
3813
7.56k
    (void) TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,quantum_info->depth);
3814
7.56k
    extra_samples=image->alpha_trait != UndefinedPixelTrait ? 1 : 0;
3815
7.56k
    extra_samples+=image->number_meta_channels;
3816
7.56k
    if (extra_samples != 0)
3817
2.86k
      {
3818
2.86k
        uint16
3819
2.86k
          sample_info[MaxPixelChannels+1],
3820
2.86k
          samples_per_pixel;
3821
3822
        /*
3823
          TIFF has a matte channel.
3824
        */
3825
2.86k
        (void) memset(sample_info,0,sizeof(sample_info));
3826
2.86k
        sample_info[0]=EXTRASAMPLE_UNSPECIFIED;
3827
2.86k
        if (image->alpha_trait != UndefinedPixelTrait)
3828
2.24k
          sample_info[0]=EXTRASAMPLE_UNASSALPHA;
3829
2.86k
        option=GetImageOption(image_info,"tiff:alpha");
3830
2.86k
        if (option != (const char *) NULL)
3831
0
          {
3832
0
            if (LocaleCompare(option,"associated") == 0)
3833
0
              sample_info[0]=EXTRASAMPLE_ASSOCALPHA;
3834
0
            else
3835
0
              if (LocaleCompare(option,"unspecified") == 0)
3836
0
                sample_info[0]=EXTRASAMPLE_UNSPECIFIED;
3837
0
          }
3838
2.86k
        (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,
3839
2.86k
          &samples_per_pixel,sans);
3840
2.86k
        (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,samples_per_pixel+
3841
2.86k
          extra_samples);
3842
2.86k
        (void) TIFFSetField(tiff,TIFFTAG_EXTRASAMPLES,(uint16) extra_samples,
3843
2.86k
          &sample_info);
3844
2.86k
        if (sample_info[0] == EXTRASAMPLE_ASSOCALPHA)
3845
0
          SetQuantumAlphaType(quantum_info,AssociatedQuantumAlpha);
3846
2.86k
      }
3847
7.56k
    (void) TIFFSetField(tiff,TIFFTAG_PHOTOMETRIC,photometric);
3848
7.56k
    switch (quantum_info->format)
3849
7.56k
    {
3850
1.09k
      case FloatingPointQuantumFormat:
3851
1.09k
      {
3852
1.09k
        double
3853
1.09k
          max = 1.0,
3854
1.09k
          min = 0.0;
3855
3856
1.09k
        (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_IEEEFP);
3857
1.09k
        (void) GetImageRange(image,&min,&max,exception);
3858
1.09k
        (void) TIFFSetField(tiff,TIFFTAG_SMINSAMPLEVALUE,min);
3859
1.09k
        (void) TIFFSetField(tiff,TIFFTAG_SMAXSAMPLEVALUE,max);
3860
1.09k
        break;
3861
0
      }
3862
0
      case SignedQuantumFormat:
3863
0
      {
3864
0
        (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_INT);
3865
0
        break;
3866
0
      }
3867
0
      case UnsignedQuantumFormat:
3868
0
      {
3869
0
        (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_UINT);
3870
0
        break;
3871
0
      }
3872
6.46k
      default:
3873
6.46k
        break;
3874
7.56k
    }
3875
7.56k
    (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
3876
7.56k
    if ((photometric == PHOTOMETRIC_RGB) &&
3877
1.89k
        ((image_info->interlace == PlaneInterlace) ||
3878
1.89k
         (image_info->interlace == PartitionInterlace)))
3879
0
      (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_SEPARATE);
3880
7.56k
    predictor=0;
3881
7.56k
    switch (compress_tag)
3882
7.56k
    {
3883
0
      case COMPRESSION_JPEG:
3884
0
      {
3885
0
#if defined(JPEG_SUPPORT)
3886
0
        if (image_info->quality != UndefinedCompressionQuality)
3887
0
          (void) TIFFSetField(tiff,TIFFTAG_JPEGQUALITY,image_info->quality);
3888
0
        (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RAW);
3889
0
        if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
3890
0
          (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RGB);
3891
0
        if (IsYCbCrCompatibleColorspace(image->colorspace) != MagickFalse)
3892
0
          {
3893
0
            const char
3894
0
              *sampling_factor,
3895
0
              *value;
3896
3897
0
            GeometryInfo
3898
0
              geometry_info;
3899
3900
0
            MagickStatusType
3901
0
              flags;
3902
3903
0
            sampling_factor=(const char *) NULL;
3904
0
            value=GetImageOption(image_info,"jpeg:sampling-factor");
3905
0
            if (value == (char *) NULL)
3906
0
              value=GetImageProperty(image,"jpeg:sampling-factor",exception);
3907
0
            if (value != (char *) NULL)
3908
0
              {
3909
0
                sampling_factor=value;
3910
0
                if (image->debug != MagickFalse)
3911
0
                  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3912
0
                    "  Input sampling-factors=%s",sampling_factor);
3913
0
              }
3914
0
            if (image_info->sampling_factor != (char *) NULL)
3915
0
              sampling_factor=image_info->sampling_factor;
3916
0
            if (sampling_factor != (const char *) NULL)
3917
0
              {
3918
0
                flags=ParseGeometry(sampling_factor,&geometry_info);
3919
0
                if ((flags & SigmaValue) == 0)
3920
0
                  geometry_info.sigma=geometry_info.rho;
3921
                /*
3922
                  To do: write pixel data in YCBCR subsampled format.
3923
3924
                  (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,(uint16)
3925
                    geometry_info.rho,(uint16) geometry_info.sigma);
3926
                */
3927
0
              }
3928
0
            }
3929
0
        (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
3930
0
          &bits_per_sample,sans);
3931
0
        if (bits_per_sample == 12)
3932
0
          (void) TIFFSetField(tiff,TIFFTAG_JPEGTABLESMODE,JPEGTABLESMODE_QUANT);
3933
0
        option=GetImageOption(image_info,"tiff:jpeg-tables-mode");
3934
0
        if (option != (char *) NULL)
3935
0
          {
3936
0
            int
3937
0
              jpeg_tables_mode;
3938
3939
0
            jpeg_tables_mode=(int) StringToUnsignedLong(option);
3940
0
            if (jpeg_tables_mode >= 0 && jpeg_tables_mode <= 3)
3941
0
              (void) TIFFSetField(tiff,TIFFTAG_JPEGTABLESMODE,jpeg_tables_mode);
3942
0
          }
3943
0
#endif
3944
0
        break;
3945
0
      }
3946
0
      case COMPRESSION_ADOBE_DEFLATE:
3947
0
      {
3948
0
        (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
3949
0
          &bits_per_sample,sans);
3950
0
        if (((photometric == PHOTOMETRIC_RGB) ||
3951
0
             (photometric == PHOTOMETRIC_SEPARATED) ||
3952
0
             (photometric == PHOTOMETRIC_MINISBLACK)) &&
3953
0
            ((bits_per_sample == 8) || (bits_per_sample == 16)))
3954
0
          predictor=PREDICTOR_HORIZONTAL;
3955
0
        (void) TIFFSetField(tiff,TIFFTAG_ZIPQUALITY,(long) (
3956
0
          image_info->quality == UndefinedCompressionQuality ? 7 :
3957
0
          MagickMin((ssize_t) image_info->quality/10,9)));
3958
0
        break;
3959
0
      }
3960
0
      case COMPRESSION_CCITTFAX3:
3961
0
      {
3962
        /*
3963
          Byte-aligned EOL.
3964
        */
3965
0
        (void) TIFFSetField(tiff,TIFFTAG_GROUP3OPTIONS,4);
3966
0
        break;
3967
0
      }
3968
1.26k
      case COMPRESSION_CCITTFAX4:
3969
1.26k
        break;
3970
#if defined(LERC_SUPPORT) && defined(COMPRESSION_LERC)
3971
      case COMPRESSION_LERC:
3972
        break;
3973
#endif
3974
#if defined(LZMA_SUPPORT) && defined(COMPRESSION_LZMA)
3975
      case COMPRESSION_LZMA:
3976
      {
3977
        if (((photometric == PHOTOMETRIC_RGB) ||
3978
             (photometric == PHOTOMETRIC_SEPARATED) ||
3979
             (photometric == PHOTOMETRIC_MINISBLACK)) &&
3980
            ((bits_per_sample == 8) || (bits_per_sample == 16)))
3981
          predictor=PREDICTOR_HORIZONTAL;
3982
        (void) TIFFSetField(tiff,TIFFTAG_LZMAPRESET,(long) (
3983
          image_info->quality == UndefinedCompressionQuality ? 7 :
3984
          MagickMin((ssize_t) image_info->quality/10,9)));
3985
        break;
3986
      }
3987
#endif
3988
0
      case COMPRESSION_LZW:
3989
0
      {
3990
0
        (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
3991
0
          &bits_per_sample,sans);
3992
0
        if (((photometric == PHOTOMETRIC_RGB) ||
3993
0
             (photometric == PHOTOMETRIC_SEPARATED) ||
3994
0
             (photometric == PHOTOMETRIC_MINISBLACK)) &&
3995
0
            ((bits_per_sample == 8) || (bits_per_sample == 16)))
3996
0
          predictor=PREDICTOR_HORIZONTAL;
3997
0
        break;
3998
0
      }
3999
#if defined(WEBP_SUPPORT) && defined(COMPRESSION_WEBP)
4000
      case COMPRESSION_WEBP:
4001
      {
4002
        (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
4003
          &bits_per_sample,sans);
4004
        if (((photometric == PHOTOMETRIC_RGB) ||
4005
             (photometric == PHOTOMETRIC_SEPARATED) ||
4006
             (photometric == PHOTOMETRIC_MINISBLACK)) &&
4007
            ((bits_per_sample == 8) || (bits_per_sample == 16)))
4008
          predictor=PREDICTOR_HORIZONTAL;
4009
        (void) TIFFSetField(tiff,TIFFTAG_WEBP_LEVEL,image_info->quality);
4010
        if (image_info->quality >= 100)
4011
          (void) TIFFSetField(tiff,TIFFTAG_WEBP_LOSSLESS,1);
4012
        break;
4013
      }
4014
#endif
4015
#if defined(ZSTD_SUPPORT) && defined(COMPRESSION_ZSTD)
4016
      case COMPRESSION_ZSTD:
4017
      {
4018
        (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
4019
          &bits_per_sample,sans);
4020
        if (((photometric == PHOTOMETRIC_RGB) ||
4021
             (photometric == PHOTOMETRIC_SEPARATED) ||
4022
             (photometric == PHOTOMETRIC_MINISBLACK)) &&
4023
            ((bits_per_sample == 8) || (bits_per_sample == 16)))
4024
          predictor=PREDICTOR_HORIZONTAL;
4025
        (void) TIFFSetField(tiff,TIFFTAG_ZSTD_LEVEL,22*image_info->quality/
4026
          100.0);
4027
        break;
4028
      }
4029
#endif
4030
6.29k
      default:
4031
6.29k
        break;
4032
7.56k
    }
4033
7.56k
    if ((compress_tag == COMPRESSION_LZW) ||
4034
7.56k
        (compress_tag == COMPRESSION_ADOBE_DEFLATE))
4035
0
      {
4036
0
        if (quantum_info->format == FloatingPointQuantumFormat)
4037
0
          predictor=PREDICTOR_FLOATINGPOINT;
4038
0
        option=GetImageOption(image_info,"tiff:predictor");
4039
0
        if (option != (const char * ) NULL)
4040
0
          predictor=(uint16) strtol(option,(char **) NULL,10);
4041
0
        if (predictor != 0)
4042
0
          (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,predictor);
4043
0
      }
4044
7.56k
    if ((image->resolution.x > 0.0) && (image->resolution.y > 0.0))
4045
1.19k
      {
4046
1.19k
        unsigned short
4047
1.19k
          units;
4048
4049
1.19k
        ssize_t
4050
1.19k
          x_position = image->page.x,
4051
1.19k
          y_position = image->page.y;
4052
4053
        /*
4054
          Set image resolution.
4055
        */
4056
1.19k
        units=RESUNIT_NONE;
4057
1.19k
        if (image->units == PixelsPerInchResolution)
4058
1.03k
          units=RESUNIT_INCH;
4059
1.19k
        if (image->units == PixelsPerCentimeterResolution)
4060
28
          units=RESUNIT_CENTIMETER;
4061
1.19k
        (void) TIFFSetField(tiff,TIFFTAG_RESOLUTIONUNIT,(uint16) units);
4062
1.19k
        (void) TIFFSetField(tiff,TIFFTAG_XRESOLUTION,image->resolution.x);
4063
1.19k
        (void) TIFFSetField(tiff,TIFFTAG_YRESOLUTION,image->resolution.y);
4064
1.19k
        if ((x_position < 0) || (y_position < 0))
4065
100
          {
4066
100
            x_position=MagickMax(x_position,0);
4067
100
            y_position=MagickMax(y_position,0);
4068
100
            (void) ThrowMagickException(exception,GetMagickModule(),
4069
100
              CoderWarning,"TIFF: negative image positions unsupported","%s",
4070
100
              image->filename);
4071
100
          }
4072
1.19k
        (void) TIFFSetField(tiff,TIFFTAG_XPOSITION,(double) x_position/
4073
1.19k
          image->resolution.x);
4074
1.19k
        (void) TIFFSetField(tiff,TIFFTAG_YPOSITION,(double) y_position/
4075
1.19k
          image->resolution.y);
4076
1.19k
      }
4077
7.56k
    if (image->chromaticity.white_point.x != 0.0)
4078
5.62k
      {
4079
5.62k
        float
4080
5.62k
          chromaticity[6];
4081
4082
        /*
4083
          Set image chromaticity.
4084
        */
4085
5.62k
        chromaticity[0]=(float) image->chromaticity.red_primary.x;
4086
5.62k
        chromaticity[1]=(float) image->chromaticity.red_primary.y;
4087
5.62k
        chromaticity[2]=(float) image->chromaticity.green_primary.x;
4088
5.62k
        chromaticity[3]=(float) image->chromaticity.green_primary.y;
4089
5.62k
        chromaticity[4]=(float) image->chromaticity.blue_primary.x;
4090
5.62k
        chromaticity[5]=(float) image->chromaticity.blue_primary.y;
4091
5.62k
        (void) TIFFSetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,chromaticity);
4092
5.62k
        chromaticity[0]=(float) image->chromaticity.white_point.x;
4093
5.62k
        chromaticity[1]=(float) image->chromaticity.white_point.y;
4094
5.62k
        (void) TIFFSetField(tiff,TIFFTAG_WHITEPOINT,chromaticity);
4095
5.62k
      }
4096
7.56k
    option=GetImageOption(image_info,"tiff:write-layers");
4097
7.56k
    if (IsStringTrue(option) != MagickFalse)
4098
0
      {
4099
0
        (void) TIFFWritePhotoshopLayers(image,image_info,endian_type,exception);
4100
0
        adjoin=MagickFalse;
4101
0
      }
4102
7.56k
    if ((LocaleCompare(image_info->magick,"PTIF") != 0) &&
4103
7.56k
        (adjoin != MagickFalse) && (number_scenes > 1))
4104
0
      {
4105
0
        (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
4106
0
        if (image->scene != 0)
4107
0
          (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,(uint16) image->scene,
4108
0
            number_scenes);
4109
0
      }
4110
7.56k
    if (image->orientation != UndefinedOrientation)
4111
7.55k
      (void) TIFFSetField(tiff,TIFFTAG_ORIENTATION,(uint16) image->orientation);
4112
7
    else
4113
7
      (void) TIFFSetField(tiff,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
4114
7.56k
    TIFFSetProfiles(tiff,image);
4115
7.56k
    {
4116
7.56k
      uint16
4117
7.56k
        page,
4118
7.56k
        pages;
4119
4120
7.56k
      page=(uint16) scene;
4121
7.56k
      pages=(uint16) number_scenes;
4122
7.56k
      if ((LocaleCompare(image_info->magick,"PTIF") != 0) &&
4123
7.56k
          (adjoin != MagickFalse) && (pages > 1))
4124
0
        (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
4125
7.56k
      (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,page,pages);
4126
7.56k
    }
4127
7.56k
    (void) TIFFSetProperties(tiff,adjoin,image,exception);
4128
    /*
4129
      Write image scanlines.
4130
    */
4131
7.56k
    if (GetTIFFInfo(image_info,tiff,&tiff_info) == MagickFalse)
4132
7.56k
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
4133
7.56k
    if (compress_tag == COMPRESSION_CCITTFAX4)
4134
1.26k
      (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,(uint32) image->rows);
4135
7.56k
    (void) SetQuantumEndian(image,quantum_info,LSBEndian);
4136
7.56k
    pixels=(unsigned char *) GetQuantumPixels(quantum_info);
4137
7.56k
    tiff_info.scanline=(unsigned char *) GetQuantumPixels(quantum_info);
4138
7.56k
    switch (photometric)
4139
7.56k
    {
4140
196
      case PHOTOMETRIC_CIELAB:
4141
551
      case PHOTOMETRIC_YCBCR:
4142
2.45k
      case PHOTOMETRIC_RGB:
4143
2.45k
      {
4144
        /*
4145
          RGB TIFF image.
4146
        */
4147
2.45k
        switch (image_info->interlace)
4148
2.45k
        {
4149
2.45k
          case NoInterlace:
4150
2.45k
          default:
4151
2.45k
          {
4152
2.45k
            quantum_type=RGBQuantum;
4153
2.45k
            if (image->alpha_trait != UndefinedPixelTrait)
4154
637
              quantum_type=RGBAQuantum;
4155
2.45k
            if (image->number_meta_channels != 0)
4156
419
              {
4157
419
                quantum_type=MultispectralQuantum;
4158
419
                (void) SetQuantumPad(image,quantum_info,0);
4159
419
              }
4160
2.45k
            status=WriteTIFFChannels(image,tiff,tiff_info,quantum_info,
4161
2.45k
              quantum_type,0,pixels,exception);
4162
2.45k
            break;
4163
2.45k
          }
4164
0
          case PlaneInterlace:
4165
0
          case PartitionInterlace:
4166
0
          {
4167
0
            tsample_t
4168
0
              sample = 0;
4169
4170
            /*
4171
              Plane interlacing:  RRRRRR...GGGGGG...BBBBBB...
4172
            */
4173
0
            status=WriteTIFFChannels(image,tiff,tiff_info,quantum_info,
4174
0
              RedQuantum,sample++,pixels,exception);
4175
0
            if (status == MagickFalse)
4176
0
              break;
4177
0
            status=WriteTIFFChannels(image,tiff,tiff_info,quantum_info,
4178
0
              GreenQuantum,sample++,pixels,exception);
4179
0
            if (status == MagickFalse)
4180
0
              break;
4181
0
            status=WriteTIFFChannels(image,tiff,tiff_info,quantum_info,
4182
0
              BlueQuantum,sample++,pixels,exception);
4183
0
            if (status == MagickFalse)
4184
0
              break;
4185
0
            if (image->alpha_trait != UndefinedPixelTrait)
4186
0
              {
4187
0
                status=WriteTIFFChannels(image,tiff,tiff_info,quantum_info,
4188
0
                  AlphaQuantum,sample++,pixels,exception);
4189
0
                if (status == MagickFalse)
4190
0
                  break;
4191
0
              }
4192
0
            for (i=0; i < (ssize_t) image->number_meta_channels; i++)
4193
0
            {
4194
0
              (void) SetQuantumMetaChannel(image,quantum_info,i);
4195
0
              status=WriteTIFFChannels(image,tiff,tiff_info,quantum_info,
4196
0
                MultispectralQuantum,sample++,pixels,exception);
4197
0
              if (status == MagickFalse)
4198
0
                break;
4199
0
            }
4200
0
            (void) SetQuantumMetaChannel(image,quantum_info,-1);
4201
0
            break;
4202
0
          }
4203
2.45k
        }
4204
2.45k
        break;
4205
2.45k
      }
4206
2.45k
      case PHOTOMETRIC_SEPARATED:
4207
1.35k
      {
4208
        /*
4209
          CMYK TIFF image.
4210
        */
4211
1.35k
        quantum_type=CMYKQuantum;
4212
1.35k
        if (image->alpha_trait != UndefinedPixelTrait)
4213
679
          quantum_type=CMYKAQuantum;
4214
1.35k
        if (image->number_meta_channels != 0)
4215
77
          {
4216
77
            quantum_type=MultispectralQuantum;
4217
77
            (void) SetQuantumPad(image,quantum_info,0);
4218
77
          }
4219
1.35k
        if (image->colorspace != CMYKColorspace)
4220
0
          (void) TransformImageColorspace(image,CMYKColorspace,exception);
4221
1.35k
        status=WriteTIFFChannels(image,tiff,tiff_info,quantum_info,
4222
1.35k
          quantum_type,0,pixels,exception);
4223
1.35k
        break;
4224
2.45k
      }
4225
176
      case PHOTOMETRIC_PALETTE:
4226
176
      {
4227
176
        uint16
4228
176
          *blue,
4229
176
          *green,
4230
176
          *red;
4231
4232
        /*
4233
          Colormapped TIFF image.
4234
        */
4235
176
        red=(uint16 *) AcquireQuantumMemory(65536,sizeof(*red));
4236
176
        green=(uint16 *) AcquireQuantumMemory(65536,sizeof(*green));
4237
176
        blue=(uint16 *) AcquireQuantumMemory(65536,sizeof(*blue));
4238
176
        if ((red == (uint16 *) NULL) || (green == (uint16 *) NULL) ||
4239
176
            (blue == (uint16 *) NULL))
4240
0
          {
4241
0
            if (red != (uint16 *) NULL)
4242
0
              red=(uint16 *) RelinquishMagickMemory(red);
4243
0
            if (green != (uint16 *) NULL)
4244
0
              green=(uint16 *) RelinquishMagickMemory(green);
4245
0
            if (blue != (uint16 *) NULL)
4246
0
              blue=(uint16 *) RelinquishMagickMemory(blue);
4247
0
            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
4248
0
          }
4249
        /*
4250
          Initialize TIFF colormap.
4251
        */
4252
176
        (void) memset(red,0,65536*sizeof(*red));
4253
176
        (void) memset(green,0,65536*sizeof(*green));
4254
176
        (void) memset(blue,0,65536*sizeof(*blue));
4255
13.4k
        for (i=0; i < (ssize_t) image->colors; i++)
4256
13.2k
        {
4257
13.2k
          red[i]=ScaleQuantumToShort((Quantum) image->colormap[i].red);
4258
13.2k
          green[i]=ScaleQuantumToShort((Quantum) image->colormap[i].green);
4259
13.2k
          blue[i]=ScaleQuantumToShort((Quantum) image->colormap[i].blue);
4260
13.2k
        }
4261
176
        (void) TIFFSetField(tiff,TIFFTAG_COLORMAP,red,green,blue);
4262
176
        red=(uint16 *) RelinquishMagickMemory(red);
4263
176
        green=(uint16 *) RelinquishMagickMemory(green);
4264
176
        blue=(uint16 *) RelinquishMagickMemory(blue);
4265
176
        magick_fallthrough;
4266
176
      }
4267
3.76k
      default:
4268
3.76k
      {
4269
        /*
4270
          Convert PseudoClass packets to contiguous grayscale scanlines.
4271
        */
4272
3.76k
        quantum_type=IndexQuantum;
4273
3.76k
        if (image->alpha_trait != UndefinedPixelTrait)
4274
929
          {
4275
929
            if (photometric != PHOTOMETRIC_PALETTE)
4276
929
              quantum_type=GrayAlphaQuantum;
4277
0
            else
4278
0
              quantum_type=IndexAlphaQuantum;
4279
929
           }
4280
2.83k
         else
4281
2.83k
           if (photometric != PHOTOMETRIC_PALETTE)
4282
2.65k
             quantum_type=GrayQuantum;
4283
3.76k
        if (image->number_meta_channels != 0)
4284
167
          quantum_type=MultispectralQuantum;
4285
3.76k
        status=WriteTIFFChannels(image,tiff,tiff_info,quantum_info,
4286
3.76k
          quantum_type,0,pixels,exception);
4287
3.76k
        break;
4288
176
      }
4289
7.56k
    }
4290
7.56k
    quantum_info=DestroyQuantumInfo(quantum_info);
4291
7.56k
    if (image->colorspace == LabColorspace)
4292
350
      DecodeLabImage(image,exception);
4293
7.56k
    DestroyTIFFInfo(&tiff_info);
4294
    /* TIFFPrintDirectory(tiff,stdout,MagickFalse); */
4295
7.56k
    if (status == MagickFalse)
4296
0
      break;
4297
7.56k
    if (TIFFWriteDirectory(tiff) == 0)
4298
5
      {
4299
5
        status=MagickFalse;
4300
5
        break;
4301
5
      }
4302
7.55k
    image=SyncNextImageInList(image);
4303
7.55k
    if (image == (Image *) NULL)
4304
7.55k
      break;
4305
0
    status=SetImageProgress(image,SaveImagesTag,scene++,number_scenes);
4306
0
    if (status == MagickFalse)
4307
0
      break;
4308
0
  } while (adjoin != MagickFalse);
4309
7.56k
  if (TIFFFlush(tiff) != 1)
4310
5
    status=MagickFalse;
4311
7.56k
  TIFFClose(tiff);
4312
7.56k
  return(status);
4313
7.56k
}
4314
#endif