[Bf-blender-cvs] [fd5ee4d] multiview: Support for saving singlelayer multiview openexr from Image Editor

Dalai Felinto noreply at git.blender.org
Wed Sep 17 14:12:38 CEST 2014


Commit: fd5ee4dd18891d39375722bafce43d7a8874e699
Author: Dalai Felinto
Date:   Tue Sep 16 17:44:37 2014 +0200
Branches: multiview
https://developer.blender.org/rBfd5ee4dd18891d39375722bafce43d7a8874e699

Support for saving singlelayer multiview openexr from Image Editor

Note, this approach could be generalized to any multiview format, but at
the moment only OpenExr supports that.

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

M	source/blender/blenkernel/BKE_image.h
M	source/blender/blenkernel/intern/image.c
M	source/blender/editors/space_image/image_ops.c
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

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

diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 629cd4d..4575a1f 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -216,7 +216,10 @@ bool BKE_image_is_openexr(struct Image *ima);
 
 /* for multiple slot render, call this before render */
 void BKE_image_backup_render(struct Scene *scene, struct Image *ima);
-	
+
+/* for singlelayer openexr saving */
+bool BKE_image_save_openexr_multiview(struct Image *ima, struct ImBuf *ibuf, const char *filepath, const int flags);
+
 /* goes over all textures that use images */
 void    BKE_image_free_all_textures(void);
 
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 5ca7b1d..938e316 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -100,6 +100,7 @@ static SpinLock image_spin;
 
 /* prototypes */
 static size_t image_num_files(struct Image *ima);
+static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r);
 
 /* max int, to indicate we don't store sequences in ibuf */
 #define IMA_NO_INDEX    0x7FEFEFEF
@@ -2683,7 +2684,17 @@ void BKE_image_multiview_index(Image *ima, ImageUser *iuser)
 {
 	if (iuser) {
 		bool is_stereo = (ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO);
-		iuser->multi_index = is_stereo ? iuser->eye : iuser->view;
+		if (is_stereo) {
+			iuser->multi_index = iuser->eye;
+		}
+		else {
+			if ((iuser->view < 0) || (iuser->view >= BLI_countlist(&ima->views))) {
+				iuser->multi_index = iuser->view = 0;
+			}
+			else {
+				iuser->multi_index = iuser->view;
+			}
+		}
 	}
 }
 
@@ -2786,6 +2797,43 @@ void BKE_image_backup_render(Scene *scene, Image *ima)
 	ima->last_render_slot = slot;
 }
 
+/**************************** multiview save openexr *********************************/
+static const char *image_get_view_cb(void *base, const size_t view_id)
+{
+	Image *ima = base;
+	ImageView *iv = BLI_findlink(&ima->views, view_id);
+	return iv ? iv->name : "";
+}
+
+static ImBuf *image_get_buffer_cb(void *base, const size_t view_id)
+{
+	Image *ima = base;
+	ImageUser iuser = {0};
+
+	iuser.view = view_id;
+	iuser.ok = 1;
+
+	BKE_image_multiview_index(ima, &iuser);
+
+	return image_acquire_ibuf(ima, &iuser, NULL);
+}
+
+bool BKE_image_save_openexr_multiview(Image *ima, ImBuf *ibuf, const char *filepath, const int flags)
+{
+	char name[FILE_MAX];
+	bool ok;
+
+	BLI_strncpy(name, filepath, sizeof(name));
+	BLI_path_abs(name, G.main->name);
+
+	ibuf->userdata = ima;
+	ok = IMB_exr_save_openexr_multiview(ibuf, name, flags, BLI_countlist(&ima->views), image_get_view_cb, image_get_buffer_cb);
+	ibuf->userdata = NULL;
+
+	return ok;
+}
+
+/**************************** multiview load openexr *********************************/
 static void image_add_view_cb(void *base, const char *str)
 {
 	Image *ima = base;
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 159ab47..c6ec9f5 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -73,6 +73,7 @@
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 #include "IMB_moviecache.h"
+#include "intern/openexr/openexr_multi.h"
 
 #include "RE_pipeline.h"
 
@@ -1776,6 +1777,12 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
 				ED_space_image_release_buffer(sima, ibuf, lock);
 			}
 		}
