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