50 const bool guess_path,
51 const bool save_as_render)
55 if (iuser ==
nullptr) {
136 if (guess_path && opts->
filepath[0] == 0) {
137 const bool is_prev_save = !
STREQ(
G.filepath_last_image,
"//");
168 return (ibuf !=
nullptr);
205 const char *filepath,
224 const bool save_copy,
225 const char *filepath,
226 bool *r_colorspace_changed)
231 "Could not write image: %s",
232 errno ? strerror(errno) :
"internal error, see console");
278 *r_colorspace_changed =
true;
285 if (colormanaged_ibuf != ibuf) {
308 bool *r_colorspace_changed)
321 ImBuf *colormanaged_ibuf =
nullptr;
352 const int layer = (iuser && !is_multilayer) ? iuser->
layer : -1;
368 R
"(Did not write, the image doesn't have a "%s" and "%s" views)",
382 R
"(Did not write, the image doesn't have a "%s" and "%s" views)",
394 double rr_ppm_prev[2] = {0, 0};
396 if (save_as_render && rr) {
400 double ppm[2] = {0, 0};
409 auto render_result_restore_ppm = [rr, save_as_render, rr_ppm_prev]() {
410 if (save_as_render && rr) {
421 render_result_restore_ppm();
438 render_result_restore_ppm();
445 (is_exr_rr ?
true : save_copy),
447 r_colorspace_changed);
459 for (
int i = 0;
i < totviews;
i++) {
461 bool ok_view =
false;
468 reports, rr, filepath, imf, save_as_render,
view, layer);
507 render_result_restore_ppm();
520 render_result_restore_ppm();
526 ImBuf *ibuf_stereo[2] = {
nullptr};
533 bool stereo_ok =
true;
535 for (
int i = 0;
i < 2;
i++) {
549 view_iuser.
view = id;
559 if (ibuf ==
nullptr) {
561 reports,
RPT_ERROR,
"Did not write, unexpected error when saving stereo image");
593 for (
int i = 0;
i < 2;
i++) {
597 render_result_restore_ppm();
602 render_result_restore_ppm();
615 if (iuser ==
nullptr) {
621 bool colorspace_changed =
false;
624 char *udim_pattern =
nullptr;
632 "When saving a tiled image, the path '%s' must contain a valid UDIM marker",
648 tile_opts.
filepath, udim_pattern, tile_format,
tile->tile_number);
667 if (colorspace_changed) {
683 if (imf ==
nullptr) {
693 tmp_output_rects.
append(output_rect);
698 output_rect, width, height, channels, from_colorspace, to_colorspace,
false);
704 float *input_buffer,
int width,
int height,
int channels,
Vector<float *> &temporary_buffers)
707 "Gray Scale Buffer For EXR");
708 temporary_buffers.
append(gray_scale_output);
712 for (
const int64_t y : sub_y_range) {
721 return gray_scale_output;
729 "Opaque Alpha Buffer For EXR");
730 temporary_buffers.
append(alpha_output);
734 for (
const int64_t y : sub_y_range) {
736 alpha_output[
y *
int64_t(width) +
x] = 1.0;
748 const char *view_name,
760 if (!is_multi_layer && layer != 0) {
767 if (!render_view->ibuf || !render_view->ibuf->float_buffer.data) {
773 if (view_name && !
STREQ(view_name, render_view->name)) {
779 const char *render_view_name = view_name ?
"" : render_view->name;
782 const int channels_count_in_buffer = 4;
784 render_view->ibuf->float_buffer.data,
785 render_result->
rectx,
786 render_result->
recty,
787 channels_count_in_buffer,
790 render_view->ibuf->float_buffer.data;
794 if (is_multi_layer) {
795 for (
int i = 0;
i < channels_count_in_buffer;
i++) {
802 channels_count_in_buffer,
803 channels_count_in_buffer * render_result->
rectx,
814 const int required_channels = imf ? imf->
planes / 8 : 4;
815 if (required_channels == 1) {
817 render_result->
rectx,
818 render_result->
recty,
819 channels_count_in_buffer,
826 render_result->
rectx,
834 for (
int i = 0;
i < required_channels;
i++) {
837 std::string(1,
"RGBA"[
i]).c_str(),
839 channels_count_in_buffer,
840 channels_count_in_buffer * render_result->
rectx,
849 const char *filepath,
851 const bool save_as_render,
859 if (!multi_layer && layer == -1) {
865 if (first_rview && (first_rview->
next || first_rview->
name[0])) {
881 if (!multi_layer && nr != layer) {
894 const char *viewname = render_pass->view;
907 const bool pass_half_float = half_float && pass_RGBA;
910 float *output_rect = (save_as_render && pass_RGBA) ?
912 render_pass->ibuf->float_buffer.data,
915 render_pass->channels,
918 render_pass->ibuf->float_buffer.data;
922 for (
int i = 0;
i < render_pass->channels;
i++) {
928 if (!has_multiple_layers && rl->name[0] ==
'\0') {
929 passname[0] = render_pass->chan_id[
i];
931 STRNCPY(layname, render_pass->name);
935 passname,
nullptr, render_pass->name,
nullptr, render_pass->chan_id,
i);
943 render_pass->channels,
944 render_pass->channels * rr->
rectx,
957 const int required_channels = imf ? imf->
planes / 8 : 4;
958 if (required_channels == render_pass->channels ||
959 (required_channels != 1 && render_pass->channels != 1))
961 for (
int i = 0;
i < std::min(required_channels, render_pass->channels);
i++) {
964 std::string(1, render_pass->chan_id[
i]).c_str(),
966 render_pass->channels,
967 render_pass->channels * rr->
rectx,
972 else if (required_channels == 1) {
976 output_rect, rr->
rectx, rr->
recty, render_pass->channels, tmp_output_rects);
978 exrhandle,
"",
"V", viewname, 1, rr->
rectx, gray_scale_output, pass_half_float);
980 else if (render_pass->channels == 1) {
984 for (
int i = 0;
i < 3;
i++) {
987 std::string(1,
"RGB"[
i]).c_str(),
998 if (required_channels == 4 && render_pass->channels < 4) {
1002 exrhandle,
"",
"A", viewname, 1, rr->
rectx, alpha_output, pass_half_float);
1011 const int compress = (imf ? imf->
exr_codec : 0);
1012 const int quality = (imf ? imf->
quality : 90);
1021 reports,
RPT_ERROR,
"Error writing render result, %s (see console)", strerror(errno));
1024 for (
float *rect : tmp_output_rects) {
1035 const char *filepath,
1042 printf(
"Saved: '%s'\n", filepath);
1048 reports,
RPT_ERROR,
"Render error (%s) cannot save: '%s'", strerror(err), filepath);
1056 const char *filepath,
1079 const char *filepath_basis,
1081 bool save_as_render)
1092 if (!save_as_render) {
1094 &
format->linear_colorspace_settings);
1098 const bool is_exr_rr =
ELEM(
1105 reports, rr, filepath_basis, &image_format, save_as_render,
nullptr, -1);
1116 STRNCPY(filepath, filepath_basis);
1124 reports, rr, filepath, &image_format, save_as_render, rv->name, -1);
1133 filepath[strlen(filepath) - 4] = 0;
1142 reports, scene, rr, ibuf, filepath, &image_format, stamp);
1153 reports, scene, rr, ibuf, filepath, &image_format, stamp);
1164 STRNCPY(filepath, filepath_basis);
1167 printf(
"Stereo 3D not supported for MultiLayer image: %s\n", filepath);
1170 ImBuf *ibuf_arr[3] = {
nullptr};
1174 for (
i = 0;
i < 2;
i++) {
1184 reports, scene, rr, ibuf_arr[2], filepath, &image_format, stamp);
1192 filepath[strlen(filepath) - 4] = 0;
1196 ibuf_arr[2]->
planes = 24;
1199 reports, scene, rr, ibuf_arr[2], filepath, &image_format, stamp);
1208 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)
void BKE_scene_ppm_get(const RenderData *rd, double r_ppm[2])
File and directory operations.
bool BLI_file_ensure_parent_dir_exists(const char *filepath) ATTR_NONNULL(1)
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count_at_most(const ListBase *listbase, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_findstringindex(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE void copy_v2_v2_db(double r[2], const double a[2])
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
bool bool BLI_path_extension_strip(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)
bool BLI_path_make_safe_filename(char *filename) ATTR_NONNULL(1)
#define SNPRINTF(dst, format,...)
char * STRNCPY(char(&dst)[N], const char *src)
#define STR_CONCAT(dst, len, suffix)
#define RE_PASSNAME_COMBINED
@ R_IMF_IMTYPE_MULTILAYER
@ R_IMF_COLOR_MANAGEMENT_FOLLOW_SCENE
#define STEREO_RIGHT_NAME
bool IMB_colormanagement_space_name_is_scene_linear(const char *name)
void IMB_colormanagement_transform_float(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide)
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)
@ COLOR_ROLE_DEFAULT_BYTE
@ COLOR_ROLE_SCENE_LINEAR
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3])
const char * IMB_colormanagement_role_colorspace_name_get(int role)
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
void IMB_freeImBuf(ImBuf *ibuf)
ImBuf * IMB_stereo3d_ImBuf(const ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right)
void IMB_free_float_pixels(ImBuf *ibuf)
void IMB_free_byte_pixels(ImBuf *ibuf)
void IMB_exr_add_view(void *handle, const char *name)
bool IMB_exr_begin_write(void *handle, const char *filepath, int width, int height, const double ppm[2], int compress, int quality, const StampData *stamp)
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)
#define ID_BLEND_PATH(_bmain, _id)
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)
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)
const ccl_global KernelWorkTile * tile
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(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)
bool RE_ResultIsMultiView(RenderResult *rr)
char filepath[IMB_FILEPATH_SIZE]
ImBufFloatBuffer float_buffer
ImbFormatOptions foptions
ImBufByteBuffer byte_buffer
ImageFormatData im_format
ColorManagedColorspaceSettings colorspace_settings
struct Stereo3dFormat * stereo3d_format
struct ImageFormatData im_format
struct StampData * stamp_data
void * BKE_image_get_tile