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