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
path: root/source
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2022-03-18 23:28:04 +0300
committerBrecht Van Lommel <brecht@blender.org>2022-03-21 18:38:13 +0300
commit8530e48f8692f4b92c43489029f2d2ef67c7cb62 (patch)
treed335479baf037b897ddf14f42c238184f65d0472 /source
parentb96462519f748fcf04028084354fbbf97eb8ce92 (diff)
Cleanup: move render image and multilayer EXR write code to image_save.cc
These share a lot of logic with regular image saving and should be unified more in the future.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_image.h6
-rw-r--r--source/blender/blenkernel/BKE_image_save.h20
-rw-r--r--source/blender/blenkernel/BKE_scene.h2
-rw-r--r--source/blender/blenkernel/intern/image.cc12
-rw-r--r--source/blender/blenkernel/intern/image_save.cc336
-rw-r--r--source/blender/blenkernel/intern/scene.c4
-rw-r--r--source/blender/editors/render/render_opengl.cc11
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h2
-rw-r--r--source/blender/imbuf/IMB_imbuf.h8
-rw-r--r--source/blender/imbuf/intern/colormanagement.c2
-rw-r--r--source/blender/imbuf/intern/stereoimbuf.c42
-rw-r--r--source/blender/render/RE_pipeline.h31
-rw-r--r--source/blender/render/intern/pipeline.c171
-rw-r--r--source/blender/render/intern/render_result.c199
-rw-r--r--source/blender/render/intern/render_result.h1
15 files changed, 433 insertions, 414 deletions
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 7b3124cca26..fba2512fa49 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -64,7 +64,7 @@ struct StampData *BKE_stamp_info_from_scene_static(const struct Scene *scene);
* Check whether the given metadata field name translates to a known field of a stamp.
*/
bool BKE_stamp_is_known_field(const char *field_name);
-void BKE_imbuf_stamp_info(struct RenderResult *rr, struct ImBuf *ibuf);
+void BKE_imbuf_stamp_info(const struct RenderResult *rr, struct ImBuf *ibuf);
void BKE_stamp_info_from_imbuf(struct RenderResult *rr, struct ImBuf *ibuf);
void BKE_stamp_info_callback(void *data,
struct StampData *stamp_data,
@@ -82,8 +82,8 @@ void BKE_image_stamp_buf(struct Scene *scene,
int height,
int channels);
bool BKE_imbuf_alpha_test(struct ImBuf *ibuf);
-int BKE_imbuf_write_stamp(struct Scene *scene,
- struct RenderResult *rr,
+int BKE_imbuf_write_stamp(const struct Scene *scene,
+ const struct RenderResult *rr,
struct ImBuf *ibuf,
const char *name,
const struct ImageFormatData *imf);
diff --git a/source/blender/blenkernel/BKE_image_save.h b/source/blender/blenkernel/BKE_image_save.h
index dea1c25cd5e..f9d07387463 100644
--- a/source/blender/blenkernel/BKE_image_save.h
+++ b/source/blender/blenkernel/BKE_image_save.h
@@ -16,6 +16,9 @@ struct Image;
struct Main;
struct ReportList;
struct Scene;
+struct RenderResult;
+
+/* Image datablock saving. */
typedef struct ImageSaveOptions {
/* Context within which image is saved. */
@@ -44,6 +47,23 @@ bool BKE_image_save(struct ReportList *reports,
struct ImageUser *iuser,
struct ImageSaveOptions *opts);
+/* Lower level image writing. */
+
+/* Save single or multilayer OpenEXR files from the render result.
+ * Optionally saves only a specific view or layer. */
+bool BKE_image_render_write_exr(struct ReportList *reports,
+ const struct RenderResult *rr,
+ const char *filename,
+ const struct ImageFormatData *imf,
+ const char *view,
+ int layer);
+
+bool BKE_image_render_write(struct ReportList *reports,
+ struct RenderResult *rr,
+ const struct Scene *scene,
+ const bool stamp,
+ const char *name);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index d06b1d43b96..8c50a89ec90 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -282,7 +282,7 @@ struct SceneRenderView *BKE_scene_multiview_render_view_findindex(const struct R
int view_id);
const char *BKE_scene_multiview_render_view_name_get(const struct RenderData *rd, int view_id);
int BKE_scene_multiview_view_id_get(const struct RenderData *rd, const char *viewname);
-void BKE_scene_multiview_filepath_get(struct SceneRenderView *srv,
+void BKE_scene_multiview_filepath_get(const struct SceneRenderView *srv,
const char *filepath,
char *r_filepath);
/**
diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc
index 51ffd3338c4..f8fb2ec7e45 100644
--- a/source/blender/blenkernel/intern/image.cc
+++ b/source/blender/blenkernel/intern/image.cc
@@ -2343,9 +2343,9 @@ static void metadata_get_field(void *data, const char *propname, char *propvalue
IMB_metadata_get_field(imbuf->metadata, propname, propvalue, len);
}
-void BKE_imbuf_stamp_info(RenderResult *rr, struct ImBuf *ibuf)
+void BKE_imbuf_stamp_info(const RenderResult *rr, ImBuf *ibuf)
{
- struct StampData *stamp_data = rr->stamp_data;
+ StampData *stamp_data = const_cast<StampData *>(rr->stamp_data);
IMB_metadata_ensure(&ibuf->metadata);
BKE_stamp_info_callback(ibuf, stamp_data, metadata_set_field, false);
}
@@ -2359,12 +2359,12 @@ static void metadata_copy_custom_fields(const char *field, const char *value, vo
BKE_render_result_stamp_data(rr, field, value);
}
-void BKE_stamp_info_from_imbuf(RenderResult *rr, struct ImBuf *ibuf)
+void BKE_stamp_info_from_imbuf(RenderResult *rr, ImBuf *ibuf)
{
if (rr->stamp_data == nullptr) {
rr->stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data");
}
- struct StampData *stamp_data = rr->stamp_data;
+ StampData *stamp_data = rr->stamp_data;
IMB_metadata_ensure(&ibuf->metadata);
BKE_stamp_info_callback(ibuf, stamp_data, metadata_get_field, true);
/* Copy render engine specific settings. */
@@ -2428,8 +2428,8 @@ int BKE_imbuf_write_as(ImBuf *ibuf, const char *name, ImageFormatData *imf, cons
return ok;
}
-int BKE_imbuf_write_stamp(Scene *scene,
- struct RenderResult *rr,
+int BKE_imbuf_write_stamp(const Scene *scene,
+ const struct RenderResult *rr,
ImBuf *ibuf,
const char *name,
const struct ImageFormatData *imf)
diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc
index 180008e0f64..fdeb5eedcde 100644
--- a/source/blender/blenkernel/intern/image_save.cc
+++ b/source/blender/blenkernel/intern/image_save.cc
@@ -20,6 +20,8 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "intern/openexr/openexr_multi.h"
+
#include "BKE_colortools.h"
#include "BKE_image.h"
#include "BKE_image_format.h"
@@ -219,14 +221,14 @@ static bool image_save_single(ReportList *reports,
/* fancy multiview OpenEXR */
if (imf->views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
/* save render result */
- ok = RE_WriteRenderResult(reports, rr, opts->filepath, imf, nullptr, layer);
+ ok = BKE_image_render_write_exr(reports, rr, opts->filepath, imf, NULL, layer);
image_save_post(reports, ima, ibuf, ok, opts, true, opts->filepath, r_colorspace_changed);
BKE_image_release_ibuf(ima, ibuf, lock);
}
/* regular mono pipeline */
else if (is_mono) {
if (is_exr_rr) {
- ok = RE_WriteRenderResult(reports, rr, opts->filepath, imf, nullptr, layer);
+ ok = BKE_image_render_write_exr(reports, rr, opts->filepath, imf, NULL, layer);
}
else {
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(
@@ -261,7 +263,7 @@ static bool image_save_single(ReportList *reports,
if (is_exr_rr) {
BKE_scene_multiview_view_filepath_get(&opts->scene->r, opts->filepath, view, filepath);
- ok_view = RE_WriteRenderResult(reports, rr, filepath, imf, view, layer);
+ ok_view = BKE_image_render_write_exr(reports, rr, filepath, imf, view, layer);
image_save_post(reports, ima, ibuf, ok_view, opts, true, filepath, r_colorspace_changed);
}
else {
@@ -308,7 +310,7 @@ static bool image_save_single(ReportList *reports,
/* stereo (multiview) images */
else if (opts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
- ok = RE_WriteRenderResult(reports, rr, opts->filepath, imf, nullptr, layer);
+ ok = BKE_image_render_write_exr(reports, rr, opts->filepath, imf, NULL, layer);
image_save_post(reports, ima, ibuf, ok, opts, true, opts->filepath, r_colorspace_changed);
BKE_image_release_ibuf(ima, ibuf, lock);
}
@@ -449,3 +451,329 @@ bool BKE_image_save(
return ok;
}
+
+/* OpenEXR saving, single and multilayer. */
+
+bool BKE_image_render_write_exr(ReportList *reports,
+ const RenderResult *rr,
+ const char *filename,
+ const ImageFormatData *imf,
+ const char *view,
+ int layer)
+{
+ void *exrhandle = IMB_exr_get_handle();
+ 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));
+
+ /* Write first layer if not multilayer and no layer was specified. */
+ if (!multi_layer && layer == -1) {
+ layer = 0;
+ }
+
+ /* First add views since IMB_exr_add_channel checks number of views. */
+ const RenderView *first_rview = (const RenderView *)rr->views.first;
+ if (first_rview && (first_rview->next || first_rview->name[0])) {
+ LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
+ if (!view || STREQ(view, rview->name)) {
+ IMB_exr_add_view(exrhandle, rview->name);
+ }
+ }
+ }
+
+ /* Compositing result. */
+ if (rr->have_combined) {
+ LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
+ if (!rview->rectf) {
+ continue;
+ }
+
+ const char *viewname = rview->name;
+ if (view) {
+ if (!STREQ(view, viewname)) {
+ continue;
+ }
+
+ viewname = "";
+ }
+
+ /* Skip compositing if only a single other layer is requested. */
+ if (!multi_layer && layer != 0) {
+ continue;
+ }
+
+ float *output_rect = rview->rectf;
+
+ for (int a = 0; a < 4; a++) {
+ char passname[EXR_PASS_MAXNAME];
+ char layname[EXR_PASS_MAXNAME];
+ const char *chan_id = "RGBA";
+
+ if (multi_layer) {
+ IMB_exr_channel_name(passname, NULL, "Combined", NULL, chan_id, a);
+ 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, output_rect + 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);
+ }
+ }
+ }
+
+ /* Other render layers. */
+ int nr = (rr->have_combined) ? 1 : 0;
+ LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
+ /* Skip other render layers if requested. */
+ if (!multi_layer && nr != layer) {
+ continue;
+ }
+
+ LISTBASE_FOREACH (RenderPass *, rp, &rl->passes) {
+ /* 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;
+ }
+
+ /* Skip pass if it does not match the requested view(s). */
+ const char *viewname = rp->view;
+ if (view) {
+ if (!STREQ(view, viewname)) {
+ continue;
+ }
+
+ viewname = "";
+ }
+
+ /* 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_half_float = half_float && pass_RGBA;
+
+ float *output_rect = rp->rect;
+
+ 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) {
+ IMB_exr_channel_name(passname, NULL, rp->name, NULL, rp->chan_id, a);
+ BLI_strncpy(layname, rl->name, sizeof(layname));
+ }
+ else {
+ passname[0] = rp->chan_id[a];
+ passname[1] = '\0';
+ layname[0] = '\0';
+ }
+
+ IMB_exr_add_channel(exrhandle,
+ layname,
+ passname,
+ viewname,
+ rp->channels,
+ rp->channels * rr->rectx,
+ output_rect + a,
+ pass_half_float);
+ }
+ }
+ }
+
+ errno = 0;
+
+ BLI_make_existing_file(filename);
+
+ 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);
+ }
+ else {
+ /* TODO: get the error from openexr's exception. */
+ BKE_reportf(
+ reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno));
+ }
+
+ IMB_exr_close(exrhandle);
+ return success;
+}
+
+/* Render output. */
+
+static void image_render_print_save_message(ReportList *reports, const char *name, int ok, int err)
+{
+ if (ok) {
+ /* no need to report, just some helpful console info */
+ printf("Saved: '%s'\n", name);
+ }
+ else {
+ /* report on error since users will want to know what failed */
+ BKE_reportf(reports, RPT_ERROR, "Render error (%s) cannot save: '%s'", strerror(err), name);
+ }
+}
+
+static int image_render_write_stamp_test(ReportList *reports,
+ const Scene *scene,
+ const RenderResult *rr,
+ ImBuf *ibuf,
+ const char *name,
+ const ImageFormatData *imf,
+ const bool stamp)
+{
+ int ok;
+
+ if (stamp) {
+ /* writes the name of the individual cameras */
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, imf);
+ }
+ else {
+ ok = BKE_imbuf_write(ibuf, name, imf);
+ }
+
+ image_render_print_save_message(reports, name, ok, errno);
+
+ return ok;
+}
+
+bool BKE_image_render_write(ReportList *reports,
+ RenderResult *rr,
+ const Scene *scene,
+ const bool stamp,
+ const char *filename)
+{
+ bool ok = true;
+ const RenderData *rd = &scene->r;
+
+ if (!rr) {
+ return false;
+ }
+
+ const bool is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
+ const bool is_exr_rr = ELEM(rd->im_format.imtype,
+ R_IMF_IMTYPE_OPENEXR,
+ R_IMF_IMTYPE_MULTILAYER) &&
+ RE_HasFloatPixels(rr);
+ const float dither = scene->r.dither_intensity;
+
+ if (rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
+ ok = BKE_image_render_write_exr(reports, rr, filename, &rd->im_format, NULL, -1);
+ image_render_print_save_message(reports, filename, ok, errno);
+ }
+
+ /* mono, legacy code */
+ else if (is_mono || (rd->im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ int view_id = 0;
+ for (const RenderView *rv = (const RenderView *)rr->views.first; rv;
+ rv = rv->next, view_id++) {
+ char filepath[FILE_MAX];
+ if (is_mono) {
+ STRNCPY(filepath, filename);
+ }
+ else {
+ BKE_scene_multiview_view_filepath_get(&scene->r, filename, rv->name, filepath);
+ }
+
+ if (is_exr_rr) {
+ ok = BKE_image_render_write_exr(reports, rr, filepath, &rd->im_format, rv->name, -1);
+ image_render_print_save_message(reports, filepath, ok, errno);
+
+ /* optional preview images for exr */
+ if (ok && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
+ ImageFormatData imf = rd->im_format;
+ imf.imtype = R_IMF_IMTYPE_JPEG90;
+
+ if (BLI_path_extension_check(filepath, ".exr")) {
+ filepath[strlen(filepath) - 4] = 0;
+ }
+ BKE_image_path_ensure_ext_from_imformat(filepath, &imf);
+
+ ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &imf, dither, view_id);
+ ibuf->planes = 24;
+ IMB_colormanagement_imbuf_for_write(
+ ibuf, true, false, &scene->view_settings, &scene->display_settings, &imf);
+
+ ok = image_render_write_stamp_test(reports, scene, rr, ibuf, filepath, &imf, stamp);
+
+ IMB_freeImBuf(ibuf);
+ }
+ }
+ else {
+ ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &rd->im_format, dither, view_id);
+
+ IMB_colormanagement_imbuf_for_write(
+ ibuf, true, false, &scene->view_settings, &scene->display_settings, &rd->im_format);
+
+ ok = image_render_write_stamp_test(
+ reports, scene, rr, ibuf, filepath, &rd->im_format, stamp);
+
+ /* imbuf knows which rects are not part of ibuf */
+ IMB_freeImBuf(ibuf);
+ }
+ }
+ }
+ else { /* R_IMF_VIEWS_STEREO_3D */
+ BLI_assert(rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D);
+
+ char filepath[FILE_MAX];
+ STRNCPY(filepath, filename);
+
+ if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
+ printf("Stereo 3D not supported for MultiLayer image: %s\n", filepath);
+ }
+ else {
+ ImBuf *ibuf_arr[3] = {NULL};
+ const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
+ ibuf_arr[i] = RE_render_result_rect_to_ibuf(rr, &rd->im_format, dither, view_id);
+ IMB_colormanagement_imbuf_for_write(ibuf_arr[i],
+ true,
+ false,
+ &scene->view_settings,
+ &scene->display_settings,
+ &rd->im_format);
+ IMB_prepare_write_ImBuf(IMB_isfloat(ibuf_arr[i]), ibuf_arr[i]);
+ }
+
+ ibuf_arr[2] = IMB_stereo3d_ImBuf(&rd->im_format, ibuf_arr[0], ibuf_arr[1]);
+
+ ok = image_render_write_stamp_test(
+ reports, scene, rr, ibuf_arr[2], filepath, &rd->im_format, stamp);
+
+ /* optional preview images for exr */
+ if (ok && is_exr_rr && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
+ ImageFormatData imf = rd->im_format;
+ imf.imtype = R_IMF_IMTYPE_JPEG90;
+
+ if (BLI_path_extension_check(filepath, ".exr")) {
+ filepath[strlen(filepath) - 4] = 0;
+ }
+
+ BKE_image_path_ensure_ext_from_imformat(filepath, &imf);
+ ibuf_arr[2]->planes = 24;
+
+ ok = image_render_write_stamp_test(reports, scene, rr, ibuf_arr[2], filepath, &imf, stamp);
+ }
+
+ /* imbuf knows which rects are not part of ibuf */
+ for (i = 0; i < 3; i++) {
+ IMB_freeImBuf(ibuf_arr[i]);
+ }
+ }
+ }
+
+ return ok;
+}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 86d38064b2d..6797538d190 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -3123,7 +3123,9 @@ int BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname)
return 0;
}
-void BKE_scene_multiview_filepath_get(SceneRenderView *srv, const char *filepath, char *r_filepath)
+void BKE_scene_multiview_filepath_get(const SceneRenderView *srv,
+ const char *filepath,
+ char *r_filepath)
{
BLI_strncpy(r_filepath, filepath, FILE_MAX);
BLI_path_suffix(r_filepath, FILE_MAX, srv->suffix, "");
diff --git a/source/blender/editors/render/render_opengl.cc b/source/blender/editors/render/render_opengl.cc
index 872e2867696..fbdc1086874 100644
--- a/source/blender/editors/render/render_opengl.cc
+++ b/source/blender/editors/render/render_opengl.cc
@@ -35,6 +35,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_image_format.h"
+#include "BKE_image_save.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -313,13 +314,13 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
imb_freerectfloatImBuf(out);
}
BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));
- RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
+ RE_render_result_rect_from_ibuf(rr, out, oglrender->view_id);
IMB_freeImBuf(out);
}
else if (gpd) {
/* If there are no strips, Grease Pencil still needs a buffer to draw on */
ImBuf *out = IMB_allocImBuf(oglrender->sizex, oglrender->sizey, 32, IB_rect);
- RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
+ RE_render_result_rect_from_ibuf(rr, out, oglrender->view_id);
IMB_freeImBuf(out);
}
@@ -415,7 +416,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) {
BKE_image_stamp_buf(scene, camera, nullptr, rect, rectf, rr->rectx, rr->recty, 4);
}
- RE_render_result_rect_from_ibuf(rr, &scene->r, ibuf_result, oglrender->view_id);
+ RE_render_result_rect_from_ibuf(rr, ibuf_result, oglrender->view_id);
IMB_freeImBuf(ibuf_result);
}
}
@@ -440,7 +441,7 @@ static void screen_opengl_render_write(OGLRender *oglrender)
/* write images as individual images or stereo */
BKE_render_result_stamp_info(scene, scene->camera, rr, false);
- ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name);
+ ok = BKE_image_render_write(oglrender->reports, rr, scene, false, name);
RE_ReleaseResultImage(oglrender->re);
@@ -1071,7 +1072,7 @@ static void write_result_func(TaskPool *__restrict pool, void *task_data_v)
nullptr);
BKE_render_result_stamp_info(scene, scene->camera, rr, false);
- ok = RE_WriteRenderViewsImage(nullptr, rr, scene, true, name);
+ ok = BKE_image_render_write(nullptr, rr, scene, true, name);
if (!ok) {
BKE_reportf(&reports, RPT_ERROR, "Write error: cannot save %s", name);
}
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 785fa2b198a..7434db732fd 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -244,7 +244,7 @@ struct ImBuf *IMB_colormanagement_imbuf_for_write(
bool allocate_result,
const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
- struct ImageFormatData *image_format_data);
+ const struct ImageFormatData *image_format_data);
void IMB_colormanagement_buffer_make_display_space(
float *buffer,
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 8929a467670..0390df06052 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -965,13 +965,13 @@ void IMB_stereo3d_write_dimensions(
char mode, bool is_squeezed, size_t width, size_t height, size_t *r_width, size_t *r_height);
void IMB_stereo3d_read_dimensions(
char mode, bool is_squeezed, size_t width, size_t height, size_t *r_width, size_t *r_height);
-int *IMB_stereo3d_from_rect(struct ImageFormatData *im_format,
+int *IMB_stereo3d_from_rect(const struct ImageFormatData *im_format,
size_t x,
size_t y,
size_t channels,
int *rect_left,
int *rect_right);
-float *IMB_stereo3d_from_rectf(struct ImageFormatData *im_format,
+float *IMB_stereo3d_from_rectf(const struct ImageFormatData *im_format,
size_t x,
size_t y,
size_t channels,
@@ -980,13 +980,13 @@ float *IMB_stereo3d_from_rectf(struct ImageFormatData *im_format,
/**
* Left/right are always float.
*/
-struct ImBuf *IMB_stereo3d_ImBuf(struct ImageFormatData *im_format,
+struct ImBuf *IMB_stereo3d_ImBuf(const struct ImageFormatData *im_format,
struct ImBuf *ibuf_left,
struct ImBuf *ibuf_right);
/**
* Reading a stereo encoded ibuf (*left) and generating two ibufs from it (*left and *right).
*/
-void IMB_ImBufFromStereo3d(struct Stereo3dFormat *s3d,
+void IMB_ImBufFromStereo3d(const struct Stereo3dFormat *s3d,
struct ImBuf *ibuf_stereo,
struct ImBuf **r_ibuf_left,
struct ImBuf **r_ibuf_right);
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index bf3e50b8870..e60df0ca1c9 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -2433,7 +2433,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf,
bool allocate_result,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
- ImageFormatData *image_format_data)
+ const ImageFormatData *image_format_data)
{
ImBuf *colormanaged_ibuf = ibuf;
bool do_colormanagement;
diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c
index c081ffb981a..52756891f21 100644
--- a/source/blender/imbuf/intern/stereoimbuf.c
+++ b/source/blender/imbuf/intern/stereoimbuf.c
@@ -28,8 +28,10 @@
/* prototypes */
struct Stereo3DData;
-static void imb_stereo3d_write_doit(struct Stereo3DData *s3d_data, struct Stereo3dFormat *s3d);
-static void imb_stereo3d_read_doit(struct Stereo3DData *s3d_data, struct Stereo3dFormat *s3d);
+static void imb_stereo3d_write_doit(struct Stereo3DData *s3d_data,
+ const struct Stereo3dFormat *s3d);
+static void imb_stereo3d_read_doit(struct Stereo3DData *s3d_data,
+ const struct Stereo3dFormat *s3d);
typedef struct Stereo3DData {
struct {
@@ -46,7 +48,7 @@ typedef struct Stereo3DData {
/** \name Local Functions
* \{ */
-static void imb_stereo3d_write_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyphType mode)
+static void imb_stereo3d_write_anaglyph(const Stereo3DData *s3d, enum eStereo3dAnaglyphType mode)
{
int x, y;
size_t width = s3d->x;
@@ -144,7 +146,7 @@ static void imb_stereo3d_write_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyp
}
}
-static void imb_stereo3d_write_interlace(Stereo3DData *s3d,
+static void imb_stereo3d_write_interlace(const Stereo3DData *s3d,
enum eStereo3dInterlaceType mode,
const bool swap)
{
@@ -402,7 +404,7 @@ static void imb_stereo3d_write_interlace(Stereo3DData *s3d,
}
/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */
-static void imb_stereo3d_write_sidebyside(Stereo3DData *s3d, const bool crosseyed)
+static void imb_stereo3d_write_sidebyside(const Stereo3DData *s3d, const bool crosseyed)
{
int y;
size_t width = s3d->x;
@@ -450,7 +452,7 @@ static void imb_stereo3d_write_sidebyside(Stereo3DData *s3d, const bool crosseye
}
/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */
-static void imb_stereo3d_write_topbottom(Stereo3DData *s3d)
+static void imb_stereo3d_write_topbottom(const Stereo3DData *s3d)
{
int y;
size_t width = s3d->x;
@@ -565,7 +567,7 @@ void IMB_stereo3d_read_dimensions(const char mode,
* \{ */
static void imb_stereo3d_squeeze_ImBuf(ImBuf *ibuf,
- Stereo3dFormat *s3d,
+ const Stereo3dFormat *s3d,
const size_t x,
const size_t y)
{
@@ -581,7 +583,7 @@ static void imb_stereo3d_squeeze_ImBuf(ImBuf *ibuf,
}
static void imb_stereo3d_unsqueeze_ImBuf(ImBuf *ibuf,
- Stereo3dFormat *s3d,
+ const Stereo3dFormat *s3d,
const size_t x,
const size_t y)
{
@@ -597,7 +599,7 @@ static void imb_stereo3d_unsqueeze_ImBuf(ImBuf *ibuf,
}
static void imb_stereo3d_squeeze_rectf(
- float *rectf, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
+ float *rectf, const Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
{
ImBuf *ibuf;
size_t width, height;
@@ -631,7 +633,7 @@ static void imb_stereo3d_squeeze_rectf(
}
static void imb_stereo3d_squeeze_rect(
- int *rect, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
+ int *rect, const Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
{
ImBuf *ibuf;
size_t width, height;
@@ -693,7 +695,7 @@ static void imb_stereo3d_data_init(Stereo3DData *s3d_data,
s3d_data->rectf.stereo = rectf_stereo;
}
-int *IMB_stereo3d_from_rect(ImageFormatData *im_format,
+int *IMB_stereo3d_from_rect(const ImageFormatData *im_format,
const size_t x,
const size_t y,
const size_t channels,
@@ -717,7 +719,7 @@ int *IMB_stereo3d_from_rect(ImageFormatData *im_format,
return r_rect;
}
-float *IMB_stereo3d_from_rectf(ImageFormatData *im_format,
+float *IMB_stereo3d_from_rectf(const ImageFormatData *im_format,
const size_t x,
const size_t y,
const size_t channels,
@@ -741,7 +743,7 @@ float *IMB_stereo3d_from_rectf(ImageFormatData *im_format,
return r_rectf;
}
-ImBuf *IMB_stereo3d_ImBuf(ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right)
+ImBuf *IMB_stereo3d_ImBuf(const ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right)
{
ImBuf *ibuf_stereo = NULL;
Stereo3DData s3d_data = {{NULL}};
@@ -776,7 +778,7 @@ ImBuf *IMB_stereo3d_ImBuf(ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *i
return ibuf_stereo;
}
-static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, Stereo3dFormat *s3d)
+static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d)
{
switch (s3d->display_mode) {
case S3D_DISPLAY_ANAGLYPH:
@@ -803,7 +805,7 @@ static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, Stereo3dFormat *s3d)
/** \name Reading Stereo ImBuf's
* \{ */
-static void imb_stereo3d_read_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyphType mode)
+static void imb_stereo3d_read_anaglyph(const Stereo3DData *s3d, enum eStereo3dAnaglyphType mode)
{
int x, y;
size_t width = s3d->x;
@@ -901,7 +903,7 @@ static void imb_stereo3d_read_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyph
}
}
-static void imb_stereo3d_read_interlace(Stereo3DData *s3d,
+static void imb_stereo3d_read_interlace(const Stereo3DData *s3d,
enum eStereo3dInterlaceType mode,
const bool swap)
{
@@ -1159,7 +1161,7 @@ static void imb_stereo3d_read_interlace(Stereo3DData *s3d,
}
/* stereo input (s3d->rectf.stereo) is always unsqueezed */
-static void imb_stereo3d_read_sidebyside(Stereo3DData *s3d, const bool crosseyed)
+static void imb_stereo3d_read_sidebyside(const Stereo3DData *s3d, const bool crosseyed)
{
int y;
size_t width = s3d->x;
@@ -1208,7 +1210,7 @@ static void imb_stereo3d_read_sidebyside(Stereo3DData *s3d, const bool crosseyed
}
/* stereo input (s3d->rectf.stereo) is always unsqueezed */
-static void imb_stereo3d_read_topbottom(Stereo3DData *s3d)
+static void imb_stereo3d_read_topbottom(const Stereo3DData *s3d)
{
int y;
size_t width = s3d->x;
@@ -1258,7 +1260,7 @@ static void imb_stereo3d_read_topbottom(Stereo3DData *s3d)
/** \name Preparing To Call The Read Functions
* \{ */
-void IMB_ImBufFromStereo3d(Stereo3dFormat *s3d,
+void IMB_ImBufFromStereo3d(const Stereo3dFormat *s3d,
ImBuf *ibuf_stereo3d,
ImBuf **r_ibuf_left,
ImBuf **r_ibuf_right)
@@ -1337,7 +1339,7 @@ void IMB_ImBufFromStereo3d(Stereo3dFormat *s3d,
*r_ibuf_right = ibuf_right;
}
-static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, Stereo3dFormat *s3d)
+static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d)
{
switch (s3d->display_mode) {
case S3D_DISPLAY_ANAGLYPH:
diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h
index a8436772299..f093f1f6e15 100644
--- a/source/blender/render/RE_pipeline.h
+++ b/source/blender/render/RE_pipeline.h
@@ -242,10 +242,13 @@ void RE_AcquiredResultGet32(struct Render *re,
unsigned int *rect,
int view_id);
+struct ImBuf *RE_render_result_rect_to_ibuf(struct RenderResult *rr,
+ const struct ImageFormatData *imf,
+ const float dither,
+ const int view_id);
void RE_render_result_rect_from_ibuf(struct RenderResult *rr,
- struct RenderData *rd,
- struct ImBuf *ibuf,
- int view_id);
+ const struct ImBuf *ibuf,
+ const int view_id);
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name);
float *RE_RenderLayerGetPass(struct RenderLayer *rl, const char *name, const char *viewname);
@@ -305,11 +308,6 @@ void RE_GetViewPlane(struct Render *re, rctf *r_viewplane, rcti *r_disprect);
*/
void RE_init_threadcount(Render *re);
-bool RE_WriteRenderViewsImage(struct ReportList *reports,
- struct RenderResult *rr,
- struct Scene *scene,
- bool stamp,
- char *name);
bool RE_WriteRenderViewsMovie(struct ReportList *reports,
struct RenderResult *rr,
struct Scene *scene,
@@ -372,16 +370,7 @@ void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene
* Only the temp file!
*/
bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode);
-/**
- * Called from the UI and render pipeline, to save multi-layer and multi-view
- * images, optionally isolating a specific, view, layer or RGBA/Z pass.
- */
-bool RE_WriteRenderResult(struct ReportList *reports,
- RenderResult *rr,
- const char *filename,
- struct ImageFormatData *imf,
- const char *view,
- int layer);
+
struct RenderResult *RE_MultilayerConvert(
void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
@@ -463,9 +452,9 @@ bool RE_allow_render_generic_object(struct Object *ob);
/******* defined in render_result.c *********/
-bool RE_HasCombinedLayer(RenderResult *res);
-bool RE_HasFloatPixels(RenderResult *res);
-bool RE_RenderResult_is_stereo(RenderResult *res);
+bool RE_HasCombinedLayer(const RenderResult *res);
+bool RE_HasFloatPixels(const RenderResult *res);
+bool RE_RenderResult_is_stereo(const RenderResult *res);
struct RenderView *RE_RenderViewGetById(struct RenderResult *rr, int view_id);
struct RenderView *RE_RenderViewGetByName(struct RenderResult *rr, const char *viewname);
diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c
index 614c03eba11..0ca2ca82cf7 100644
--- a/source/blender/render/intern/pipeline.c
+++ b/source/blender/render/intern/pipeline.c
@@ -45,6 +45,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_image_format.h"
+#include "BKE_image_save.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_lib_remap.h"
@@ -223,41 +224,6 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
fflush(stdout);
}
-static void render_print_save_message(ReportList *reports, const char *name, int ok, int err)
-{
- if (ok) {
- /* no need to report, just some helpful console info */
- printf("Saved: '%s'\n", name);
- }
- else {
- /* report on error since users will want to know what failed */
- BKE_reportf(reports, RPT_ERROR, "Render error (%s) cannot save: '%s'", strerror(err), name);
- }
-}
-
-static int render_imbuf_write_stamp_test(ReportList *reports,
- Scene *scene,
- struct RenderResult *rr,
- ImBuf *ibuf,
- const char *name,
- const ImageFormatData *imf,
- bool stamp)
-{
- int ok;
-
- if (stamp) {
- /* writes the name of the individual cameras */
- ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, imf);
- }
- else {
- ok = BKE_imbuf_write(ibuf, name, imf);
- }
-
- render_print_save_message(reports, name, ok, errno);
-
- return ok;
-}
-
void RE_FreeRenderResult(RenderResult *rr)
{
render_result_free(rr);
@@ -1385,7 +1351,7 @@ static void do_render_sequencer(Render *re)
if (ibuf_arr[view_id]) {
/* copy ibuf into combined pixel rect */
- RE_render_result_rect_from_ibuf(rr, &re->r, ibuf_arr[view_id], view_id);
+ RE_render_result_rect_from_ibuf(rr, ibuf_arr[view_id], view_id);
if (ibuf_arr[view_id]->metadata && (re->r.stamp & R_STAMP_STRIPMETA)) {
/* ensure render stamp info first */
@@ -1979,129 +1945,6 @@ void RE_RenderFreestyleExternal(Render *re)
/** \name Read/Write Render Result (Images & Movies)
* \{ */
-bool RE_WriteRenderViewsImage(
- ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name)
-{
- bool ok = true;
- RenderData *rd = &scene->r;
-
- if (!rr) {
- return false;
- }
-
- bool is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
- bool is_exr_rr = ELEM(rd->im_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
- RE_HasFloatPixels(rr);
-
- if (rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
- ok = RE_WriteRenderResult(reports, rr, name, &rd->im_format, NULL, -1);
- render_print_save_message(reports, name, ok, errno);
- }
-
- /* mono, legacy code */
- else if (is_mono || (rd->im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
- RenderView *rv;
- int view_id;
- char filepath[FILE_MAX];
-
- BLI_strncpy(filepath, name, sizeof(filepath));
-
- for (view_id = 0, rv = rr->views.first; rv; rv = rv->next, view_id++) {
- if (!is_mono) {
- BKE_scene_multiview_view_filepath_get(&scene->r, filepath, rv->name, 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);
-
- /* optional preview images for exr */
- if (ok && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
- ImageFormatData imf = rd->im_format;
- imf.imtype = R_IMF_IMTYPE_JPEG90;
-
- if (BLI_path_extension_check(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;
- IMB_colormanagement_imbuf_for_write(
- ibuf, true, false, &scene->view_settings, &scene->display_settings, &imf);
-
- 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);
- }
- }
- }
- else { /* R_IMF_VIEWS_STEREO_3D */
- BLI_assert(scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D);
-
- if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
- printf("Stereo 3D not supported for MultiLayer image: %s\n", name);
- }
- else {
- ImBuf *ibuf_arr[3] = {NULL};
- const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- int i;
-
- for (i = 0; i < 2; i++) {
- int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
- ibuf_arr[i] = render_result_rect_to_ibuf(rr, rd, view_id);
- IMB_colormanagement_imbuf_for_write(ibuf_arr[i],
- true,
- false,
- &scene->view_settings,
- &scene->display_settings,
- &scene->r.im_format);
- IMB_prepare_write_ImBuf(IMB_isfloat(ibuf_arr[i]), ibuf_arr[i]);
- }
-
- ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]);
-
- ok = render_imbuf_write_stamp_test(
- reports, scene, rr, ibuf_arr[2], name, &rd->im_format, stamp);
-
- /* optional preview images for exr */
- if (ok && is_exr_rr && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
- ImageFormatData imf = rd->im_format;
- imf.imtype = R_IMF_IMTYPE_JPEG90;
-
- if (BLI_path_extension_check(name, ".exr")) {
- name[strlen(name) - 4] = 0;
- }
-
- BKE_image_path_ensure_ext_from_imformat(name, &imf);
- ibuf_arr[2]->planes = 24;
-
- ok = render_imbuf_write_stamp_test(
- reports, scene, rr, ibuf_arr[2], name, &rd->im_format, stamp);
- }
-
- /* imbuf knows which rects are not part of ibuf */
- for (i = 0; i < 3; i++) {
- IMB_freeImBuf(ibuf_arr[i]);
- }
- }
- }
-
- return ok;
-}
-
bool RE_WriteRenderViewsMovie(ReportList *reports,
RenderResult *rr,
Scene *scene,
@@ -2111,20 +1954,20 @@ bool RE_WriteRenderViewsMovie(ReportList *reports,
const int totvideos,
bool preview)
{
- bool is_mono;
bool ok = true;
if (!rr) {
return false;
}
- is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
+ const bool is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
+ const float dither = scene->r.dither_intensity;
if (is_mono || (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
int view_id;
for (view_id = 0; view_id < totvideos; view_id++) {
const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
- ImBuf *ibuf = render_result_rect_to_ibuf(rr, &scene->r, view_id);
+ ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &rd->im_format, dither, view_id);
IMB_colormanagement_imbuf_for_write(
ibuf, true, false, &scene->view_settings, &scene->display_settings, &scene->r.im_format);
@@ -2153,7 +1996,7 @@ bool RE_WriteRenderViewsMovie(ReportList *reports,
for (i = 0; i < 2; i++) {
int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
- ibuf_arr[i] = render_result_rect_to_ibuf(rr, &scene->r, view_id);
+ ibuf_arr[i] = RE_render_result_rect_to_ibuf(rr, &rd->im_format, dither, view_id);
IMB_colormanagement_imbuf_for_write(ibuf_arr[i],
true,
@@ -2225,7 +2068,7 @@ static int do_write_image_or_movie(Render *re,
}
/* write images as individual images or stereo */
- ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, true, name);
+ ok = BKE_image_render_write(re->reports, &rres, scene, true, name);
}
RE_ReleaseResultImageViews(re, &rres);
diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c
index f4ae3caa77b..d938c15e35e 100644
--- a/source/blender/render/intern/render_result.c
+++ b/source/blender/render/intern/render_result.c
@@ -27,6 +27,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_image_format.h"
+#include "BKE_image_save.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -749,12 +750,6 @@ void render_result_views_new(RenderResult *rr, const RenderData *rd)
}
}
-bool render_result_has_views(const RenderResult *rr)
-{
- const RenderView *rv = rr->views.first;
- return (rv && (rv->next || rv->name[0]));
-}
-
/*********************************** Merge ***********************************/
static void do_merge_tile(
@@ -809,162 +804,6 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
}
}
-bool RE_WriteRenderResult(ReportList *reports,
- RenderResult *rr,
- const char *filename,
- ImageFormatData *imf,
- const char *view,
- int layer)
-{
- void *exrhandle = IMB_exr_get_handle();
- 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));
-
- /* Write first layer if not multilayer and no layer was specified. */
- if (!multi_layer && layer == -1) {
- layer = 0;
- }
-
- /* First add views since IMB_exr_add_channel checks number of views. */
- if (render_result_has_views(rr)) {
- LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
- if (!view || STREQ(view, rview->name)) {
- IMB_exr_add_view(exrhandle, rview->name);
- }
- }
- }
-
- /* Compositing result. */
- if (rr->have_combined) {
- LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
- if (!rview->rectf) {
- continue;
- }
-
- const char *viewname = rview->name;
- if (view) {
- if (!STREQ(view, viewname)) {
- continue;
- }
-
- viewname = "";
- }
-
- /* Skip compositing if only a single other layer is requested. */
- if (!multi_layer && layer != 0) {
- continue;
- }
-
- for (int a = 0; a < 4; a++) {
- char passname[EXR_PASS_MAXNAME];
- char layname[EXR_PASS_MAXNAME];
- const char *chan_id = "RGBA";
-
- if (multi_layer) {
- IMB_exr_channel_name(passname, NULL, "Combined", NULL, chan_id, a);
- 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);
- }
- }
- }
-
- /* 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;
- }
-
- LISTBASE_FOREACH (RenderPass *, rp, &rl->passes) {
- /* 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;
- }
-
- /* Skip pass if it does not match the requested view(s). */
- const char *viewname = rp->view;
- if (view) {
- if (!STREQ(view, viewname)) {
- continue;
- }
-
- viewname = "";
- }
-
- /* We only store RGBA passes as half float, for
- * others precision loss can be problematic. */
- bool pass_half_float = half_float &&
- (STR_ELEM(rp->chan_id, "RGB", "RGBA", "R", "G", "B", "A"));
-
- 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) {
- IMB_exr_channel_name(passname, NULL, rp->name, NULL, rp->chan_id, a);
- BLI_strncpy(layname, rl->name, sizeof(layname));
- }
- else {
- passname[0] = rp->chan_id[a];
- passname[1] = '\0';
- layname[0] = '\0';
- }
-
- IMB_exr_add_channel(exrhandle,
- layname,
- passname,
- viewname,
- rp->channels,
- rp->channels * rr->rectx,
- rp->rect + a,
- pass_half_float);
- }
- }
- }
-
- errno = 0;
-
- BLI_make_existing_file(filename);
-
- 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);
- }
- else {
- /* TODO: get the error from openexr's exception. */
- BKE_reportf(
- reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno));
- }
-
- IMB_exr_close(exrhandle);
- return success;
-}
-
/**************************** Single Layer Rendering *************************/
void render_result_single_layer_begin(Render *re)
@@ -1117,7 +956,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, NULL, -1);
+ BKE_image_render_write_exr(NULL, rr, str, NULL, NULL, -1);
}
bool render_result_exr_file_cache_read(Render *re)
@@ -1153,9 +992,12 @@ bool render_result_exr_file_cache_read(Render *re)
/*************************** Combined Pixel Rect *****************************/
-ImBuf *render_result_rect_to_ibuf(RenderResult *rr, const RenderData *rd, const int view_id)
+ImBuf *RE_render_result_rect_to_ibuf(RenderResult *rr,
+ const ImageFormatData *imf,
+ const float dither,
+ const int view_id)
{
- ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
+ ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, imf->planes, 0);
RenderView *rv = RE_RenderViewGetById(rr, view_id);
/* if not exists, BKE_imbuf_write makes one */
@@ -1164,15 +1006,15 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, const RenderData *rd, const
ibuf->zbuf_float = rv->rectz;
/* float factor for random dither, imbuf takes care of it */
- ibuf->dither = rd->dither_intensity;
+ ibuf->dither = dither;
/* prepare to gamma correct to sRGB color space
* note that sequence editor can generate 8bpc render buffers
*/
if (ibuf->rect) {
- if (BKE_imtype_valid_depths(rd->im_format.imtype) &
+ if (BKE_imtype_valid_depths(imf->imtype) &
(R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) {
- if (rd->im_format.depth == R_IMF_CHAN_DEPTH_8) {
+ if (imf->depth == R_IMF_CHAN_DEPTH_8) {
/* Higher depth bits are supported but not needed for current file output. */
ibuf->rect_float = NULL;
}
@@ -1188,7 +1030,7 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, const RenderData *rd, const
/* Color -> gray-scale. */
/* editing directly would alter the render view */
- if (rd->im_format.planes == R_IMF_PLANES_BW) {
+ if (imf->planes == R_IMF_PLANES_BW) {
ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
IMB_color_to_bw(ibuf_bw);
IMB_freeImBuf(ibuf);
@@ -1198,10 +1040,7 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, const RenderData *rd, const
return ibuf;
}
-void RE_render_result_rect_from_ibuf(RenderResult *rr,
- RenderData *UNUSED(rd),
- ImBuf *ibuf,
- const int view_id)
+void RE_render_result_rect_from_ibuf(RenderResult *rr, const ImBuf *ibuf, const int view_id)
{
RenderView *rv = RE_RenderViewGetById(rr, view_id);
@@ -1278,15 +1117,13 @@ void render_result_rect_get_pixels(RenderResult *rr,
/*************************** multiview functions *****************************/
-bool RE_HasCombinedLayer(RenderResult *rr)
+bool RE_HasCombinedLayer(const RenderResult *rr)
{
- RenderView *rv;
-
if (rr == NULL) {
return false;
}
- rv = rr->views.first;
+ const RenderView *rv = rr->views.first;
if (rv == NULL) {
return false;
}
@@ -1294,11 +1131,9 @@ bool RE_HasCombinedLayer(RenderResult *rr)
return (rv->rect32 || rv->rectf);
}
-bool RE_HasFloatPixels(RenderResult *rr)
+bool RE_HasFloatPixels(const RenderResult *rr)
{
- RenderView *rview;
-
- for (rview = rr->views.first; rview; rview = rview->next) {
+ for (const RenderView *rview = rr->views.first; rview; rview = rview->next) {
if (rview->rect32 && !rview->rectf) {
return false;
}
@@ -1307,7 +1142,7 @@ bool RE_HasFloatPixels(RenderResult *rr)
return true;
}
-bool RE_RenderResult_is_stereo(RenderResult *rr)
+bool RE_RenderResult_is_stereo(const RenderResult *rr)
{
if (!BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name))) {
return false;
diff --git a/source/blender/render/intern/render_result.h b/source/blender/render/intern/render_result.h
index 07929f4351f..30f49775562 100644
--- a/source/blender/render/intern/render_result.h
+++ b/source/blender/render/intern/render_result.h
@@ -131,7 +131,6 @@ void render_result_views_shallowcopy(struct RenderResult *dst, struct RenderResu
* Free the views created temporarily.
*/
void render_result_views_shallowdelete(struct RenderResult *rr);
-bool render_result_has_views(const struct RenderResult *rr);
#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_) \
{ \