[gimp] file-exr: Add initial implementation (loader)



commit 8d89efaff5bd4f397e711b2b511d2841e39b8526
Author: Mukund Sivaraman <muks banu com>
Date:   Sat May 4 07:25:49 2013 +0530

    file-exr: Add initial implementation (loader)
    
    This is a basic implementation of an OpenEXR loader. This
    "infrastructure" is required for any further work. It consists of:
    
    * The build system changes.
    
    * A C wrapper around the OpenEXR library, which is necessary as it's not
      possible to intermix GIMP's code with C++ code.
    
    * A basic image loader. Chroma is not supported currently, and some
      other weird files like multi-view files are unsupported. These can be
      added when necessary. There is no UI, but it should be straightforward
      to add new features like this on top of this work.

 configure.ac                         |   31 ++++
 plug-ins/Makefile.am                 |    5 +
 plug-ins/file-exr/.gitignore         |    7 +
 plug-ins/file-exr/Makefile.am        |   51 ++++++
 plug-ins/file-exr/file-exr.c         |  303 ++++++++++++++++++++++++++++++++++
 plug-ins/file-exr/openexr-wrapper.cc |  283 +++++++++++++++++++++++++++++++
 plug-ins/file-exr/openexr-wrapper.h  |   61 +++++++
 7 files changed, 741 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 6f3c544..4c0b03e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -64,6 +64,7 @@ m4_define([exif_required_version], [0.6.15])
 m4_define([lcms_required_version], [2.2])
 m4_define([libpng_required_version], [1.2.37])
 m4_define([liblzma_required_version], [5.0.0])
