Blender  V2.93
COM_OutputFileMultiViewOperation.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2015, Blender Foundation.
17  */
18 
21 
22 #include <cstring>
23 
24 #include "BLI_listbase.h"
25 #include "BLI_path_util.h"
26 #include "BLI_string.h"
27 
28 #include "BKE_global.h"
29 #include "BKE_image.h"
30 #include "BKE_main.h"
31 #include "BKE_scene.h"
32 
33 #include "DNA_color_types.h"
34 #include "MEM_guardedalloc.h"
35 
36 #include "IMB_colormanagement.h"
37 #include "IMB_imbuf.h"
38 #include "IMB_imbuf_types.h"
39 
40 namespace blender::compositor {
41 
42 /************************************ OpenEXR Singlelayer Multiview ******************************/
43 
45  const RenderData *rd,
46  const bNodeTree *tree,
47  DataType datatype,
49  const char *path,
50  const ColorManagedViewSettings *viewSettings,
51  const ColorManagedDisplaySettings *displaySettings,
52  const char *viewName,
53  const bool saveAsRender)
55  rd, tree, datatype, format, path, viewSettings, displaySettings, viewName, saveAsRender)
56 {
57 }
58 
60 {
61  size_t width = this->getWidth();
62  size_t height = this->getHeight();
63  SceneRenderView *srv;
64 
65  if (width != 0 && height != 0) {
66  void *exrhandle;
67 
68  exrhandle = IMB_exr_get_handle_name(filename);
69 
71  return exrhandle;
72  }
73 
74  IMB_exr_clear_channels(exrhandle);
75 
76  for (srv = (SceneRenderView *)this->m_rd->views.first; srv; srv = srv->next) {
77  if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false) {
78  continue;
79  }
80 
81  IMB_exr_add_view(exrhandle, srv->name);
82  add_exr_channels(exrhandle, nullptr, this->m_datatype, srv->name, width, false, nullptr);
83  }
84 
85  BLI_make_existing_file(filename);
86 
87  /* prepare the file with all the channels */
88 
90  exrhandle, filename, width, height, this->m_format->exr_codec, nullptr) == 0) {
91  printf("Error Writing Singlelayer Multiview Openexr\n");
92  IMB_exr_close(exrhandle);
93  }
94  else {
95  IMB_exr_clear_channels(exrhandle);
96  return exrhandle;
97  }
98  }
99  return nullptr;
100 }
101 
103 {
104  unsigned int width = this->getWidth();
105  unsigned int height = this->getHeight();
106 
107  if (width != 0 && height != 0) {
108  void *exrhandle;
109  char filename[FILE_MAX];
110 
112  this->m_path,
114  this->m_rd->cfra,
116  (this->m_rd->scemode & R_EXTENSION) != 0,
117  true,
118  nullptr);
119 
120  exrhandle = this->get_handle(filename);
121  add_exr_channels(exrhandle,
122  nullptr,
123  this->m_datatype,
124  this->m_viewName,
125  width,
127  this->m_outputBuffer);
128 
129  /* memory can only be freed after we write all views to the file */
130  this->m_outputBuffer = nullptr;
131  this->m_imageInput = nullptr;
132 
133  /* ready to close the file */
135  IMB_exr_write_channels(exrhandle);
136 
137  /* free buffer memory for all the views */
138  free_exr_channels(exrhandle, this->m_rd, nullptr, this->m_datatype);
139 
140  /* remove exr handle and data */
141  IMB_exr_close(exrhandle);
142  }
143  }
144 }
145 
146 /************************************ OpenEXR Multilayer Multiview *******************************/
147 
149  const Scene *scene,
150  const RenderData *rd,
151  const bNodeTree *tree,
152  const char *path,
153  char exr_codec,
154  bool exr_half_float,
155  const char *viewName)
156  : OutputOpenExrMultiLayerOperation(scene, rd, tree, path, exr_codec, exr_half_float, viewName)
157 {
158 }
159 
161 {
162  unsigned int width = this->getWidth();
163  unsigned int height = this->getHeight();
164 
165  if (width != 0 && height != 0) {
166 
167  void *exrhandle;
168  SceneRenderView *srv;
169 
170  /* get a new global handle */
171  exrhandle = IMB_exr_get_handle_name(filename);
172 
174  return exrhandle;
175  }
176 
177  IMB_exr_clear_channels(exrhandle);
178 
179  /* check renderdata for amount of views */
180  for (srv = (SceneRenderView *)this->m_rd->views.first; srv; srv = srv->next) {
181 
182  if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false) {
183  continue;
184  }
185 
186  IMB_exr_add_view(exrhandle, srv->name);
187 
188  for (unsigned int i = 0; i < this->m_layers.size(); i++) {
189  add_exr_channels(exrhandle,
190  this->m_layers[i].name,
191  this->m_layers[i].datatype,
192  srv->name,
193  width,
194  this->m_exr_half_float,
195  nullptr);
196  }
197  }
198 
199  BLI_make_existing_file(filename);
200 
201  /* prepare the file with all the channels for the header */
202  StampData *stamp_data = createStampData();
203  if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, stamp_data) ==
204  0) {
205  printf("Error Writing Multilayer Multiview Openexr\n");
206  IMB_exr_close(exrhandle);
207  BKE_stamp_data_free(stamp_data);
208  }
209  else {
210  IMB_exr_clear_channels(exrhandle);
211  BKE_stamp_data_free(stamp_data);
212  return exrhandle;
213  }
214  }
215  return nullptr;
216 }
217 
219 {
220  unsigned int width = this->getWidth();
221  unsigned int height = this->getHeight();
222 
223  if (width != 0 && height != 0) {
224  void *exrhandle;
225  char filename[FILE_MAX];
226 
228  this->m_path,
230  this->m_rd->cfra,
232  (this->m_rd->scemode & R_EXTENSION) != 0,
233  true,
234  nullptr);
235 
236  exrhandle = this->get_handle(filename);
237 
238  for (unsigned int i = 0; i < this->m_layers.size(); i++) {
239  add_exr_channels(exrhandle,
240  this->m_layers[i].name,
241  this->m_layers[i].datatype,
242  this->m_viewName,
243  width,
244  this->m_exr_half_float,
245  this->m_layers[i].outputBuffer);
246  }
247 
248  for (unsigned int i = 0; i < this->m_layers.size(); i++) {
249  /* memory can only be freed after we write all views to the file */
250  this->m_layers[i].outputBuffer = nullptr;
251  this->m_layers[i].imageInput = nullptr;
252  }
253 
254  /* ready to close the file */
256  IMB_exr_write_channels(exrhandle);
257 
258  /* free buffer memory for all the views */
259  for (unsigned int i = 0; i < this->m_layers.size(); i++) {
261  exrhandle, this->m_rd, this->m_layers[i].name, this->m_layers[i].datatype);
262  }
263 
264  IMB_exr_close(exrhandle);
265  }
266  }
267 }
268 
269 /******************************** Stereo3D ******************************/
270 
272  const bNodeTree *tree,
273  DataType datatype,
275  const char *path,
276  const char *name,
277  const ColorManagedViewSettings *viewSettings,
278  const ColorManagedDisplaySettings *displaySettings,
279  const char *viewName,
280  const bool saveAsRender)
282  rd, tree, datatype, format, path, viewSettings, displaySettings, viewName, saveAsRender)
283 {
284  BLI_strncpy(this->m_name, name, sizeof(this->m_name));
285  this->m_channels = get_datatype_size(datatype);
286 }
287 
288 void *OutputStereoOperation::get_handle(const char *filename)
289 {
290  size_t width = this->getWidth();
291  size_t height = this->getHeight();
292  const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
293  size_t i;
294 
295  if (width != 0 && height != 0) {
296  void *exrhandle;
297 
298  exrhandle = IMB_exr_get_handle_name(filename);
299 
301  return exrhandle;
302  }
303 
304  IMB_exr_clear_channels(exrhandle);
305 
306  for (i = 0; i < 2; i++) {
307  IMB_exr_add_view(exrhandle, names[i]);
308  }
309 
310  return exrhandle;
311  }
312  return nullptr;
313 }
314 
316 {
317  unsigned int width = this->getWidth();
318  unsigned int height = this->getHeight();
319 
320  if (width != 0 && height != 0) {
321  void *exrhandle;
322 
323  exrhandle = this->get_handle(this->m_path);
324  float *buf = this->m_outputBuffer;
325 
326  /* populate single EXR channel with view data */
327  IMB_exr_add_channel(exrhandle,
328  nullptr,
329  this->m_name,
330  this->m_viewName,
331  1,
332  this->m_channels * width * height,
333  buf,
335 
336  this->m_imageInput = nullptr;
337  this->m_outputBuffer = nullptr;
338 
339  /* create stereo ibuf */
341  ImBuf *ibuf[3] = {nullptr};
342  const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
343  char filename[FILE_MAX];
344  int i;
345 
346  /* get rectf from EXR */
347  for (i = 0; i < 2; i++) {
348  float *rectf = IMB_exr_channel_rect(exrhandle, nullptr, this->m_name, names[i]);
349  ibuf[i] = IMB_allocImBuf(width, height, this->m_format->planes, 0);
350 
351  ibuf[i]->channels = this->m_channels;
352  ibuf[i]->rect_float = rectf;
353  ibuf[i]->mall |= IB_rectfloat;
354  ibuf[i]->dither = this->m_rd->dither_intensity;
355 
356  /* do colormanagement in the individual views, so it doesn't need to do in the stereo */
358  ibuf[i], true, false, this->m_viewSettings, this->m_displaySettings, this->m_format);
359  IMB_prepare_write_ImBuf(IMB_isfloat(ibuf[i]), ibuf[i]);
360  }
361 
362  /* create stereo buffer */
363  ibuf[2] = IMB_stereo3d_ImBuf(this->m_format, ibuf[0], ibuf[1]);
364 
366  this->m_path,
368  this->m_rd->cfra,
369  this->m_format,
370  (this->m_rd->scemode & R_EXTENSION) != 0,
371  true,
372  nullptr);
373 
374  BKE_imbuf_write(ibuf[2], filename, this->m_format);
375 
376  /* imbuf knows which rects are not part of ibuf */
377  for (i = 0; i < 3; i++) {
378  IMB_freeImBuf(ibuf[i]);
379  }
380 
381  IMB_exr_close(exrhandle);
382  }
383  }
384 }
385 
386 } // namespace blender::compositor
void BKE_stamp_data_free(struct StampData *stamp_data)
Definition: image.c:2757
int BKE_imbuf_write(struct ImBuf *ibuf, const char *name, const struct ImageFormatData *imf)
void BKE_image_path_from_imformat(char *string, const char *base, const char *relbase, int frame, const struct ImageFormatData *im_format, const bool use_ext, const bool use_frames, const char *suffix)
void BKE_image_path_from_imtype(char *string, const char *base, const char *relbase, int frame, const char imtype, const bool use_ext, const bool use_frames, const char *suffix)
Definition: image.c:3091
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:439
bool BKE_scene_multiview_is_render_view_active(const struct RenderData *rd, const struct SceneRenderView *srv)
bool BKE_scene_multiview_is_render_view_last(const struct RenderData *rd, const char *viewname)
bool BKE_scene_multiview_is_render_view_first(const struct RenderData *rd, const char *viewname)
bool BLI_make_existing_file(const char *name)
Definition: path_util.c:1347
#define FILE_MAX
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define STEREO_LEFT_NAME
#define R_EXTENSION
#define R_IMF_IMTYPE_MULTILAYER
@ R_IMF_CHAN_DEPTH_16
#define STEREO_RIGHT_NAME
#define R_IMF_IMTYPE_OPENEXR
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
struct ImBuf * IMB_colormanagement_imbuf_for_write(struct ImBuf *ibuf, bool save_as_render, bool allocate_result, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, struct ImageFormatData *image_format_data)
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:478
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
bool IMB_prepare_write_ImBuf(const bool isfloat, struct ImBuf *ibuf)
Definition: writeimage.c:68
struct ImBuf * IMB_stereo3d_ImBuf(struct ImageFormatData *im_format, struct ImBuf *ibuf_left, struct ImBuf *ibuf_right)
Definition: stereoimbuf.c:761
bool IMB_isfloat(const struct ImBuf *ibuf)
Contains defines and structs used throughout the imbuf module.
@ IB_rectfloat
Read Guarded memory(de)allocation.
OutputOpenExrMultiLayerMultiViewOperation(const Scene *scene, const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec, bool exr_half_float, const char *viewName)
OutputOpenExrSingleLayerMultiViewOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName, const bool saveAsRender)
const ColorManagedDisplaySettings * m_displaySettings
OutputStereoOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, struct ImageFormatData *format, const char *path, const char *name, const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings, const char *viewName, const bool saveAsRender)
Scene scene
void * tree
DataType
possible data types for sockets
Definition: COM_defines.h:27
format
Definition: logImageCore.h:47
static char ** names
Definition: makesdna.c:162
int get_datatype_size(DataType datatype)
void add_exr_channels(void *exrhandle, const char *layerName, const DataType datatype, const char *viewName, const size_t width, bool use_half_float, float *buf)
void free_exr_channels(void *exrhandle, const RenderData *rd, const char *layerName, const DataType datatype)
void IMB_exr_add_view(void *handle, const char *name)
void IMB_exr_close(void *handle)
void IMB_exr_clear_channels(void *handle)
void * IMB_exr_get_handle_name(const char *name)
void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, const char *viewname, int xstride, int ystride, float *rect, bool use_half_float)
void IMB_exr_write_channels(void *handle)
int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress, const StampData *stamp)
float * IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *viewname)
int channels
float dither
float * rect_float
void * first
Definition: DNA_listBase.h:47
float dither_intensity
ListBase views
struct SceneRenderView * next