]> granicus.if.org Git - imagemagick/blobdiff - coders/dng.c
...
[imagemagick] / coders / dng.c
index b72d3d0664c29c0dad903bcce258087faa74c09d..c306a661188879939318dc1e868fc0b4bf6d6de6 100644 (file)
@@ -17,7 +17,7 @@
 %                                 July 1999                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2018 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.  You may  %
@@ -57,6 +57,8 @@
 #include "MagickCore/monitor-private.h"
 #include "MagickCore/opencl.h"
 #include "MagickCore/pixel-accessor.h"
+#include "MagickCore/profile.h"
+#include "MagickCore/property.h"
 #include "MagickCore/quantum-private.h"
 #include "MagickCore/resource_.h"
 #include "MagickCore/static.h"
@@ -145,6 +147,7 @@ static void InitializeDcrawOpenCL(ExceptionInfo *exception)
   }
 }
 #else
+#if !defined(MAGICKCORE_RAW_R_DELEGATE)
 static void InitializeDcrawOpenCL(ExceptionInfo *magick_unused(exception))
 {
   magick_unreferenced(exception);
@@ -153,18 +156,88 @@ static void InitializeDcrawOpenCL(ExceptionInfo *magick_unused(exception))
 #endif
 }
 #endif
+#endif
 
-static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
+#if defined(MAGICKCORE_RAW_R_DELEGATE)
+static void SetDNGProperties(Image *image,const libraw_data_t *raw_info,
+  ExceptionInfo *exception)
 {
-  ExceptionInfo
-    *sans_exception;
+  char
+    property[MagickPathExtent],
+    timestamp[MagickPathExtent];
+
+  (void) SetImageProperty(image,"dng:make",raw_info->idata.make,exception);
+  (void) SetImageProperty(image,"dng:camera.model.name",raw_info->idata.model,
+    exception);
+  (void) FormatMagickTime(raw_info->other.timestamp,MagickPathExtent,timestamp);
+  (void) SetImageProperty(image,"dng:create.date",timestamp,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.1f",
+    raw_info->other.iso_speed);
+  (void) SetImageProperty(image,"dng:iso.setting",property,exception);
+#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,18)
+  (void) SetImageProperty(image,"dng:software",raw_info->idata.software,
+    exception);
+  if (*raw_info->shootinginfo.BodySerial != '\0')
+    (void) SetImageProperty(image,"dng:serial.number",
+      raw_info->shootinginfo.BodySerial,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.2f",
+    raw_info->other.FlashEC);
+  (void) SetImageProperty(image,"dng:flash.exposure.compensation",property,
+    exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"1/%0.1f",
+    1.0/raw_info->other.shutter);
+  (void) SetImageProperty(image,"dng:exposure.time",property,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.1f",
+    raw_info->other.aperture);
+  (void) SetImageProperty(image,"dng:f.number",property,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.1f",
+    raw_info->lens.EXIF_MaxAp);
+  (void) SetImageProperty(image,"dng:max.aperture.value",property,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.1f",
+    raw_info->other.focal_len);
+  (void) SetImageProperty(image,"dng:focal.length",property,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%f %f %f %f",
+    raw_info->color.cam_mul[0],raw_info->color.cam_mul[2],
+    raw_info->color.cam_mul[1],raw_info->color.cam_mul[3]);
+  (void) SetImageProperty(image,"dng:wb.rb.levels",property,exception);
+  (void) SetImageProperty(image,"dng:lens.type",
+    raw_info->lens.makernotes.LensFeatures_suf,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,
+    "%0.1f-%0.1fmm f/%0.1f-%0.1f",raw_info->lens.makernotes.MinFocal,
+    raw_info->lens.makernotes.MaxFocal,
+    raw_info->lens.makernotes.MaxAp4MinFocal,
+    raw_info->lens.makernotes.MaxAp4MaxFocal);
+  (void) SetImageProperty(image,"dng:lens",property,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.2f",
+    raw_info->lens.makernotes.LensFStops);
+  (void) SetImageProperty(image,"dng:lens.f.stops",property,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.1f mm",
+    raw_info->lens.makernotes.MinFocal);
+  (void) SetImageProperty(image,"dng:min.focal.length",property,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.1f mm",
+    raw_info->lens.makernotes.MaxFocal);
+  (void) SetImageProperty(image,"dng:max.focal.length",property,exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.1f",
+    raw_info->lens.makernotes.MaxAp4MinFocal);
+  (void) SetImageProperty(image,"dng:max.aperture.at.min.focal",property,
+    exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%0.1f",
+    raw_info->lens.makernotes.MaxAp4MaxFocal);
+  (void) SetImageProperty(image,"dng:max.aperture.at.max.focal",property,
+    exception);
+  (void) FormatLocaleString(property,MagickPathExtent,"%d mm",
+    raw_info->lens.FocalLengthIn35mmFormat);
+  (void) SetImageProperty(image,"dng:focal.length.in.35mm.format",property,
+    exception);
+#endif
+}
+#endif
 