+		else if ((imf->imtype == R_IMF_IMTYPE_OPENEXR) && (simopts->im_format.views_format == R_IMF_VIEWS_MULTIVIEW)) {
+			/* treat special Openexr case separetely (this is the singlelayer multiview OpenEXR */
+			BKE_imbuf_prepare_write(ibuf, imf);
+			ok = BKE_image_save_openexr_multiview(ima, ibuf, simopts->filepath, (IB_rect | IB_zbuf | IB_zbuffloat | IB_multiview));
+			IMB_freeImBuf(ibuf);
+		}
 		/* stereo (multiview) images */
 		else if (simopts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
 			if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index ff6941b..adc9e28 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -112,7 +112,7 @@ typedef struct ImBuf {
 	int index;						/* reference index for ImBuf lists */
 	int	userflags;					/* used to set imbuf to dirty and other stuff */
 	struct ImMetaData *metadata;	/* image metadata */
-	void *userdata;					/* temporary storage, only used by baking at the moment */
+	void *userdata;					/* temporary storage */
 
 	/* file information */
 	int	ftype;							/* file type we are going to save as */
@@ -175,6 +175,7 @@ typedef struct ImBuf {
 #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)
+#define IB_multiview		(1 << 16)
 
 /*
  * 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 fce79ee..8d808aa 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -336,13 +336,21 @@ static void openexr_header_metadata(Header *header, struct ImBuf *ibuf)
 		addXDensity(*header, ibuf->ppm[0] / 39.3700787); /* 1 meter = 39.3700787 inches */
 }
 
-static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags)
+static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags, const size_t totviews,
+                                  const char * (*getview)(void *base, size_t view_id),
+                                  ImBuf * (*getbuffer)(void *base, const size_t view_id))
 {
 	const int channels = ibuf->channels;
 	const int is_alpha = (channels >= 4) && (ibuf->planes == 32);
 	const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
 	const int width = ibuf->x;
 	const int height = ibuf->y;
+	const bool is_multiview = (flags & IB_multiview) && ibuf->userdata;
+
+	BLI_assert((!is_multiview) || (getview && getbuffer));
+
+	std::vector <string> views;
+	size_t view_id;
 
 	try
 	{
@@ -351,13 +359,22 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags
 		openexr_header_compression(&header, ibuf->ftype & OPENEXR_COMPRESS);
 		openexr_header_metadata(&header, ibuf);
 
-		header.channels().insert("R", Channel(HALF));
-		header.channels().insert("G", Channel(HALF));
-		header.channels().insert("B", Channel(HALF));
-		if (is_alpha)
-			header.channels().insert("A", Channel(HALF));
-		if (is_zbuf)     // z we do as float always
-			header.channels().insert("Z", Channel(Imf::FLOAT));
+		/* create views when possible */
+		for (view_id = 0; view_id < totviews; view_id ++)
+			views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : "");
+
+		if (is_multiview)
+			addMultiView(header, views);
+
+		for (view_id = 0; view_id < totviews; view_id ++) {
+			header.channels().insert(insertViewName("R", views, view_id), Channel(HALF));
+			header.channels().insert(insertViewName("G", views, view_id), Channel(HALF));
+			header.channels().insert(insertViewName("B", views, view_id), Channel(HALF));
+			if (is_alpha)
+				header.channels().insert(insertViewName("A", views, view_id), Channel(HALF));
+			if (is_zbuf)     // z we do as float always
+				header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT));
+		}
 
 		FrameBuffer frameBuffer;
 
@@ -366,52 +383,60 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags
 		OutputFile file(file_stream, header);
 
 		/* we store first everything in half array */
-		RGBAZ *pixels = new RGBAZ[height * width];
-		RGBAZ *to = pixels;
+		RGBAZ *pixels = new RGBAZ[height * width * totviews];
 		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));
-		if (is_alpha)
-			frameBuffer.insert("A", Slice(HALF, (char *) &pixels[0].a, xstride, ystride));
-		if (is_zbuf)
-			frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)(ibuf->zbuf_float + (height - 1) * width),
-			                              sizeof(float), sizeof(float) * -width));
-		if (ibuf->rect_float) {
-			float *from;
-
-			for (int i = ibuf->y - 1; i >= 0; i--) {
-				from = ibuf->rect_float + channels * i * width;
-
-				for (int j = ibuf->x; j > 0; j--) {
-					to->r = from[0];
-					to->g = (channels >= 2) ? from[1] : from[0];
-					to->b = (channels >= 3) ? from[2] : from[0];
-					to->a = (channels >= 4) ? from[3] : 1.0f;
-					to++; from += channels;
+		for (view_id = 0; view_id < totviews; view_id ++) {
+			ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf;
+			const size_t offset = view_id * width * height;
+			RGBAZ *to = pixels + offset;
+
+			/* indicate used buffers */
+			frameBuffer.insert(insertViewName("R", views, view_id), Slice(HALF,  (char *) &pixels[offset].r, xstride, ystride));
+			frameBuffer.insert(insertViewName("G", views, view_id), Slice(HALF,  (char *) &pixels[offset].g, xstride, ystride));
+			frameBuffer.insert(insertViewName("B", views, view_id), Slice(HALF,  (char *) &pixels[offset].b, xstride, ystride));
+			if (is_alpha)
+				frameBuffer.insert(insertViewName("A", views, view_id), Slice(HALF, (char *) &pixels[offset].a, xstride, ystride));
+			if (is_zbuf)
+				frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *)(view_ibuf->zbuf_float + (height - 1) * width),
+				                   sizeof(float), sizeof(float) * -width));
+			if (view_ibuf->rect_float) {
+				float *from;
+
+				for (int i = view_ibuf->y - 1; i >= 0; i--) {
+					from = view_ibuf->rect_float + channels * i * width;
+
+					for (int j = view_ibuf->x; j > 0; j--) {
+						to->r 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list