Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2017-10-20 16:18:26 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2017-11-08 01:20:22 +0300
commit2a097527f20da98bb4c1199c2854a15eea241153 (patch)
tree57915a10d37a0451c8493297f2a3ed62a7b264f9 /source/blender/render
parented7260071bc397dd389737088fce869e8adc0dc3 (diff)
Fix various issues with (multiview) OpenEXR file save/load.
* Fix saving a multiview render from the image editor giving invalid files. * Fix failure to load multiview images with a single view per part. * Fix loss of multiview metadata when saving/loading a single view. * Fix Z-Buffer writing option for single layer EXR not being respected. Multiview EXRs are now always handled as multilayer internally, significantly reducing the amount of code. Reviewed By: dfelinto Differential Revision: https://developer.blender.org/D2887
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h2
-rw-r--r--source/blender/render/intern/include/render_result.h1
-rw-r--r--source/blender/render/intern/source/pipeline.c39
-rw-r--r--source/blender/render/intern/source/render_result.c181
4 files changed, 129 insertions, 94 deletions
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index a94d048e26d..c7b7b35474e 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -310,7 +310,7 @@ void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene
bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode);
bool RE_WriteRenderResult(
struct ReportList *reports, RenderResult *rr, const char *filename,
- struct ImageFormatData *imf, const bool multiview, const char *view);
+ struct ImageFormatData *imf, const char *view, const int layer);
struct RenderResult *RE_MultilayerConvert(
void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 4057d8c1052..8d293c938c7 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -115,6 +115,7 @@ void render_result_rect_get_pixels(struct RenderResult *rr,
void render_result_views_shallowcopy(struct RenderResult *dst, struct RenderResult *src);
void render_result_views_shallowdelete(struct RenderResult *rr);
+bool render_result_has_views(struct RenderResult *rr);
#endif /* __RENDER_RESULT_H__ */
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 96a9bb44bcc..f5577ae89ea 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -437,6 +437,8 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
rr->rectz = rv->rectz;
rr->rect32 = rv->rect32;
+ rr->have_combined = (rv->rectf != NULL);
+
/* active layer */
rl = render_get_active_layer(re, re->result);
@@ -3307,19 +3309,18 @@ void RE_RenderFreestyleExternal(Render *re)
bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name)
{
- bool is_mono;
bool ok = true;
RenderData *rd = &scene->r;
if (!rr)
return false;
- is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2;
+ bool is_mono = BLI_listbase_count_ex(&rr->views, 2) < 2;
+ bool is_exr_rr = ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER);
- if (ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
- rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW)
+ if (rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr)
{
- ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, true, NULL);
+ ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, NULL, -1);
render_print_save_message(reports, name, ok, errno);
}
@@ -3337,30 +3338,34 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen
BKE_scene_multiview_view_filepath_get(&scene->r, filepath, rv->name, name);
}
- if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
- ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, false, rv->name);
+ if (is_exr_rr) {
+ ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, rv->name, -1);
render_print_save_message(reports, name, ok, errno);
- }
- else {
- ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id);
-
- IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
- &scene->display_settings, &rd->im_format);
-
- ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &rd->im_format, stamp);
/* optional preview images for exr */
- if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
+ if (ok && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
ImageFormatData imf = rd->im_format;
imf.imtype = R_IMF_IMTYPE_JPEG90;
if (BLI_testextensie(name, ".exr"))
name[strlen(name) - 4] = 0;
BKE_image_path_ensure_ext_from_imformat(name, &imf);
+
+ ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id);
ibuf->planes = 24;
ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &imf, stamp);
+
+ IMB_freeImBuf(ibuf);
}
+ }
+ else {
+ ImBuf *ibuf = render_result_rect_to_ibuf(rr, rd, view_id);
+
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
+ &scene->display_settings, &rd->im_format);
+
+ ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf, name, &rd->im_format, stamp);
/* imbuf knows which rects are not part of ibuf */
IMB_freeImBuf(ibuf);
@@ -3391,7 +3396,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen
ok = render_imbuf_write_stamp_test(reports, scene, rr, ibuf_arr[2], name, &rd->im_format, stamp);
/* optional preview images for exr */
- if (ok && rd->im_format.imtype == R_IMF_IMTYPE_OPENEXR &&
+ if (ok && is_exr_rr &&
(rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG))
{
ImageFormatData imf = rd->im_format;
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index dbb2ef7ae51..631503bdad5 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -585,7 +585,7 @@ static void *ml_addlayer_cb(void *base, const char *str)
rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
BLI_addtail(&rr->layers, rl);
-
+
BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME);
return rl;
}
@@ -756,6 +756,12 @@ void render_result_views_new(RenderResult *rr, RenderData *rd)
}
}
+bool render_result_has_views(RenderResult *rr)
+{
+ RenderView *rv = rr->views.first;
+ return (rv && (rv->next || rv->name[0]));
+}
+
/*********************************** Merge ***********************************/
static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
@@ -820,101 +826,124 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
}
}
-/* 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)
+/* Called from the UI and render pipeline, to save multilayer and multiview
+ * images, optionally isolating a specific, view, layer or RGBA/Z pass. */
+bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const char *view, int layer)
{
- 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;
+ const bool half_float = (imf && imf->depth == R_IMF_CHAN_DEPTH_16);
+ const bool multi_layer = !(imf && imf->imtype == R_IMF_IMTYPE_OPENEXR);
+ const bool write_z = !multi_layer && (imf && (imf->flag & R_IMF_FLAG_ZBUF));
- 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);
+ /* Write first layer if not multilayer and no layer was specified. */
+ if (!multi_layer && layer == -1) {
+ layer = 0;
+ }
- 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);
- }
+ /* First add views since IMB_exr_add_channel checks number of views. */
+ if (render_result_has_views(rr)) {
+ for (RenderView *rview = rr->views.first; rview; rview = rview->next) {
+ if (!view || STREQ(view, rview->name)) {
+ IMB_exr_add_view(exrhandle, rview->name);
}
}
}
- else {
- for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) {
- if (is_mono) {
- if (!STREQ(view, rview->name)) {
+
+ /* Compositing result. */
+ if (rr->have_combined) {
+ for (RenderView *rview = rr->views.first; rview; rview = rview->next) {
+ if (!rview->rectf) {
+ continue;
+ }
+
+ const char *viewname = rview->name;
+ if (view) {
+ if (!STREQ(view, viewname)) {
continue;
}
- chan_view = "";
- }
- else {
- /* if rendered only one view, we treat as a a non-view render */
- chan_view = rview->name;
+ else {
+ viewname = "";
+ }
}
- IMB_exr_add_view(exrhandle, rview->name);
+ /* Skip compositing if only a single other layer is requested. */
+ if (!multi_layer && layer != 0) {
+ continue;
+ }
- if (rview->rectf) {
+ for (int a = 0; a < 4; a++) {
char passname[EXR_PASS_MAXNAME];
- for (a = 0; a < 4; a++) {
- set_pass_name(passname, RE_PASSNAME_COMBINED, a, "RGBA");
- IMB_exr_add_channel(exrhandle, "Composite", passname,
- chan_view, 4, 4 * width, rview->rectf + a,
- use_half_float);
+ char layname[EXR_PASS_MAXNAME];
+ const char *chan_id = "RGBA";
+
+ if (multi_layer) {
+ set_pass_name(passname, "Combined", a, chan_id);
+ BLI_strncpy(layname, "Composite", sizeof(layname));
}
+ else {
+ passname[0] = chan_id[a];
+ passname[1] = '\0';
+ layname[0] = '\0';
+ }
+
+ IMB_exr_add_channel(exrhandle, layname, passname, viewname,
+ 4, 4 * rr->rectx, rview->rectf + a, half_float);
+ }
+
+ if (write_z && rview->rectz) {
+ const char *layname = (multi_layer)? "Composite": "";
+ IMB_exr_add_channel(exrhandle, layname, "Z", viewname,
+ 1, rr->rectx, rview->rectz, false);
}
}
+ }
- /* add layers/passes and assign channels */
- for (rl = rr->layers.first; rl; rl = rl->next) {
+ /* Other render layers. */
+ int nr = (rr->have_combined)? 1: 0;
+ for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next, nr++) {
+ /* Skip other render layers if requested. */
+ if (!multi_layer && nr != layer) {
+ continue;
+ }
- /* passes are allocated in sync */
- for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
- const int xstride = rpass->channels;
- char passname[EXR_PASS_MAXNAME];
+ for (RenderPass *rp = rl->passes.first; rp; rp = rp->next) {
+ /* Skip non-RGBA and Z passes if not using multi layer. */
+ if (!multi_layer && !(STREQ(rp->name, RE_PASSNAME_COMBINED) ||
+ STREQ(rp->name, "") ||
+ (STREQ(rp->name, RE_PASSNAME_Z) && write_z))) {
+ continue;
+ }
- if (is_mono) {
- if (!STREQ(view, rpass->view)) {
- continue;
- }
- chan_view = "";
+ /* Skip pass if it does not match the requested view(s). */
+ const char *viewname = rp->view;
+ if (view) {
+ if (!STREQ(view, viewname)) {
+ continue;
}
else {
- /* if rendered only one view, we treat as a a non-view render */
- chan_view = (nr > 1 ? rpass->view :"");
+ viewname = "";
}
+ }
- for (a = 0; a < xstride; a++) {
- set_pass_name(passname, rpass->name, a, rpass->chan_id);
- IMB_exr_add_channel(exrhandle, rl->name, passname, chan_view,
- xstride, xstride * width, rpass->rect + a,
- STREQ(rpass->name, RE_PASSNAME_Z) ? false : use_half_float);
+ for (int a = 0; a < rp->channels; a++) {
+ /* Save Combined as RGBA if single layer save. */
+ char passname[EXR_PASS_MAXNAME];
+ char layname[EXR_PASS_MAXNAME];
+
+ if (multi_layer) {
+ set_pass_name(passname, rp->name, a, rp->chan_id);
+ BLI_strncpy(layname, rl->name, sizeof(layname));
+ }
+ else {
+ passname[0] = rp->chan_id[a];
+ passname[1] = '\0';
+ layname[0] = '\0';
}
+
+ /* Add channel. */
+ IMB_exr_add_channel(exrhandle, layname, passname, viewname,
+ rp->channels, rp->channels * rr->rectx, rp->rect + a,
+ STREQ(rp->name, RE_PASSNAME_Z) ? false : half_float);
}
}
}
@@ -923,14 +952,14 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
BLI_make_existing_file(filename);
- if (IMB_exr_begin_write(exrhandle, filename, width, height, compress, rr->stamp_data)) {
+ int compress = (imf ? imf->exr_codec : 0);
+ bool success = IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress, rr->stamp_data);
+ if (success) {
IMB_exr_write_channels(exrhandle);
- success = true;
}
else {
/* TODO, get the error from openexr's exception */
BKE_reportf(reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno));
- success = false;
}
IMB_exr_close(exrhandle);
@@ -1245,7 +1274,7 @@ void render_result_exr_file_cache_write(Render *re)
render_result_exr_file_cache_path(re->scene, root, str);
printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str);
- RE_WriteRenderResult(NULL, rr, str, NULL, true, NULL);
+ RE_WriteRenderResult(NULL, rr, str, NULL, NULL, -1);
}
/* For cache, makes exact copy of render result */