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