+m4_define([openexr_required_version], [1.7.1])
 
 
 AC_INIT([GIMP], [gimp_version],
@@ -159,6 +160,9 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
 AC_PROG_CC
 AM_PROG_CC_C_O
 
+# Determine a C++ compiler to use
+AC_PROG_CXX
+
 # Initialize libtool
 LT_PREREQ([2.2])
 LT_INIT([disable-static win32-dll])
@@ -1357,6 +1361,31 @@ AC_SUBST(FILE_XPM)
 AC_SUBST(XPM_LIBS)
 
 
+###################
+# Check for OpenEXR
+###################
+
+AC_ARG_WITH(openexr, [  --without-openexr       build without OpenEXR support])
+
+have_openexr=no
+if test "x$with_openexr" != xno; then
+  have_openexr=yes
+  PKG_CHECK_MODULES(OPENEXR, OpenEXR >= openexr_required_version,
+    FILE_EXR='file-exr$(EXEEXT)',
+    [have_openexr="no (OpenEXR not found)"])
+fi
+
+if test "x$have_openexr" = xyes; then
+  MIME_TYPES="$MIME_TYPES;image/x-exr"
+fi
+
+AC_SUBST(OPENEXR_CFLAGS)
+AC_SUBST(OPENEXR_LIBS)
+AC_SUBST(FILE_EXR)
+
+AM_CONDITIONAL(HAVE_OPENEXR, test "x$have_openexr" = xyes)
+
+
 ##################
 # Check for webkit
 ##################
@@ -2214,6 +2243,7 @@ plug-ins/color-rotate/Makefile
 plug-ins/color-rotate/images/Makefile
 plug-ins/file-bmp/Makefile
 plug-ins/file-compressor/Makefile
+plug-ins/file-exr/Makefile
 plug-ins/file-faxg3/Makefile
 plug-ins/file-fits/Makefile
 plug-ins/file-fli/Makefile
@@ -2366,6 +2396,7 @@ Optional Plug-Ins:
   JPEG:                $jpeg_ok
   JPEG 2000:           $have_jp2
   MNG:                 $have_libmng
+  OpenEXR:             $have_openexr
   PDF (import):        $have_poppler
   PDF (export):        $have_cairo_pdf
   PNG:                 $have_libpng
diff --git a/plug-ins/Makefile.am b/plug-ins/Makefile.am
index 8305398..50eb645 100644
--- a/plug-ins/Makefile.am
+++ b/plug-ins/Makefile.am
@@ -4,6 +4,10 @@ if HAVE_WEBKIT
 help_browser = help-browser
 endif
 
+if HAVE_OPENEXR
+file_exr = file-exr
+endif
+
 if BUILD_JPEG
 file_jpeg = file-jpeg
 file_psd = file-psd
@@ -58,6 +62,7 @@ SUBDIRS = \
        color-rotate            \
        file-bmp                \
        $(file_compressor)      \
+       $(file_exr)             \
        file-faxg3              \
        file-fits               \
        file-fli                \
diff --git a/plug-ins/file-exr/.gitignore b/plug-ins/file-exr/.gitignore
new file mode 100644
index 0000000..6f8c193
--- /dev/null
+++ b/plug-ins/file-exr/.gitignore
@@ -0,0 +1,7 @@
+/Makefile.in
+/Makefile
+/.deps
+/_libs
+/.libs
+/file-exr
+/file-exr.exe
diff --git a/plug-ins/file-exr/Makefile.am b/plug-ins/file-exr/Makefile.am
new file mode 100644
index 0000000..e7c4ebe
--- /dev/null
+++ b/plug-ins/file-exr/Makefile.am
@@ -0,0 +1,51 @@
+## Process this file with automake to produce Makefile.in
+
+libgimpui = $(top_builddir)/libgimp/libgimpui-$(GIMP_API_VERSION).la
+libgimpconfig = $(top_builddir)/libgimpconfig/libgimpconfig-$(GIMP_API_VERSION).la
+libgimpwidgets = $(top_builddir)/libgimpwidgets/libgimpwidgets-$(GIMP_API_VERSION).la
+libgimp = $(top_builddir)/libgimp/libgimp-$(GIMP_API_VERSION).la
+libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la
+libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la
+libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la
+
+if OS_WIN32
+mwindows = -mwindows
+endif
+
+# if HAVE_WINDRES
+# include $(top_srcdir)/build/windows/gimprc-plug-ins.rule
+# file_exr_RC = file-exr.rc.o
+# endif
+
+AM_LDFLAGS = $(mwindows)
+
+libexecdir = $(gimpplugindir)/plug-ins
+
+INCLUDES = \
+       -I$(top_srcdir)   \
+       $(GTK_CFLAGS)     \
+       $(GEGL_CFLAGS)    \
+       $(OPENEXR_CFLAGS) \
+       -I$(includedir)
+
+libexec_PROGRAMS = file-exr
+
+file_exr_SOURCES = \
+       file-exr.c              \
+       openexr-wrapper.cc      \
+       openexr-wrapper.h
+
+file_exr_LDADD = \
+       $(OPENEXR_LIBS)         \
+       $(libgimpui)            \
+       $(libgimpwidgets)       \
+       $(libgimpconfig)        \
+       $(libgimp)              \
+       $(libgimpcolor)         \
+       $(libgimpmath)          \
+       $(libgimpbase)          \
+       $(GTK_LIBS)             \
+       $(GEGL_LIBS)            \
+       $(RT_LIBS)              \
+       $(INTLLIBS)             \
+       $(file_exr_RC)
diff --git a/plug-ins/file-exr/file-exr.c b/plug-ins/file-exr/file-exr.c
new file mode 100644
index 0000000..4758e91
--- /dev/null
+++ b/plug-ins/file-exr/file-exr.c
@@ -0,0 +1,303 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "libgimp/stdplugins-intl.h"
+
+#include "openexr-wrapper.h"
+
+#define LOAD_PROC          "file-exr-load"
+#define PLUG_IN_BINARY     "file-exr"
+#define PLUG_IN_ROLE       "gimp-file-exr"
+#define PLUG_IN_VERSION    "0.0.0"
+
+
+/*
+ * Declare some local functions.
+ */
+static void     query       (void);
+static void     run         (const gchar      *name,
+                             gint              nparams,
+                             const GimpParam  *param,
+                             gint             *nreturn_vals,
+                             GimpParam       **return_vals);
+
+static gint32    load_image (const gchar      *filename,
+                             gboolean          interactive,
+                             GError          **error);
+/*
+ * Some global variables.
+ */
+
+const GimpPlugInInfo PLUG_IN_INFO =
+{
+  NULL,  /* init_proc  */
+  NULL,  /* quit_proc  */
+  query, /* query_proc */
+  run,   /* run_proc   */
+};
+
+
+MAIN ()
+
+static void
+query (void)
+{
+  static const GimpParamDef load_args[] =
+  {
+    { GIMP_PDB_INT32,  "run-mode",     "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
+    { GIMP_PDB_STRING, "filename",     "The name of the file to load" },
+    { GIMP_PDB_STRING, "raw-filename", "The name of the file to load" }
+  };
+  static const GimpParamDef load_return_vals[] =
+  {
+    { GIMP_PDB_IMAGE, "image", "Output image" }
+  };
+
+  gimp_install_procedure (LOAD_PROC,
+                          "Loads files in the OpenEXR file format",
+                          "This plug-in loads OpenEXR files. ",
+                          "Dominik Ernst <dernst gmx de>, "
+                          "Mukund Sivaraman <muks banu com>",
+                          "Dominik Ernst <dernst gmx de>, "
+                          "Mukund Sivaraman <muks banu com>",
+                          PLUG_IN_VERSION,
+                          N_("OpenEXR image"),
+                          NULL,
+                          GIMP_PLUGIN,
+                          G_N_ELEMENTS (load_args),
+                          G_N_ELEMENTS (load_return_vals),
+                          load_args, load_return_vals);
+
+  gimp_register_file_handler_mime (LOAD_PROC, "image/x-exr");
+  gimp_register_magic_load_handler (LOAD_PROC,
+                                    "exr", "", "0,lelong,20000630");
+}
+
+static void
+run (const gchar      *name,
+     gint              nparams,
+     const GimpParam  *param,
+     gint             *nreturn_vals,
+     GimpParam       **return_vals)
+{
+  static GimpParam  values[2];
+  GimpRunMode       run_mode;
+  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
+  gint32            image_ID;
+  GError           *error  = NULL;
+
+  INIT_I18N ();
+  gegl_init (NULL, NULL);
+
+  *nreturn_vals = 1;
+  *return_vals  = values;
+
+  values[0].type          = GIMP_PDB_STATUS;
+  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
+
+  if (strcmp (name, LOAD_PROC) == 0)
+    {
+      run_mode = param[0].data.d_int32;
+
+      image_ID = load_image (param[1].data.d_string,
+                             run_mode == GIMP_RUN_INTERACTIVE, &error);
+
+      if (image_ID != -1)
+        {
+          *nreturn_vals = 2;
+          values[1].type = GIMP_PDB_IMAGE;
+          values[1].data.d_image = image_ID;
+        }
+      else
+        {
+          status = GIMP_PDB_EXECUTION_ERROR;
+        }
+    }
+  else
+    {
+      status = GIMP_PDB_CALLING_ERROR;
+    }
+
+  if (status != GIMP_PDB_SUCCESS && error)
+    {
+      *nreturn_vals = 2;
+      values[1].type          = GIMP_PDB_STRING;
+      values[1].data.d_string = error->message;
+    }
+
+  values[0].data.d_status = status;
+}
+
+static gint32
+load_image (const gchar  *filename,
+            gboolean      interactive,
+            GError      **error)
+{
+  gint32 status = -1;
+  EXRLoader *loader;
+  int width;
+  int height;
+  gboolean has_alpha;
+  GimpImageBaseType image_type;
+  GimpPrecision image_precision;
+  gint32 image = -1;
+  GimpImageType layer_type;
+  int layer;
+  const Babl *format;
+  GeglBuffer *buffer = NULL;
+  int bpp;
+  int tile_height;
+  gchar *pixels = NULL;
+  int begin;
+  int end;
+  int num;
+
+  loader = exr_loader_new (filename);
+  if (!loader)
+    {
+      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                   _("Error opening file '%s' for reading"),
+                   gimp_filename_to_utf8 (filename));
+      goto out;
+    }
+
+  width = exr_loader_get_width (loader);
+  height = exr_loader_get_height (loader);
+  if ((width < 1) || (height < 1))
+    {
+      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                   _("Error querying image dimensions from '%s'"),
+                   gimp_filename_to_utf8 (filename));
+      goto out;
+    }
+
+  has_alpha = exr_loader_has_alpha (loader) ? TRUE : FALSE;
+
+  switch (exr_loader_get_precision (loader))
+    {
+    case PREC_UINT:
+      image_precision = GIMP_PRECISION_U32;
+      break;
+    case PREC_HALF:
+      image_precision = GIMP_PRECISION_HALF;
+      break;
+    case PREC_FLOAT:
+      image_precision = GIMP_PRECISION_FLOAT;
+      break;
+    default:
+      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                   _("Error querying image precision from '%s'"),
+                   gimp_filename_to_utf8 (filename));
+      goto out;
+    }
+
+  switch (exr_loader_get_image_type (loader))
+    {
+    case IMAGE_TYPE_RGB:
+      image_type = GIMP_RGB;
+      layer_type = has_alpha ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
+      break;
+    case IMAGE_TYPE_GRAY:
+      image_precision = GIMP_GRAY;
+      layer_type = has_alpha ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
+      break;
+    default:
+      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                   _("Error querying image type from '%s'"),
+                   gimp_filename_to_utf8 (filename));
+      goto out;
+    }
+
+  gimp_progress_init_printf (_("Opening '%s'"),
+                             gimp_filename_to_utf8 (filename));
+
+  image = gimp_image_new_with_precision (width, height,
+                                         image_type, image_precision);
+  if (image == -1)
+    {
+      g_set_error (error, 0, 0,
+                   _("Could not create new image for '%s': %s"),
+                   gimp_filename_to_utf8 (filename), gimp_get_pdb_error ());
+      goto out;
+    }
+
+  gimp_image_set_filename (image, filename);
+
+  layer = gimp_layer_new (image, _("Background"), width, height,
+                          layer_type, 100, GIMP_NORMAL_MODE);
+  gimp_image_insert_layer (image, layer, -1, 0);
+
+  buffer = gimp_drawable_get_buffer (layer);
+  format = gimp_drawable_get_format (layer);
+  bpp = babl_format_get_bytes_per_pixel (format);
+
+  tile_height = gimp_tile_height ();
+  pixels = g_new0 (gchar, tile_height * width * bpp);
+
+  for (begin = 0; begin < height; begin += tile_height)
+    {
+      int retval;
+      int i;
+      end = MIN (begin + tile_height, height);
+      num = end - begin;
+
+      for (i = 0; i < num; i++)
+        {
+          retval = exr_loader_read_pixel_row (loader,
+                                              pixels + (i * width * bpp),
+                                              bpp, begin + i);
+          if (retval < 0)
+            {
+              g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                           _("Error reading pixel data from '%s'"),
+                           gimp_filename_to_utf8 (filename));
+              goto out;
+            }
+        }
+
+      gegl_buffer_set (buffer, GEGL_RECTANGLE (0, begin, width, num),
+                       0, NULL, pixels, GEGL_AUTO_ROWSTRIDE);
+
+      gimp_progress_update ((gdouble) begin / (gdouble) height);
+    }
+
+  gimp_progress_update (1.0);
+
+  status = image;
+
+ out:
+  if (buffer)
+    g_object_unref (buffer);
+
+  if ((status != image) && (image != -1))
+    {
+      /* This should clean up any associated layers too. */
+      gimp_image_delete (image);
+    }
+
+  if (pixels)
+    g_free (pixels);
+
+  exr_loader_unref (loader);
+
+  return status;
+}
diff --git a/plug-ins/file-exr/openexr-wrapper.cc b/plug-ins/file-exr/openexr-wrapper.cc
new file mode 100644
index 0000000..3be6e2c
--- /dev/null
+++ b/plug-ins/file-exr/openexr-wrapper.cc
@@ -0,0 +1,283 @@
+#include "config.h"
+
+#include "openexr-wrapper.h"
+
+#include <ImfInputFile.h>
+#include <ImfChannelList.h>
+#include <ImfRgbaFile.h>
+#include <ImfRgbaYca.h>
+#include <ImfStandardAttributes.h>
+
+#include <string>
+
+using namespace Imf;
+using namespace Imf::RgbaYca;
+using namespace Imath;
+
+struct _EXRLoader
+{
+  _EXRLoader(const char* filename) :
+    refcount_(1),
+    file_(filename),
+    data_window_(file_.header().dataWindow()),
+    channels_(file_.header().channels())
+  {
+    const Channel* chan;
+
+    if (channels_.findChannel("R") ||
+        channels_.findChannel("G") ||
+        channels_.findChannel("B"))
+      {
+        format_string_ = "RGB";
+        image_type_ = IMAGE_TYPE_RGB;
+
+        if ((chan = channels_.findChannel("R")))
+          pt_ = chan->type;
+        else if ((chan = channels_.findChannel("G")))
+          pt_ = chan->type;
+        else
+          pt_ = channels_.findChannel("B")->type;
+      }
+    else if (channels_.findChannel("Y") &&
+             (channels_.findChannel("RY") ||
+              channels_.findChannel("BY")))
+      {
+        format_string_ = "RGB";
+        image_type_ = IMAGE_TYPE_RGB;
+
+        pt_ = channels_.findChannel("Y")->type;
+
+        // FIXME: no chroma handling for now.
+        throw;
+      }
+    else if (channels_.findChannel("Y"))
+      {
+        format_string_ = "Y";
+        image_type_ = IMAGE_TYPE_GRAY;
+
+        pt_ = channels_.findChannel("Y")->type;
+      }
+    else
+      {
+        throw;
+      }
+
+    if (channels_.findChannel("A"))
+      {
+        format_string_.append("A");
+        has_alpha_ = true;
+      }
+    else
+      {
+        has_alpha_ = false;
+      }
+
+    switch (pt_)
+      {
+      case UINT:
+        format_string_.append(" u32");
+        bpc_ = 4;
+        break;
+      case HALF:
+        format_string_.append(" half");
+        bpc_ = 2;
+        break;
+      case FLOAT:
+      default:
+        format_string_.append(" float");
+        bpc_ = 4;
+      }
+  }
+
+  int readPixelRow(char* pixels,
+                   int bpp,
+                   int row)
+  {
+    const int actual_row = data_window_.min.y + row;
+    FrameBuffer fb;
+    // This is necessary because OpenEXR expects the buffer to begin at
+    // (0, 0). Though it probably results in some unmapped address,
+    // hopefully OpenEXR will not make use of it. :/
+    char* base = pixels - (data_window_.min.x * bpp);
+
+    switch (image_type_)
+      {
+      case IMAGE_TYPE_GRAY:
+        fb.insert("Y", Slice(pt_, base, bpp, 0, 1, 1, 0.5));
+        if (hasAlpha())
+          {
+            fb.insert("A", Slice(pt_, base + bpc_, bpp, 0, 1, 1, 1.0));
+          }
+        break;
+
+      case IMAGE_TYPE_RGB:
+      default:
+        fb.insert("R", Slice(pt_, base + (bpc_ * 0), bpp, 0, 1, 1, 0.0));
+        fb.insert("G", Slice(pt_, base + (bpc_ * 1), bpp, 0, 1, 1, 0.0));
+        fb.insert("B", Slice(pt_, base + (bpc_ * 2), bpp, 0, 1, 1, 0.0));
+        if (hasAlpha())
+          {
+            fb.insert("A", Slice(pt_, base + (bpc_ * 3), bpp, 0, 1, 1, 1.0));
+          }
+      }
+
+    file_.setFrameBuffer(fb);
+    file_.readPixels(actual_row);
+
+    return 0;
+  }
+
+  int getWidth() const {
+    return data_window_.max.x - data_window_.min.x + 1;
+  }
+
+  int getHeight() const {
+    return data_window_.max.y - data_window_.min.y + 1;
+  }
+
+  EXRPrecision getPrecision() const {
+    EXRPrecision prec;
+
+    switch (pt_)
+      {
+      case UINT:
+        prec = PREC_UINT;
+        break;
+      case HALF:
+        prec = PREC_HALF;
+        break;
+      case FLOAT:
+      default:
+        prec = PREC_FLOAT;
+      }
+
+    return prec;
+  }
+
+  EXRImageType getImageType() const {
+    return image_type_;
+  }
+
+  int hasAlpha() const {
+    return has_alpha_ ? 1 : 0;
+  }
+
+  size_t refcount_;
+  InputFile file_;
+  const Box2i data_window_;
+  const ChannelList& channels_;
+  PixelType pt_;
+  int bpc_;
+  EXRImageType image_type_;
+  bool has_alpha_;
+  std::string format_string_;
+};
+
+EXRLoader*
+exr_loader_new (const char *filename)
+{
+  EXRLoader* file;
+
+  // Don't let any exceptions propagate to the C layer.
+  try
+    {
+      file = new EXRLoader(filename);
+    }
+  catch (...)
+    {
+      file = NULL;
+    }
+
+  return file;
+}
+
+EXRLoader*
+exr_loader_ref (EXRLoader *loader)
+{
+  ++loader->refcount_;
+  return loader;
+}
+
+void
+exr_loader_unref (EXRLoader *loader)
+{
+  if (--loader->refcount_ == 0)
+    {
+      delete loader;
+    }
+}
+
+int
+exr_loader_get_width (EXRLoader *loader)
+{
+  int width;
+  // Don't let any exceptions propagate to the C layer.
+  try
+    {
+      width = loader->getWidth();
+    }
+  catch (...)
+    {
+      width = -1;
+    }
+
+  return width;
+}
+
+int
+exr_loader_get_height (EXRLoader *loader)
+{
+  int height;
+  // Don't let any exceptions propagate to the C layer.
+  try
+    {
+      height = loader->getHeight();
+    }
+  catch (...)
+    {
+      height = -1;
+    }
+
+  return height;
+}
+
+EXRImageType
+exr_loader_get_image_type (EXRLoader *loader)
+{
+  // This does not throw.
+  return loader->getImageType();
+}
+
+EXRPrecision
+exr_loader_get_precision (EXRLoader *loader)
+{
+  // This does not throw.
+  return loader->getPrecision();
+}
+
+int
+exr_loader_has_alpha (EXRLoader *loader)
+{
+  // This does not throw.
+  return loader->hasAlpha();
+}
+
+int
+exr_loader_read_pixel_row (EXRLoader *loader,
+                           char *pixels,
+                           int bpp,
+                           int row)
+{
+  int retval = -1;
+  // Don't let any exceptions propagate to the C layer.
+  try
+    {
+      retval = loader->readPixelRow(pixels, bpp, row);
+    }
+  catch (...)
+    {
+      retval = -1;
+    }
+
+  return retval;
+}
diff --git a/plug-ins/file-exr/openexr-wrapper.h b/plug-ins/file-exr/openexr-wrapper.h
new file mode 100644
index 0000000..3827607
--- /dev/null
+++ b/plug-ins/file-exr/openexr-wrapper.h
@@ -0,0 +1,61 @@
+#ifndef OPENEXR_WRAPPER_H
+#define OPENEXR_WRAPPER_H
+
+/* Use C linkage so that the plug-in code written in C can use the
+ * wrapper.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This is fully opaque on purpose, as the calling C code must not be
+ * exposed to more than this.
+ */
+typedef struct _EXRLoader EXRLoader;
+
+typedef enum {
+  PREC_UINT,
+  PREC_HALF,
+  PREC_FLOAT
+} EXRPrecision;
+
+typedef enum {
+  IMAGE_TYPE_RGB,
+  IMAGE_TYPE_GRAY
+} EXRImageType;
+
+EXRLoader *
+exr_loader_new (const char *filename);
+
+EXRLoader *
+exr_loader_ref (EXRLoader *loader);
+
+void
+exr_loader_unref (EXRLoader *loader);
+
+int
+exr_loader_get_width (EXRLoader *loader);
+
+int
+exr_loader_get_height (EXRLoader *loader);
+
+EXRPrecision
+exr_loader_get_precision (EXRLoader *loader);
+
+EXRImageType
+exr_loader_get_image_type (EXRLoader *loader);
+
+int
+exr_loader_has_alpha (EXRLoader *loader);
+
+int
+exr_loader_read_pixel_row (EXRLoader *loader,
+                           char *pixels,
+                           int bpp,
+                           int row);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPENEXR_WRAPPER_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]