[Bf-blender-cvs] [23c71a5fab4] master: ImBuf: support detecting the file format from in-memory images

Campbell Barton noreply at git.blender.org
Tue Nov 10 12:25:51 CET 2020


Commit: 23c71a5fab42e22266196a45f1f2ac77e815bcd3
Author: Campbell Barton
Date:   Tue Nov 10 22:16:29 2020 +1100
Branches: master
https://developer.blender.org/rB23c71a5fab42e22266196a45f1f2ac77e815bcd3

ImBuf: support detecting the file format from in-memory images

Add `IMB_ispic_type_from_memory` so we can detect the file format
of in-memory images.

This removes `is_a_filepath` callback and uses a magic check for
photo-shop files that's compatible with OIIO.

Even though OIIO doesn't support packed images, we can still use the
file magic for detecting the format.

This change allows D9500 (a fix for unpacking images),
to be implemented without a significant performance penalty,
although the actual performance cost would depend heavily on the
blend file.

Reviewed By: dfelinto, sergey

Ref D9517

===================================================================

M	source/blender/imbuf/IMB_imbuf.h
M	source/blender/imbuf/intern/IMB_filetype.h
M	source/blender/imbuf/intern/filetype.c
M	source/blender/imbuf/intern/oiio/openimageio_api.cpp
M	source/blender/imbuf/intern/oiio/openimageio_api.h
M	source/blender/imbuf/intern/util.c

===================================================================

diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 2f848b5be08..0f9aa7055e7 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -474,6 +474,8 @@ bool IMB_prepare_write_ImBuf(const bool isfloat, struct ImBuf *ibuf);
  * \attention Defined in util.c
  */
 bool IMB_ispic(const char *name);
+bool IMB_ispic_type_matches(const char *name, int filetype);
+int IMB_ispic_type_from_memory(const unsigned char *mem, const size_t mem_size);
 int IMB_ispic_type(const char *name);
 
 /**
diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h
index 53d9a1a2919..b7763976853 100644
--- a/source/blender/imbuf/intern/IMB_filetype.h
+++ b/source/blender/imbuf/intern/IMB_filetype.h
@@ -33,7 +33,6 @@ typedef struct ImFileType {
   void (*exit)(void);
 
   int (*is_a)(const unsigned char *buf);
-  int (*is_a_filepath)(const char *filepath);
   int (*ftype)(const struct ImFileType *type, const struct ImBuf *ibuf);
   struct ImBuf *(*load)(const unsigned char *mem,
                         size_t size,
diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index 667027ebfeb..1746be85131 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -54,7 +54,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_jpeg,
-     NULL,
      imb_ftype_default,
      imb_load_jpeg,
      NULL,
@@ -66,7 +65,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_png,
-     NULL,
      imb_ftype_default,
      imb_loadpng,
      NULL,
@@ -78,7 +76,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_bmp,
-     NULL,
      imb_ftype_default,
      imb_bmp_decode,
      NULL,
@@ -90,7 +87,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_targa,
-     NULL,
      imb_ftype_default,
      imb_loadtarga,
      NULL,
@@ -102,7 +98,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_iris,
-     NULL,
      imb_ftype_iris,
      imb_loadiris,
      NULL,
@@ -115,7 +110,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_dpx,
-     NULL,
      imb_ftype_default,
      imb_load_dpx,
      NULL,
@@ -127,7 +121,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_cineon,
-     NULL,
      imb_ftype_default,
      imb_load_cineon,
      NULL,
@@ -141,7 +134,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {imb_inittiff,
      NULL,
      imb_is_a_tiff,
-     NULL,
      imb_ftype_default,
      imb_loadtiff,
      NULL,
@@ -155,7 +147,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_hdr,
-     NULL,
      imb_ftype_default,
      imb_loadhdr,
      NULL,
@@ -169,7 +160,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {imb_initopenexr,
      imb_exitopenexr,
      imb_is_a_openexr,
-     NULL,
      imb_ftype_default,
      imb_load_openexr,
      NULL,
@@ -183,7 +173,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_jp2,
-     NULL,
      imb_ftype_default,
      imb_load_jp2,
      NULL,
@@ -197,7 +186,6 @@ const ImFileType IMB_FILE_TYPES[] = {
     {NULL,
      NULL,
      imb_is_a_dds,
-     NULL,
      imb_ftype_default,
      imb_load_dds,
      NULL,
@@ -210,8 +198,7 @@ const ImFileType IMB_FILE_TYPES[] = {
 #ifdef WITH_OPENIMAGEIO
     {NULL,
      NULL,
-     NULL,
-     imb_is_a_filepath_photoshop,
+     imb_is_a_photoshop,
      imb_ftype_default,
      NULL,
      imb_load_photoshop,
@@ -221,7 +208,7 @@ const ImFileType IMB_FILE_TYPES[] = {
      IMB_FTYPE_PSD,
      COLOR_ROLE_DEFAULT_FLOAT},
 #endif
-    {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0},
+    {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0},
 };
 
 const ImFileType *IMB_FILE_TYPES_LAST = &IMB_FILE_TYPES[ARRAY_SIZE(IMB_FILE_TYPES) - 1];
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
index 9d8c5d50a89..0b787a7842f 100644
--- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
@@ -163,16 +163,10 @@ static ImBuf *imb_oiio_load_image_float(
 
 extern "C" {
 
-int imb_is_a_filepath_photoshop(const char *filename)
+int imb_is_a_photoshop(const unsigned char *mem)
 {
-  const char *photoshop_extension[] = {
-      ".psd",
-      ".pdd",
-      ".psb",
-      nullptr,
-  };
-
-  return BLI_path_extension_check_array(filename, photoshop_extension);
+  const unsigned char magic[4] = {'8', 'B', 'P', 'S'};
+  return memcmp(magic, mem, sizeof(magic)) == 0;
 }
 
 int imb_save_photoshop(struct ImBuf *ibuf, const char * /*name*/, int flags)
