]> granicus.if.org Git - imagemagick/blobdiff - coders/tiff.c
(no commit message)
[imagemagick] / coders / tiff.c
index 6c4e07181ba4279cf144b252991e2a388f6eda0c..229639dd06fcc360c613c4344a5607899ca50781 100644 (file)
@@ -491,8 +491,8 @@ static void TIFFErrors(const char *module,const char *format,va_list error)
   (void) ConcatenateMagickString(message,".",MaxTextExtent);
   exception=(ExceptionInfo *) MagickGetThreadValue(tiff_exception);
   if (exception != (ExceptionInfo *) NULL)
-    (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning,
-      message,"`%s'",module);
+    (void) ThrowMagickException(exception,GetMagickModule(),CoderError,message,
+      "`%s'",module);
 }
 
 static void TIFFGetProfiles(TIFF *tiff,Image *image)
@@ -782,8 +782,8 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
   uint16
     compress_tag,
     bits_per_sample,
+    endian,
     extra_samples,
-    fill_order,
     interlace,
     max_sample_value,
     min_sample_value,
@@ -804,6 +804,9 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
   unsigned char
     *pixels;
 
+  size_t
+    lsb_first;
+
   /*
     Open image.
   */
@@ -856,13 +859,13 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
   {
     if (0 && (image_info->verbose != MagickFalse))
       TIFFPrintDirectory(tiff,stdout,MagickFalse);
+    (void) SetImageProperty(image,"tiff:endian",TIFFIsBigEndian(tiff) == 0 ?
+      "lsb" : "msb");
     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_COMPRESSION,&compress_tag);
     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_ORIENTATION,&orientation);
     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_IMAGEWIDTH,&width);
     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_IMAGELENGTH,&height);
-    (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&fill_order);
-    (void) SetImageProperty(image,"tiff:fill_order",
-      fill_order == FILLORDER_LSB2MSB ? "lsb" : "msb");
+    (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian);
     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_PLANARCONFIG,&interlace);
     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,&bits_per_sample);
     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLEFORMAT,&sample_format);
@@ -901,6 +904,11 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
         (void) SetImageProperty(image,"tiff:photometric","separated");
         break;
       }
+      case PHOTOMETRIC_YCBCR:
+      {
+        (void) SetImageProperty(image,"tiff:photometric","YCBCR");
+        break;
+      }
       default:
       {
         (void) SetImageProperty(image,"tiff:photometric","unknown");
@@ -928,7 +936,10 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
     if (image->debug != MagickFalse)
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Image depth: %.20g",
         (double) image->depth);
-    image->endian=TIFFIsBigEndian(tiff) != 0 ? MSBEndian : LSBEndian;
+    lsb_first=1;
+    image->endian=MSBEndian;
+    if ((int) (*(char *) &lsb_first) != 0)
+      image->endian=LSBEndian;
     if (photometric == PHOTOMETRIC_SEPARATED)
       image->colorspace=CMYKColorspace;
     if (photometric == PHOTOMETRIC_CIELAB)
@@ -1135,6 +1146,8 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
     if ((photometric != PHOTOMETRIC_SEPARATED) &&
         (interlace == PLANARCONFIG_SEPARATE))
       method=ReadGenericMethod;
+    if (image->compression == JPEGCompression)
+      method=ReadGenericMethod;
     if (TIFFIsTiled(tiff) != MagickFalse)
       method=ReadTileMethod;
     quantum_type=RGBQuantum;
@@ -1557,7 +1570,8 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
             q->green=ScaleCharToQuantum((unsigned char) TIFFGetG(*p));
             q->blue=ScaleCharToQuantum((unsigned char) TIFFGetB(*p));
             if (image->matte != MagickFalse)
-              q->opacity=ScaleCharToQuantum((unsigned char) TIFFGetA(*p));
+              q->opacity=(Quantum) (QuantumRange-
+                ScaleCharToQuantum((unsigned char) TIFFGetA(*p)));
             p--;
             q--;
           }
@@ -1587,6 +1601,9 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
       }
     if (image->storage_class == PseudoClass)
       image->depth=GetImageDepth(image,exception);
+    image->endian=MSBEndian;
+    if (endian == FILLORDER_LSB2MSB)
+      image->endian=LSBEndian;
     if ((photometric == PHOTOMETRIC_LOGL) ||
         (photometric == PHOTOMETRIC_MINISBLACK) ||
         (photometric == PHOTOMETRIC_MINISWHITE))
@@ -1698,6 +1715,7 @@ ModuleExport size_t RegisterTIFFImage(void)
   entry->raw=MagickTrue;
   entry->endian_support=MagickTrue;
   entry->adjoin=MagickFalse;
