[Bf-blender-cvs] [cfc0790a459] master: Movieclip: Improve support of multilayer EXR files

Sergey Sharybin noreply at git.blender.org
Tue Feb 5 16:26:19 CET 2019


Commit: cfc0790a459a710fcb4328b399d9d1f2dd3aab0d
Author: Sergey Sharybin
Date:   Tue Feb 5 16:23:53 2019 +0100
Branches: master
https://developer.blender.org/rBcfc0790a459a710fcb4328b399d9d1f2dd3aab0d

Movieclip: Improve support of multilayer EXR files

Use first combined pass if possible. Is not ideal but better than
showing completely empty image.

Also, covers quite a lot of usecases when movie clip editor is
used to review animation render of single-layer renders but with
multiple passes.

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

M	source/blender/blenkernel/intern/movieclip.c

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

diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index fa3f3759e50..5d2616b7720 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -197,6 +197,82 @@ static void get_proxy_fname(const MovieClip *clip,
 	strcat(name, ".jpg");
 }
 
+typedef struct MultilayerConvertContext {
+	float *combined_pass;
+	int num_combined_channels;
+} MultilayerConvertContext;
+
+static void *movieclip_convert_multilayer_add_view(
+        void *UNUSED(ctx_v),
+        const char *UNUSED(view_name))
+{
+	return NULL;
+}
+
+static void *movieclip_convert_multilayer_add_layer(
+        void *ctx_v,
+        const char *UNUSED(layer_name))
+{
+	/* Return dummy non-NULL value, we don't use layer handle but need to return
+	 * something, so render API invokes the add_pass() callbacks. */
+	return ctx_v;
+}
+
+static void movieclip_convert_multilayer_add_pass(
+        void *UNUSED(layer),
+        void *ctx_v,
+        const char *pass_name,
+        float *rect,
+        int num_channels,
+        const char *chan_id,
+        const char *UNUSED(view_name))
+{
+	/* NOTE: This function must free pass pixels data if it is not used, this
+	 * is how IMB_exr_multilayer_convert() is working. */
+	MultilayerConvertContext *ctx = ctx_v;
+	/* If we've found a first combined pass, skip all the rest ones. */
+	if (ctx->combined_pass != NULL) {
+		MEM_freeN(rect);
+		return;
+	}
+	if (STREQ(pass_name, RE_PASSNAME_COMBINED) ||
+	    STREQ(chan_id, "RGBA") ||
+		STREQ(chan_id, "RGB"))
+	{
+		ctx->combined_pass = rect;
+		ctx->num_combined_channels = num_channels;
+	}
+	else {
+		MEM_freeN(rect);
+	}
+}
+
+/* Will try to make image buffer usable when originating from the multi-layer
+ * source.
+ * Internally finds a first combined pass and uses that as a buffer. Not ideal,
+ * but is better than a complete empty buffer. */
+static void movieclip_convert_multilayer(ImBuf *ibuf)
+{
+	MultilayerConvertContext ctx;
+	ctx.combined_pass = NULL;
+	ctx.num_combined_channels = 0;
+	IMB_exr_multilayer_convert(
+	        ibuf->userdata,
+	        &ctx,
+	        movieclip_convert_multilayer_add_view,
+	        movieclip_convert_multilayer_add_layer,
+	        movieclip_convert_multilayer_add_pass);
+	if (ctx.combined_pass != NULL) {
+		BLI_assert(ibuf->rect_float == NULL);
+		ibuf->rect_float = ctx.combined_pass;
+		ibuf->channels = ctx.num_combined_channels;
+		ibuf->flags |= IB_rectfloat;
+		ibuf->mall |= IB_rectfloat;
+	}
+	IMB_exr_close(ibuf->userdata);
+	ibuf->userdata = NULL;
+}
+
 static ImBuf *movieclip_load_sequence_file(MovieClip *clip,
                                            const MovieClipUser *user,
                                            int framenr,
@@ -238,8 +314,7 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip,
 #ifdef WITH_OPENEXR
 	if (ibuf) {
 		if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
-			IMB_exr_close(ibuf->userdata);
-			ibuf->userdata = NULL;
+			movieclip_convert_multilayer(ibuf);
 		}
 	}
 #endif



More information about the Bf-blender-cvs mailing list