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