diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc index fa07199c356..115e8386629 100644 --- a/source/blender/blenkernel/intern/image_save.cc +++ b/source/blender/blenkernel/intern/image_save.cc @@ -813,7 +813,7 @@ bool BKE_image_render_write_exr(ReportList *reports, /* We only store RGBA passes as half float, for * others precision loss can be problematic. */ - const bool pass_RGBA = STR_ELEM(rp->chan_id, "RGB", "RGBA", "R", "G", "B", "A"); + const bool pass_RGBA = RE_RenderPassIsColor(rp); const bool pass_half_float = half_float && pass_RGBA; /* Color-space conversion only happens on RGBA passes. */ diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h index b07f8868db5..88af53e3ab2 100644 --- a/source/blender/render/RE_pipeline.h +++ b/source/blender/render/RE_pipeline.h @@ -502,6 +502,9 @@ RenderResult *RE_DuplicateRenderResult(RenderResult *rr); struct ImBuf *RE_RenderPassEnsureImBuf(RenderPass *render_pass); struct ImBuf *RE_RenderViewEnsureImBuf(const RenderResult *render_result, RenderView *render_view); +/* Returns true if the pass is a color (as opposite of data) and needs to be color managed. */ +bool RE_RenderPassIsColor(const RenderPass *render_pass); + #ifdef __cplusplus } #endif diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc index 5e70e2a4186..a14957a3bdd 100644 --- a/source/blender/render/intern/render_result.cc +++ b/source/blender/render/intern/render_result.cc @@ -167,6 +167,31 @@ void render_result_views_shallowdelete(RenderResult *rr) /** \name New * \{ */ +static int get_num_planes_for_pass_ibuf(const RenderPass &render_pass) +{ + switch (render_pass.channels) { + case 1: + return R_IMF_PLANES_BW; + case 3: + return R_IMF_PLANES_RGB; + case 4: + return R_IMF_PLANES_RGBA; + } + + /* Fallback to a commonly used default value of planes for odd-ball number of channel. */ + return R_IMF_PLANES_RGBA; +} + +static void assign_render_pass_ibuf_colorspace(RenderPass &render_pass) +{ + if (RE_RenderPassIsColor(&render_pass)) { + return; + } + + const char *data_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA); + IMB_colormanagement_assign_float_colorspace(render_pass.ibuf, data_colorspace); +} + static void render_layer_allocate_pass(RenderResult *rr, RenderPass *rp) { if (rp->ibuf && rp->ibuf->float_buffer.data) { @@ -179,9 +204,10 @@ static void render_layer_allocate_pass(RenderResult *rr, RenderPass *rp) const size_t rectsize = size_t(rr->rectx) * rr->recty * rp->channels; float *buffer_data = MEM_cnew_array(rectsize, rp->name); - rp->ibuf = IMB_allocImBuf(rr->rectx, rr->recty, 32, 0); + rp->ibuf = IMB_allocImBuf(rr->rectx, rr->recty, get_num_planes_for_pass_ibuf(*rp), 0); rp->ibuf->channels = rp->channels; IMB_assign_float_buffer(rp->ibuf, buffer_data, IB_TAKE_OWNERSHIP); + assign_render_pass_ibuf_colorspace(*rp); if (STREQ(rp->name, RE_PASSNAME_VECTOR)) { /* initialize to max speed */ @@ -680,6 +706,7 @@ RenderResult *render_result_new_from_exr( RenderResult *rr = MEM_cnew(__func__); const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get( COLOR_ROLE_SCENE_LINEAR); + const char *data_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA); rr->rectx = rectx; rr->recty = recty; @@ -696,7 +723,7 @@ RenderResult *render_result_new_from_exr( rpass->rectx = rectx; rpass->recty = recty; - if (rpass->channels >= 3) { + if (RE_RenderPassIsColor(rpass)) { IMB_colormanagement_transform(rpass->ibuf->float_buffer.data, rpass->rectx, rpass->recty, @@ -705,6 +732,9 @@ RenderResult *render_result_new_from_exr( to_colorspace, predivide); } + else { + IMB_colormanagement_assign_float_colorspace(rpass->ibuf, data_colorspace); + } } } @@ -1302,8 +1332,10 @@ RenderResult *RE_DuplicateRenderResult(RenderResult *rr) ImBuf *RE_RenderPassEnsureImBuf(RenderPass *render_pass) { if (!render_pass->ibuf) { - render_pass->ibuf = IMB_allocImBuf(render_pass->rectx, render_pass->recty, 32, 0); + render_pass->ibuf = IMB_allocImBuf( + render_pass->rectx, render_pass->recty, get_num_planes_for_pass_ibuf(*render_pass), 0); render_pass->ibuf->channels = render_pass->channels; + assign_render_pass_ibuf_colorspace(*render_pass); } return render_pass->ibuf; @@ -1318,4 +1350,9 @@ ImBuf *RE_RenderViewEnsureImBuf(const RenderResult *render_result, RenderView *r return render_view->ibuf; } +bool RE_RenderPassIsColor(const RenderPass *render_pass) +{ + return STR_ELEM(render_pass->chan_id, "RGB", "RGBA", "R", "G", "B", "A"); +} + /** \} */