diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-02-05 18:23:53 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-02-05 18:26:16 +0300 |
commit | cfc0790a459a710fcb4328b399d9d1f2dd3aab0d (patch) | |
tree | 2d98589a599249591565cf9bc5e8c458a87879ee /source/blender/blenkernel/intern/movieclip.c | |
parent | 7a2a08e0cd967554c7ec6fee36805921e2e28228 (diff) |
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.
Diffstat (limited to 'source/blender/blenkernel/intern/movieclip.c')
-rw-r--r-- | source/blender/blenkernel/intern/movieclip.c | 79 |
1 files changed, 77 insertions, 2 deletions
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 |