@@ -198,7 +192,7 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac
   const bool is_colorspace_manually_set = (colorspace[0] != '\0');
 
   /* load image from file through OIIO */
-  if (imb_is_a_filepath_photoshop(filename) == 0) {
+  if (IMB_ispic_type_matches(filename, IMB_FTYPE_PSD) == 0) {
     return nullptr;
   }
 
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.h b/source/blender/imbuf/intern/oiio/openimageio_api.h
index 135e3521f71..0ac6e560cfa 100644
--- a/source/blender/imbuf/intern/oiio/openimageio_api.h
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.h
@@ -31,7 +31,7 @@ extern "C" {
 
 struct ImBuf;
 
-int imb_is_a_filepath_photoshop(const char *name);
+int imb_is_a_photoshop(const unsigned char *mem);
 
 int imb_save_photoshop(struct ImBuf *ibuf, const char *name, int flags);
 
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 7be58a9ca14..37a1afb5dd7 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -117,13 +117,11 @@ const char *imb_ext_audio[] = {
     NULL,
 };
 
-int IMB_ispic_type(const char *name)
-{
-  /* increased from 32 to 64 because of the bitmaps header size */
+/* Increased from 32 to 64 because of the bitmaps header size. */
 #define HEADER_SIZE 64
 
-  unsigned char buf[HEADER_SIZE];
-  const ImFileType *type;
+static bool imb_ispic_read_header_from_filename(const char *name, unsigned char buf[HEADER_SIZE])
+{
   BLI_stat_t st;
   int fp;
 
@@ -144,32 +142,70 @@ int IMB_ispic_type(const char *name)
     return false;
   }
 
-  memset(buf, 0, sizeof(buf));
+  memset(buf, 0, HEADER_SIZE);
   if (read(fp, buf, HEADER_SIZE) <= 0) {
     close(fp);
     return false;
   }
 
   close(fp);
+  return true;
+}
 
-  for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
+int IMB_ispic_type_from_memory(const unsigned char *mem, const size_t mem_size)
+{
+  unsigned char buf_static[HEADER_SIZE];
+  const unsigned char *buf;
+
+  if (mem_size >= HEADER_SIZE) {
+    buf = buf_static;
+  }
+  else {
+    memset(buf_static, 0, HEADER_SIZE);
+    memcpy(buf_static, mem, mem_size);
+    buf = buf_static;
+  }
+
+  for (const ImFileType *type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
     if (type->is_a) {
       if (type->is_a(buf)) {
         return type->filetype;
       }
     }
-    else if (type->is_a_filepath) {
-      if (type->is_a_filepath(name)) {
-        return type->filetype;
-      }
-    }
   }
 
   return 0;
+}
 
-#undef HEADER_SIZE
+int IMB_ispic_type(const char *name)
+{
+  unsigned char buf[HEADER_SIZE];
+  if (!imb_ispic_read_header_from_filename(name, buf)) {
+    return false;
+  }
+  return IMB_ispic_type_from_memory(buf, HEADER_SIZE);
 }
 
+bool IMB_ispic_type_matches(const char *name, int filetype)
+{
+  unsigned char buf[HEADER_SIZE];
+  if (!imb_ispic_read_header_from_filename(name, buf)) {
+    return false;
+  }
+
+  for (const ImFileType *type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
+    if (type->filetype == filetype) {
+      /* Requesting to load a type that can't check it's own header doesn't make sense.
+       * Keep the check for developers. */
+      BLI_assert(type->is_a != NULL);
+      return type->is_a ? type->is_a(buf) : false;
+    }
+  }
+  return false;
+}
+
+#undef HEADER_SIZE
+
 bool IMB_ispic(const char *name)
 {
   return (IMB_ispic_type(name) != 0);



More information about the Bf-blender-cvs mailing list