]> 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->mime_type=ConstantString("image/tiff");
1893   entry->module=ConstantString("TIFF");
1894   (void) RegisterMagickInfo(entry);
1895   entry=SetMagickInfo("PTIF");
1896 #if defined(MAGICKCORE_TIFF_DELEGATE)
1897   entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
1898   entry->encoder=(EncodeImageHandler *) WritePTIFImage;
1899 #endif
1900   entry->endian_support=MagickTrue;
1901   entry->seekable_stream=MagickTrue;
1902   entry->thread_support=NoThreadSupport;
1903   entry->description=ConstantString("Pyramid encoded TIFF");
1904   entry->mime_type=ConstantString("image/tiff");
1905   entry->module=ConstantString("TIFF");
1906   (void) RegisterMagickInfo(entry);
1907   entry=SetMagickInfo("TIF");
1908 #if defined(MAGICKCORE_TIFF_DELEGATE)
1909   entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
1910   entry->encoder=(EncodeImageHandler *) WriteTIFFImage;
1911 #endif
1912   entry->endian_support=MagickTrue;
1913   entry->seekable_stream=MagickTrue;
1914   entry->stealth=MagickTrue;
1915   entry->thread_support=NoThreadSupport;
1916   entry->description=ConstantString(TIFFDescription);
1917   if (*version != '\0')
1918     entry->version=ConstantString(version);
1919   entry->mime_type=ConstantString("image/tiff");
1920   entry->module=ConstantString("TIFF");
1921   (void) RegisterMagickInfo(entry);
1922   entry=SetMagickInfo("TIFF");
1923 #if defined(MAGICKCORE_TIFF_DELEGATE)
1924   entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
1925   entry->encoder=(EncodeImageHandler *) WriteTIFFImage;
1926 #endif
1927   entry->magick=(IsImageFormatHandler *) IsTIFF;
1928   entry->endian_support=MagickTrue;
1929   entry->seekable_stream=MagickTrue;
1930   entry->thread_support=NoThreadSupport;
1931   entry->description=ConstantString(TIFFDescription);
1932   if (*version != '\0')
1933     entry->version=ConstantString(version);
1934   entry->mime_type=ConstantString("image/tiff");
1935   entry->module=ConstantString("TIFF");
1936   (void) RegisterMagickInfo(entry);
1937   entry=SetMagickInfo("TIFF64");
1938 #if defined(TIFF_VERSION_BIG)
1939   entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
1940   entry->encoder=(EncodeImageHandler *) WriteTIFFImage;
1941 #endif
1942   entry->adjoin=MagickFalse;
1943   entry->endian_support=MagickTrue;
1944   entry->seekable_stream=MagickTrue;
1945   entry->thread_support=NoThreadSupport;
1946   entry->description=ConstantString("Tagged Image File Format (64-bit)");
1947   if (*version != '\0')
1948     entry->version=ConstantString(version);
1949   entry->mime_type=ConstantString("image/tiff");
1950   entry->module=ConstantString("TIFF");
1951   (void) RegisterMagickInfo(entry);
1952   return(MagickImageCoderSignature);
1953 }
1954 \f
1955 /*
1956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1957 %                                                                             %
1958 %                                                                             %
1959 %                                                                             %
1960 %   U n r e g i s t e r T I F F I m a g e                                     %
1961 %                                                                             %
1962 %                                                                             %
1963 %                                                                             %
1964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1965 %
1966 %  UnregisterTIFFImage() removes format registrations made by the TIFF module
1967 %  from the list of supported formats.
1968 %
1969 %  The format of the UnregisterTIFFImage method is:
1970 %
1971 %      UnregisterTIFFImage(void)
1972 %
1973 */
1974 ModuleExport void UnregisterTIFFImage(void)
1975 {
1976   (void) UnregisterMagickInfo("TIFF64");
1977   (void) UnregisterMagickInfo("TIFF");
1978   (void) UnregisterMagickInfo("TIF");
1979   (void) UnregisterMagickInfo("PTIF");
1980   if (tiff_semaphore == (SemaphoreInfo *) NULL)
1981     tiff_semaphore=AllocateSemaphoreInfo();
1982   LockSemaphoreInfo(tiff_semaphore);
1983   if (instantiate_key != MagickFalse)
1984     {
1985 #if defined(MAGICKCORE_HAVE_TIFFMERGEFIELDINFO) && defined(MAGICKCORE_HAVE_TIFFSETTAGEXTENDER)
1986       if (tag_extender == (TIFFExtendProc) NULL)
1987         (void) TIFFSetTagExtender(tag_extender);
1988 #endif
1989       if (MagickDeleteThreadKey(tiff_exception) == MagickFalse)
1990         ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1991       instantiate_key=MagickFalse;
1992     }
1993   UnlockSemaphoreInfo(tiff_semaphore);
1994   DestroySemaphoreInfo(&tiff_semaphore);
1995 }
1996 \f
1997 #if defined(MAGICKCORE_TIFF_DELEGATE)
1998 /*
1999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2000 %                                                                             %
2001 %                                                                             %
2002 %                                                                             %
2003 %   W r i t e G R O U P 4 I m a g e                                           %
2004 %                                                                             %
2005 %                                                                             %
2006 %                                                                             %
2007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2008 %
2009 %  WriteGROUP4Image() writes an image in the raw CCITT Group 4 image format.
2010 %
2011 %  The format of the WriteGROUP4Image method is:
2012 %
2013 %      MagickBooleanType WriteGROUP4Image(const ImageInfo *image_info,
2014 %        Image *image,ExceptionInfo *)
2015 %
2016 %  A description of each parameter follows:
2017 %
2018 %    o image_info: the image info.
2019 %
2020 %    o image:  The image.
2021 %
2022 %    o exception: return any errors or warnings in this structure.
2023 %
2024 */
2025 static MagickBooleanType WriteGROUP4Image(const ImageInfo *image_info,
2026   Image *image,ExceptionInfo *exception)
2027 {
2028   char
2029     filename[MaxTextExtent];
2030
2031   FILE
2032     *file;
2033
2034   Image
2035     *huffman_image;
2036
2037   ImageInfo
2038     *write_info;
2039
2040   int
2041     unique_file;
2042
2043   MagickBooleanType
2044     status;
2045
2046   register ssize_t
2047     i;
2048
2049   ssize_t
2050     count;
2051
2052   TIFF
2053     *tiff;
2054
2055   toff_t
2056     *byte_count,
2057     strip_size;
2058
2059   unsigned char
2060     *buffer;
2061
2062   /*
2063     Write image as CCITT Group4 TIFF image to a temporary file.
2064   */
2065   assert(image_info != (const ImageInfo *) NULL);
2066   assert(image_info->signature == MagickSignature);
2067   assert(image != (Image *) NULL);
2068   assert(image->signature == MagickSignature);
2069   if (image->debug != MagickFalse)
2070     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2071   assert(exception != (ExceptionInfo *) NULL);
2072   assert(exception->signature == MagickSignature);
2073   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2074   if (status == MagickFalse)
2075     return(status);
2076   huffman_image=CloneImage(image,0,0,MagickTrue,exception);
2077   if (huffman_image == (Image *) NULL)
2078     {
2079       (void) CloseBlob(image);
2080       return(MagickFalse);
2081     }
2082   huffman_image->endian=MSBEndian;
2083   file=(FILE *) NULL;
2084   unique_file=AcquireUniqueFileResource(filename);
2085   if (unique_file != -1)
2086     file=fdopen(unique_file,"wb");
2087   if ((unique_file == -1) || (file == (FILE *) NULL))
2088     {
2089       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2090         filename);
2091       return(MagickFalse);
2092     }
2093   (void) FormatLocaleString(huffman_image->filename,MaxTextExtent,"tiff:%s",
2094     filename);
2095   (void) SetImageType(huffman_image,BilevelType,exception);
2096   write_info=CloneImageInfo((ImageInfo *) NULL);
2097   SetImageInfoFile(write_info,file);
2098   write_info->compression=Group4Compression;
2099   write_info->type=BilevelType;
2100   (void) SetImageOption(write_info,"quantum:polarity","min-is-white");
2101   status=WriteTIFFImage(write_info,huffman_image,exception);
2102   (void) fflush(file);
2103   write_info=DestroyImageInfo(write_info);
2104   if (status == MagickFalse)
2105     {
2106       huffman_image=DestroyImage(huffman_image);
2107       (void) fclose(file);
2108       (void) RelinquishUniqueFileResource(filename);
2109       return(MagickFalse);
2110     }
2111   tiff=TIFFOpen(filename,"rb");
2112   if (tiff == (TIFF *) NULL)
2113     {
2114       huffman_image=DestroyImage(huffman_image);
2115       (void) fclose(file);
2116       (void) RelinquishUniqueFileResource(filename);
2117       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2118         image_info->filename);
2119       return(MagickFalse);
2120     }
2121   /*
2122     Allocate raw strip buffer.
2123   */
2124   if (TIFFGetField(tiff,TIFFTAG_STRIPBYTECOUNTS,&byte_count) != 1)
2125     {
2126       TIFFClose(tiff);
2127       huffman_image=DestroyImage(huffman_image);
2128       (void) fclose(file);
2129       (void) RelinquishUniqueFileResource(filename);
2130       return(MagickFalse);
2131     }
2132   strip_size=byte_count[0];
2133   for (i=1; i < (ssize_t) TIFFNumberOfStrips(tiff); i++)
2134     if (byte_count[i] > strip_size)
2135       strip_size=byte_count[i];
2136   buffer=(unsigned char *) AcquireQuantumMemory((size_t) strip_size,
2137     sizeof(*buffer));
2138   if (buffer == (unsigned char *) NULL)
2139     {
2140       TIFFClose(tiff);
2141       huffman_image=DestroyImage(huffman_image);
2142       (void) fclose(file);
2143       (void) RelinquishUniqueFileResource(filename);
2144       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2145         image_info->filename);
2146     }
2147   /*
2148     Compress runlength encoded to 2D Huffman pixels.
2149   */
2150   for (i=0; i < (ssize_t) TIFFNumberOfStrips(tiff); i++)
2151   {
2152     count=(ssize_t) TIFFReadRawStrip(tiff,(uint32) i,buffer,strip_size);
2153     if (WriteBlob(image,(size_t) count,buffer) != count)
2154       status=MagickFalse;
2155   }
2156   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2157   TIFFClose(tiff);
2158   huffman_image=DestroyImage(huffman_image);
2159   (void) fclose(file);
2160   (void) RelinquishUniqueFileResource(filename);
2161   (void) CloseBlob(image);
2162   return(status);
2163 }
2164 #endif
2165 \f
2166 #if defined(MAGICKCORE_TIFF_DELEGATE)
2167 /*
2168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2169 %                                                                             %
2170 %                                                                             %
2171 %                                                                             %
2172 %   W r i t e P T I F I m a g e                                               %
2173 %                                                                             %
2174 %                                                                             %
2175 %                                                                             %
2176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2177 %
2178 %  WritePTIFImage() writes an image in the pyrimid-encoded Tagged image file
2179 %  format.
2180 %
2181 %  The format of the WritePTIFImage method is:
2182 %
2183 %      MagickBooleanType WritePTIFImage(const ImageInfo *image_info,
2184 %        Image *image,ExceptionInfo *exception)
2185 %
2186 %  A description of each parameter follows:
2187 %
2188 %    o image_info: the image info.
2189 %
2190 %    o image:  The image.
2191 %
2192 %    o exception: return any errors or warnings in this structure.
2193 %
2194 */
2195 static MagickBooleanType WritePTIFImage(const ImageInfo *image_info,
2196   Image *image,ExceptionInfo *exception)
2197 {
2198   Image
2199     *images,
2200     *next,
2201     *pyramid_image;
2202
2203   ImageInfo
2204     *write_info;
2205
2206   MagickBooleanType
2207     status;
2208
2209   PointInfo
2210     resolution;
2211
2212   size_t
2213     columns,
2214     rows;
2215
2216   /*
2217     Create pyramid-encoded TIFF image.
2218   */
2219   images=NewImageList();
2220   for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
2221   {
2222     AppendImageToList(&images,CloneImage(next,0,0,MagickFalse,exception));
2223     columns=next->columns;
2224     rows=next->rows;
2225     resolution=next->resolution;
2226     while ((columns > 64) && (rows > 64))
2227     {
2228       columns/=2;
2229       rows/=2;
2230       resolution.x/=2;
2231       resolution.y/=2;
2232       pyramid_image=ResizeImage(next,columns,rows,image->filter,exception);
2233       if (pyramid_image == (Image *) NULL)
2234         break;
2235       pyramid_image->resolution=resolution;
2236       AppendImageToList(&images,pyramid_image);
2237     }
2238   }
2239   images=GetFirstImageInList(images);
2240   /*
2241     Write pyramid-encoded TIFF image.
2242   */
2243   write_info=CloneImageInfo(image_info);
2244   write_info->adjoin=MagickTrue;
2245   (void) CopyMagickString(write_info->magick,"TIFF",MaxTextExtent);
2246   (void) CopyMagickString(images->magick,"TIFF",MaxTextExtent);
2247   status=WriteTIFFImage(write_info,images,exception);
2248   images=DestroyImageList(images);
2249   write_info=DestroyImageInfo(write_info);
2250   return(status);
2251 }
2252 #endif
2253 \f
2254 #if defined(MAGICKCORE_TIFF_DELEGATE)
2255 /*
2256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2257 %                                                                             %
2258 %                                                                             %
2259 %   W r i t e T I F F I m a g e                                               %
2260 %                                                                             %
2261 %                                                                             %
2262 %                                                                             %
2263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264 %
2265 %  WriteTIFFImage() writes an image in the Tagged image file format.
2266 %
2267 %  The format of the WriteTIFFImage method is:
2268 %
2269 %      MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
2270 %        Image *image,ExceptionInfo *exception)
2271 %
2272 %  A description of each parameter follows:
2273 %
2274 %    o image_info: the image info.
2275 %
2276 %    o image:  The image.
2277 %
2278 %    o exception: return any errors or warnings in this structure.
2279 %
2280 */
2281
2282 typedef struct _TIFFInfo
2283 {
2284   RectangleInfo
2285     tile_geometry;
2286
2287   unsigned char
2288     *scanline,
2289     *scanlines,
2290     *pixels;
2291 } TIFFInfo;
2292
2293 static void DestroyTIFFInfo(TIFFInfo *tiff_info)
2294 {
2295   assert(tiff_info != (TIFFInfo *) NULL);
2296   if (tiff_info->scanlines != (unsigned char *) NULL)
2297     tiff_info->scanlines=(unsigned char *) RelinquishMagickMemory(
2298       tiff_info->scanlines);
2299   if (tiff_info->pixels != (unsigned char *) NULL)
2300     tiff_info->pixels=(unsigned char *) RelinquishMagickMemory(
2301       tiff_info->pixels);
2302 }
2303
2304 static MagickBooleanType EncodeLabImage(Image *image,ExceptionInfo *exception)
2305 {
2306   CacheView
2307     *image_view;
2308
2309   MagickBooleanType
2310     status;
2311
2312   ssize_t
2313     y;
2314
2315   status=MagickTrue;
2316   image_view=AcquireAuthenticCacheView(image,exception);
2317   for (y=0; y < (ssize_t) image->rows; y++)
2318   {
2319     register Quantum
2320       *restrict q;
2321
2322     register ssize_t
2323       x;
2324
2325     if (status == MagickFalse)
2326       continue;
2327     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2328     if (q == (Quantum *) NULL)
2329       {
2330         status=MagickFalse;
2331         continue;
2332       }
2333     for (x=0; x < (ssize_t) image->columns; x++)
2334     {
2335       double
2336         a,
2337         b;
2338
2339       a=QuantumScale*GetPixela(image,q)-0.5;
2340       if (a < 0.0)
2341         a+=1.0;
2342       b=QuantumScale*GetPixelb(image,q)-0.5;
2343       if (b < 0.0)
2344         b+=1.0;
2345       SetPixela(image,QuantumRange*a,q);
2346       SetPixelb(image,QuantumRange*b,q);
2347       q+=GetPixelChannels(image);
2348     }
2349     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2350       status=MagickFalse;
2351   }
2352   image_view=DestroyCacheView(image_view);
2353   return(status);
2354 }
2355
2356 static MagickBooleanType GetTIFFInfo(const ImageInfo *image_info,
2357   TIFF *tiff,TIFFInfo *tiff_info)
2358 {
2359   const char
2360     *option;
2361
2362   MagickStatusType
2363     flags;
2364
2365   uint32
2366     tile_columns,
2367     tile_rows;
2368
2369   assert(tiff_info != (TIFFInfo *) NULL);
2370   (void) ResetMagickMemory(tiff_info,0,sizeof(*tiff_info));
2371   option=GetImageOption(image_info,"tiff:tile-geometry");
2372   if (option == (const char *) NULL)
2373     return(MagickTrue);
2374   flags=ParseAbsoluteGeometry(option,&tiff_info->tile_geometry);
2375   if ((flags & HeightValue) == 0)
2376     tiff_info->tile_geometry.height=tiff_info->tile_geometry.width;
2377   tile_columns=(uint32) tiff_info->tile_geometry.width;
2378   tile_rows=(uint32) tiff_info->tile_geometry.height;
2379   TIFFDefaultTileSize(tiff,&tile_columns,&tile_rows);
2380   (void) TIFFSetField(tiff,TIFFTAG_TILEWIDTH,tile_columns);
2381   (void) TIFFSetField(tiff,TIFFTAG_TILELENGTH,tile_rows);
2382   tiff_info->tile_geometry.width=tile_columns;
2383   tiff_info->tile_geometry.height=tile_rows;
2384   tiff_info->scanlines=(unsigned char *) AcquireQuantumMemory((size_t)
2385     tile_rows*TIFFScanlineSize(tiff),sizeof(*tiff_info->scanlines));
2386   tiff_info->pixels=(unsigned char *) AcquireQuantumMemory((size_t)
2387     tile_rows*TIFFTileSize(tiff),sizeof(*tiff_info->scanlines));
2388   if ((tiff_info->scanlines == (unsigned char *) NULL) ||
2389       (tiff_info->pixels == (unsigned char *) NULL))
2390     {
2391       DestroyTIFFInfo(tiff_info);
2392       return(MagickFalse);
2393     }
2394   return(MagickTrue);
2395 }
2396
2397 static int32 TIFFWritePixels(TIFF *tiff,TIFFInfo *tiff_info,ssize_t row,
2398   tsample_t sample,Image *image)
2399 {
2400   int32
2401     status;
2402
2403   register ssize_t
2404     i;
2405
2406   register unsigned char
2407     *p,
2408     *q;
2409
2410   size_t
2411     number_tiles,
2412     tile_width;
2413
2414   ssize_t
2415     bytes_per_pixel,
2416     j,
2417     k,
2418     l;
2419
2420   if (TIFFIsTiled(tiff) == 0)
2421     return(TIFFWriteScanline(tiff,tiff_info->scanline,(uint32) row,sample));
2422   /*
2423     Fill scanlines to tile height.
2424   */
2425   i=(ssize_t) (row % tiff_info->tile_geometry.height)*TIFFScanlineSize(tiff);
2426   (void) CopyMagickMemory(tiff_info->scanlines+i,(char *) tiff_info->scanline,
2427     (size_t) TIFFScanlineSize(tiff));
2428   if (((size_t) (row % tiff_info->tile_geometry.height) !=
2429       (tiff_info->tile_geometry.height-1)) &&
2430       (row != (ssize_t) (image->rows-1)))
2431     return(0);
2432   /*
2433     Write tile to TIFF image.
2434   */
2435   status=0;
2436   bytes_per_pixel=TIFFTileSize(tiff)/(ssize_t) (
2437     tiff_info->tile_geometry.height*tiff_info->tile_geometry.width);
2438   number_tiles=(image->columns+tiff_info->tile_geometry.width)/
2439     tiff_info->tile_geometry.width;
2440   for (i=0; i < (ssize_t) number_tiles; i++)
2441   {
2442     tile_width=(i == (ssize_t) (number_tiles-1)) ? image->columns-(i*
2443       tiff_info->tile_geometry.width) : tiff_info->tile_geometry.width;
2444     for (j=0; j < (ssize_t) ((row % tiff_info->tile_geometry.height)+1); j++)
2445       for (k=0; k < (ssize_t) tile_width; k++)
2446       {
2447         if (bytes_per_pixel == 0)
2448           {
2449             p=tiff_info->scanlines+(j*TIFFScanlineSize(tiff)+(i*
2450               tiff_info->tile_geometry.width+k)/8);
2451             q=tiff_info->pixels+(j*TIFFTileRowSize(tiff)+k/8);
2452             *q++=(*p++);
2453             continue;
2454           }
2455         p=tiff_info->scanlines+(j*TIFFScanlineSize(tiff)+(i*
2456           tiff_info->tile_geometry.width+k)*bytes_per_pixel);
2457         q=tiff_info->pixels+(j*TIFFTileRowSize(tiff)+k*bytes_per_pixel);
2458         for (l=0; l < bytes_per_pixel; l++)
2459           *q++=(*p++);
2460       }
2461     if ((i*tiff_info->tile_geometry.width) != image->columns)
2462       status=TIFFWriteTile(tiff,tiff_info->pixels,(uint32) (i*
2463         tiff_info->tile_geometry.width),(uint32) ((row/
2464         tiff_info->tile_geometry.height)*tiff_info->tile_geometry.height),0,
2465         sample);
2466     if (status < 0)
2467       break;
2468   }
2469   return(status);
2470 }
2471
2472 static void TIFFSetProfiles(TIFF *tiff,Image *image)
2473 {
2474   const char
2475     *name;
2476
2477   const StringInfo
2478     *profile;
2479
2480   if (image->profiles == (void *) NULL)
2481     return;
2482   ResetImageProfileIterator(image);
2483   for (name=GetNextImageProfile(image); name != (const char *) NULL; )
2484   {
2485     profile=GetImageProfile(image,name);
2486     if (GetStringInfoLength(profile) == 0)
2487       {
2488         name=GetNextImageProfile(image);
2489         continue;
2490       }
2491 #if defined(TIFFTAG_XMLPACKET)
2492     if (LocaleCompare(name,"xmp") == 0)
2493       (void) TIFFSetField(tiff,TIFFTAG_XMLPACKET,(uint32) GetStringInfoLength(
2494         profile),GetStringInfoDatum(profile));
2495 #endif
2496 #if defined(TIFFTAG_ICCPROFILE)
2497     if (LocaleCompare(name,"icc") == 0)
2498       (void) TIFFSetField(tiff,TIFFTAG_ICCPROFILE,(uint32) GetStringInfoLength(
2499         profile),GetStringInfoDatum(profile));
2500 #endif
2501     if (LocaleCompare(name,"iptc") == 0)
2502       {
2503         size_t
2504           length;
2505
2506         StringInfo
2507           *iptc_profile;
2508
2509         iptc_profile=CloneStringInfo(profile);
2510         length=GetStringInfoLength(profile)+4-(GetStringInfoLength(profile) &
2511           0x03);
2512         SetStringInfoLength(iptc_profile,length);
2513         if (TIFFIsByteSwapped(tiff))
2514           TIFFSwabArrayOfLong((uint32 *) GetStringInfoDatum(iptc_profile),
2515             (unsigned long) (length/4));
2516         (void) TIFFSetField(tiff,TIFFTAG_RICHTIFFIPTC,(uint32)
2517           GetStringInfoLength(iptc_profile)/4,GetStringInfoDatum(iptc_profile));
2518         iptc_profile=DestroyStringInfo(iptc_profile);
2519       }
2520 #if defined(TIFFTAG_PHOTOSHOP)
2521     if (LocaleCompare(name,"8bim") == 0)
2522       (void) TIFFSetField(tiff,TIFFTAG_PHOTOSHOP,(uint32)
2523         GetStringInfoLength(profile),GetStringInfoDatum(profile));
2524 #endif
2525     if (LocaleCompare(name,"tiff:37724") == 0)
2526       (void) TIFFSetField(tiff,37724,(uint32) GetStringInfoLength(profile),
2527         GetStringInfoDatum(profile));
2528     if (LocaleCompare(name,"tiff:34118") == 0)
2529       (void) TIFFSetField(tiff,34118,(uint32) GetStringInfoLength(profile),
2530         GetStringInfoDatum(profile));
2531     name=GetNextImageProfile(image);
2532   }
2533 }
2534
2535 static void TIFFSetProperties(TIFF *tiff,Image *image,ExceptionInfo *exception)
2536 {
2537   const char
2538     *value;
2539
2540   (void) TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,image->filename);
2541   value=GetImageProperty(image,"tiff:hostcomputer",exception);
2542   if (value != (const char *) NULL)
2543     (void) TIFFSetField(tiff,TIFFTAG_HOSTCOMPUTER,value);
2544   value=GetImageProperty(image,"tiff:artist",exception);
2545   if (value != (const char *) NULL)
2546     (void) TIFFSetField(tiff,TIFFTAG_ARTIST,value);
2547   value=GetImageProperty(image,"tiff:timestamp",exception);
2548   if (value != (const char *) NULL)
2549     (void) TIFFSetField(tiff,TIFFTAG_DATETIME,value);
2550   value=GetImageProperty(image,"tiff:make",exception);
2551   if (value != (const char *) NULL)
2552     (void) TIFFSetField(tiff,TIFFTAG_MAKE,value);
2553   value=GetImageProperty(image,"tiff:model",exception);
2554   if (value != (const char *) NULL)
2555     (void) TIFFSetField(tiff,TIFFTAG_MODEL,value);
2556   value=GetImageProperty(image,"tiff:software",exception);
2557   if (value != (const char *) NULL)
2558     (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,value);
2559   value=GetImageProperty(image,"tiff:copyright",exception);
2560   if (value != (const char *) NULL)
2561     (void) TIFFSetField(tiff,TIFFTAG_COPYRIGHT,value);
2562   value=GetImageProperty(image,"kodak-33423",exception);
2563   if (value != (const char *) NULL)
2564     (void) TIFFSetField(tiff,33423,value);
2565   value=GetImageProperty(image,"kodak-36867",exception);
2566   if (value != (const char *) NULL)
2567     (void) TIFFSetField(tiff,36867,value);
2568   value=GetImageProperty(image,"label",exception);
2569   if (value != (const char *) NULL)
2570     (void) TIFFSetField(tiff,TIFFTAG_PAGENAME,value);
2571   value=GetImageProperty(image,"comment",exception);
2572   if (value != (const char *) NULL)
2573     (void) TIFFSetField(tiff,TIFFTAG_IMAGEDESCRIPTION,value);
2574 }
2575
2576 static void TIFFSetEXIFProperties(TIFF *tiff,Image *image,
2577   ExceptionInfo *exception)
2578 {
2579 #if defined(MAGICKCORE_HAVE_TIFFREADEXIFDIRECTORY)
2580   const char
2581     *value;
2582
2583   register ssize_t
2584     i;
2585
2586   uint32
2587     offset;
2588
2589   /*
2590     Write EXIF properties.
2591   */
2592   offset=0;
2593   (void) TIFFSetField(tiff,TIFFTAG_SUBIFD,1,&offset);
2594   for (i=0; exif_info[i].tag != 0; i++)
2595   {
2596     value=GetImageProperty(image,exif_info[i].property,exception);
2597     if (value == (const char *) NULL)
2598       continue;
2599     switch (exif_info[i].type)
2600     {
2601       case TIFF_ASCII:
2602       {
2603         (void) TIFFSetField(tiff,exif_info[i].tag,value);
2604         break;
2605       }
2606       case TIFF_SHORT:
2607       {
2608         uint16
2609           shorty;
2610
2611         shorty=(uint16) StringToLong(value);
2612         (void) TIFFSetField(tiff,exif_info[i].tag,shorty);
2613         break;
2614       }
2615       case TIFF_LONG:
2616       {
2617         uint16
2618           ssize_ty;
2619
2620         ssize_ty=(uint16) StringToLong(value);
2621         (void) TIFFSetField(tiff,exif_info[i].tag,ssize_ty);
2622         break;
2623       }
2624       case TIFF_RATIONAL:
2625       case TIFF_SRATIONAL:
2626       {
2627         float
2628           rational;
2629
2630         rational=StringToDouble(value,(char **) NULL);
2631         (void) TIFFSetField(tiff,exif_info[i].tag,rational);
2632         break;
2633       }
2634       default:
2635         break;
2636     }
2637   }
2638   /* (void) TIFFSetField(tiff,TIFFTAG_EXIFIFD,offset); */
2639 #else
2640   (void) tiff;
2641   (void) image;
2642 #endif
2643 }
2644
2645 static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
2646   Image *image,ExceptionInfo *exception)
2647 {
2648 #if !defined(TIFFDefaultStripSize)
2649 #define TIFFDefaultStripSize(tiff,request)  (8192UL/TIFFScanlineSize(tiff))
2650 #endif
2651
2652   const char
2653     *mode,
2654     *option;
2655
2656   CompressionType
2657     compression;
2658
2659   EndianType
2660     endian_type;
2661
2662   MagickBooleanType
2663     debug,
2664     status;
2665
2666   MagickOffsetType
2667     scene;
2668
2669   QuantumInfo
2670     *quantum_info;
2671
2672   QuantumType
2673     quantum_type;
2674
2675   register ssize_t
2676     i;
2677
2678   size_t
2679     length;
2680
2681   ssize_t
2682     y;
2683
2684   TIFF
2685     *tiff;
2686
2687   TIFFErrorHandler
2688     error_handler,
2689     warning_handler;
2690
2691   TIFFInfo
2692     tiff_info;
2693
2694   uint16
2695     bits_per_sample,
2696     compress_tag,
2697     endian,
2698     photometric;
2699
2700   uint32
2701     rows_per_strip;
2702
2703   unsigned char
2704     *pixels;
2705
2706   /*
2707     Open TIFF file.
2708   */
2709   assert(image_info != (const ImageInfo *) NULL);
2710   assert(image_info->signature == MagickSignature);
2711   assert(image != (Image *) NULL);
2712   assert(image->signature == MagickSignature);
2713   if (image->debug != MagickFalse)
2714     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2715   assert(exception != (ExceptionInfo *) NULL);
2716   assert(exception->signature == MagickSignature);
2717   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2718   if (status == MagickFalse)
2719     return(status);
2720   (void) MagickSetThreadValue(tiff_exception,exception);
2721   error_handler=TIFFSetErrorHandler((TIFFErrorHandler) TIFFErrors);
2722   warning_handler=TIFFSetWarningHandler((TIFFErrorHandler) TIFFWarnings);
2723   endian_type=UndefinedEndian;
2724   option=GetImageOption(image_info,"tiff:endian");
2725   if (option != (const char *) NULL)
2726     {
2727       if (LocaleNCompare(option,"msb",3) == 0)
2728         endian_type=MSBEndian;
2729       if (LocaleNCompare(option,"lsb",3) == 0)
2730         endian_type=LSBEndian;;
2731     }
2732   switch (endian_type)
2733   {
2734     case LSBEndian: mode="wl"; break;
2735     case MSBEndian: mode="wb"; break;
2736     default: mode="w"; break;
2737   }
2738 #if defined(TIFF_VERSION_BIG)
2739   if (LocaleCompare(image_info->magick,"TIFF64") == 0)
2740     switch (endian_type)
2741     {
2742       case LSBEndian: mode="wl8"; break;
2743       case MSBEndian: mode="wb8"; break;
2744       default: mode="w8"; break;
2745     }
2746 #endif
2747   tiff=TIFFClientOpen(image->filename,mode,(thandle_t) image,TIFFReadBlob,
2748     TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
2749     TIFFUnmapBlob);
2750   if (tiff == (TIFF *) NULL)
2751     {
2752       (void) TIFFSetWarningHandler(warning_handler);
2753       (void) TIFFSetErrorHandler(error_handler);
2754       return(MagickFalse);
2755     }
2756   scene=0;
2757   debug=IsEventLogging();
2758   (void) debug;
2759   do
2760   {
2761     /*
2762       Initialize TIFF fields.
2763     */
2764     if ((image_info->type != UndefinedType) &&
2765         (image_info->type != OptimizeType))
2766       (void) SetImageType(image,image_info->type,exception);
2767     quantum_info=AcquireQuantumInfo(image_info,image);
2768     if (quantum_info == (QuantumInfo *) NULL)
2769       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2770     if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
2771         (quantum_info->format == UndefinedQuantumFormat) &&
2772         (IsHighDynamicRangeImage(image,exception) != MagickFalse))
2773       {
2774         status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
2775         if (status == MagickFalse)
2776           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2777       }
2778     if ((LocaleCompare(image_info->magick,"PTIF") == 0) &&
2779         (GetPreviousImageInList(image) != (Image *) NULL))
2780       (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_REDUCEDIMAGE);
2781     if ((image->columns != (uint32) image->columns) ||
2782         (image->rows != (uint32) image->rows))
2783       ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
2784     (void) TIFFSetField(tiff,TIFFTAG_IMAGELENGTH,(uint32) image->rows);
2785     (void) TIFFSetField(tiff,TIFFTAG_IMAGEWIDTH,(uint32) image->columns);
2786     compression=image->compression;
2787     if (image_info->compression != UndefinedCompression)
2788       compression=image_info->compression;
2789     switch (compression)
2790     {
2791       case FaxCompression:
2792       {
2793         compress_tag=COMPRESSION_CCITTFAX3;
2794         SetQuantumMinIsWhite(quantum_info,MagickTrue);
2795         break;
2796       }
2797       case Group4Compression:
2798       {
2799         compress_tag=COMPRESSION_CCITTFAX4;
2800         SetQuantumMinIsWhite(quantum_info,MagickTrue);
2801         break;
2802       }
2803 #if defined(COMPRESSION_JBIG)
2804       case JBIG1Compression:
2805       {
2806         compress_tag=COMPRESSION_JBIG;
2807         break;
2808       }
2809 #endif
2810       case JPEGCompression:
2811       {
2812         compress_tag=COMPRESSION_JPEG;
2813         break;
2814       }
2815 #if defined(COMPRESSION_LZMA)
2816       case LZMACompression:
2817       {
2818         compress_tag=COMPRESSION_LZMA;
2819         break;
2820       }
2821 #endif
2822       case LZWCompression:
2823       {
2824         compress_tag=COMPRESSION_LZW;
2825         break;
2826       }
2827       case RLECompression:
2828       {
2829         compress_tag=COMPRESSION_PACKBITS;
2830         break;
2831       }
2832       case ZipCompression:
2833       {
2834         compress_tag=COMPRESSION_ADOBE_DEFLATE;
2835         break;
2836       }
2837       case NoCompression:
2838       default:
2839       {
2840         compress_tag=COMPRESSION_NONE;
2841         break;
2842       }
2843     }
2844 #if defined(MAGICKCORE_HAVE_TIFFISCODECCONFIGURED) || (TIFFLIB_VERSION > 20040919)
2845     if ((compress_tag != COMPRESSION_NONE) &&
2846         (TIFFIsCODECConfigured(compress_tag) == 0))
2847       {
2848         (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
2849           "CompressionNotSupported","`%s'",CommandOptionToMnemonic(
2850           MagickCompressOptions,(ssize_t) compression));
2851         compress_tag=COMPRESSION_NONE;
2852         compression=NoCompression;
2853       }
2854 #else
2855       switch (compress_tag)
2856       {
2857 #if defined(CCITT_SUPPORT)
2858         case COMPRESSION_CCITTFAX3:
2859         case COMPRESSION_CCITTFAX4:
2860 #endif
2861 #if defined(YCBCR_SUPPORT) && defined(JPEG_SUPPORT)
2862         case COMPRESSION_JPEG:
2863 #endif
2864 #if defined(LZMA_SUPPORT) && defined(COMPRESSION_LZMA)
2865         case COMPRESSION_LZMA:
2866 #endif
2867 #if defined(LZW_SUPPORT)
2868         case COMPRESSION_LZW:
2869 #endif
2870 #if defined(PACKBITS_SUPPORT)
2871         case COMPRESSION_PACKBITS:
2872 #endif
2873 #if defined(ZIP_SUPPORT)
2874         case COMPRESSION_ADOBE_DEFLATE:
2875 #endif
2876         case COMPRESSION_NONE:
2877           break;
2878         default:
2879         {
2880           (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
2881             "CompressionNotSupported","`%s'",CommandOptionToMnemonic(
2882               MagickCompressOptions,(ssize_t) compression));
2883           compress_tag=COMPRESSION_NONE;
2884           compression=NoCompression;
2885           break;
2886         }
2887       }
2888 #endif
2889     switch (compression)
2890     {
2891       case FaxCompression:
2892       case Group4Compression:
2893       {
2894         (void) SetImageType(image,BilevelType,exception);
2895         break;
2896       }
2897       case JPEGCompression:
2898       {
2899         (void) SetImageStorageClass(image,DirectClass,exception);
2900         (void) SetImageDepth(image,8,exception);
2901         break;
2902       }
2903       default:
2904         break;
2905     }
2906     if (image->colorspace == CMYKColorspace)
2907       {
2908         photometric=PHOTOMETRIC_SEPARATED;
2909         (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,4);
2910         (void) TIFFSetField(tiff,TIFFTAG_INKSET,INKSET_CMYK);
2911       }
2912     else
2913       {
2914         /*
2915           Full color TIFF raster.
2916         */
2917         if (image->colorspace == LabColorspace)
2918           {
2919             photometric=PHOTOMETRIC_CIELAB;
2920             EncodeLabImage(image,exception);
2921           }
2922         else
2923           if (image->colorspace == YCbCrColorspace)
2924             {
2925               photometric=PHOTOMETRIC_YCBCR;
2926               (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,1,1);
2927               (void) SetImageStorageClass(image,DirectClass,exception);
2928               (void) SetImageDepth(image,8,exception);
2929             }
2930           else
2931             photometric=PHOTOMETRIC_RGB;
2932         (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,3);
2933         if ((image_info->type != TrueColorType) &&
2934             (image_info->type != TrueColorMatteType))
2935           {
2936             if ((image_info->type != PaletteType) &&
2937                 (IsImageGray(image,exception) != MagickFalse))
2938               {
2939                 photometric=(uint16) (quantum_info->min_is_white !=
2940                   MagickFalse ? PHOTOMETRIC_MINISWHITE :
2941                   PHOTOMETRIC_MINISBLACK);
2942                 (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
2943                 if ((image_info->depth == 0) &&
2944                     (image->alpha_trait != BlendPixelTrait) &&
2945                     (IsImageMonochrome(image,exception) != MagickFalse))
2946                   {
2947                     status=SetQuantumDepth(image,quantum_info,1);
2948                     if (status == MagickFalse)
2949                       ThrowWriterException(ResourceLimitError,
2950                         "MemoryAllocationFailed");
2951                   }
2952               }
2953             else
2954               if (image->storage_class == PseudoClass)
2955                 {
2956                   size_t
2957                     depth;
2958
2959                   /*
2960                     Colormapped TIFF raster.
2961                   */
2962                   (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
2963                   photometric=PHOTOMETRIC_PALETTE;
2964                   depth=1;
2965                   while ((GetQuantumRange(depth)+1) < image->colors)
2966                     depth<<=1;
2967                   status=SetQuantumDepth(image,quantum_info,depth);
2968                   if (status == MagickFalse)
2969                     ThrowWriterException(ResourceLimitError,
2970                       "MemoryAllocationFailed");
2971                 }
2972           }
2973       }
2974     if ((photometric == PHOTOMETRIC_RGB) &&
2975         (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
2976       (void) TransformImageColorspace(image,sRGBColorspace,exception);
2977     switch (image->endian)
2978     {
2979       case LSBEndian:
2980       {
2981         endian=FILLORDER_LSB2MSB;
2982         break;
2983       }
2984       case MSBEndian:
2985       {
2986         endian=FILLORDER_MSB2LSB;
2987         break;
2988       }
2989       case UndefinedEndian:
2990       default:
2991       {
2992         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian);
2993         break;
2994       }
2995     }
2996     if ((compress_tag == COMPRESSION_CCITTFAX3) &&
2997         (photometric != PHOTOMETRIC_MINISWHITE))
2998       {
2999         compress_tag=COMPRESSION_NONE;
3000         endian=FILLORDER_MSB2LSB;
3001       }
3002     else
3003       if ((compress_tag == COMPRESSION_CCITTFAX4) &&
3004          (photometric != PHOTOMETRIC_MINISWHITE))
3005        {
3006          compress_tag=COMPRESSION_NONE;
3007          endian=FILLORDER_MSB2LSB;
3008        }
3009     option=GetImageOption(image_info,"tiff:fill-order");
3010     if (option != (const char *) NULL)
3011       {
3012         if (LocaleNCompare(option,"msb",3) == 0)
3013           endian=FILLORDER_MSB2LSB;
3014         if (LocaleNCompare(option,"lsb",3) == 0)
3015           endian=FILLORDER_LSB2MSB;
3016       }
3017     (void) TIFFSetField(tiff,TIFFTAG_COMPRESSION,compress_tag);
3018     (void) TIFFSetField(tiff,TIFFTAG_FILLORDER,endian);
3019     (void) TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,quantum_info->depth);
3020     if (image->alpha_trait == BlendPixelTrait)
3021       {
3022         uint16
3023           extra_samples,
3024           sample_info[1],
3025           samples_per_pixel;
3026
3027         /*
3028           TIFF has a matte channel.
3029         */
3030         extra_samples=1;
3031         sample_info[0]=EXTRASAMPLE_UNASSALPHA;
3032         option=GetImageOption(image_info,"tiff:alpha");
3033         if ((option != (const char *) NULL) &&
3034             (LocaleCompare(option,"associated") == 0))
3035           sample_info[0]=EXTRASAMPLE_ASSOCALPHA;
3036         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,
3037           &samples_per_pixel);
3038         (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,samples_per_pixel+1);
3039         (void) TIFFSetField(tiff,TIFFTAG_EXTRASAMPLES,extra_samples,
3040           &sample_info);
3041         if (sample_info[0] == EXTRASAMPLE_ASSOCALPHA)
3042           SetQuantumAlphaType(quantum_info,AssociatedQuantumAlpha);
3043       }
3044     (void) TIFFSetField(tiff,TIFFTAG_PHOTOMETRIC,photometric);
3045     switch (quantum_info->format)
3046     {
3047       case FloatingPointQuantumFormat:
3048       {
3049         (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_IEEEFP);
3050         (void) TIFFSetField(tiff,TIFFTAG_SMINSAMPLEVALUE,quantum_info->minimum);
3051         (void) TIFFSetField(tiff,TIFFTAG_SMAXSAMPLEVALUE,quantum_info->maximum);
3052         break;
3053       }
3054       case SignedQuantumFormat:
3055       {
3056         (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_INT);
3057         break;
3058       }
3059       case UnsignedQuantumFormat:
3060       {
3061         (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_UINT);
3062         break;
3063       }
3064       default:
3065         break;
3066     }
3067     (void) TIFFSetField(tiff,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
3068     (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
3069     if (photometric == PHOTOMETRIC_RGB)
3070       if ((image_info->interlace == PlaneInterlace) ||
3071           (image_info->interlace == PartitionInterlace))
3072         (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_SEPARATE);
3073     rows_per_strip=1;
3074     if (TIFFScanlineSize(tiff) != 0)
3075       rows_per_strip=(uint32) MagickMax((size_t) TIFFDefaultStripSize(tiff,0),
3076         1);
3077     option=GetImageOption(image_info,"tiff:rows-per-strip");
3078     if (option != (const char *) NULL)
3079       rows_per_strip=(size_t) strtol(option,(char **) NULL,10);
3080     switch (compress_tag)
3081     {
3082       case COMPRESSION_JPEG:
3083       {
3084 #if defined(JPEG_SUPPORT)
3085         const char
3086           *sampling_factor;
3087
3088         GeometryInfo
3089           geometry_info;
3090
3091         MagickStatusType
3092           flags;
3093
3094         rows_per_strip+=(16-(rows_per_strip % 16));
3095         if (image->quality != 0)
3096           (void) TIFFSetField(tiff,TIFFTAG_JPEGQUALITY,image->quality);
3097         if (image_info->quality != UndefinedCompressionQuality)
3098           (void) TIFFSetField(tiff,TIFFTAG_JPEGQUALITY,image_info->quality);
3099         (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RAW);
3100         if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
3101           {
3102             const char
3103               *value;
3104
3105             (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RGB);
3106             sampling_factor=(const char *) NULL;
3107             value=GetImageProperty(image,"jpeg:sampling-factor",exception);
3108             if (value != (char *) NULL)
3109               {
3110                 sampling_factor=value;
3111                 if (image->debug != MagickFalse)
3112                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3113                     "  Input sampling-factors=%s",sampling_factor);
3114               }
3115             if (image_info->sampling_factor != (char *) NULL)
3116               sampling_factor=image_info->sampling_factor;
3117             if (sampling_factor != (const char *) NULL)
3118               {
3119                 flags=ParseGeometry(sampling_factor,&geometry_info);
3120                 if ((flags & SigmaValue) == 0)
3121                   geometry_info.sigma=geometry_info.rho;
3122                 if (image->colorspace == YCbCrColorspace)
3123                   (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,(uint16)
3124                     geometry_info.rho,(uint16) geometry_info.sigma);
3125               }
3126           }
3127         if (bits_per_sample == 12)
3128           (void) TIFFSetField(tiff,TIFFTAG_JPEGTABLESMODE,JPEGTABLESMODE_QUANT);
3129 #endif
3130         break;
3131       }
3132       case COMPRESSION_ADOBE_DEFLATE:
3133       {
3134         rows_per_strip=(uint32) image->rows;
3135         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
3136           &bits_per_sample);
3137         if (((photometric == PHOTOMETRIC_RGB) ||
3138              (photometric == PHOTOMETRIC_MINISBLACK)) &&
3139             ((bits_per_sample == 8) || (bits_per_sample == 16)))
3140           (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
3141         (void) TIFFSetField(tiff,TIFFTAG_ZIPQUALITY,(long) (
3142           image_info->quality == UndefinedCompressionQuality ? 7 :
3143           MagickMin((ssize_t) image_info->quality/10,9)));
3144         break;
3145       }
3146       case COMPRESSION_CCITTFAX3:
3147       {
3148         /*
3149           Byte-aligned EOL.
3150         */
3151         rows_per_strip=(uint32) image->rows;
3152         (void) TIFFSetField(tiff,TIFFTAG_GROUP3OPTIONS,4);
3153         break;
3154       }
3155       case COMPRESSION_CCITTFAX4:
3156       {
3157         rows_per_strip=(uint32) image->rows;
3158         break;
3159       }
3160 #if defined(LZMA_SUPPORT) && defined(COMPRESSION_LZMA)
3161       case COMPRESSION_LZMA:
3162       {
3163         if (((photometric == PHOTOMETRIC_RGB) ||
3164              (photometric == PHOTOMETRIC_MINISBLACK)) &&
3165             ((bits_per_sample == 8) || (bits_per_sample == 16)))
3166           (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
3167         (void) TIFFSetField(tiff,TIFFTAG_LZMAPRESET,(long) (
3168           image_info->quality == UndefinedCompressionQuality ? 7 :
3169           MagickMin((ssize_t) image_info->quality/10,9)));
3170         break;
3171       }
3172 #endif
3173       case COMPRESSION_LZW:
3174       {
3175         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
3176           &bits_per_sample);
3177         if (((photometric == PHOTOMETRIC_RGB) ||
3178              (photometric == PHOTOMETRIC_MINISBLACK)) &&
3179             ((bits_per_sample == 8) || (bits_per_sample == 16)))
3180           (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
3181         break;
3182       }
3183       default:
3184         break;
3185     }
3186     (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
3187     if ((image->resolution.x != 0.0) && (image->resolution.y != 0.0))
3188       {
3189         unsigned short
3190           units;
3191
3192         /*
3193           Set image resolution.
3194         */
3195         units=RESUNIT_NONE;
3196         if (image->units == PixelsPerInchResolution)
3197           units=RESUNIT_INCH;
3198         if (image->units == PixelsPerCentimeterResolution)
3199           units=RESUNIT_CENTIMETER;
3200         (void) TIFFSetField(tiff,TIFFTAG_RESOLUTIONUNIT,(uint16) units);
3201         (void) TIFFSetField(tiff,TIFFTAG_XRESOLUTION,image->resolution.x);
3202         (void) TIFFSetField(tiff,TIFFTAG_YRESOLUTION,image->resolution.y);
3203         if ((image->page.x < 0) || (image->page.y < 0))
3204           (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
3205             "TIFF: negative image positions unsupported","%s",image->filename);
3206         if ((image->page.x > 0) && (image->resolution.x > 0.0))
3207           {
3208             /*
3209               Set horizontal image position.
3210             */
3211             (void) TIFFSetField(tiff,TIFFTAG_XPOSITION,(float) image->page.x/
3212               image->resolution.x);
3213           }
3214         if ((image->page.y > 0) && (image->resolution.y > 0.0))
3215           {
3216             /*
3217               Set vertical image position.
3218             */
3219             (void) TIFFSetField(tiff,TIFFTAG_YPOSITION,(float) image->page.y/
3220               image->resolution.y);
3221           }
3222       }
3223     if (image->chromaticity.white_point.x != 0.0)
3224       {
3225         float
3226           chromaticity[6];
3227
3228         /*
3229           Set image chromaticity.
3230         */
3231         chromaticity[0]=(float) image->chromaticity.red_primary.x;
3232         chromaticity[1]=(float) image->chromaticity.red_primary.y;
3233         chromaticity[2]=(float) image->chromaticity.green_primary.x;
3234         chromaticity[3]=(float) image->chromaticity.green_primary.y;
3235         chromaticity[4]=(float) image->chromaticity.blue_primary.x;
3236         chromaticity[5]=(float) image->chromaticity.blue_primary.y;
3237         (void) TIFFSetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,chromaticity);
3238         chromaticity[0]=(float) image->chromaticity.white_point.x;
3239         chromaticity[1]=(float) image->chromaticity.white_point.y;
3240         (void) TIFFSetField(tiff,TIFFTAG_WHITEPOINT,chromaticity);
3241       }
3242     if ((LocaleCompare(image_info->magick,"PTIF") != 0) &&
3243         (image_info->adjoin != MagickFalse) && (GetImageListLength(image) > 1))
3244       {
3245         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
3246         if (image->scene != 0)
3247           (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,(uint16) image->scene,
3248             GetImageListLength(image));
3249       }
3250     if (image->orientation != UndefinedOrientation)
3251       (void) TIFFSetField(tiff,TIFFTAG_ORIENTATION,(uint16) image->orientation);
3252     (void) TIFFSetProfiles(tiff,image);
3253     {
3254       uint16
3255         page,
3256         pages;
3257
3258       page=(uint16) scene;
3259       pages=(uint16) GetImageListLength(image);
3260       if ((LocaleCompare(image_info->magick,"PTIF") != 0) &&
3261           (image_info->adjoin != MagickFalse) && (pages > 1))
3262         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
3263       (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,page,pages);
3264     }
3265     (void) TIFFSetProperties(tiff,image,exception);
3266     if (0)
3267       (void) TIFFSetEXIFProperties(tiff,image,exception);
3268     /*
3269       Write image scanlines.
3270     */
3271     if (GetTIFFInfo(image_info,tiff,&tiff_info) == MagickFalse)
3272       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
3273     quantum_info->endian=LSBEndian;
3274     pixels=GetQuantumPixels(quantum_info);
3275     tiff_info.scanline=GetQuantumPixels(quantum_info);
3276     switch (photometric)
3277     {
3278       case PHOTOMETRIC_CIELAB:
3279       case PHOTOMETRIC_YCBCR:
3280       case PHOTOMETRIC_RGB:
3281       {
3282         /*
3283           RGB TIFF image.
3284         */
3285         switch (image_info->interlace)
3286         {
3287           case NoInterlace:
3288           default:
3289           {
3290             quantum_type=RGBQuantum;
3291             if (image->alpha_trait == BlendPixelTrait)
3292               quantum_type=RGBAQuantum;
3293             for (y=0; y < (ssize_t) image->rows; y++)
3294             {
3295               register const Quantum
3296                 *restrict p;
3297
3298               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3299               if (p == (const Quantum *) NULL)
3300                 break;
3301               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3302                 quantum_type,pixels,exception);
3303               (void) length;
3304               if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
3305                 break;
3306               if (image->previous == (Image *) NULL)
3307                 {
3308                   status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
3309                     y,image->rows);
3310                   if (status == MagickFalse)
3311                     break;
3312                 }
3313             }
3314             break;
3315           }
3316           case PlaneInterlace:
3317           case PartitionInterlace:
3318           {
3319             /*
3320               Plane interlacing:  RRRRRR...GGGGGG...BBBBBB...
3321             */
3322             for (y=0; y < (ssize_t) image->rows; y++)
3323             {
3324               register const Quantum
3325                 *restrict p;
3326
3327               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3328               if (p == (const Quantum *) NULL)
3329                 break;
3330               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3331                 RedQuantum,pixels,exception);
3332               if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
3333                 break;
3334             }
3335             if (image->previous == (Image *) NULL)
3336               {
3337                 status=SetImageProgress(image,SaveImageTag,100,400);
3338                 if (status == MagickFalse)
3339                   break;
3340               }
3341             for (y=0; y < (ssize_t) image->rows; y++)
3342             {
3343               register const Quantum
3344                 *restrict p;
3345
3346               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3347               if (p == (const Quantum *) NULL)
3348                 break;
3349               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3350                 GreenQuantum,pixels,exception);
3351               if (TIFFWritePixels(tiff,&tiff_info,y,1,image) == -1)
3352                 break;
3353             }
3354             if (image->previous == (Image *) NULL)
3355               {
3356                 status=SetImageProgress(image,SaveImageTag,200,400);
3357                 if (status == MagickFalse)
3358                   break;
3359               }
3360             for (y=0; y < (ssize_t) image->rows; y++)
3361             {
3362               register const Quantum
3363                 *restrict p;
3364
3365               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3366               if (p == (const Quantum *) NULL)
3367                 break;
3368               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3369                 BlueQuantum,pixels,exception);
3370               if (TIFFWritePixels(tiff,&tiff_info,y,2,image) == -1)
3371                 break;
3372             }
3373             if (image->previous == (Image *) NULL)
3374               {
3375                 status=SetImageProgress(image,SaveImageTag,300,400);
3376                 if (status == MagickFalse)
3377                   break;
3378               }
3379             if (image->alpha_trait == BlendPixelTrait)
3380               for (y=0; y < (ssize_t) image->rows; y++)
3381               {
3382                 register const Quantum
3383                   *restrict p;
3384
3385                 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3386                 if (p == (const Quantum *) NULL)
3387                   break;
3388                 length=ExportQuantumPixels(image,(CacheView *) NULL,
3389                   quantum_info,AlphaQuantum,pixels,exception);
3390                 if (TIFFWritePixels(tiff,&tiff_info,y,3,image) == -1)
3391                   break;
3392               }
3393             if (image->previous == (Image *) NULL)
3394               {
3395                 status=SetImageProgress(image,SaveImageTag,400,400);
3396                 if (status == MagickFalse)
3397                   break;
3398               }
3399             break;
3400           }
3401         }
3402         break;
3403       }
3404       case PHOTOMETRIC_SEPARATED:
3405       {
3406         /*
3407           CMYK TIFF image.
3408         */
3409         quantum_type=CMYKQuantum;
3410         if (image->alpha_trait == BlendPixelTrait)
3411           quantum_type=CMYKAQuantum;
3412         if (image->colorspace != CMYKColorspace)
3413           (void) TransformImageColorspace(image,CMYKColorspace,exception);
3414         for (y=0; y < (ssize_t) image->rows; y++)
3415         {
3416           register const Quantum
3417             *restrict p;
3418
3419           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3420           if (p == (const Quantum *) NULL)
3421             break;
3422           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3423             quantum_type,pixels,exception);
3424           if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
3425             break;
3426           if (image->previous == (Image *) NULL)
3427             {
3428               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
3429                 image->rows);
3430               if (status == MagickFalse)
3431                 break;
3432             }
3433         }
3434         break;
3435       }
3436       case PHOTOMETRIC_PALETTE:
3437       {
3438         uint16
3439           *blue,
3440           *green,
3441           *red;
3442
3443         /*
3444           Colormapped TIFF image.
3445         */
3446         red=(uint16 *) AcquireQuantumMemory(65536,sizeof(*red));
3447         green=(uint16 *) AcquireQuantumMemory(65536,sizeof(*green));
3448         blue=(uint16 *) AcquireQuantumMemory(65536,sizeof(*blue));
3449         if ((red == (uint16 *) NULL) || (green == (uint16 *) NULL) ||
3450             (blue == (uint16 *) NULL))
3451           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
3452         /*
3453           Initialize TIFF colormap.
3454         */
3455         (void) ResetMagickMemory(red,0,65536*sizeof(*red));
3456         (void) ResetMagickMemory(green,0,65536*sizeof(*green));
3457         (void) ResetMagickMemory(blue,0,65536*sizeof(*blue));
3458         for (i=0; i < (ssize_t) image->colors; i++)
3459         {
3460           red[i]=ScaleQuantumToShort(image->colormap[i].red);
3461           green[i]=ScaleQuantumToShort(image->colormap[i].green);
3462           blue[i]=ScaleQuantumToShort(image->colormap[i].blue);
3463         }
3464         (void) TIFFSetField(tiff,TIFFTAG_COLORMAP,red,green,blue);
3465         red=(uint16 *) RelinquishMagickMemory(red);
3466         green=(uint16 *) RelinquishMagickMemory(green);
3467         blue=(uint16 *) RelinquishMagickMemory(blue);
3468       }
3469       default:
3470       {
3471         /*
3472           Convert PseudoClass packets to contiguous grayscale scanlines.
3473         */
3474         quantum_type=IndexQuantum;
3475         if (image->alpha_trait == BlendPixelTrait)
3476           {
3477             if (photometric != PHOTOMETRIC_PALETTE)
3478               quantum_type=GrayAlphaQuantum;
3479             else
3480               quantum_type=IndexAlphaQuantum;
3481            }
3482          else
3483            if (photometric != PHOTOMETRIC_PALETTE)
3484              quantum_type=GrayQuantum;
3485         for (y=0; y < (ssize_t) image->rows; y++)
3486         {
3487           register const Quantum
3488             *restrict p;
3489
3490           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3491           if (p == (const Quantum *) NULL)
3492             break;
3493           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3494             quantum_type,pixels,exception);
3495           if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
3496             break;
3497           if (image->previous == (Image *) NULL)
3498             {
3499               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
3500                 image->rows);
3501               if (status == MagickFalse)
3502                 break;
3503             }
3504         }
3505         break;
3506       }
3507     }
3508     quantum_info=DestroyQuantumInfo(quantum_info);
3509     if (image->colorspace == LabColorspace)
3510       DecodeLabImage(image,exception);
3511     DestroyTIFFInfo(&tiff_info);
3512     if (0 && (image_info->verbose == MagickTrue))
3513       TIFFPrintDirectory(tiff,stdout,MagickFalse);
3514     (void) TIFFWriteDirectory(tiff);
3515     image=SyncNextImageInList(image);
3516     if (image == (Image *) NULL)
3517       break;
3518     status=SetImageProgress(image,SaveImagesTag,scene++,
3519       GetImageListLength(image));
3520     if (status == MagickFalse)
3521       break;
3522   } while (image_info->adjoin != MagickFalse);
3523   (void) TIFFSetWarningHandler(warning_handler);
3524   (void) TIFFSetErrorHandler(error_handler);
3525   TIFFClose(tiff);
3526   return(MagickTrue);
3527 }
3528 #endif