87 const bool guess_path,
88 const bool save_as_render)
92 if (iuser ==
nullptr) {
98 memset(opts, 0,
sizeof(*opts));
110 bool is_depth_set =
false;
159 if (is_depth_set ==
false) {
169 if (guess_path && opts->
filepath[0] == 0) {
170 const bool is_prev_save = !
STREQ(
G.filepath_last_image,
"//");
201 return (ibuf !=
nullptr);
221 &image->colorspace_settings);
238 const char *filepath,
257 const bool save_copy,
258 const char *filepath,
259 bool *r_colorspace_changed)
295 base_tile->
gen_flag &= ~IMA_GEN_TILE;
308 *r_colorspace_changed =
true;
315 if (colormanaged_ibuf != ibuf) {
338 bool *r_colorspace_changed)
351 ImBuf *colormanaged_ibuf =
nullptr;
383 const int layer = (iuser && !is_multilayer) ? iuser->
layer : -1;
398 R
"(Did not write, the image doesn't have a "%s" and "%s" views)",
412 R
"(Did not write, the image doesn't have a "%s" and "%s" views)",
427 reports, rr, opts->
filepath, imf, save_as_render,
nullptr, layer);
435 reports, rr, opts->
filepath, imf, save_as_render,
nullptr, layer);
447 (is_exr_rr ?
true : save_copy),
449 r_colorspace_changed);
461 for (
int i = 0; i < totviews; i++) {
463 bool ok_view =
false;
470 reports, rr, filepath, imf, save_as_render, view, layer);
471 image_save_post(reports, ima, ibuf, ok_view, opts,
true, filepath, r_colorspace_changed);
486 view_iuser.
flag &= ~IMA_SHOW_STEREO;
503 image_save_post(reports, ima, ibuf, ok_view, opts,
true, filepath, r_colorspace_changed);
517 reports, rr, opts->
filepath, imf, save_as_render,
nullptr, layer);
522 ImBuf *ibuf_stereo[2] = {
nullptr};
529 bool stereo_ok =
true;
531 for (
int i = 0; i < 2; i++) {
541 view_iuser.
flag &= ~IMA_SHOW_STEREO;
545 view_iuser.
view = id;
555 if (ibuf ==
nullptr) {
557 reports,
RPT_ERROR,
"Did not write, unexpected error when saving stereo image");
587 for (
int i = 0; i < 2; i++) {
605 if (iuser ==
nullptr) {
611 bool colorspace_changed =
false;
614 char *udim_pattern =
nullptr;
622 "When saving a tiled image, the path '%s' must contain a valid UDIM marker",
638 tile_opts.
filepath, udim_pattern, tile_format,
tile->tile_number);
650 tile->gen_flag &= ~IMA_GEN_TILE;
657 if (colorspace_changed) {
673 if (imf ==
nullptr) {
683 tmp_output_rects.
append(output_rect);
688 output_rect, width, height, channels, from_colorspace, to_colorspace,
false);
694 float *input_buffer,
int width,
int height,
int channels,
Vector<float *> &temporary_buffers)
696 float *gray_scale_output =
static_cast<float *
>(
698 temporary_buffers.
append(gray_scale_output);
702 for (
const int64_t y : sub_y_range) {
711 return gray_scale_output;
718 float *alpha_output =
static_cast<float *
>(
719 MEM_malloc_arrayN(width * height,
sizeof(
float),
"Opaque Alpha Buffer For EXR"));
720 temporary_buffers.
append(alpha_output);
724 for (
const int64_t y : sub_y_range) {
726 alpha_output[y *
int64_t(width) +
x] = 1.0;
738 const char *view_name,
750 if (!is_multi_layer && layer != 0) {
757 if (!render_view->ibuf || !render_view->ibuf->float_buffer.data) {
763 if (view_name && !
STREQ(view_name, render_view->name)) {
769 const char *render_view_name = view_name ?
"" : render_view->name;
772 const int channels_count_in_buffer = 4;
774 render_view->ibuf->float_buffer.data,
775 render_result->
rectx,
776 render_result->
recty,
777 channels_count_in_buffer,
780 render_view->ibuf->float_buffer.data;
784 if (is_multi_layer) {
785 for (
int i = 0; i < channels_count_in_buffer; i++) {
792 channels_count_in_buffer,
793 channels_count_in_buffer * render_result->
rectx,
804 const int required_channels = imf ? imf->
planes / 8 : 4;
805 if (required_channels == 1) {
807 render_result->
rectx,
808 render_result->
recty,
809 channels_count_in_buffer,
816 render_result->
rectx,
824 for (
int i = 0; i < required_channels; i++) {
827 std::string(1,
"RGBA"[i]).c_str(),
829 channels_count_in_buffer,
830 channels_count_in_buffer * render_result->
rectx,
839 const char *filepath,
841 const bool save_as_render,
849 if (!multi_layer && layer == -1) {
855 if (first_rview && (first_rview->
next || first_rview->
name[0])) {
857 if (!view ||
STREQ(view, rview->name)) {
871 if (!multi_layer && nr != layer) {
884 const char *viewname = render_pass->view;
886 if (!
STREQ(view, viewname)) {
897 const bool pass_half_float = half_float && pass_RGBA;
900 float *output_rect = (save_as_render && pass_RGBA) ?
902 render_pass->ibuf->float_buffer.data,
905 render_pass->channels,
908 render_pass->ibuf->float_buffer.data;
912 for (
int i = 0; i < render_pass->channels; i++) {
918 if (!has_multiple_layers && rl->name[0] ==
'\0') {
919 passname[0] = render_pass->chan_id[i];
921 STRNCPY(layname, render_pass->name);
925 passname,
nullptr, render_pass->name,
nullptr, render_pass->chan_id, i);
933 render_pass->channels,
934 render_pass->channels * rr->
rectx,
947 const int required_channels = imf ? imf->
planes / 8 : 4;
948 if (required_channels == render_pass->channels ||
949 (required_channels != 1 && render_pass->channels != 1))
951 for (
int i = 0; i < std::min(required_channels, render_pass->channels); i++) {
954 std::string(1, render_pass->chan_id[i]).c_str(),
956 render_pass->channels,
957 render_pass->channels * rr->
rectx,
962 else if (required_channels == 1) {
966 output_rect, rr->
rectx, rr->
recty, render_pass->channels, tmp_output_rects);
968 exrhandle,
"",
"V", viewname, 1, rr->
rectx, gray_scale_output, pass_half_float);
970 else if (render_pass->channels == 1) {
974 for (
int i = 0; i < 3; i++) {
977 std::string(1,
"RGB"[i]).c_str(),
988 if (required_channels == 4 && render_pass->channels < 4) {
992 exrhandle,
"",
"A", viewname, 1, rr->
rectx, alpha_output, pass_half_float);
1001 int compress = (imf ? imf->
exr_codec : 0);
1010 reports,
RPT_ERROR,
"Error writing render result, %s (see console)", strerror(errno));
1013 for (
float *rect : tmp_output_rects) {
1024 const char *filepath,
1031 printf(
"Saved: '%s'\n", filepath);
1037 reports,
RPT_ERROR,
"Render error (%s) cannot save: '%s'", strerror(err), filepath);
1045 const char *filepath,
1068 const char *filepath_basis,
1070 bool save_as_render)
1081 if (!save_as_render) {
1083 &
format->linear_colorspace_settings);
1087 const bool is_exr_rr =
ELEM(
1090 const float dither = scene->r.dither_intensity;
1094 reports, rr, filepath_basis, &image_format, save_as_render,
nullptr, -1);
1105 STRNCPY(filepath, filepath_basis);
1113 reports, rr, filepath, &image_format, save_as_render, rv->name, -1);
1122 filepath[strlen(filepath) - 4] = 0;
1131 reports, scene, rr, ibuf, filepath, &image_format, stamp);
1142 reports, scene, rr, ibuf, filepath, &image_format, stamp);
1153 STRNCPY(filepath, filepath_basis);
1156 printf(
"Stereo 3D not supported for MultiLayer image: %s\n", filepath);
1159 ImBuf *ibuf_arr[3] = {
nullptr};
1163 for (i = 0; i < 2; i++) {
1172 reports, scene, rr, ibuf_arr[2], filepath, &image_format, stamp);
1180 filepath[strlen(filepath) - 4] = 0;
1184 ibuf_arr[2]->
planes = 24;
1187 reports, scene, rr, ibuf_arr[2], filepath, &image_format, stamp);
1191 for (i = 0; i < 3; i++) {
void BKE_imbuf_stamp_info(const RenderResult *rr, ImBuf *ibuf)
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
char * BKE_image_get_tile_strformat(const char *filepath, eUDIM_TILE_FORMAT *r_tile_format)
void BKE_image_set_filepath_from_tile_number(char *filepath, const char *pattern, eUDIM_TILE_FORMAT tile_format, int tile_number)
RenderPass * BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_image_release_renderresult(Scene *scene, Image *ima, RenderResult *render_result)
void BKE_image_user_file_path_ex(const Main *bmain, const ImageUser *iuser, const Image *ima, char *filepath, const bool resolve_udim, const bool resolve_multiview)
#define IMA_SIGNAL_COLORMANAGE
bool BKE_imbuf_alpha_test(ImBuf *ibuf)
void BKE_imageuser_default(ImageUser *iuser)
bool BKE_image_is_stereo(const Image *ima)
bool BKE_image_is_multiview(const Image *ima)
bool BKE_imbuf_write(ImBuf *ibuf, const char *filepath, const ImageFormatData *imf)
void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
bool BKE_imbuf_write_stamp(const Scene *scene, const RenderResult *rr, ImBuf *ibuf, const char *filepath, const ImageFormatData *imf)
bool BKE_imbuf_write_as(ImBuf *ibuf, const char *filepath, const ImageFormatData *imf, bool save_copy)
RenderResult * BKE_image_acquire_renderresult(Scene *scene, Image *ima)
void BKE_image_multiview_index(const Image *ima, ImageUser *iuser)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
void BKE_scene_multiview_view_filepath_get(const RenderData *rd, const char *filepath, const char *view, char *r_filepath)
File and directory operations.
bool BLI_file_ensure_parent_dir_exists(const char *filepath) ATTR_NONNULL(1)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count_at_most(const struct ListBase *listbase, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_findstringindex(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
bool BLI_path_make_safe(char *path) ATTR_NONNULL(1)
#define BLI_path_join(...)
bool BLI_path_extension_check(const char *path, const char *ext) ATTR_NONNULL(1
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
#define STRNCPY(dst, src)
#define STR_CONCAT(dst, len, suffix)
#define ID_BLEND_PATH(_bmain, _id)
#define RE_PASSNAME_COMBINED
@ R_IMF_IMTYPE_MULTILAYER
#define STEREO_RIGHT_NAME
@ R_IMF_COLOR_MANAGEMENT_FOLLOW_SCENE
bool IMB_colormanagement_space_name_is_scene_linear(const char *name)
ImBuf * IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, bool allocate_result, const ImageFormatData *image_format)
bool IMB_colormanagement_space_name_is_data(const char *name)
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3])
const char * IMB_colormanagement_role_colorspace_name_get(int role)
@ COLOR_ROLE_DEFAULT_BYTE
@ COLOR_ROLE_SCENE_LINEAR
void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide)
void imb_freerectImBuf(ImBuf *ibuf)
void imb_freerectfloatImBuf(ImBuf *ibuf)
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
ImBuf * IMB_stereo3d_ImBuf(const ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right)
Contains defines and structs used throughout the imbuf module.
bool IMB_exr_begin_write(void *handle, const char *filepath, int width, int height, int compress, const StampData *stamp)
void IMB_exr_add_view(void *handle, const char *name)
void IMB_exr_close(void *handle)
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)
void * IMB_exr_get_handle()
Read Guarded memory(de)allocation.
void append(const T &value)
void IMB_freeImBuf(ImBuf *)
bool BKE_image_save(ReportList *reports, Main *bmain, Image *ima, ImageUser *iuser, const ImageSaveOptions *opts)
static float * image_exr_from_scene_linear_to_output(float *rect, const int width, const int height, const int channels, const ImageFormatData *imf, Vector< float * > &tmp_output_rects)
static void image_save_post(ReportList *reports, Image *ima, ImBuf *ibuf, int ok, const ImageSaveOptions *opts, const bool save_copy, const char *filepath, bool *r_colorspace_changed)
static void imbuf_save_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf)
bool BKE_image_render_write_exr(ReportList *reports, const RenderResult *rr, const char *filepath, const ImageFormatData *imf, const bool save_as_render, const char *view, int layer)
static bool image_render_write_stamp_test(ReportList *reports, const Scene *scene, const RenderResult *rr, ImBuf *ibuf, const char *filepath, const ImageFormatData *imf, const bool stamp)
static char imtype_best_depth(ImBuf *ibuf, const char imtype)
bool BKE_image_save_options_init(ImageSaveOptions *opts, Main *bmain, Scene *scene, Image *ima, ImageUser *iuser, const bool guess_path, const bool save_as_render)
static float * image_exr_from_rgb_to_bw(float *input_buffer, int width, int height, int channels, Vector< float * > &temporary_buffers)
static bool image_save_single(ReportList *reports, Image *ima, ImageUser *iuser, const ImageSaveOptions *opts, bool *r_colorspace_changed)
static float * image_exr_opaque_alpha_buffer(int width, int height, Vector< float * > &temporary_buffers)
static void image_render_print_save_message(ReportList *reports, const char *filepath, int ok, int err)
static void image_save_update_filepath(Image *ima, const char *filepath, const ImageSaveOptions *opts)
bool BKE_image_render_write(ReportList *reports, RenderResult *rr, const Scene *scene, const bool stamp, const char *filepath_basis, const ImageFormatData *format, bool save_as_render)
void BKE_image_save_options_update(ImageSaveOptions *opts, const Image *image)
static void add_exr_compositing_result(void *exr_handle, const RenderResult *render_result, const ImageFormatData *imf, bool save_as_render, const char *view_name, int layer, Vector< float * > &temporary_buffers)
void BKE_image_save_options_free(ImageSaveOptions *opts)
ccl_global const KernelWorkTile * tile
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_dupallocN)(const void *vmemh)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
bool RE_RenderPassIsColor(const RenderPass *render_pass)
bool RE_HasFloatPixels(const RenderResult *result)
ImBuf * RE_render_result_rect_to_ibuf(RenderResult *rr, const ImageFormatData *imf, const float dither, const int view_id)
void RE_render_result_full_channel_name(char *fullname, const char *layname, const char *passname, const char *viewname, const char *chan_id, const int channel)
char filepath[IMB_FILEPATH_SIZE]
ImBufFloatBuffer float_buffer
ImbFormatOptions foptions
ImBufByteBuffer byte_buffer
ImageFormatData im_format
ColorManagedColorspaceSettings colorspace_settings
struct Stereo3dFormat * stereo3d_format
struct StampData * stamp_data
void * BKE_image_get_tile