mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
77087aba2d
commit
8d89efaff5
31
configure.ac
31
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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/Makefile.in
|
||||
/Makefile
|
||||
/.deps
|
||||
/_libs
|
||||
/.libs
|
||||
/file-exr
|
||||
/file-exr.exe
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
Loading…
Reference in New Issue