Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_output.py36
-rw-r--r--source/blender/blenkernel/BKE_image_save.h3
-rw-r--r--source/blender/blenkernel/intern/image_format.cc27
-rw-r--r--source/blender/blenkernel/intern/image_save.cc69
-rw-r--r--source/blender/editors/interface/interface_templates.c7
-rw-r--r--source/blender/editors/space_image/image_buttons.c30
-rw-r--r--source/blender/editors/space_image/image_ops.c21
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h1
-rw-r--r--source/blender/imbuf/intern/colormanagement.c38
-rw-r--r--source/blender/makesdna/DNA_scene_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_color.c5
-rw-r--r--source/blender/makesrna/intern/rna_scene.c56
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_output_file.cc16
-rw-r--r--source/blender/render/intern/render_result.c2
14 files changed, 262 insertions, 55 deletions
diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py
index 34e86184097..312a580bf7d 100644
--- a/release/scripts/startup/bl_ui/properties_output.py
+++ b/release/scripts/startup/bl_ui/properties_output.py
@@ -296,6 +296,41 @@ class RENDER_PT_output_views(RenderOutputButtonsPanel, Panel):
layout.template_image_views(rd.image_settings)
+class RENDER_PT_output_color_management(RenderOutputButtonsPanel, Panel):
+ bl_label = "Color Management"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = "RENDER_PT_output"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ def draw(self, context):
+ scene = context.scene
+ image_settings = scene.render.image_settings
+
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ layout.row().prop(image_settings, "color_management", text=" ", expand=True)
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
+
+ if image_settings.color_management == 'OVERRIDE':
+ owner = image_settings
+ else:
+ owner = scene
+ flow.enabled = False
+
+ col = flow.column()
+
+ if image_settings.has_linear_colorspace:
+ if hasattr(owner, 'linear_colorspace_settings'):
+ col.prop(owner.linear_colorspace_settings, "name", text="Color Space")
+ else:
+ col.prop(owner.display_settings, "display_device")
+ col.separator()
+ col.template_colormanaged_view_settings(owner, "view_settings")
+
+
class RENDER_PT_encoding(RenderOutputButtonsPanel, Panel):
bl_label = "Encoding"
bl_parent_id = "RENDER_PT_output"
@@ -484,6 +519,7 @@ classes = (
RENDER_PT_stereoscopy,
RENDER_PT_output,
RENDER_PT_output_views,
+ RENDER_PT_output_color_management,
RENDER_PT_encoding,
RENDER_PT_encoding_video,
RENDER_PT_encoding_audio,
diff --git a/source/blender/blenkernel/BKE_image_save.h b/source/blender/blenkernel/BKE_image_save.h
index f9d07387463..b022e677845 100644
--- a/source/blender/blenkernel/BKE_image_save.h
+++ b/source/blender/blenkernel/BKE_image_save.h
@@ -47,7 +47,7 @@ bool BKE_image_save(struct ReportList *reports,
struct ImageUser *iuser,
struct ImageSaveOptions *opts);
-/* Lower level image writing. */
+/* Render saving. */
/* Save single or multilayer OpenEXR files from the render result.
* Optionally saves only a specific view or layer. */
@@ -55,6 +55,7 @@ bool BKE_image_render_write_exr(struct ReportList *reports,
const struct RenderResult *rr,
const char *filename,
const struct ImageFormatData *imf,
+ const bool save_as_render,
const char *view,
int layer);
diff --git a/source/blender/blenkernel/intern/image_format.cc b/source/blender/blenkernel/intern/image_format.cc
index 0783e343ec9..44aa9e21195 100644
--- a/source/blender/blenkernel/intern/image_format.cc
+++ b/source/blender/blenkernel/intern/image_format.cc
@@ -904,8 +904,27 @@ void BKE_image_format_init_for_write(ImageFormatData *imf,
{
*imf = (imf_src) ? *imf_src : scene_src->r.im_format;
- /* Use general scene settings also used for display. */
- BKE_color_managed_display_settings_copy(&imf->display_settings, &scene_src->display_settings);
- BKE_color_managed_view_settings_copy(&imf->view_settings, &scene_src->view_settings);
- BKE_color_managed_colorspace_settings_init(&imf->linear_colorspace_settings);
+ if (imf_src && imf_src->color_management == R_IMF_COLOR_MANAGEMENT_OVERRIDE) {
+ /* Use settings specific to one node, image save operation, etc. */
+ BKE_color_managed_display_settings_copy(&imf->display_settings, &imf_src->display_settings);
+ BKE_color_managed_view_settings_copy(&imf->view_settings, &imf_src->view_settings);
+ BKE_color_managed_colorspace_settings_copy(&imf->linear_colorspace_settings,
+ &imf_src->linear_colorspace_settings);
+ }
+ else if (scene_src->r.im_format.color_management == R_IMF_COLOR_MANAGEMENT_OVERRIDE) {
+ /* Use scene settings specific to render output. */
+ BKE_color_managed_display_settings_copy(&imf->display_settings,
+ &scene_src->r.im_format.display_settings);
+ BKE_color_managed_view_settings_copy(&imf->view_settings,
+ &scene_src->r.im_format.view_settings);
+ BKE_color_managed_colorspace_settings_copy(&imf->linear_colorspace_settings,
+ &scene_src->r.im_format.linear_colorspace_settings);
+ }
+ else {
+ /* Use general scene settings also used for display. */
+ BKE_color_managed_display_settings_copy(&imf->display_settings, &scene_src->display_settings);
+ BKE_color_managed_view_settings_copy(&imf->view_settings, &scene_src->view_settings);
+ STRNCPY(imf->linear_colorspace_settings.name,
+ IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR));
+ }
}
diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc
index b7f234aea59..f530183f967 100644
--- a/source/blender/blenkernel/intern/image_save.cc
+++ b/source/blender/blenkernel/intern/image_save.cc
@@ -11,6 +11,7 @@
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_vector.hh"
#include "DNA_image_types.h"
@@ -31,6 +32,8 @@
#include "RE_pipeline.h"
+using blender::Vector;
+
void BKE_image_save_options_init(ImageSaveOptions *opts, Main *bmain, Scene *scene)
{
memset(opts, 0, sizeof(*opts));
@@ -220,14 +223,16 @@ static bool image_save_single(ReportList *reports,
/* fancy multiview OpenEXR */
if (imf->views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
/* save render result */
- ok = BKE_image_render_write_exr(reports, rr, opts->filepath, imf, nullptr, layer);
+ ok = BKE_image_render_write_exr(
+ reports, rr, opts->filepath, imf, save_as_render, nullptr, layer);
image_save_post(reports, ima, ibuf, ok, opts, true, opts->filepath, r_colorspace_changed);
BKE_image_release_ibuf(ima, ibuf, lock);
}
/* regular mono pipeline */
else if (is_mono) {
if (is_exr_rr) {
- ok = BKE_image_render_write_exr(reports, rr, opts->filepath, imf, nullptr, layer);
+ ok = BKE_image_render_write_exr(
+ reports, rr, opts->filepath, imf, save_as_render, nullptr, layer);
}
else {
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, imf);
@@ -261,7 +266,8 @@ static bool image_save_single(ReportList *reports,
if (is_exr_rr) {
BKE_scene_multiview_view_filepath_get(&opts->scene->r, opts->filepath, view, filepath);
- ok_view = BKE_image_render_write_exr(reports, rr, filepath, imf, view, layer);
+ ok_view = BKE_image_render_write_exr(
+ reports, rr, filepath, imf, save_as_render, view, layer);
image_save_post(reports, ima, ibuf, ok_view, opts, true, filepath, r_colorspace_changed);
}
else {
@@ -307,7 +313,8 @@ static bool image_save_single(ReportList *reports,
/* stereo (multiview) images */
else if (opts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
- ok = BKE_image_render_write_exr(reports, rr, opts->filepath, imf, nullptr, layer);
+ ok = BKE_image_render_write_exr(
+ reports, rr, opts->filepath, imf, save_as_render, nullptr, layer);
image_save_post(reports, ima, ibuf, ok, opts, true, opts->filepath, r_colorspace_changed);
BKE_image_release_ibuf(ima, ibuf, lock);
}
@@ -450,10 +457,38 @@ bool BKE_image_save(
/* OpenEXR saving, single and multilayer. */
+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)
+{
+ if (imf == nullptr) {
+ return rect;
+ }
+
+ const char *to_colorspace = imf->linear_colorspace_settings.name;
+ if (to_colorspace[0] == '\0' || IMB_colormanagement_space_name_is_scene_linear(to_colorspace)) {
+ return rect;
+ }
+
+ float *output_rect = (float *)MEM_dupallocN(rect);
+ tmp_output_rects.append(output_rect);
+
+ const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(
+ COLOR_ROLE_SCENE_LINEAR);
+ IMB_colormanagement_transform(
+ output_rect, width, height, channels, from_colorspace, to_colorspace, false);
+
+ return output_rect;
+}
+
bool BKE_image_render_write_exr(ReportList *reports,
const RenderResult *rr,
- const char *filename,
+ const char *filepath,
const ImageFormatData *imf,
+ const bool save_as_render,
const char *view,
int layer)
{
@@ -461,6 +496,7 @@ bool BKE_image_render_write_exr(ReportList *reports,
const bool half_float = (imf && imf->depth == R_IMF_CHAN_DEPTH_16);
const bool multi_layer = !(imf && imf->imtype == R_IMF_IMTYPE_OPENEXR);
const bool write_z = !multi_layer && (imf && (imf->flag & R_IMF_FLAG_ZBUF));
+ Vector<float *> tmp_output_rects;
/* Write first layer if not multilayer and no layer was specified. */
if (!multi_layer && layer == -1) {
@@ -498,7 +534,10 @@ bool BKE_image_render_write_exr(ReportList *reports,
continue;
}
- float *output_rect = rview->rectf;
+ float *output_rect = (save_as_render) ?
+ image_exr_from_scene_linear_to_output(
+ rview->rectf, rr->rectx, rr->recty, 4, imf, tmp_output_rects) :
+ rview->rectf;
for (int a = 0; a < 4; a++) {
char passname[EXR_PASS_MAXNAME];
@@ -556,7 +595,11 @@ bool BKE_image_render_write_exr(ReportList *reports,
const bool pass_RGBA = (STR_ELEM(rp->chan_id, "RGB", "RGBA", "R", "G", "B", "A"));
const bool pass_half_float = half_float && pass_RGBA;
- float *output_rect = rp->rect;
+ /* Colorspace conversion only happens on RGBA passes. */
+ float *output_rect = (save_as_render && pass_RGBA) ?
+ image_exr_from_scene_linear_to_output(
+ rp->rect, rr->rectx, rr->recty, 4, imf, tmp_output_rects) :
+ rp->rect;
for (int a = 0; a < rp->channels; a++) {
/* Save Combined as RGBA if single layer save. */
@@ -587,11 +630,11 @@ bool BKE_image_render_write_exr(ReportList *reports,
errno = 0;
- BLI_make_existing_file(filename);
+ BLI_make_existing_file(filepath);
int compress = (imf ? imf->exr_codec : 0);
bool success = IMB_exr_begin_write(
- exrhandle, filename, rr->rectx, rr->recty, compress, rr->stamp_data);
+ exrhandle, filepath, rr->rectx, rr->recty, compress, rr->stamp_data);
if (success) {
IMB_exr_write_channels(exrhandle);
}
@@ -601,6 +644,10 @@ bool BKE_image_render_write_exr(ReportList *reports,
reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno));
}
+ for (float *rect : tmp_output_rects) {
+ MEM_freeN(rect);
+ }
+
IMB_exr_close(exrhandle);
return success;
}
@@ -664,7 +711,7 @@ bool BKE_image_render_write(ReportList *reports,
const float dither = scene->r.dither_intensity;
if (image_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
- ok = BKE_image_render_write_exr(reports, rr, filename, &image_format, nullptr, -1);
+ ok = BKE_image_render_write_exr(reports, rr, filename, &image_format, true, nullptr, -1);
image_render_print_save_message(reports, filename, ok, errno);
}
@@ -682,7 +729,7 @@ bool BKE_image_render_write(ReportList *reports,
}
if (is_exr_rr) {
- ok = BKE_image_render_write_exr(reports, rr, filepath, &image_format, rv->name, -1);
+ ok = BKE_image_render_write_exr(reports, rr, filepath, &image_format, true, rv->name, -1);
image_render_print_save_message(reports, filepath, ok, errno);
/* optional preview images for exr */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 077eedd6e58..38499a7f089 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -6223,16 +6223,13 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout,
ColorManagedViewSettings *view_settings = view_transform_ptr.data;
uiLayout *col = uiLayoutColumn(layout, false);
-
- uiLayout *row = uiLayoutRow(col, false);
- uiItemR(row, &view_transform_ptr, "view_transform", 0, IFACE_("View"), ICON_NONE);
+ uiItemR(col, &view_transform_ptr, "view_transform", 0, IFACE_("View"), ICON_NONE);
+ uiItemR(col, &view_transform_ptr, "look", 0, IFACE_("Look"), ICON_NONE);
col = uiLayoutColumn(layout, false);
uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE);
uiItemR(col, &view_transform_ptr, "gamma", 0, NULL, ICON_NONE);
- uiItemR(col, &view_transform_ptr, "look", 0, IFACE_("Look"), ICON_NONE);
-
col = uiLayoutColumn(layout, false);
uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, NULL, ICON_NONE);
if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index abde5f52bb0..208928afc1f 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -958,14 +958,11 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_ma
{
ImageFormatData *imf = imfptr->data;
ID *id = imfptr->owner_id;
- PointerRNA display_settings_ptr;
- PropertyRNA *prop;
const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
/* some settings depend on this being a scene that's rendered */
const bool is_render_out = (id && GS(id->name) == ID_SCE);
uiLayout *col;
- bool show_preview = false;
col = uiLayoutColumn(layout, false);
@@ -1005,7 +1002,6 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_ma
}
if (is_render_out && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
- show_preview = true;
uiItemR(col, imfptr, "use_preview", 0, NULL, ICON_NONE);
}
@@ -1037,18 +1033,22 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_ma
uiItemR(col, imfptr, "tiff_codec", 0, NULL, ICON_NONE);
}
- /* color management */
- if (color_management && (!BKE_imtype_requires_linear_float(imf->imtype) ||
- (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG))) {
- prop = RNA_struct_find_property(imfptr, "display_settings");
- display_settings_ptr = RNA_property_pointer_get(imfptr, prop);
-
- col = uiLayoutColumn(layout, false);
- uiItemL(col, IFACE_("Color Management"), ICON_NONE);
-
- uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE);
+ /* Override color management */
+ if (color_management) {
+ uiItemS(col);
+ uiItemR(col, imfptr, "color_management", 0, NULL, ICON_NONE);
- uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings");
+ if (imf->color_management == R_IMF_COLOR_MANAGEMENT_OVERRIDE) {
+ if (BKE_imtype_requires_linear_float(imf->imtype)) {
+ PointerRNA linear_settings_ptr = RNA_pointer_get(imfptr, "linear_colorspace_settings");
+ uiItemR(col, &linear_settings_ptr, "name", 0, IFACE_("Color Space"), ICON_NONE);
+ }
+ else {
+ PointerRNA display_settings_ptr = RNA_pointer_get(imfptr, "display_settings");
+ uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE);
+ uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings");
+ }
+ }
}
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index c4d69d589bf..1c4a1d7e8c9 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1737,7 +1737,7 @@ static int image_save_options_init(Main *bmain,
if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) {
/* imtype */
- BKE_image_format_copy(&opts->im_format, &scene->r.im_format);
+ BKE_image_format_init_for_write(&opts->im_format, scene, NULL);
is_depth_set = true;
if (!BKE_image_is_multiview(ima)) {
/* In case multiview is disabled,
@@ -1759,8 +1759,12 @@ static int image_save_options_init(Main *bmain,
/* use the multiview image settings as the default */
opts->im_format.stereo3d_format = *ima->stereo3d_format;
opts->im_format.views_format = ima->views_format;
+
+ BKE_image_format_color_management_copy_from_scene(&opts->im_format, scene);
}
+ opts->im_format.color_management = R_IMF_COLOR_MANAGEMENT_FOLLOW_SCENE;
+
if (ima->source == IMA_SRC_TILED) {
BLI_strncpy(opts->filepath, ima->filepath, sizeof(opts->filepath));
BLI_path_abs(opts->filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
@@ -1810,9 +1814,6 @@ static int image_save_options_init(Main *bmain,
STR_CONCAT(opts->filepath, len, ".<UDIM>");
}
}
-
- /* color management */
- BKE_image_format_color_management_copy_from_scene(&opts->im_format, scene);
}
BKE_image_release_ibuf(ima, ibuf, lock);
@@ -2002,15 +2003,21 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
ImageSaveData *isd = op->customdata;
PointerRNA imf_ptr;
const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview");
+ const bool use_color_management = RNA_boolean_get(op->ptr, "save_as_render");
- /* image template */
- RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->im_format, &imf_ptr);
- uiTemplateImageSettings(layout, &imf_ptr, false);
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
/* main draw call */
uiDefAutoButsRNA(
layout, op->ptr, image_save_as_draw_check_prop, NULL, NULL, UI_BUT_LABEL_ALIGN_NONE, false);
+ uiItemS(layout);
+
+ /* image template */
+ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->im_format, &imf_ptr);
+ uiTemplateImageSettings(layout, &imf_ptr, use_color_management);
+
/* multiview template */
if (is_multiview) {
uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index a336cc1770a..7cf2c02e657 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -53,6 +53,7 @@ bool IMB_colormanagement_space_is_data(struct ColorSpace *colorspace);
bool IMB_colormanagement_space_is_scene_linear(struct ColorSpace *colorspace);
bool IMB_colormanagement_space_is_srgb(struct ColorSpace *colorspace);
bool IMB_colormanagement_space_name_is_data(const char *name);
+bool IMB_colormanagement_space_name_is_scene_linear(const char *name);
/**
* Convert a float RGB triplet to the correct luminance weighted average.
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 8624a7866b6..15a586ea762 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -1394,6 +1394,12 @@ bool IMB_colormanagement_space_name_is_data(const char *name)
return (colorspace && colorspace->is_data);
}
+bool IMB_colormanagement_space_name_is_scene_linear(const char *name)
+{
+ ColorSpace *colorspace = colormanage_colorspace_get_named(name);
+ return (colorspace && IMB_colormanagement_space_is_scene_linear(colorspace));
+}
+
const float *IMB_colormanagement_get_xyz_to_rgb()
{
return &imbuf_xyz_to_rgb[0][0];
@@ -2444,9 +2450,13 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf,
ibuf->userflags &= ~(IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID);
}
- const bool do_colormanagement = save_as_render && (is_movie || !requires_linear_float);
+ const bool do_colormanagement_display = save_as_render && (is_movie || !requires_linear_float);
+ const bool do_colormanagement_linear = save_as_render && requires_linear_float &&
+ imf->linear_colorspace_settings.name[0] &&
+ !IMB_colormanagement_space_name_is_scene_linear(
+ imf->linear_colorspace_settings.name);
- if (do_colormanagement || do_alpha_under) {
+ if (do_colormanagement_display || do_colormanagement_linear || do_alpha_under) {
if (allocate_result) {
colormanaged_ibuf = IMB_dupImBuf(ibuf);
}
@@ -2499,7 +2509,8 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf,
}
}
- if (do_colormanagement) {
+ if (do_colormanagement_display) {
+ /* Color management with display and view transform. */
bool make_byte = false;
/* for proper check whether byte buffer is required by a format or not
@@ -2532,6 +2543,27 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf,
&imf->view_settings, &imf->display_settings);
}
}
+ else if (do_colormanagement_linear) {
+ /* Color management transform to another linear color space. */
+ if (!colormanaged_ibuf->rect_float) {
+ IMB_float_from_rect(colormanaged_ibuf);
+ imb_freerectImBuf(colormanaged_ibuf);
+ }
+
+ if (colormanaged_ibuf->rect_float) {
+ const char *from_colorspace = (ibuf->float_colorspace) ? ibuf->float_colorspace->name :
+ global_role_scene_linear;
+ const char *to_colorspace = imf->linear_colorspace_settings.name;
+
+ IMB_colormanagement_transform(colormanaged_ibuf->rect_float,
+ colormanaged_ibuf->x,
+ colormanaged_ibuf->y,
+ colormanaged_ibuf->channels,
+ from_colorspace,
+ to_colorspace,
+ false);
+ }
+ }
if (colormanaged_ibuf != ibuf) {
IMB_metadata_copy(colormanaged_ibuf, ibuf);
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index be8f9f938a3..24c120ae860 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -429,6 +429,8 @@ typedef struct ImageFormatData {
Stereo3dFormat stereo3d_format;
/* color management */
+ char color_management;
+ char _pad1[7];
ColorManagedViewSettings view_settings;
ColorManagedDisplaySettings display_settings;
ColorManagedColorspaceSettings linear_colorspace_settings;
@@ -527,6 +529,10 @@ enum {
R_IMF_TIFF_CODEC_NONE = 3,
};
+/** #ImageFormatData.color_management */
+#define R_IMF_COLOR_MANAGEMENT_FOLLOW_SCENE 0
+#define R_IMF_COLOR_MANAGEMENT_OVERRIDE 1
+
typedef struct BakeData {
struct ImageFormatData im_format;
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 373aec975c2..840674c7bc6 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -605,6 +605,11 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *bmain,
{
ID *id = ptr->owner_id;
+ if (!id) {
+ /* Happens for color space settings on operators. */
+ return;
+ }
+
if (GS(id->name) == ID_IM) {
Image *ima = (Image *)id;
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 04afcd61717..e056ab7377c 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -20,6 +20,7 @@
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "BLI_listbase.h"
@@ -29,6 +30,7 @@
#include "BKE_armature.h"
#include "BKE_editmesh.h"
+#include "BKE_idtype.h"
#include "BKE_paint.h"
#include "BKE_volume.h"
@@ -1440,6 +1442,35 @@ static const EnumPropertyItem *rna_ImageFormatSettings_exr_codec_itemf(bContext
}
# endif
+
+static bool rna_ImageFormatSettings_has_linear_colorspace_get(PointerRNA *ptr)
+{
+ ImageFormatData *imf = (ImageFormatData *)ptr->data;
+ return BKE_imtype_requires_linear_float(imf->imtype);
+}
+
+static void rna_ImageFormatSettings_color_management_set(PointerRNA *ptr, int value)
+{
+ ImageFormatData *imf = (ImageFormatData *)ptr->data;
+
+ if (imf->color_management != value) {
+ imf->color_management = value;
+
+ /* Copy from scene when enabling override. */
+ if (imf->color_management == R_IMF_COLOR_MANAGEMENT_OVERRIDE) {
+ ID *owner_id = ptr->owner_id;
+ if (owner_id && GS(owner_id->name) == ID_NT) {
+ /* For compositing nodes, find the corresponding scene. */
+ const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(owner_id);
+ owner_id = type_info->owner_get(G_MAIN, owner_id);
+ }
+ if (owner_id && GS(owner_id->name) == ID_SCE) {
+ BKE_image_format_color_management_copy_from_scene(imf, (Scene *)owner_id);
+ }
+ }
+ }
+}
+
static int rna_SceneRender_file_ext_length(PointerRNA *ptr)
{
RenderData *rd = (RenderData *)ptr->data;
@@ -5458,6 +5489,12 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
};
# endif
+ static const EnumPropertyItem color_management_items[] = {
+ {R_IMF_COLOR_MANAGEMENT_FOLLOW_SCENE, "FOLLOW_SCENE", 0, "Follow Scene", ""},
+ {R_IMF_COLOR_MANAGEMENT_OVERRIDE, "OVERRIDE", 0, "Override", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
StructRNA *srna;
PropertyRNA *prop;
@@ -5616,17 +5653,32 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Stereo 3D Format", "Settings for stereo 3D");
/* color management */
+ prop = RNA_def_property(srna, "color_management", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, color_management_items);
+ RNA_def_property_ui_text(
+ prop, "Color Management", "Which color management settings to use for file saving");
+ RNA_def_property_enum_funcs(prop, NULL, "rna_ImageFormatSettings_color_management_set", NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "view_settings");
RNA_def_property_struct_type(prop, "ColorManagedViewSettings");
RNA_def_property_ui_text(
prop, "View Settings", "Color management settings applied on image before saving");
prop = RNA_def_property(srna, "display_settings", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "display_settings");
RNA_def_property_struct_type(prop, "ColorManagedDisplaySettings");
RNA_def_property_ui_text(
prop, "Display Settings", "Settings of device saved image would be displayed on");
+
+ prop = RNA_def_property(srna, "linear_colorspace_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
+ RNA_def_property_ui_text(prop, "Color Space Settings", "Output color space settings");
+
+ prop = RNA_def_property(srna, "has_linear_colorspace", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_ImageFormatSettings_has_linear_colorspace_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(
+ prop, "Has Linear Color Space", "File format expects linear color space");
}
static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
diff --git a/source/blender/nodes/composite/nodes/node_composite_output_file.cc b/source/blender/nodes/composite/nodes/node_composite_output_file.cc
index 28de1f48b79..1fd6e62b4c5 100644
--- a/source/blender/nodes/composite/nodes/node_composite_output_file.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_output_file.cc
@@ -303,7 +303,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
node_composit_buts_file_output(layout, C, ptr);
- uiTemplateImageSettings(layout, &imfptr, false);
+ uiTemplateImageSettings(layout, &imfptr, true);
/* disable stereo output for multilayer, too much work for something that no one will use */
/* if someone asks for that we can implement it */
@@ -422,12 +422,16 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
ICON_NONE);
}
- col = uiLayoutColumn(layout, false);
- uiLayoutSetActive(col, use_node_format == false);
- uiTemplateImageSettings(col, &imfptr, false);
+ if (!use_node_format) {
+ const bool use_color_management = RNA_boolean_get(&active_input_ptr, "save_as_render");
- if (is_multiview) {
- uiTemplateImageFormatViews(layout, &imfptr, nullptr);
+ col = uiLayoutColumn(layout, false);
+ uiTemplateImageSettings(col, &imfptr, use_color_management);
+
+ if (is_multiview) {
+ col = uiLayoutColumn(layout, false);
+ uiTemplateImageFormatViews(col, &imfptr, nullptr);
+ }
}
}
}
diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c
index 3ea708a5b72..ea7fa961f0d 100644
--- a/source/blender/render/intern/render_result.c
+++ b/source/blender/render/intern/render_result.c
@@ -993,7 +993,7 @@ void render_result_exr_file_cache_write(Render *re)
render_result_exr_file_cache_path(re->scene, root, str);
printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str);
- BKE_image_render_write_exr(NULL, rr, str, NULL, NULL, -1);
+ BKE_image_render_write_exr(NULL, rr, str, NULL, true, NULL, -1);
}
bool render_result_exr_file_cache_read(Render *re)