+static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
+{
   Image
     *image;
 
-  ImageInfo
-    *read_info;
-
   MagickBooleanType
     status;
 
@@ -189,7 +262,7 @@ static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
 #if defined(MAGICKCORE_RAW_R_DELEGATE)
   {
     int
-      status;
+      errcode;
 
     libraw_data_t
       *raw_info;
@@ -200,52 +273,82 @@ static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
     register ssize_t
       y;
 
+    StringInfo
+      *profile;
+
     unsigned short
       *p;
 
-    status=0;
+    errcode=0;
     raw_info=libraw_init(0);
     if (raw_info == (libraw_data_t *) NULL)
       {
         (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
-          libraw_strerror(status),"`%s'",image->filename);
+          libraw_strerror(errcode),"`%s'",image->filename);
         return(DestroyImageList(image));
       }
-    status=libraw_open_file(raw_info,image->filename);
-    if (status != LIBRAW_SUCCESS)
+#if defined(MAGICKCORE_WINDOWS_SUPPORT) && defined(_MSC_VER) && (_MSC_VER > 1310)
+    {
+      wchar_t
+        fileName[MagickPathExtent];
+
+      MultiByteToWideChar(CP_UTF8,0,image->filename,-1,fileName,
+        MagickPathExtent);
+      errcode=libraw_open_wfile(raw_info,fileName);
+    }
+#else
+    errcode=libraw_open_file(raw_info,image->filename);
+#endif
+    if (errcode != LIBRAW_SUCCESS)
       {
         (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
-          libraw_strerror(status),"`%s'",image->filename);
+          libraw_strerror(errcode),"`%s'",image->filename);
         return(DestroyImageList(image));
       }
-    status=libraw_unpack(raw_info);
-    if (status != LIBRAW_SUCCESS)
+    image->columns=raw_info->sizes.width;
+    image->rows=raw_info->sizes.height;
+    image->page.width=raw_info->sizes.raw_width;
+    image->page.height=raw_info->sizes.raw_height;
+    image->page.x=raw_info->sizes.left_margin;
+    image->page.y=raw_info->sizes.top_margin;
+    if (image_info->ping != MagickFalse)
       {
         libraw_close(raw_info);
+        return(image);
+      }
+    errcode=libraw_unpack(raw_info);
+    if (errcode != LIBRAW_SUCCESS)
+      {
         (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
-          libraw_strerror(status),"`%s'",image->filename);
+          libraw_strerror(errcode),"`%s'",image->filename);
+        libraw_close(raw_info);
         return(DestroyImageList(image));
       }
     raw_info->params.output_bps=16;
-    status=libraw_dcraw_process(raw_info);
-    if (status != LIBRAW_SUCCESS)
+    errcode=libraw_dcraw_process(raw_info);
+    if (errcode != LIBRAW_SUCCESS)
       {
-        libraw_close(raw_info);
         (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
-          libraw_strerror(status),"`%s'",image->filename);
+          libraw_strerror(errcode),"`%s'",image->filename);
+        libraw_close(raw_info);
         return(DestroyImageList(image));
       }
-    raw_image=libraw_dcraw_make_mem_image(raw_info,&status);
-    if (status != LIBRAW_SUCCESS)
+    raw_image=libraw_dcraw_make_mem_image(raw_info,&errcode);
+    if ((errcode != LIBRAW_SUCCESS) ||
+        (raw_image == (libraw_processed_image_t *) NULL) ||
+        (raw_image->type != LIBRAW_IMAGE_BITMAP) || (raw_image->bits != 16) ||
+        (raw_image->colors < 3) || (raw_image->colors > 4))
       {
-        libraw_close(raw_info);
+        if (raw_image != (libraw_processed_image_t *) NULL)
+          libraw_dcraw_clear_mem(raw_image);
         (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
-          libraw_strerror(status),"`%s'",image->filename);
+          libraw_strerror(errcode),"`%s'",image->filename);
+        libraw_close(raw_info);
         return(DestroyImageList(image));
       }
     image->columns=raw_image->width;
     image->rows=raw_image->height;
