Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2006-01-09 03:40:35 +0300
committerTon Roosendaal <ton@blender.org>2006-01-09 03:40:35 +0300
commit014aa7261e29810b35b3d65c759f9d255bf8a277 (patch)
tree360325f8db9431bdd187c0f0e7f7c40dcaa3a073 /source/blender/imbuf/intern/openexr
parent104ab9b103ab30ca87ccb9e739a58863fc29d3bf (diff)
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to Austin Benesh for bringing it further. Kent Mein provided a lot of code for integrating float buffers in Blender imbuf and ImBuf API cleanup, and provided Make and Scons and static linking. At this moment; the EXR libraries are a *dependency*, so you cannot get the Orange branch compiled without having OpenEXR installed. Get the (precompiled or sources) stuff from www.openexr.com. Current default is that the headers and lib resides in /user/local/ Several changes/additions/fixes were added: - EXR code only supported 'half' format (16 bits per channel). I've added float writing, but for reading it I need tomorrow. :) - Quite some clumsy copying of data happened in EXR code. - cleaned up the api calls already a bit, preparing for more advanced support - Zbuffers were saved 16 bits, now 32 bits - automatic adding of .exr extensions went wrong Imbuf: - added proper imbuf->flags and imbuf->mall support for float buffers, it was created for *each* imbuf. :) - found bugs for float buffers in scaling and flipping. Code there will need more checks still - imbuf also needs to be verified to behave properly when no 32 bits rect exists (for saving for example) TODO: - support internal float images for textures, backbuf, AO probes, and display in Image window Hope this commit won't screwup syncing with bf-blender... :/
Diffstat (limited to 'source/blender/imbuf/intern/openexr')
-rw-r--r--source/blender/imbuf/intern/openexr/Makefile51
-rw-r--r--source/blender/imbuf/intern/openexr/SConscript22
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp441
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.h63
4 files changed, 577 insertions, 0 deletions
diff --git a/source/blender/imbuf/intern/openexr/Makefile b/source/blender/imbuf/intern/openexr/Makefile
new file mode 100644
index 00000000000..48abc4c4331
--- /dev/null
+++ b/source/blender/imbuf/intern/openexr/Makefile
@@ -0,0 +1,51 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# 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 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Gernot Ziegler <gz@lysator.liu.se>
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = openexr
+DIR = $(OCGDIR)/blender/imbuf/openexr
+
+include nan_compile.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I../../../makesdna
+CPPFLAGS += -I../../../blenkernel
+CPPFLAGS += -I../../../blenlib
+CPPFLAGS += -I../../../imbuf
+CPPFLAGS += -I../../../imbuf/intern
+CPPFLAGS += $(NAN_OPENEXR_INC)
+CPPFLAGS += -I.
diff --git a/source/blender/imbuf/intern/openexr/SConscript b/source/blender/imbuf/intern/openexr/SConscript
new file mode 100644
index 00000000000..ee834669b04
--- /dev/null
+++ b/source/blender/imbuf/intern/openexr/SConscript
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+Import ('extra_includes')
+Import ('user_options_dict')
+Import ('library_env')
+
+openexr_env = library_env.Copy ()
+
+source_files = ['openexr_api.cpp'
+ ]
+
+include_paths = ['.',
+ '../blenkernel',
+ '../imbuf',
+ '../imbuf/intern',
+ '../blenlib',
+ '../makesdna']
+
+openexr_env.Append(CPPPATH = extra_includes)
+openexr_env.Append(CPPPATH = include_paths)
+openexr_env.Prepend (CPPPATH = user_options_dict['OPENEXR_INCLUDE'])
+#ftf_env.Append(CPPDEFINES = 'FTGL_STATIC_LIBRARY')
+openexr_env.Library (target='#'+user_options_dict['BUILD_DIR']+'/lib/blender_openexr', source=source_files)
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
new file mode 100644
index 00000000000..86beab537ef
--- /dev/null
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -0,0 +1,441 @@
+/**
+*
+ * ***** BEGIN GPLLICENSE BLOCK *****
+ *
+ * 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 2
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright by Gernot Ziegler <gz@lysator.liu.se>.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Austin Benesh, Ton Roosendaal (float, half, speedup, cleanup...).
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string>
+
+
+#include <openexr_api.h>
+
+extern "C"
+{
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "BKE_global.h"
+#include "DNA_scene_types.h"
+}
+
+#include <iostream>
+
+#include <OpenEXR/half.h>
+#include <OpenEXR/ImfVersion.h>
+#include <OpenEXR/ImathBox.h>
+#include <OpenEXR/ImfArray.h>
+#include <OpenEXR/ImfIO.h>
+#include <OpenEXR/ImfChannelList.h>
+#include <OpenEXR/ImfPixelType.h>
+#include <OpenEXR/ImfInputFile.h>
+#include <OpenEXR/ImfOutputFile.h>
+#include <OpenEXR/ImfCompression.h>
+#include <OpenEXR/ImfCompressionAttribute.h>
+
+using namespace Imf;
+using namespace Imath;
+
+class Mem_IStream: public IStream
+{
+public:
+
+ Mem_IStream (unsigned char *exrbuf, int exrsize):
+ IStream("dummy"), _exrpos (0), _exrsize(exrsize) { _exrbuf = exrbuf; }
+
+ virtual bool read (char c[], int n);
+ virtual Int64 tellg ();
+ virtual void seekg (Int64 pos);
+ virtual void clear ();
+ //virtual ~Mem_IStream() {}; // unused
+
+private:
+
+ Int64 _exrpos;
+ Int64 _exrsize;
+ unsigned char *_exrbuf;
+};
+
+bool Mem_IStream::read (char c[], int n)
+{
+ if (n + _exrpos <= _exrsize)
+ {
+ memcpy(c, (void *)(&_exrbuf[_exrpos]), n);
+ _exrpos += n;
+ return true;
+ }
+ else
+ return false;
+}
+
+Int64 Mem_IStream::tellg ()
+{
+ return _exrpos;
+}
+
+void Mem_IStream::seekg (Int64 pos)
+{
+ _exrpos = pos;
+}
+
+void Mem_IStream::clear ()
+{
+}
+
+struct _RGBAZ
+{
+ half r;
+ half g;
+ half b;
+ half a;
+ half z;
+};
+
+typedef struct _RGBAZ RGBAZ;
+
+extern "C"
+{
+
+int imb_is_a_openexr(unsigned char *mem)
+{
+ return Imf::isImfMagic ((const char *)mem);
+}
+
+static void openexr_header_compression(Header *header, int compression)
+{
+ switch(compression)
+ {
+ case 0:
+ header->compression() = NO_COMPRESSION;
+ break;
+ case 1:
+ header->compression() = PXR24_COMPRESSION;
+ break;
+ case 2:
+ header->compression() = ZIP_COMPRESSION;
+ break;
+ case 3:
+ header->compression() = PIZ_COMPRESSION;
+ break;
+ case 4:
+ header->compression() = RLE_COMPRESSION;
+ break;
+ default:
+ header->compression() = NO_COMPRESSION;
+ break;
+ }
+}
+
+short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags)
+{
+
+ int width = ibuf->x;
+ int height = ibuf->y;
+
+ if (flags & IB_mem)
+ {
+ printf("OpenEXR-save: Create EXR in memory CURRENTLY NOT SUPPORTED !\n");
+ imb_addencodedbufferImBuf(ibuf);
+ ibuf->encodedsize = 0;
+ return(0);
+ }
+
+ int write_zbuf = (flags & IB_zbuf) && ibuf->zbuf != NULL; // summarize
+
+ try
+ {
+ Header header (width, height);
+
+ openexr_header_compression(&header, G.scene->r.quality);
+
+ header.channels().insert ("R", Channel (HALF));
+ header.channels().insert ("G", Channel (HALF));
+ header.channels().insert ("B", Channel (HALF));
+ header.channels().insert ("A", Channel (HALF));
+ if (write_zbuf) // z we do as uint always
+ header.channels().insert ("Z", Channel (UINT));
+
+ FrameBuffer frameBuffer;
+ OutputFile *file = new OutputFile(name, header);
+
+ /* we store first everything in half array */
+ RGBAZ *pixels = new RGBAZ[height * width];
+ RGBAZ *to = pixels;
+ int xstride= sizeof (RGBAZ);
+ int ystride= xstride*width;
+
+ /* indicate used buffers */
+ frameBuffer.insert ("R", Slice (HALF, (char *) &pixels[0].r, xstride, ystride));
+ frameBuffer.insert ("G", Slice (HALF, (char *) &pixels[0].g, xstride, ystride));
+ frameBuffer.insert ("B", Slice (HALF, (char *) &pixels[0].b, xstride, ystride));
+ frameBuffer.insert ("A", Slice (HALF, (char *) &pixels[0].a, xstride, ystride));
+
+ if (write_zbuf)
+ frameBuffer.insert ("Z", Slice (UINT, (char *) ibuf->zbuf + 4*(height-1)*width,
+ sizeof(int), sizeof(int) * -width));
+ if(ibuf->rect_float) {
+ float *from;
+
+ for (int i = ibuf->y-1; i >= 0; i--)
+ {
+ from= ibuf->rect_float + 4*i*width;
+
+ for (int j = ibuf->x; j > 0; j--)
+ {
+ to->r = from[0];
+ to->g = from[1];
+ to->b = from[2];
+ to->a = from[3];
+ to++; from += 4;
+ }
+ }
+ }
+ else {
+ unsigned char *from;
+
+ for (int i = ibuf->y-1; i >= 0; i--)
+ {
+ from= (unsigned char *)(ibuf->rect + i*width);
+
+ for (int j = ibuf->x; j > 0; j--)
+ {
+ to->r = (float)(from[0])/255.0;
+ to->g = (float)(from[1])/255.0;
+ to->b = (float)(from[2])/255.0;
+ to->a = (float)(from[3])/255.0;
+ to++; from += 4;
+ }
+ }
+ }
+
+// printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height);
+
+ file->setFrameBuffer (frameBuffer);
+ file->writePixels (height);
+ delete file;
+ }
+ catch (const std::exception &exc)
+ {
+ printf("OpenEXR-save: ERROR: %s\n", exc.what());
+ if (ibuf) IMB_freeImBuf(ibuf);
+
+ return (0);
+ }
+
+ return (1);
+}
+
+short imb_save_openexr_float(struct ImBuf *ibuf, char *name, int flags)
+{
+
+ int width = ibuf->x;
+ int height = ibuf->y;
+
+ if (flags & IB_mem)
+ {
+ printf("OpenEXR-save: Create EXR in memory CURRENTLY NOT SUPPORTED !\n");
+ imb_addencodedbufferImBuf(ibuf);
+ ibuf->encodedsize = 0;
+ return(0);
+ }
+
+ if (ibuf->rect_float==NULL)
+ return(0);
+
+ int write_zbuf = (flags & IB_zbuf) && ibuf->zbuf != NULL; // summarize
+
+ try
+ {
+ Header header (width, height);
+
+ openexr_header_compression(&header, G.scene->r.quality);
+
+ header.channels().insert ("R", Channel (FLOAT));
+ header.channels().insert ("G", Channel (FLOAT));
+ header.channels().insert ("B", Channel (FLOAT));
+ header.channels().insert ("A", Channel (FLOAT));
+ if (write_zbuf)
+ header.channels().insert ("Z", Channel (UINT));
+
+ FrameBuffer frameBuffer;
+ OutputFile *file = new OutputFile(name, header);
+ float *first= ibuf->rect_float + 4*(height-1)*width;
+ int xstride = sizeof(float) * 4;
+ int ystride = - xstride*width;
+
+ frameBuffer.insert ("R", Slice (FLOAT, (char *) first, xstride, ystride));
+ frameBuffer.insert ("G", Slice (FLOAT, (char *) (first+1), xstride, ystride));
+ frameBuffer.insert ("B", Slice (FLOAT, (char *) (first+2), xstride, ystride));
+ frameBuffer.insert ("A", Slice (FLOAT, (char *) (first+3), xstride, ystride));
+
+ if (write_zbuf)
+ frameBuffer.insert ("Z", Slice (UINT, (char *) ibuf->zbuf + 4*(height-1)*width,
+ sizeof(int), sizeof(int) * -width));
+
+ file->setFrameBuffer (frameBuffer);
+ file->writePixels (height);
+ delete file;
+ }
+ catch (const std::exception &exc)
+ {
+ printf("OpenEXR-save: ERROR: %s\n", exc.what());
+ if (ibuf) IMB_freeImBuf(ibuf);
+
+ return (0);
+ }
+
+ return (1);
+ // printf("OpenEXR-save: Done.\n");
+}
+
+
+
+struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags)
+{
+ struct ImBuf *ibuf = 0;
+ InputFile *file = NULL;
+
+// printf("OpenEXR-load: testing input, size is %d\n", size);
+ if (imb_is_a_openexr(mem) == 0) return(NULL);
+
+ try
+ {
+// printf("OpenEXR-load: Creating InputFile from mem source\n");
+ Mem_IStream membuf(mem, size);
+ file = new InputFile(membuf);
+
+ Box2i dw = file->header().dataWindow();
+ int width = dw.max.x - dw.min.x + 1;
+ int height = dw.max.y - dw.min.y + 1;
+
+// printf("OpenEXR-load: image data window %d %d %d %d\n",
+// dw.min.x, dw.min.y, dw.max.x, dw.max.y);
+
+ const ChannelList &channels = file->header().channels();
+
+ for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i)
+ {
+ const Channel &channel = i.channel();
+// printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type);
+ if (channel.type != 1)
+ {
+ printf("OpenEXR-load: Can only process HALF input !!\n");
+ return(NULL);
+ }
+ }
+
+ RGBAZ *pixels = new RGBAZ[height * width];
+
+ FrameBuffer frameBuffer;
+
+ frameBuffer.insert ("R",
+ Slice (HALF,
+ (char *) &pixels[0].r,
+ sizeof (pixels[0]) * 1,
+ sizeof (pixels[0]) * width));
+
+ frameBuffer.insert ("G",
+ Slice (HALF,
+ (char *) &pixels[0].g,
+ sizeof (pixels[0]) * 1,
+ sizeof (pixels[0]) * width));
+
+ frameBuffer.insert ("B",
+ Slice (HALF,
+ (char *) &pixels[0].b,
+ sizeof (pixels[0]) * 1,
+ sizeof (pixels[0]) * width));
+
+ frameBuffer.insert ("A",
+ Slice (HALF,
+ (char *) &pixels[0].a,
+ sizeof (pixels[0]) * 1,
+ sizeof (pixels[0]) * width));
+
+ // FIXME ? Would be able to read Z data or other channels here !
+
+// printf("OpenEXR-load: Reading pixel data\n");
+ file->setFrameBuffer (frameBuffer);
+ file->readPixels (dw.min.y, dw.max.y);
+
+// printf("OpenEXR-load: Converting to Blender float ibuf\n");
+
+ int bytesperpixel = 4; // since OpenEXR fills in unknown channels
+ ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0, 0);
+
+ if (ibuf)
+ {
+ ibuf->ftype = OPENEXR;
+
+ imb_addrectImBuf(ibuf);
+ imb_addrectfloatImBuf(ibuf);
+
+ if (!(flags & IB_test))
+ {
+ unsigned char *to = (unsigned char *) ibuf->rect;
+ float *tof = ibuf->rect_float;
+ RGBAZ *from = pixels;
+ RGBAZ prescale;
+
+ for (int i = ibuf->x * ibuf->y; i > 0; i--)
+ {
+ to[0] = (unsigned char)(from->r > 1.0 ? 1.0 : (float)from->r) * 255;
+ to[1] = (unsigned char)(from->g > 1.0 ? 1.0 : (float)from->g) * 255;
+ to[2] = (unsigned char)(from->b > 1.0 ? 1.0 : (float)from->b) * 255;
+ to[3] = (unsigned char)(from->a > 1.0 ? 1.0 : (float)from->a) * 255;
+ to += 4;
+
+ tof[0] = from->r;
+ tof[1] = from->g;
+ tof[2] = from->b;
+ tof[3] = from->a;
+
+ from++;
+ }
+ }
+
+ IMB_flipy(ibuf);
+
+ }
+ else
+ printf("Couldn't allocate memory for OpenEXR image\n");
+
+// printf("OpenEXR-load: Done\n");
+
+ return(ibuf);
+ }
+ catch (const std::exception &exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ if (ibuf) IMB_freeImBuf(ibuf);
+
+ return (0);
+ }
+
+}
+
+} // export "C"
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h
new file mode 100644
index 00000000000..882b9d98a06
--- /dev/null
+++ b/source/blender/imbuf/intern/openexr/openexr_api.h
@@ -0,0 +1,63 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Austin Benesh.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef _OPENEXR_API_H
+#define _OPENEXR_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define OPENEXR_FLOATRGB 0x1
+#define OPENEXR_ZBUF 0x2
+
+#include <stdio.h>
+
+ /**
+ * Test presence of OpenEXR file.
+ * @param mem pointer to loaded OpenEXR bitstream
+ */
+
+int imb_is_a_openexr(unsigned char *mem);
+
+short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags);
+short imb_save_openexr_float(struct ImBuf *ibuf, char *name, int flags);
+
+struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif /* __OPENEXR_API_H */