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