-    image->depth=16;
+    image->depth=raw_image->bits;
     status=SetImageExtent(image,image->columns,image->rows,exception);
     if (status == MagickFalse)
       {
@@ -270,6 +373,8 @@ static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
         SetPixelRed(image,ScaleShortToQuantum(*p++),q);
         SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
         SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
+        if (raw_image->colors > 3)
+          SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
         q+=GetPixelChannels(image);
       }
       if (SyncAuthenticPixels(image,exception) == MagickFalse)
@@ -283,100 +388,136 @@ static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
         }
     }
     libraw_dcraw_clear_mem(raw_image);
+    /*
+      Set DNG image metadata.
+    */
+    if (raw_info->color.profile)
+      {
+        profile=BlobToStringInfo(raw_info->color.profile,
+          raw_info->color.profile_length);
+        if (profile != (StringInfo *) NULL)
+          {
+            SetImageProfile(image,"ICC",profile,exception);
+            profile=DestroyStringInfo(profile);
+          }
+      }
+#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,18)
+    if (raw_info->idata.xmpdata)
+      {
+        profile=BlobToStringInfo(raw_info->idata.xmpdata,
+          raw_info->idata.xmplen);
+        if (profile != (StringInfo *) NULL)
+          {
+            SetImageProfile(image,"XMP",profile,exception);
+            profile=DestroyStringInfo(profile);
+          }
+      }
+#endif
+    SetDNGProperties(image,raw_info,exception);
     libraw_close(raw_info);
     return(image);
   }
