]> granicus.if.org Git - imagemagick/commitdiff
Added support for reading Photoshop layers in TIFF files.
authordirk <dirk@git.imagemagick.org>
Mon, 25 May 2015 11:52:13 +0000 (11:52 +0000)
committerdirk <dirk@git.imagemagick.org>
Mon, 25 May 2015 11:52:13 +0000 (11:52 +0000)
coders/psd-private.h [new file with mode: 0644]
coders/psd.c
coders/tiff.c

diff --git a/coders/psd-private.h b/coders/psd-private.h
new file mode 100644 (file)
index 0000000..8a4c45e
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization
+  dedicated to making software imaging solutions freely available.
+
+  You may not use this file except in compliance with the License.
+  obtain a copy of the License at
+
+    http://www.imagemagick.org/script/license.php
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+  Private header to reuse psd functionality.
+*/
+#ifndef _PSD_PRIVATE_H
+#define _PSD_PRIVATE_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+typedef struct _PSDInfo
+{
+  char
+    signature[4];
+
+  size_t
+    rows,
+    columns;
+
+  unsigned char
+    reserved[6];
+
+  unsigned short
+    channels,
+    depth,
+    mode,
+    version;
+} PSDInfo;
+
+extern ModuleExport MagickStatusType
+  ReadPSDLayers(Image *image,const ImageInfo *image_info,
+  const PSDInfo *psd_info,const MagickBooleanType skip_layers,
+  ExceptionInfo *exception);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif
\ No newline at end of file
index 1ce127853645f49068686762000551a253bdd18d..1325917c52892e7ab747e9922c44729c346a0c90 100644 (file)
@@ -75,7 +75,8 @@
 #ifdef MAGICKCORE_ZLIB_DELEGATE
 #include <zlib.h>
 #endif
-\f
+#include "psd-private.h"
+
 /*
   Define declaractions.
 */
@@ -163,27 +164,6 @@ typedef struct _LayerInfo
   unsigned short
     channels;
 } LayerInfo;
-\ftypedef struct _PSDInfo
-{
-  char
-    signature[4];
-
-  unsigned short
-    channels,
-    version;
-
-  unsigned char
-    reserved[6];
-
-  size_t
-    rows,
-    columns;
-
-  unsigned short
-    depth,
-    mode;
-} PSDInfo;
-
 
 /*
   Forward declarations.
@@ -1238,9 +1218,9 @@ static MagickStatusType ReadPSDLayer(Image *image,const PSDInfo *psd_info,
   return(status);
 }
 
-static MagickStatusType ReadPSDLayers(Image *image,const ImageInfo *image_info,
-  const PSDInfo *psd_info,const MagickBooleanType skip_layers,
-  ExceptionInfo *exception)
+ModuleExport MagickStatusType ReadPSDLayers(Image *image,
+  const ImageInfo *image_info,const PSDInfo *psd_info,
+  const MagickBooleanType skip_layers,ExceptionInfo *exception)
 {
   char
     type[4];
index 1c25f89e0571ed750b923e39ee7b0ef163d69728..5f646bb9449dfecb386f33eb50f29b81d67add0f 100644 (file)
 # if !defined(TIFFTAG_OPIIMAGEID)
 #  define TIFFTAG_OPIIMAGEID  32781
 # endif
-\f
+#include "psd-private.h"
+
 /*
   Typedef declarations.
 */
@@ -500,7 +501,7 @@ static MagickBooleanType DecodeLabImage(Image *image,ExceptionInfo *exception)
 }
 
 static MagickBooleanType ReadProfile(Image *image,const char *name,
-  unsigned char *datum,ssize_t length,ExceptionInfo *exception)
+  const unsigned char *datum,ssize_t length,ExceptionInfo *exception)
 {
   MagickBooleanType
     status;
@@ -557,7 +558,8 @@ static toff_t TIFFGetBlobSize(thandle_t image)
   return((toff_t) GetBlobSize((Image *) image));
 }
 
-static void TIFFGetProfiles(TIFF *tiff,Image *image,ExceptionInfo *exception)
+static void TIFFGetProfiles(TIFF *tiff,Image *image,MagickBooleanType ping,
+  ExceptionInfo *exception)
 {
   uint32
     length;
@@ -566,36 +568,39 @@ static void TIFFGetProfiles(TIFF *tiff,Image *image,ExceptionInfo *exception)
     *profile;
 
   length=0;
+  if (ping == MagickFalse)
+    {
 #if defined(TIFFTAG_ICCPROFILE)
-  if ((TIFFGetField(tiff,TIFFTAG_ICCPROFILE,&length,&profile) == 1) &&
-      (profile != (unsigned char *) NULL))
-    (void) ReadProfile(image,"icc",profile,(ssize_t) length,exception);
+      if ((TIFFGetField(tiff,TIFFTAG_ICCPROFILE,&length,&profile) == 1) &&
+          (profile != (unsigned char *) NULL))
+        (void) ReadProfile(image,"icc",profile,(ssize_t) length,exception);
 #endif
 #if defined(TIFFTAG_PHOTOSHOP)
-  if ((TIFFGetField(tiff,TIFFTAG_PHOTOSHOP,&length,&profile) == 1) &&
-      (profile != (unsigned char *) NULL))
-    (void) ReadProfile(image,"8bim",profile,(ssize_t) length,exception);
+      if ((TIFFGetField(tiff,TIFFTAG_PHOTOSHOP,&length,&profile) == 1) &&
+          (profile != (unsigned char *) NULL))
+        (void) ReadProfile(image,"8bim",profile,(ssize_t) length,exception);
 #endif
 #if defined(TIFFTAG_RICHTIFFIPTC)
-  if ((TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC,&length,&profile) == 1) &&
-      (profile != (unsigned char *) NULL))
-    {
-      if (TIFFIsByteSwapped(tiff) != 0)
-        TIFFSwabArrayOfLong((uint32 *) profile,(size_t) length);
-      (void) ReadProfile(image,"iptc",profile,4L*length,exception);
-    }
+      if ((TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC,&length,&profile) == 1) &&
+          (profile != (unsigned char *) NULL))
+        {
+          if (TIFFIsByteSwapped(tiff) != 0)
+            TIFFSwabArrayOfLong((uint32 *) profile,(size_t) length);
+          (void) ReadProfile(image,"iptc",profile,4L*length,exception);
+        }
 #endif
 #if defined(TIFFTAG_XMLPACKET)
-  if ((TIFFGetField(tiff,TIFFTAG_XMLPACKET,&length,&profile) == 1) &&
-      (profile != (unsigned char *) NULL))
-    (void) ReadProfile(image,"xmp",profile,(ssize_t) length,exception);
+      if ((TIFFGetField(tiff,TIFFTAG_XMLPACKET,&length,&profile) == 1) &&
+          (profile != (unsigned char *) NULL))
+        (void) ReadProfile(image,"xmp",profile,(ssize_t) length,exception);
 #endif
+      if ((TIFFGetField(tiff,34118,&length,&profile) == 1) &&
+          (profile != (unsigned char *) NULL))
+        (void) ReadProfile(image,"tiff:34118",profile,(ssize_t) length,exception);
+    }
   if ((TIFFGetField(tiff,37724,&length,&profile) == 1) &&
       (profile != (unsigned char *) NULL))
     (void) ReadProfile(image,"tiff:37724",profile,(ssize_t) length,exception);
-  if ((TIFFGetField(tiff,34118,&length,&profile) == 1) &&
-      (profile != (unsigned char *) NULL))
-    (void) ReadProfile(image,"tiff:34118",profile,(ssize_t) length,exception);
 }
 
 static void TIFFGetProperties(TIFF *tiff,Image *image,ExceptionInfo *exception)
@@ -939,6 +944,67 @@ static TIFFMethodType GetJPEGMethod(Image* image,TIFF *tiff,uint16 photometric,
   return(method);
 }
 
+static void TIFFReadPhotoshopLayers(Image* image,const ImageInfo *image_info,
+  ExceptionInfo *exception)
+{
+  const char
+    *option;
+
+  const StringInfo
+    *layer_info;
+
+  Image
+    *layers;
+
+  PSDInfo
+    info;
+
+  register ssize_t
+    i;
+
+  if (GetImageListLength(image) != 1)
+    return;
+  option=GetImageOption(image_info,"tiff:ignore-layers");
+  if (IsStringTrue(option) != MagickFalse)
+    return;
+  layer_info=GetImageProfile(image,"tiff:37724");
+  if (layer_info == (const StringInfo *) NULL)
+    return;
+  for (i=0; i < (ssize_t) layer_info->length-8; i++)
+  {
+    if (LocaleNCompare((const char *) (layer_info->datum+i),"8BIM",4) != 0)
+      continue;
+    i+=4;
+    if ((LocaleNCompare((const char *) (layer_info->datum+i),"Layr",4) == 0) ||
+        (LocaleNCompare((const char *) (layer_info->datum+i),"LMsk",4) == 0) ||
+        (LocaleNCompare((const char *) (layer_info->datum+i),"Lr16",4) == 0) ||
+        (LocaleNCompare((const char *) (layer_info->datum+i),"Lr32",4) == 0))
+      break;
+  }
+  i+=4;
+  if (i >= layer_info->length-8)
+    return;
+  layers=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
+  RemoveImageProfile(layers,"tiff:37724");
+  AttachBlob(layers->blob,layer_info->datum,layer_info->length);
+  SeekBlob(layers,(MagickOffsetType) i,SEEK_SET);
+  info.version=1;
+  info.columns=layers->columns;
+  info.rows=layers->rows;
+  info.channels=layers->number_channels;
+  ReadPSDLayers(layers,image_info,&info,MagickFalse,exception);
+  DeleteImageFromList(&layers);
+  if (layers != (Image *) NULL)
+    {
+      AppendImageToList(&image,layers);
+      while (layers != (Image *) NULL)
+      {
+        DetachBlob(layers->blob);
+        layers=GetNextImageInList(layers);
+      }
+    }
+}
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
@@ -1208,8 +1274,7 @@ RestoreMSCWarning
       SetImageColorspace(image,CMYKColorspace,exception);
     if (photometric == PHOTOMETRIC_CIELAB)
       SetImageColorspace(image,LabColorspace,exception);
-    if (image_info->ping == MagickFalse)
-      TIFFGetProfiles(tiff,image,exception);
+    TIFFGetProfiles(tiff,image,image_info->ping,exception);
     TIFFGetProperties(tiff,image,exception);
     option=GetImageOption(image_info,"tiff:exif-properties");
     if (IfMagickTrue(IsStringNotFalse(option))) /* enabled by default */
@@ -1990,6 +2055,7 @@ RestoreMSCWarning
   (void) TIFFSetWarningHandler(warning_handler);
   (void) TIFFSetErrorHandler(error_handler);
   TIFFClose(tiff);
+  TIFFReadPhotoshopLayers(image,image_info,exception);
   return(GetFirstImageInList(image));
 }
 #endif