Color Management: support different settings for render and compositing output
The Output Properties > Output panel now has a Color Management subpanel to override scene settings. When set to Override instead of Follow Scene, there are settings to: * For OpenEXR, choose a (linear) colorspace for RGBA passes * For other file formats, use different display/view/look/exposure/gamma These settings affect animation render output, image save of renders and the compositor file output node. Additionally, the image save operator and compositor file output nodes also support overriding color management. Includes some layout changes to the relevant panels to accomdate the new settings and to improve consistency. Ideally subpanels would be used to better organize these settings, however nodes and operators don't currently support creating subpanels. Differential Revision: https://developer.blender.org/D14402
This commit is contained in:
parent
51727fe86f
commit
7aab508e32
Notes:
blender-bot
2023-02-14 02:30:10 +01:00
Referenced by issue #99949, Regression: Crash when last input from File Output node is deleted Referenced by issue #99028, Crash on Removing File Output Node when Color Management Referenced by issue #68926, Color Management Improvements
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
/* Override color management */
|
||||
if (color_management) {
|
||||
uiItemS(col);
|
||||
uiItemR(col, imfptr, "color_management", 0, NULL, ICON_NONE);
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
uiItemL(col, IFACE_("Color Management"), ICON_NONE);
|
||||
|
||||
uiItemR(col, &display_settings_ptr, "display_device", 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue