Blender V5.0
render_context.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <memory>
6#include <string>
7
8#include "BLI_assert.h"
9#include "BLI_listbase.h"
10#include "BLI_map.hh"
11#include "BLI_math_vector.h"
13#include "BLI_string.h"
14#include "BLI_string_utf8.h"
15#include "BLI_utildefines.h"
16
17#include "MEM_guardedalloc.h"
18
19#include "IMB_imbuf.hh"
20#include "IMB_imbuf_types.hh"
21
22#include "DNA_scene_types.h"
24
25#include "BKE_image.hh"
26#include "BKE_image_save.hh"
27#include "BKE_report.hh"
28#include "BKE_scene.hh"
29
30#include "RE_pipeline.h"
31
32#include "COM_render_context.hh"
33
34namespace blender::compositor {
35
36/* ------------------------------------------------------------------------------------------------
37 * File Output
38 */
39
40FileOutput::FileOutput(const std::string &path,
42 int2 size,
43 bool save_as_render)
44 : path_(path), format_(format), save_as_render_(save_as_render)
45{
46 render_result_ = MEM_callocN<RenderResult>("Temporary Render Result For File Output");
47
48 render_result_->rectx = size.x;
49 render_result_->recty = size.y;
50
51 /* NOTE: set dummy values which will won't be used unless overwritten.
52 * When `save_as_render` is set, this is overwritten by the scenes PPM setting.
53 * We *could* support setting the DPI in the file output node too. */
54 render_result_->ppm[0] = 0.0;
55 render_result_->ppm[1] = 0.0;
56
57 /* File outputs are always single layer, as images are actually stored in passes on that single
58 * layer. Create a single unnamed layer to add the passes to. A single unnamed layer is treated
59 * by the EXR writer as a special case where the channel names take the form:
60 * <pass-name>.<view-name>.<channel-id>
61 * Otherwise, the layer name would have preceded in the pass name in yet another section. */
62 RenderLayer *render_layer = MEM_callocN<RenderLayer>("Render Layer For File Output.");
63 BLI_addtail(&render_result_->layers, render_layer);
64 render_layer->name[0] = '\0';
65
66 /* File outputs do not support previews. */
67 format_.flag &= ~R_IMF_FLAG_PREVIEW_JPG;
68}
69
71{
72 RE_FreeRenderResult(render_result_);
73}
74
75void FileOutput::add_view(const char *view_name)
76{
77 /* Empty views can only be added for EXR images. */
79
80 RenderView *render_view = MEM_callocN<RenderView>("Render View For File Output.");
81 BLI_addtail(&render_result_->views, render_view);
82 STRNCPY_UTF8(render_view->name, view_name);
83}
84
85void FileOutput::add_view(const char *view_name, int channels, float *buffer)
86{
87 RenderView *render_view = MEM_callocN<RenderView>("Render View For File Output.");
88 BLI_addtail(&render_result_->views, render_view);
89 STRNCPY_UTF8(render_view->name, view_name);
90
91 render_view->ibuf = IMB_allocImBuf(
92 render_result_->rectx, render_result_->recty, channels * 8, 0);
93 render_view->ibuf->channels = channels;
94 IMB_assign_float_buffer(render_view->ibuf, buffer, IB_TAKE_OWNERSHIP);
95}
96
97void FileOutput::add_pass(const char *pass_name,
98 const char *view_name,
99 const char *channels,
100 float *buffer)
101{
102 /* Passes can only be added for EXR images. */
104
105 RenderLayer *render_layer = static_cast<RenderLayer *>(render_result_->layers.first);
106 RenderPass *render_pass = MEM_callocN<RenderPass>("Render Pass For File Output.");
107 BLI_addtail(&render_layer->passes, render_pass);
108 STRNCPY(render_pass->name, pass_name);
109 STRNCPY(render_pass->view, view_name);
110 STRNCPY(render_pass->chan_id, channels);
111
112 const int channels_count = BLI_strnlen(channels, 4);
113 render_pass->rectx = render_result_->rectx;
114 render_pass->recty = render_result_->recty;
115 render_pass->channels = channels_count;
116
117 render_pass->ibuf = IMB_allocImBuf(
118 render_result_->rectx, render_result_->recty, channels_count * 8, 0);
119 render_pass->ibuf->channels = channels_count;
120 copy_v2_v2_db(render_pass->ibuf->ppm, render_result_->ppm);
121 IMB_assign_float_buffer(render_pass->ibuf, buffer, IB_TAKE_OWNERSHIP);
122}
123
124void FileOutput::add_meta_data(std::string key, std::string value)
125{
126 meta_data_.add(key, value);
127}
128
130{
131 ReportList reports;
132 BKE_reports_init(&reports, RPT_STORE);
133
134 /* Add scene stamp data as meta data as well as the custom meta data. */
135 BKE_render_result_stamp_info(scene, nullptr, render_result_, false);
136 for (const auto &field : meta_data_.items()) {
137 BKE_render_result_stamp_data(render_result_, field.key.c_str(), field.value.c_str());
138 }
139
140 /* NOTE: without this the file will be written without any density information.
141 * So always write this. */
142 if (save_as_render_ || true) {
143 BKE_scene_ppm_get(&scene->r, render_result_->ppm);
144 }
145
147 &reports, render_result_, scene, true, path_.c_str(), &format_, save_as_render_);
148
149 BKE_reports_free(&reports);
150}
151
152/* ------------------------------------------------------------------------------------------------
153 * Render Context
154 */
155
158 int2 size,
159 bool save_as_render)
160{
161 return *file_outputs_.lookup_or_add_cb(
162 path, [&]() { return std::make_unique<FileOutput>(path, format, size, save_as_render); });
163}
164
166{
167 for (std::unique_ptr<FileOutput> &file_output : file_outputs_.values()) {
168 file_output->save(scene);
169 }
170}
171
172} // namespace blender::compositor
void BKE_render_result_stamp_info(Scene *scene, Object *camera, RenderResult *rr, bool allocate_only)
void BKE_render_result_stamp_data(RenderResult *rr, const char *key, const char *value)
bool BKE_image_render_write(ReportList *reports, RenderResult *rr, const Scene *scene, const bool stamp, const char *filepath_basis, const ImageFormatData *format=nullptr, bool save_as_render=true)
@ RPT_STORE
Definition BKE_report.hh:56
void BKE_reports_free(ReportList *reports)
Definition report.cc:97
void BKE_reports_init(ReportList *reports, int flag)
Definition report.cc:82
void BKE_scene_ppm_get(const RenderData *rd, double r_ppm[2])
Definition scene.cc:3234
#define BLI_assert(a)
Definition BLI_assert.h:46
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
MINLINE void copy_v2_v2_db(double r[2], const double a[2])
int char char int int int int size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.cc:913
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
#define STRNCPY_UTF8(dst, src)
#define ELEM(...)
@ R_IMF_IMTYPE_OPENEXR
@ R_IMF_IMTYPE_MULTILAYER
@ R_IMF_FLAG_PREVIEW_JPG
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership)
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
@ IB_TAKE_OWNERSHIP
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void add_view(const char *view_name)
FileOutput(const std::string &path, const ImageFormatData &format, int2 size, bool save_as_render)
void add_pass(const char *pass_name, const char *view_name, const char *channels, float *buffer)
void add_meta_data(std::string key, std::string value)
FileOutput & get_file_output(std::string path, ImageFormatData format, int2 size, bool save_as_render)
format
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
VecBase< int32_t, 2 > int2
void RE_FreeRenderResult(RenderResult *rr)
double ppm[2]
ListBase passes
Definition RE_pipeline.h:94
char name[RE_MAXNAME]
Definition RE_pipeline.h:89
char chan_id[24]
Definition RE_pipeline.h:56
struct ImBuf * ibuf
Definition RE_pipeline.h:67
char name[64]
Definition RE_pipeline.h:55
char view[64]
Definition RE_pipeline.h:72
struct ImBuf * ibuf
Definition RE_pipeline.h:49
char name[64]
Definition RE_pipeline.h:42
struct RenderData r