+  entry->format_type=ImplicitFormatType;
   entry->seekable_stream=MagickTrue;
   entry->thread_support=NoThreadSupport;
   entry->description=ConstantString("Raw CCITT Group4");
@@ -2096,6 +2114,10 @@ static MagickBooleanType GetTIFFInfo(const ImageInfo *image_info,TIFF *tiff,
   MagickStatusType
     flags;
 
+  uint32
+    tile_columns,
+    tile_rows;
+
   assert(tiff_info != (TIFFInfo *) NULL);
   (void) ResetMagickMemory(tiff_info,0,sizeof(*tiff_info));
   option=GetImageOption(image_info,"tiff:tile-geometry");
@@ -2104,15 +2126,17 @@ static MagickBooleanType GetTIFFInfo(const ImageInfo *image_info,TIFF *tiff,
   flags=ParseAbsoluteGeometry(option,&tiff_info->tile_geometry);
   if ((flags & HeightValue) == 0)
     tiff_info->tile_geometry.height=tiff_info->tile_geometry.width;
-  (void) TIFFSetField(tiff,TIFFTAG_TILEWIDTH,(uint32)
-    tiff_info->tile_geometry.width);
-  (void) TIFFSetField(tiff,TIFFTAG_TILELENGTH,(uint32)
-    tiff_info->tile_geometry.height);
+  tile_columns=(uint32) tiff_info->tile_geometry.width;
+  tile_rows=(uint32) tiff_info->tile_geometry.height;
+  TIFFDefaultTileSize(tiff,&tile_columns,&tile_rows);
+  (void) TIFFSetField(tiff,TIFFTAG_TILEWIDTH,tile_columns);
+  (void) TIFFSetField(tiff,TIFFTAG_TILELENGTH,tile_rows);
+  tiff_info->tile_geometry.width=tile_columns;
+  tiff_info->tile_geometry.height=tile_rows;
   tiff_info->scanlines=(unsigned char *) AcquireQuantumMemory((size_t)
-    tiff_info->tile_geometry.height*TIFFScanlineSize(tiff),
-    sizeof(*tiff_info->scanlines));
+    tile_rows*TIFFScanlineSize(tiff),sizeof(*tiff_info->scanlines));
   tiff_info->pixels=(unsigned char *) AcquireQuantumMemory((size_t)
-    TIFFTileSize(tiff),sizeof(*tiff_info->scanlines));
+    tile_rows*TIFFTileSize(tiff),sizeof(*tiff_info->scanlines));
   if ((tiff_info->scanlines == (unsigned char *) NULL) ||
       (tiff_info->pixels == (unsigned char *) NULL))
     {
@@ -2256,6 +2280,7 @@ static void TIFFSetProperties(TIFF *tiff,Image *image)
   const char
     *value;
 
+  (void) TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,image->filename);
   value=GetImageProperty(image,"tiff:hostcomputer");
   if (value != (const char *) NULL)
     (void) TIFFSetField(tiff,TIFFTAG_HOSTCOMPUTER,value);
@@ -2271,9 +2296,9 @@ static void TIFFSetProperties(TIFF *tiff,Image *image)
   value=GetImageProperty(image,"tiff:model");
   if (value != (const char *) NULL)
     (void) TIFFSetField(tiff,TIFFTAG_MODEL,value);
-  (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,
-    GetMagickVersion((size_t *) NULL));
-  (void) TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,image->filename);
+  value=GetImageProperty(image,"tiff:software");
+  if (value != (const char *) NULL)
+    (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,value);
   value=GetImageProperty(image,"tiff:copyright");
   if (value != (const char *) NULL)
     (void) TIFFSetField(tiff,33432,value);
@@ -2373,6 +2398,9 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
   CompressionType
     compression;
 
+  EndianType
+    endian_type;
+
   ssize_t
     y;
 
@@ -2408,7 +2436,7 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
   uint16
     bits_per_sample,
     compress_tag,
-    fill_order,
+    endian,
     photometric;
 
   uint32
@@ -2417,6 +2445,9 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
   unsigned char
     *pixels;
 
+  size_t
+    lsb_first;
+
   /*
     Open TIFF file.
   */
@@ -2432,7 +2463,16 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
   (void) MagickSetThreadValue(tiff_exception,&image->exception);
   error_handler=TIFFSetErrorHandler((TIFFErrorHandler) TIFFErrors);
   warning_handler=TIFFSetWarningHandler((TIFFErrorHandler) TIFFWarnings);
