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)
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);
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++) {
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);
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);
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])) {
871 if (!multi_layer && nr != layer) {
884 const char *viewname = render_pass->view;
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(
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
@ COLOR_ROLE_DEFAULT_BYTE
@ COLOR_ROLE_SCENE_LINEAR
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)
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.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
void append(const T &value)
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
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 ImageFormatData im_format
struct StampData * stamp_data
void * BKE_image_get_tile