/* called from within UI, saves both rendered result as a file-read result */ int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress) { RenderLayer *rl; RenderPass *rpass; void *exrhandle = IMB_exr_get_handle(); int success; BLI_make_existing_file(filename); /* composite result */ if (rr->rectf) { IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4 * rr->rectx, rr->rectf); IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4 * rr->rectx, rr->rectf + 1); IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4 * rr->rectx, rr->rectf + 2); IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4 * rr->rectx, rr->rectf + 3); } /* add layers/passes and assign channels */ for (rl = rr->layers.first; rl; rl = rl->next) { /* combined */ if (rl->rectf) { int a, xstride = 4; for (a = 0; a < xstride; a++) { IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), xstride, xstride * rr->rectx, rl->rectf + a); } } /* passes are allocated in sync */ for (rpass = rl->passes.first; rpass; rpass = rpass->next) { int a, xstride = rpass->channels; for (a = 0; a < xstride; a++) { if (rpass->passtype) { IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), xstride, xstride * rr->rectx, rpass->rect + a); } else { IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), xstride, xstride * rr->rectx, rpass->rect + a); } } } } /* when the filename has no permissions, this can fail */ if (IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) { IMB_exr_write_channels(exrhandle); success = TRUE; } else { /* TODO, get the error from openexr's exception */ BKE_report(reports, RPT_ERROR, "Error writing render result (see console)"); success = FALSE; } IMB_exr_close(exrhandle); return success; }
/* called from within UI and render pipeline, saves both rendered result as a file-read result * if multiview is true saves all views in a multiview exr * else if view is not NULL saves single view * else saves stereo3d */ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const bool multiview, const char *view) { RenderLayer *rl; RenderPass *rpass; RenderView *rview; void *exrhandle = IMB_exr_get_handle(); bool success; int a, nr; const char *chan_view = NULL; int compress = (imf ? imf->exr_codec : 0); size_t width, height; const bool is_mono = view && !multiview; const bool use_half_float = (imf != NULL) ? (imf->depth == R_IMF_CHAN_DEPTH_16) : false; width = rr->rectx; height = rr->recty; if (imf && imf->imtype == R_IMF_IMTYPE_OPENEXR && multiview) { /* single layer OpenEXR */ const char *RGBAZ[] = {"R", "G", "B", "A", "Z"}; for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) { IMB_exr_add_view(exrhandle, rview->name); if (rview->rectf) { for (a = 0; a < 4; a++) { IMB_exr_add_channel(exrhandle, "", RGBAZ[a], rview->name, 4, 4 * width, rview->rectf + a, use_half_float); } if (rview->rectz) { /* Z pass is always stored as float. */ IMB_exr_add_channel(exrhandle, "", RGBAZ[4], rview->name, 1, width, rview->rectz, false); } } } } else { for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) { if (is_mono) { if (!STREQ(view, rview->name)) { continue; } chan_view = ""; } else { /* if rendered only one view, we treat as a a non-view render */ chan_view = rview->name; } IMB_exr_add_view(exrhandle, rview->name); if (rview->rectf) { for (a = 0; a < 4; a++) { IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a), chan_view, 4, 4 * width, rview->rectf + a, use_half_float); } } } /* add layers/passes and assign channels */ for (rl = rr->layers.first; rl; rl = rl->next) { /* passes are allocated in sync */ for (rpass = rl->passes.first; rpass; rpass = rpass->next) { const int xstride = rpass->channels; if (is_mono) { if (!STREQ(view, rpass->view)) { continue; } chan_view = ""; } else { /* if rendered only one view, we treat as a a non-view render */ chan_view = (nr > 1 ? rpass->view :""); } for (a = 0; a < xstride; a++) { if (rpass->passtype) { IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view, xstride, xstride * width, rpass->rect + a, rpass->passtype == SCE_PASS_Z ? false : use_half_float); } else { IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view, xstride, xstride * width, rpass->rect + a, use_half_float); } } } } } BLI_make_existing_file(filename); if (IMB_exr_begin_write(exrhandle, filename, width, height, compress, rr->stamp_data)) { IMB_exr_write_channels(exrhandle); success = true; } else { /* TODO, get the error from openexr's exception */ BKE_report(reports, RPT_ERROR, "Error writing render result (see console)"); success = false; } IMB_exr_close(exrhandle); return success; }