Compositor: "Save as Render" for the file output node

This commit adds the "Save as Render" feature to the file output node,
that allows to disable the application of the configured view transform
and other color management settings on the image. If disable it uses
the standard view transform instead. This feature was originally
suggested in T83842 and is part of the color management improvements
task in T68926. With this feature it is possible to toggle the
application of the color management settings for each input socket
of the File Output node individually.

Reviewed By: brecht

Maniphest Tasks: T68926, T83842

Differential Revision: https://developer.blender.org/D9921
This commit is contained in:
Robert Guetzkow 2021-01-13 11:01:44 +01:00 committed by Robert Guetzkow
parent 614bd239f8
commit 27b78c9c94
Notes: blender-bot 2023-02-14 09:24:53 +01:00
Referenced by issue #83842, Blender applies color management to AOVs, effectively destroying them
Referenced by issue #68926, Color Management Improvements
11 changed files with 59 additions and 15 deletions

View File

@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 10
#define BLENDER_FILE_SUBVERSION 11
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -1518,6 +1518,24 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
/* Enable "Save as Render" option for file output node by default (apply view transform to image
* on save) */
if (!MAIN_VERSION_ATLEAST(bmain, 292, 11)) {
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type == NTREE_COMPOSIT) {
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == CMP_NODE_OUTPUT_FILE) {
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
NodeImageMultiFileSocket *simf = sock->storage;
simf->save_as_render = true;
}
}
}
}
}
FOREACH_NODETREE_END;
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -113,7 +113,8 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
path,
context.getViewSettings(),
context.getDisplaySettings(),
context.getViewName());
context.getViewName(),
sockdata->save_as_render);
}
else if ((!is_multiview) || (format->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
outputOperation = new OutputSingleLayerOperation(context.getRenderData(),
@ -123,7 +124,8 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
path,
context.getViewSettings(),
context.getDisplaySettings(),
context.getViewName());
context.getViewName(),
sockdata->save_as_render);
}
else { /* R_IMF_VIEWS_STEREO_3D */
outputOperation = new OutputStereoOperation(context.getRenderData(),
@ -134,7 +136,8 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
sockdata->layer,
context.getViewSettings(),
context.getDisplaySettings(),
context.getViewName());
context.getViewName(),
sockdata->save_as_render);
}
converter.addOperation(outputOperation);

View File

@ -47,9 +47,10 @@ OutputOpenExrSingleLayerMultiViewOperation::OutputOpenExrSingleLayerMultiViewOpe
const char *path,
const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings,
const char *viewName)
const char *viewName,
const bool saveAsRender)
: OutputSingleLayerOperation(
rd, tree, datatype, format, path, viewSettings, displaySettings, viewName)
rd, tree, datatype, format, path, viewSettings, displaySettings, viewName, saveAsRender)
{
}
@ -273,9 +274,10 @@ OutputStereoOperation::OutputStereoOperation(const RenderData *rd,
const char *name,
const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings,
const char *viewName)
const char *viewName,
const bool saveAsRender)
: OutputSingleLayerOperation(
rd, tree, datatype, format, path, viewSettings, displaySettings, viewName)
rd, tree, datatype, format, path, viewSettings, displaySettings, viewName, saveAsRender)
{
BLI_strncpy(this->m_name, name, sizeof(this->m_name));
this->m_channels = get_datatype_size(datatype);

View File

@ -38,7 +38,8 @@ class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOpera
const char *path,
const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings,
const char *viewName);
const char *viewName,
const bool saveAsRender);
void *get_handle(const char *filename);
void deinitExecution();
@ -74,7 +75,8 @@ class OutputStereoOperation : public OutputSingleLayerOperation {
const char *name,
const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings,
const char *viewName);
const char *viewName,
const bool saveAsRender);
void *get_handle(const char *filename);
void deinitExecution();
};

View File

@ -215,7 +215,8 @@ OutputSingleLayerOperation::OutputSingleLayerOperation(
const char *path,
const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings,
const char *viewName)
const char *viewName,
const bool saveAsRender)
{
this->m_rd = rd;
this->m_tree = tree;
@ -232,6 +233,7 @@ OutputSingleLayerOperation::OutputSingleLayerOperation(
this->m_viewSettings = viewSettings;
this->m_displaySettings = displaySettings;
this->m_viewName = viewName;
this->m_saveAsRender = saveAsRender;
}
void OutputSingleLayerOperation::initExecution()
@ -265,7 +267,7 @@ void OutputSingleLayerOperation::deinitExecution()
ibuf->dither = this->m_rd->dither_intensity;
IMB_colormanagement_imbuf_for_write(
ibuf, true, false, m_viewSettings, m_displaySettings, this->m_format);
ibuf, m_saveAsRender, false, m_viewSettings, m_displaySettings, this->m_format);
suffix = BKE_scene_multiview_view_suffix_get(this->m_rd, this->m_viewName);

View File

@ -44,6 +44,7 @@ class OutputSingleLayerOperation : public NodeOperation {
const ColorManagedDisplaySettings *m_displaySettings;
const char *m_viewName;
bool m_saveAsRender;
public:
OutputSingleLayerOperation(const RenderData *rd,
@ -53,7 +54,8 @@ class OutputSingleLayerOperation : public NodeOperation {
const char *path,
const ColorManagedViewSettings *viewSettings,
const ColorManagedDisplaySettings *displaySettings,
const char *viewName);
const char *viewName,
const bool saveAsRender);
void executeRegion(rcti *rect, unsigned int tileNumber);
bool isOutputOperation(bool /*rendering*/) const

View File

@ -1884,6 +1884,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
PointerRNA active_input_ptr, op_ptr;
uiLayout *row, *col;
const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
const bool is_exr = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_OPENEXR;
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
node_composit_buts_file_output(layout, C, ptr);
@ -1991,8 +1992,15 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
uiItemL(col, IFACE_("Format:"), ICON_NONE);
uiItemR(col, &active_input_ptr, "use_node_format", DEFAULT_FLAGS, NULL, ICON_NONE);
const bool is_socket_exr = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_OPENEXR;
const bool use_node_format = RNA_boolean_get(&active_input_ptr, "use_node_format");
if ((!is_exr && use_node_format) || (!is_socket_exr && !use_node_format)) {
uiItemR(col, &active_input_ptr, "save_as_render", DEFAULT_FLAGS, NULL, ICON_NONE);
}
col = uiLayoutColumn(layout, false);
uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == false);
uiLayoutSetActive(col, use_node_format == false);
uiTemplateImageSettings(col, &imfptr, false);
if (is_multiview) {

View File

@ -735,7 +735,8 @@ typedef struct NodeImageMultiFileSocket {
short use_render_format DNA_DEPRECATED;
/** Use overall node image format. */
short use_node_format;
char _pad1[4];
char save_as_render;
char _pad1[3];
/** 1024 = FILE_MAX. */
char path[1024];
ImageFormatData format;

View File

@ -6289,6 +6289,11 @@ static void rna_def_cmp_output_file_slot_file(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Node Format", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
prop = RNA_def_property(srna, "save_as_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "save_as_render", 1);
RNA_def_property_ui_text(prop, "Save as Render", "Apply render part of display transform when saving byte image");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
prop = RNA_def_property(srna, "format", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ImageFormatSettings");

View File

@ -146,6 +146,7 @@ bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree,
}
/* use node data format by default */
sockdata->use_node_format = true;
sockdata->save_as_render = true;
nimf->active_input = BLI_findindex(&node->inputs, sock);