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