-#endif
-  (void) DestroyImageList(image);
-  /*
-    Convert DNG to PPM with delegate.
-  */
-  InitializeDcrawOpenCL(exception);
-  image=AcquireImage(image_info,exception);
-  read_info=CloneImageInfo(image_info);
-  SetImageInfoBlob(read_info,(void *) NULL,0);
-  (void) InvokeDelegate(read_info,image,"dng:decode",(char *) NULL,exception);
-  image=DestroyImage(image);
-  (void) FormatLocaleString(read_info->filename,MagickPathExtent,"%s.png",
-    read_info->unique);
-  sans_exception=AcquireExceptionInfo();
-  image=ReadImage(read_info,sans_exception);
-  sans_exception=DestroyExceptionInfo(sans_exception);
-  if (image == (Image *) NULL)
-    {
-      (void) FormatLocaleString(read_info->filename,MagickPathExtent,"%s.ppm",
-        read_info->unique);
-      image=ReadImage(read_info,exception);
-    }
-  (void) RelinquishUniqueFileResource(read_info->filename);
-  if (image != (Image *) NULL)
-    {
-      char
-        filename[MagickPathExtent],
-        *xml;
-
-      ExceptionInfo
-        *sans;
+#else
+  {
+    ExceptionInfo
+      *sans_exception;
 
-      (void) CopyMagickString(image->magick,read_info->magick,MagickPathExtent);
-      (void) FormatLocaleString(filename,MagickPathExtent,"%s.ufraw",
-        read_info->unique);
-      sans=AcquireExceptionInfo();
-      xml=FileToString(filename,MagickPathExtent,sans);
-      (void) RelinquishUniqueFileResource(filename);
-      if (xml != (char *) NULL)
-        {
-          XMLTreeInfo
-            *ufraw;
+    ImageInfo
+      *read_info;
 
-          /*
-            Inject.
-          */
-          ufraw=NewXMLTree(xml,sans);
-          if (ufraw != (XMLTreeInfo *) NULL)
-            {
-              char
-                *content,
-                property[MagickPathExtent];
+    /*
+      Convert DNG to PPM with delegate.
+    */
+    (void) DestroyImageList(image);
+    InitializeDcrawOpenCL(exception);
+    image=AcquireImage(image_info,exception);
+    read_info=CloneImageInfo(image_info);
+    SetImageInfoBlob(read_info,(void *) NULL,0);
+    (void) InvokeDelegate(read_info,image,"dng:decode",(char *) NULL,exception);
+    image=DestroyImage(image);
+    (void) FormatLocaleString(read_info->filename,MagickPathExtent,"%s.png",
+      read_info->unique);
+    sans_exception=AcquireExceptionInfo();
+    image=ReadImage(read_info,sans_exception);
+    sans_exception=DestroyExceptionInfo(sans_exception);
+    if (image == (Image *) NULL)
+      {
+        (void) FormatLocaleString(read_info->filename,MagickPathExtent,"%s.ppm",
+          read_info->unique);
+        image=ReadImage(read_info,exception);
+      }
+    (void) RelinquishUniqueFileResource(read_info->filename);
+    if (image != (Image *) NULL)
+      {
+        char
+          filename[MagickPathExtent],
+          *xml;
 
-              const char
-                *tag;
+        ExceptionInfo
+          *sans;
 
-              XMLTreeInfo
-                *next;
+        (void) CopyMagickString(image->magick,read_info->magick,
+          MagickPathExtent);
+        (void) FormatLocaleString(filename,MagickPathExtent,"%s.ufraw",
+          read_info->unique);
+        sans=AcquireExceptionInfo();
+        xml=FileToString(filename,MagickPathExtent,sans);
+        (void) RelinquishUniqueFileResource(filename);
+        if (xml != (char *) NULL)
+          {
+            XMLTreeInfo
+              *ufraw;
 
-              if (image->properties == (void *) NULL)
-                ((Image *) image)->properties=NewSplayTree(
-                  CompareSplayTreeString,RelinquishMagickMemory,
-                  RelinquishMagickMemory);
-              next=GetXMLTreeChild(ufraw,(const char *) NULL);
-              while (next != (XMLTreeInfo *) NULL)
+            /*
+              Inject.
+            */
+            ufraw=NewXMLTree(xml,sans);
+            if (ufraw != (XMLTreeInfo *) NULL)
               {
-                tag=GetXMLTreeTag(next);
-                if (tag == (char *) NULL)
-                  tag="unknown";
-                (void) FormatLocaleString(property,MagickPathExtent,"dng:%s",
-                  tag);
-                content=ConstantString(GetXMLTreeContent(next));
-                StripString(content);
-                if ((LocaleCompare(tag,"log") != 0) &&
-                    (LocaleCompare(tag,"InputFilename") != 0) &&
-                    (LocaleCompare(tag,"OutputFilename") != 0) &&
-                    (LocaleCompare(tag,"OutputType") != 0) &&
-                    (strlen(content) != 0))
-                  (void) AddValueToSplayTree((SplayTreeInfo *)
-                    ((Image *) image)->properties,ConstantString(property),
-                    content);
-                next=GetXMLTreeSibling(next);
+                char
+                  *content,
+                  property[MagickPathExtent];
+
+                const char
+                  *tag;
+
+                XMLTreeInfo
+                  *next;
+
+                if (image->properties == (void *) NULL)
+                  ((Image *) image)->properties=NewSplayTree(
+                    CompareSplayTreeString,RelinquishMagickMemory,
+                    RelinquishMagickMemory);
+                next=GetXMLTreeChild(ufraw,(const char *) NULL);
+                while (next != (XMLTreeInfo *) NULL)
+                {
+                  tag=GetXMLTreeTag(next);
+                  if (tag == (char *) NULL)
+                    tag="unknown";
+                  (void) FormatLocaleString(property,MagickPathExtent,"dng:%s",
+                    tag);
+                  content=ConstantString(GetXMLTreeContent(next));
+                  StripString(content);
+                  if ((LocaleCompare(tag,"log") != 0) &&
+                      (LocaleCompare(tag,"InputFilename") != 0) &&
+                      (LocaleCompare(tag,"OutputFilename") != 0) &&
+                      (LocaleCompare(tag,"OutputType") != 0) &&
+                      (strlen(content) != 0))
+                    (void) AddValueToSplayTree((SplayTreeInfo *)
+                      ((Image *) image)->properties,ConstantString(property),
+                      content);
+                  next=GetXMLTreeSibling(next);
+                }
+                ufraw=DestroyXMLTree(ufraw);
               }
-              ufraw=DestroyXMLTree(ufraw);
-            }
-          xml=DestroyString(xml);
-        }
-      sans=DestroyExceptionInfo(sans);
-    }
-  read_info=DestroyImageInfo(read_info);
-  return(image);
+            xml=DestroyString(xml);
+          }
+        sans=DestroyExceptionInfo(sans);
+      }
+    read_info=DestroyImageInfo(read_info);
+    return(image);
+  }
+#endif
 }
 \f
 /*