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