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