-  switch (image_info->endian)
+  endian_type=UndefinedEndian;
+  option=GetImageOption(image_info,"tiff:endian");
+  if (option != (const char *) NULL)
+    {
+      if (LocaleNCompare(option,"msb",3) == 0)
+        endian_type=MSBEndian;
+      if (LocaleNCompare(option,"lsb",3) == 0)
+        endian_type=LSBEndian;;
+    }
+  switch (endian_type)
   {
     case LSBEndian: mode="wl"; break;
     case MSBEndian: mode="wb"; break;
@@ -2440,7 +2480,7 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
   }
 #if defined(TIFF_VERSION_BIG)
   if (LocaleCompare(image_info->magick,"TIFF64") == 0)
-    switch (image_info->endian)
+    switch (endian_type)
     {
       case LSBEndian: mode="wl8"; break;
       case MSBEndian: mode="wb8"; break;
@@ -2606,6 +2646,7 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
             {
               photometric=PHOTOMETRIC_YCBCR;
               (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,1,1);
+              (void) SetImageStorageClass(image,DirectClass);
               (void) SetImageDepth(image,8);
             }
           else
@@ -2625,7 +2666,7 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
                   MagickFalse ? PHOTOMETRIC_MINISWHITE :
                   PHOTOMETRIC_MINISBLACK);
                 (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
-                if ((image_info->depth == 0) &&
+                if ((image_info->depth == 0) && (image->matte == MagickFalse) &&
                     (IsMonochromeImage(image,&image->exception) != MagickFalse))
                   {
                     status=SetQuantumDepth(image,quantum_info,1);
@@ -2655,30 +2696,52 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
                 }
           }
       }
-    (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&fill_order);
+    switch (image->endian)
+    {
+      case LSBEndian:
+      {
+        endian=FILLORDER_LSB2MSB;
+        break;
+      }
+      case MSBEndian:
+      {
+        endian=FILLORDER_MSB2LSB;
+        break;
+      }
+      case UndefinedEndian:
+      default:
+      {
+        (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian);
+        break;
+      }
+    }
+    lsb_first=1;
+    image->endian=MSBEndian;
+    if ((int) (*(char *) &lsb_first) != 0)
+      image->endian=LSBEndian;
     if ((compress_tag == COMPRESSION_CCITTFAX3) &&
         (photometric != PHOTOMETRIC_MINISWHITE))
       {
         compress_tag=COMPRESSION_NONE;
-        fill_order=FILLORDER_MSB2LSB;
+        endian=FILLORDER_MSB2LSB;
       }
     else
       if ((compress_tag == COMPRESSION_CCITTFAX4) &&
          (photometric != PHOTOMETRIC_MINISWHITE))
        {
          compress_tag=COMPRESSION_NONE;
-         fill_order=FILLORDER_MSB2LSB;
+         endian=FILLORDER_MSB2LSB;
        }
-    (void) TIFFSetField(tiff,TIFFTAG_COMPRESSION,compress_tag);
     option=GetImageProperty(image,"tiff:fill-order");
     if (option != (const char *) NULL)
       {
         if (LocaleNCompare(option,"msb",3) == 0)
-          fill_order=FILLORDER_MSB2LSB;
+          endian=FILLORDER_MSB2LSB;
         if (LocaleNCompare(option,"lsb",3) == 0)
-          fill_order=FILLORDER_LSB2MSB;
+          endian=FILLORDER_LSB2MSB;
       }
-    (void) TIFFSetField(tiff,TIFFTAG_FILLORDER,fill_order);
+    (void) TIFFSetField(tiff,TIFFTAG_COMPRESSION,compress_tag);
+    (void) TIFFSetField(tiff,TIFFTAG_FILLORDER,endian);
     (void) TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,quantum_info->depth);
     if (image->matte != MagickFalse)
       {
@@ -2782,8 +2845,9 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
                 flags=ParseGeometry(sampling_factor,&geometry_info);
                 if ((flags & SigmaValue) == 0)
                   geometry_info.sigma=geometry_info.rho;
-                (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,(uint16)
-                  geometry_info.rho,(uint16) geometry_info.sigma);
+                if (image->colorspace == YCbCrColorspace)
+                  (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,(uint16)
+                    geometry_info.rho,(uint16) geometry_info.sigma);
               }
           }
         if (bits_per_sample == 12)
@@ -2832,7 +2896,9 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
       default:
         break;
     }
-    (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
+    option=GetImageOption(image_info,"tiff:tile-geometry");
+    if (option == (const char *) NULL)
+      (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
     if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
       {
         unsigned short
@@ -3151,6 +3217,9 @@ static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
     if (0 && (image_info->verbose == MagickTrue))
       TIFFPrintDirectory(tiff,stdout,MagickFalse);
     (void) TIFFWriteDirectory(tiff);
+    image->endian=MSBEndian;
+    if (endian == FILLORDER_LSB2MSB)
+      image->endian=LSBEndian;
     image=SyncNextImageInList(image);
     if (image == (Image *) NULL)
       break;