[Bf-blender-cvs] [63d30c7] multiview: Multiview Base Commit 3/10: OpenEXR/Imbuf - support for MultiPart EXR

Dalai Felinto noreply at git.blender.org
Sat May 10 20:18:08 CEST 2014


Commit: 63d30c704dc61d0cb41097fa33ab3b51ee5ca99b
Author: Dalai Felinto
Date:   Sat May 10 14:58:04 2014 -0300
https://developer.blender.org/rB63d30c704dc61d0cb41097fa33ab3b51ee5ca99b

Multiview Base Commit 3/10: OpenEXR/Imbuf - support for MultiPart EXR

This is part of the multiview rebase from a github to git.blender.org
repository. The rebase was made based on file areas, so build is likely
broken in some of those parts, but it bulds fine in the end.

The documentation and sample files were removed and now live in:
https://github.com/dfelinto/multiview-samples

The original git history can be found in:
https://github.com/dfelinto/blender/tree/multiview-pre-b3d

Code contributors of the original branch in github:
* Alexey Akishin
* Gabriel Caraballo

Original design made in contribution with Francesco Siddi
Original branch and design partially reviewed by Brecht Van Lommel

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

M	source/blender/imbuf/IMB_imbuf_types.h
M	source/blender/imbuf/intern/openexr/openexr_api.cpp
M	source/blender/imbuf/intern/openexr/openexr_multi.h
M	source/blender/imbuf/intern/openexr/openexr_stub.cpp
M	source/blender/imbuf/intern/thumbs.c

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

diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 44cb7f1..ff6941b 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -174,6 +174,7 @@ typedef struct ImBuf {
 #define IB_alphamode_premul	(1 << 12)  /* indicates whether image on disk have premul alpha */
 #define IB_alphamode_detect	(1 << 13)  /* if this flag is set, alpha mode would be guessed from file */
 #define IB_ignore_alpha		(1 << 14)  /* ignore alpha on load and substitude it with 1.0f */
+#define IB_thumbnail		(1 << 15)
 
 /*
  * The bit flag is stored in the ImBuf.ftype variable.
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 401070c..2393b48 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -88,9 +88,27 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void)
 #include <ImfStringAttribute.h>
 #include <ImfStandardAttributes.h>
 
+/* multiview/multipart */
+#include <ImfMultiView.h>
+#include <ImfMultiPartInputFile.h>
+#include <ImfInputPart.h>
+#include <ImfOutputPart.h>
+#include <ImfMultiPartOutputFile.h>
+#include <ImfTiledOutputPart.h>
+#include <ImfPartType.h>
+#include <ImfPartHelper.h>
+
 using namespace Imf;
 using namespace Imath;
 
+extern "C"
+{
+/* prototype */
+static struct ExrPass *imb_exr_get_pass(ListBase *lb, char *passname);
+
+static void exr_printf(const char *__restrict format, ...);
+}
+
 /* Memory Input Stream */
 
 class Mem_IStream : public Imf::IStream
@@ -497,18 +515,22 @@ static ListBase exrhandles = {NULL, NULL};
 
 typedef struct ExrHandle {
 	struct ExrHandle *next, *prev;
+	char name[FILE_MAX];
 
 	IFileStream *ifile_stream;
-	InputFile *ifile;
+	MultiPartInputFile *ifile;
 
 	OFileStream *ofile_stream;
-	TiledOutputFile *tofile;
+	MultiPartOutputFile *mpofile;
 	OutputFile *ofile;
 
 	int tilex, tiley;
 	int width, height;
 	int mipmap;
 
+	StringVector *multiView; /* it needs to be a pointer due to Windows release builds of EXR2.0 segfault when opening EXR bug */
+	int parts;
+
 	ListBase channels;  /* flattened out, ExrChannel */
 	ListBase layers;    /* hierarchical, pointing in end to ExrChannel */
 } ExrHandle;
@@ -517,10 +539,12 @@ typedef struct ExrHandle {
 typedef struct ExrChannel {
 	struct ExrChannel *next, *prev;
 
-	char name[EXR_TOT_MAXNAME + 1];  /* full name of layer+pass */
+	char name[EXR_TOT_MAXNAME + 1];  /* full name with everything */
+	struct MultiViewChannelName *m;  /* struct to store all multipart channel info */
 	int xstride, ystride;            /* step to next pixel, to next scanline */
 	float *rect;                     /* first pointer to write in */
 	char chan_id;                    /* quick lookup of channel char */
+	int view_id;                     /* quick lookup of channel view */
 } ExrChannel;
 
 
@@ -532,6 +556,10 @@ typedef struct ExrPass {
 	float *rect;
 	struct ExrChannel *chan[EXR_PASS_MAXCHAN];
 	char chan_id[EXR_PASS_MAXCHAN];
+
+	char internal_name[EXR_PASS_MAXNAME]; /* name with no view */
+	char view[EXR_VIEW_MAXNAME];
+	int view_id;
 } ExrPass;
 
 typedef struct ExrLayer {
@@ -545,39 +573,183 @@ typedef struct ExrLayer {
 void *IMB_exr_get_handle(void)
 {
 	ExrHandle *data = (ExrHandle *)MEM_callocN(sizeof(ExrHandle), "exr handle");
+	data->multiView = new StringVector();
+
 	BLI_addtail(&exrhandles, data);
 	return data;
 }
 
+void *IMB_exr_get_handle_name(const char *name)
+{
+	ExrHandle *data = (ExrHandle *) BLI_rfindstring(&exrhandles, name, offsetof(ExrHandle, name));
+
+	if (data==NULL) {
+		data = (ExrHandle *)IMB_exr_get_handle();
+		BLI_strncpy(data->name, name, strlen(name)+1);
+	}
+	return data;
+}
+
+/* multiview functions */
+} // extern "C"
+static StringVector *imb_exr_multiView(void *handle)
+{
+	ExrHandle *data = (ExrHandle *)handle;
+	return data->multiView;
+}
+
+
+
+extern "C"
+{
+
+void IMB_exr_add_view(void *handle, const char *name)
+{
+	ExrHandle *data = (ExrHandle *)handle;
+	data->multiView->push_back(name);
+}
+
+void IMB_exr_get_multiView_name(void *handle, int view_id, char *view)
+{
+	StringVector *views = imb_exr_multiView(handle);
+	std::string retstr ( view_id >= views->size() ? "" : (*views)[view_id].c_str() );
+
+	BLI_strncpy(view, retstr.c_str(), sizeof(view));
+}
+
+int IMB_exr_get_multiView_count(void *handle)
+{
+	ExrHandle *data = (ExrHandle *) handle;
+	return data->multiView->size();
+}
+
+static int imb_exr_get_multiView_id(StringVector& views, const std::string& name)
+{
+	int count = 0;
+	for (StringVector::const_iterator i = views.begin(); count < views.size(); ++i) {
+		if (name == *i)
+			return count;
+		else
+			count ++;
+	}
+
+	/* no views or wrong name */
+	return -1;
+}
+
+static void imb_exr_get_views(MultiPartInputFile *file, StringVector& views)
+{
+	if(file->parts() == 1) {
+		if(hasMultiView(file->header(0))) {
+			StringVector sv = multiView(file->header(0));
+			for (StringVector::const_iterator i = sv.begin(); i != sv.end(); ++i)
+				views.push_back(*i);
+		}
+	}
+
+	else {
+		for(int p=0;p<file->parts();p++) {
+			std::string view="";
+			if(file->header(p).hasView())
+				view=file->header(p).view();
+
+			if (imb_exr_get_multiView_id(views, view) == -1)
+				views.push_back(view);
+		}
+	}
+}
+
+static const char *imb_exr_insert_view_name(const char* passname, const char* view)
+{
+	if (view == NULL || view[0] == '\0')
+		return passname;
+
+	static char retstr[EXR_PASS_MAXNAME];
+	const char *end = passname + strlen(passname);
+	const char *token;
+
+	int len = IMB_exr_split_token(passname, end, &token);
+
+	if (len == 0)
+		BLI_snprintf(retstr, sizeof(retstr), "%s.%s", passname, view);
+	else
+		BLI_snprintf(retstr, sizeof(retstr),  "%.*s%s.%s",
+					 (int)(end-passname) - len, passname, view, token);
+
+	return retstr;
+}
+
+/* from exrmultipart.cpp (OpenEXR source code) */
+static void imb_exr_make_unique_names (std::vector<Header> & headers)
+{
+	std::set<string> names;
+	for ( size_t i = 0 ; i < headers.size() ; i++ ) {
+		std::string base_name;
+		// if no name at all, set it to <type><partnum> (first part is part 1)
+		if (!headers[i].hasName()) {
+			std::ostringstream s;
+			s << headers[i].type() << (i + 1);
+			base_name = s.str();
+			headers[i].setName (base_name);
+		}
+		else {
+			base_name = headers[i].name();
+		}
+		// check name has already been used, if so add a _<number> to it
+		if (names.find (base_name) == names.end()) {
+			std::ostringstream s;
+			size_t backup=1;
+			do {
+				s.clear();
+				s << headers[i].type() << i << "_" << backup;
+				backup++;
+			}
+			while (names.find(s.str()) != names.end());
+			headers[i].setName (s.str());
+		}
+	}
+}
+
 /* adds flattened ExrChannels */
 /* xstride, ystride and rect can be done in set_channel too, for tile writing */
-void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect)
+/* passname does not include view */
+void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, const char *view, int xstride, int ystride, float *rect)
 {
 	ExrHandle *data = (ExrHandle *)handle;
 	ExrChannel *echan;
 
-	echan = (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr tile channel");
+	echan = (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr channel");
+	echan->m = new MultiViewChannelName ();
 
-	if (layname) {
-		char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1];
-		BLI_strncpy(lay, layname, EXR_LAY_MAXNAME);
-		BLI_strncpy(pass, passname, EXR_PASS_MAXNAME);
-
-		BLI_snprintf(echan->name, sizeof(echan->name), "%s.%s", lay, pass);
+	if (layname && layname[0] != '\0') {
+		echan->m->name = layname;
+		echan->m->name.append(".");
+		echan->m->name.append(passname);
 	}
 	else {
-		BLI_strncpy(echan->name, passname, EXR_TOT_MAXNAME - 1);
+		echan->m->name.assign(passname);
 	}
 
+	echan->m->internal_name = echan->m->name;
+
+	echan->m->view.assign(view ? view : "");
+
+	/* name has to be unique, thus it's a combination of layer, pass, view, and channel */
+	std::string raw_name = imb_exr_insert_view_name(echan->m->name.c_str(), echan->m->view.c_str());
+	BLI_strncpy(echan->name, raw_name.c_str(), EXR_TOT_MAXNAME - raw_name.size());
+
 	echan->xstride = xstride;
 	echan->ystride = ystride;
 	echan->rect = rect;
 
-	// printf("added channel %s\n", echan->name);
+	/* quick look up */
+	echan->view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, echan->m->view));
+
+	exr_printf("added channel %s\n", echan->name);
 	BLI_addtail(&data->channels, echan);
 }
 
-/* only used for writing temp. render results (not image files) */
+/* used for mono view output files (single and multilayer) */
 int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress)
 {
 	ExrHandle *data = (ExrHandle *)handle;
@@ -615,10 +787,13 @@ int IMB_exr_begin_write(void *handle, const char *filename, int width, int heigh
 	return (data->ofile != NULL);
 }
 
+/* only used for writing temp. render results (not image files)
+ * (FSA and Save Buffers) */
 void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley)
 {
 	ExrHandle *data = (ExrHandle *)handle;
 	Header header(width, height);
+	std::vector<Header> headers;
 	ExrChannel *echan;
 
 	data->tilex = tilex;
@@ -627,40 +802,192 @@ void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int
 	data->height = height;
 	data->mipmap = mipmap;
 
-	for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next)
-		header.channels().insert(echan->name, Channel(Imf::FLOAT));
-
 	header.setTileDescription(TileDescription(tilex, tiley, (mipmap) ? MIPMAP_LEVELS : ONE_LEVEL));
-	header.lineOrder() = RANDOM_Y;
 	header.compression() = RLE_COMPRESSION;
+	header.setType(TILEDIMAGE);
 
 	header.insert("BlenderMultiChannel", StringAttribute("Blender V2.43"));
 
+	int numparts = data->multiView->size();
+
+	/* copy header from all parts of input to our header array
+	 * those temporary files have one part per view */
+	for (int i = 0; i < numparts; i++)
+	{
+		headers.push_back (header);
+		

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list