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