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