Cleanup: refactor passing of color management settings for image save

Make a copy of ImageFormatData that contains the effective color management
settings, and pass that along to the various functions. This will make it
possible to add more complex logic later.

For compositing nodes, passing along view and display settings through
many functions made it harder to add additional settings, so just get those
from the scene now.

Differential Revision: https://developer.blender.org/D14401
This commit is contained in:
Brecht Van Lommel 2022-03-11 18:21:05 +01:00
parent 2ebcb7fab3
commit 3b5224b57c
26 changed files with 184 additions and 303 deletions

View File

@ -16,6 +16,7 @@ struct BlendWriter;
struct ImbFormatOptions;
struct ImageFormatData;
struct ImBuf;
struct Scene;
/* Init/Copy/Free */
@ -75,6 +76,22 @@ char BKE_imtype_from_arg(const char *arg);
void BKE_image_format_from_imbuf(struct ImageFormatData *im_format, const struct ImBuf *imbuf);
void BKE_image_format_to_imbuf(struct ImBuf *ibuf, const struct ImageFormatData *imf);
/* Color Management */
void BKE_image_format_color_management_copy(struct ImageFormatData *imf,
const struct ImageFormatData *imf_src);
void BKE_image_format_color_management_copy_from_scene(struct ImageFormatData *imf,
const struct Scene *scene);
/* Image Output
*
* Initialize an image format that can be used for file writing, including
* color management settings from the scene. */
void BKE_image_format_init_for_write(struct ImageFormatData *imf,
const struct Scene *scene_src,
const struct ImageFormatData *imf_src);
#ifdef __cplusplus
}
#endif

View File

@ -14,6 +14,7 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@ -872,3 +873,39 @@ void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
/* planes */
im_format->planes = imbuf->planes;
}
/* Color Management */
void BKE_image_format_color_management_copy(ImageFormatData *imf, const ImageFormatData *imf_src)
{
BKE_color_managed_view_settings_free(&imf->view_settings);
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);
}
void BKE_image_format_color_management_copy_from_scene(ImageFormatData *imf, const Scene *scene)
{
BKE_color_managed_view_settings_free(&imf->view_settings);
BKE_color_managed_display_settings_copy(&imf->display_settings, &scene->display_settings);
BKE_color_managed_view_settings_copy(&imf->view_settings, &scene->view_settings);
STRNCPY(imf->linear_colorspace_settings.name,
IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR));
}
/* Output */
void BKE_image_format_init_for_write(ImageFormatData *imf,
const Scene *scene_src,
const ImageFormatData *imf_src)
{
*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);
}

View File

@ -230,8 +230,7 @@ static bool image_save_single(ReportList *reports,
ok = BKE_image_render_write_exr(reports, rr, opts->filepath, imf, nullptr, layer);
}
else {
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(
ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, imf);
ok = BKE_imbuf_write_as(colormanaged_ibuf, opts->filepath, imf, save_copy);
imbuf_save_post(ibuf, colormanaged_ibuf);
}
@ -292,8 +291,7 @@ static bool image_save_single(ReportList *reports,
BKE_scene_multiview_view_filepath_get(&opts->scene->r, opts->filepath, view, filepath);
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(
ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, imf);
ok_view = BKE_imbuf_write_as(colormanaged_ibuf, filepath, &opts->im_format, save_copy);
imbuf_save_post(ibuf, colormanaged_ibuf);
image_save_post(reports, ima, ibuf, ok_view, opts, true, filepath, r_colorspace_changed);
@ -358,8 +356,7 @@ static bool image_save_single(ReportList *reports,
ibuf->planes = planes;
/* color manage the ImBuf leaving it ready for saving */
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(
ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, imf);
BKE_image_format_to_imbuf(colormanaged_ibuf, imf);
IMB_prepare_write_ImBuf(IMB_isfloat(colormanaged_ibuf), colormanaged_ibuf);
@ -652,26 +649,27 @@ bool BKE_image_render_write(ReportList *reports,
const char *filename)
{
bool ok = true;
const RenderData *rd = &scene->r;
if (!rr) {
return false;
}
ImageFormatData image_format;
BKE_image_format_init_for_write(&image_format, scene, nullptr);
const bool is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
const bool is_exr_rr = ELEM(rd->im_format.imtype,
R_IMF_IMTYPE_OPENEXR,
R_IMF_IMTYPE_MULTILAYER) &&
const bool is_exr_rr = ELEM(
image_format.imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) &&
RE_HasFloatPixels(rr);
const float dither = scene->r.dither_intensity;
if (rd->im_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
ok = BKE_image_render_write_exr(reports, rr, filename, &rd->im_format, nullptr, -1);
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);
image_render_print_save_message(reports, filename, ok, errno);
}
/* mono, legacy code */
else if (is_mono || (rd->im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
else if (is_mono || (image_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
int view_id = 0;
for (const RenderView *rv = (const RenderView *)rr->views.first; rv;
rv = rv->next, view_id++) {
@ -684,37 +682,35 @@ bool BKE_image_render_write(ReportList *reports,
}
if (is_exr_rr) {
ok = BKE_image_render_write_exr(reports, rr, filepath, &rd->im_format, rv->name, -1);
ok = BKE_image_render_write_exr(reports, rr, filepath, &image_format, rv->name, -1);
image_render_print_save_message(reports, filepath, ok, errno);
/* optional preview images for exr */
if (ok && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
ImageFormatData imf = rd->im_format;
imf.imtype = R_IMF_IMTYPE_JPEG90;
if (ok && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
image_format.imtype = R_IMF_IMTYPE_JPEG90;
if (BLI_path_extension_check(filepath, ".exr")) {
filepath[strlen(filepath) - 4] = 0;
}
BKE_image_path_ensure_ext_from_imformat(filepath, &imf);
BKE_image_path_ensure_ext_from_imformat(filepath, &image_format);
ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &imf, dither, view_id);
ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &image_format, dither, view_id);
ibuf->planes = 24;
IMB_colormanagement_imbuf_for_write(
ibuf, true, false, &scene->view_settings, &scene->display_settings, &imf);
IMB_colormanagement_imbuf_for_write(ibuf, true, false, &image_format);
ok = image_render_write_stamp_test(reports, scene, rr, ibuf, filepath, &imf, stamp);
ok = image_render_write_stamp_test(
reports, scene, rr, ibuf, filepath, &image_format, stamp);
IMB_freeImBuf(ibuf);
}
}
else {
ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &rd->im_format, dither, view_id);
ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &image_format, dither, view_id);
IMB_colormanagement_imbuf_for_write(
ibuf, true, false, &scene->view_settings, &scene->display_settings, &rd->im_format);
IMB_colormanagement_imbuf_for_write(ibuf, true, false, &image_format);
ok = image_render_write_stamp_test(
reports, scene, rr, ibuf, filepath, &rd->im_format, stamp);
reports, scene, rr, ibuf, filepath, &image_format, stamp);
/* imbuf knows which rects are not part of ibuf */
IMB_freeImBuf(ibuf);
@ -722,12 +718,12 @@ bool BKE_image_render_write(ReportList *reports,
}
}
else { /* R_IMF_VIEWS_STEREO_3D */
BLI_assert(rd->im_format.views_format == R_IMF_VIEWS_STEREO_3D);
BLI_assert(image_format.views_format == R_IMF_VIEWS_STEREO_3D);
char filepath[FILE_MAX];
STRNCPY(filepath, filename);
if (rd->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
if (image_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
printf("Stereo 3D not supported for MultiLayer image: %s\n", filepath);
}
else {
@ -737,34 +733,29 @@ bool BKE_image_render_write(ReportList *reports,
for (i = 0; i < 2; i++) {
int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
ibuf_arr[i] = RE_render_result_rect_to_ibuf(rr, &rd->im_format, dither, view_id);
IMB_colormanagement_imbuf_for_write(ibuf_arr[i],
true,
false,
&scene->view_settings,
&scene->display_settings,
&rd->im_format);
ibuf_arr[i] = RE_render_result_rect_to_ibuf(rr, &image_format, dither, view_id);
IMB_colormanagement_imbuf_for_write(ibuf_arr[i], true, false, &image_format);
IMB_prepare_write_ImBuf(IMB_isfloat(ibuf_arr[i]), ibuf_arr[i]);
}
ibuf_arr[2] = IMB_stereo3d_ImBuf(&rd->im_format, ibuf_arr[0], ibuf_arr[1]);
ibuf_arr[2] = IMB_stereo3d_ImBuf(&image_format, ibuf_arr[0], ibuf_arr[1]);
ok = image_render_write_stamp_test(
reports, scene, rr, ibuf_arr[2], filepath, &rd->im_format, stamp);
reports, scene, rr, ibuf_arr[2], filepath, &image_format, stamp);
/* optional preview images for exr */
if (ok && is_exr_rr && (rd->im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
ImageFormatData imf = rd->im_format;
imf.imtype = R_IMF_IMTYPE_JPEG90;
if (ok && is_exr_rr && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
image_format.imtype = R_IMF_IMTYPE_JPEG90;
if (BLI_path_extension_check(filepath, ".exr")) {
filepath[strlen(filepath) - 4] = 0;
}
BKE_image_path_ensure_ext_from_imformat(filepath, &imf);
BKE_image_path_ensure_ext_from_imformat(filepath, &image_format);
ibuf_arr[2]->planes = 24;
ok = image_render_write_stamp_test(reports, scene, rr, ibuf_arr[2], filepath, &imf, stamp);
ok = image_render_write_stamp_test(
reports, scene, rr, ibuf_arr[2], filepath, &image_format, stamp);
}
/* imbuf knows which rects are not part of ibuf */
@ -774,5 +765,7 @@ bool BKE_image_render_write(ReportList *reports,
}
}
BKE_image_format_free(&image_format);
return ok;
}

View File

@ -318,12 +318,6 @@ extern "C" {
* - output nodes can have different priorities in the WorkScheduler.
* This is implemented in the COM_execute function.
*
* \param view_settings:
* reference to view settings used for color management
*
* \param display_settings:
* reference to display settings used for color management
*
* OCIO_TODO: this options only used in rare cases, namely in output file node,
* so probably this settings could be passed in a nicer way.
* should be checked further, probably it'll be also needed for preview
@ -335,8 +329,6 @@ void COM_execute(RenderData *render_data,
Scene *scene,
bNodeTree *node_tree,
int rendering,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name);
/**

View File

@ -12,8 +12,6 @@ CompositorContext::CompositorContext()
quality_ = eCompositorQuality::High;
hasActiveOpenCLDevices_ = false;
fast_calculation_ = false;
view_settings_ = nullptr;
display_settings_ = nullptr;
bnodetree_ = nullptr;
}

View File

@ -64,10 +64,6 @@ class CompositorContext {
*/
bool fast_calculation_;
/* \brief color management settings */
const ColorManagedViewSettings *view_settings_;
const ColorManagedDisplaySettings *display_settings_;
/**
* \brief active rendering view name
*/
@ -152,38 +148,6 @@ class CompositorContext {
return previews_;
}
/**
* \brief set view settings of color management
*/
void set_view_settings(const ColorManagedViewSettings *view_settings)
{
view_settings_ = view_settings;
}
/**
* \brief get view settings of color management
*/
const ColorManagedViewSettings *get_view_settings() const
{
return view_settings_;
}
/**
* \brief set display settings of color management
*/
void set_display_settings(const ColorManagedDisplaySettings *display_settings)
{
display_settings_ = display_settings;
}
/**
* \brief get display settings of color management
*/
const ColorManagedDisplaySettings *get_display_settings() const
{
return display_settings_;
}
/**
* \brief set the quality
*/

View File

@ -23,8 +23,6 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
bNodeTree *editingtree,
bool rendering,
bool fastcalculation,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name)
{
num_work_threads_ = WorkScheduler::get_num_cpu_threads();
@ -45,8 +43,6 @@ ExecutionSystem::ExecutionSystem(RenderData *rd,
(editingtree->flag & NTREE_COM_OPENCL));
context_.set_render_data(rd);
context_.set_view_settings(view_settings);
context_.set_display_settings(display_settings);
BLI_mutex_init(&work_mutex_);
BLI_condition_init(&work_finished_cond_);

View File

@ -160,8 +160,6 @@ class ExecutionSystem {
bNodeTree *editingtree,
bool rendering,
bool fastcalculation,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name);
/**

View File

@ -221,8 +221,9 @@ PreviewOperation *NodeOperationBuilder::make_preview_operation() const
bNodeInstanceHash *previews = context_->get_preview_hash();
if (previews) {
PreviewOperation *operation = new PreviewOperation(context_->get_view_settings(),
context_->get_display_settings(),
Scene *scene = context_->get_scene();
PreviewOperation *operation = new PreviewOperation(&scene->view_settings,
&scene->display_settings,
current_node_->get_bnode()->preview_xsize,
current_node_->get_bnode()->preview_ysize);
operation->set_bnodetree(context_->get_bnodetree());

View File

@ -49,8 +49,6 @@ void COM_execute(RenderData *render_data,
Scene *scene,
bNodeTree *node_tree,
int rendering,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name)
{
/* Initialize mutex, TODO: this mutex init is actually not thread safe and
@ -80,14 +78,8 @@ void COM_execute(RenderData *render_data,
/* Execute. */
const bool twopass = (node_tree->flag & NTREE_TWO_PASS) && !rendering;
if (twopass) {
blender::compositor::ExecutionSystem fast_pass(render_data,
scene,
node_tree,
rendering,
true,
view_settings,
display_settings,
view_name);
blender::compositor::ExecutionSystem fast_pass(
render_data, scene, node_tree, rendering, true, view_name);
fast_pass.execute();
if (node_tree->test_break(node_tree->tbh)) {
@ -97,7 +89,7 @@ void COM_execute(RenderData *render_data,
}
blender::compositor::ExecutionSystem system(
render_data, scene, node_tree, rendering, false, view_settings, display_settings, view_name);
render_data, scene, node_tree, rendering, false, view_name);
system.execute();
BLI_mutex_unlock(&g_compositor.mutex);

View File

@ -106,36 +106,33 @@ void OutputFileNode::convert_to_operations(NodeConverter &converter,
if (is_multiview && format->views_format == R_IMF_VIEWS_MULTIVIEW) {
output_operation = new OutputOpenExrSingleLayerMultiViewOperation(
context.get_scene(),
context.get_render_data(),
context.get_bnodetree(),
input->get_data_type(),
format,
path,
context.get_view_settings(),
context.get_display_settings(),
context.get_view_name(),
sockdata->save_as_render);
}
else if ((!is_multiview) || (format->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
output_operation = new OutputSingleLayerOperation(context.get_render_data(),
output_operation = new OutputSingleLayerOperation(context.get_scene(),
context.get_render_data(),
context.get_bnodetree(),
input->get_data_type(),
format,
path,
context.get_view_settings(),
context.get_display_settings(),
context.get_view_name(),
sockdata->save_as_render);
}
else { /* R_IMF_VIEWS_STEREO_3D */
output_operation = new OutputStereoOperation(context.get_render_data(),
output_operation = new OutputStereoOperation(context.get_scene(),
context.get_render_data(),
context.get_bnodetree(),
input->get_data_type(),
format,
path,
sockdata->layer,
context.get_view_settings(),
context.get_display_settings(),
context.get_view_name(),
sockdata->save_as_render);
}

View File

@ -24,6 +24,7 @@ void SplitViewerNode::convert_to_operations(NodeConverter &converter,
NodeInput *image2Socket = this->get_input_socket(1);
Image *image = (Image *)this->get_bnode()->id;
ImageUser *image_user = (ImageUser *)this->get_bnode()->storage;
Scene *scene = context.get_scene();
SplitOperation *split_viewer_operation = new SplitOperation();
split_viewer_operation->set_split_percentage(this->get_bnode()->custom1);
@ -36,8 +37,8 @@ void SplitViewerNode::convert_to_operations(NodeConverter &converter,
ViewerOperation *viewer_operation = new ViewerOperation();
viewer_operation->set_image(image);
viewer_operation->set_image_user(image_user);
viewer_operation->set_view_settings(context.get_view_settings());
viewer_operation->set_display_settings(context.get_display_settings());
viewer_operation->set_view_settings(&scene->view_settings);
viewer_operation->set_display_settings(&scene->display_settings);
viewer_operation->set_render_data(context.get_render_data());
viewer_operation->set_view_name(context.get_view_name());

View File

@ -17,8 +17,7 @@ void TextureNode::convert_to_operations(NodeConverter &converter,
bNode *editor_node = this->get_bnode();
Tex *texture = (Tex *)editor_node->id;
TextureOperation *operation = new TextureOperation();
const ColorManagedDisplaySettings *display_settings = context.get_display_settings();
bool scene_color_manage = !STREQ(display_settings->display_device, "None");
bool scene_color_manage = !STREQ(context.get_scene()->display_settings.display_device, "None");
operation->set_texture(texture);
operation->set_render_data(context.get_render_data());
operation->set_scene_color_manage(scene_color_manage);

View File

@ -37,8 +37,9 @@ void ViewerNode::convert_to_operations(NodeConverter &converter,
viewer_operation->set_render_data(context.get_render_data());
viewer_operation->set_view_name(context.get_view_name());
viewer_operation->set_view_settings(context.get_view_settings());
viewer_operation->set_display_settings(context.get_display_settings());
Scene *scene = context.get_scene();
viewer_operation->set_view_settings(&scene->view_settings);
viewer_operation->set_display_settings(&scene->display_settings);
viewer_operation->set_canvas_input_index(0);
if (!image_socket->is_linked()) {

View File

@ -17,24 +17,16 @@ namespace blender::compositor {
/************************************ OpenEXR Singlelayer Multiview ******************************/
OutputOpenExrSingleLayerMultiViewOperation::OutputOpenExrSingleLayerMultiViewOperation(
const Scene *scene,
const RenderData *rd,
const bNodeTree *tree,
DataType datatype,
ImageFormatData *format,
const char *path,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name,
const bool save_as_render)
: OutputSingleLayerOperation(rd,
tree,
datatype,
format,
path,
view_settings,
display_settings,
view_name,
save_as_render)
: OutputSingleLayerOperation(
scene, rd, tree, datatype, format, path, view_name, save_as_render)
{
}
@ -68,7 +60,7 @@ void *OutputOpenExrSingleLayerMultiViewOperation::get_handle(const char *filenam
/* prepare the file with all the channels */
if (!IMB_exr_begin_write(exrhandle, filename, width, height, format_->exr_codec, nullptr)) {
if (!IMB_exr_begin_write(exrhandle, filename, width, height, format_.exr_codec, nullptr)) {
printf("Error Writing Singlelayer Multiview Openexr\n");
IMB_exr_close(exrhandle);
}
@ -104,7 +96,7 @@ void OutputOpenExrSingleLayerMultiViewOperation::deinit_execution()
datatype_,
view_name_,
width,
format_->depth == R_IMF_CHAN_DEPTH_16,
format_.depth == R_IMF_CHAN_DEPTH_16,
output_buffer_);
/* memory can only be freed after we write all views to the file */
@ -247,25 +239,17 @@ void OutputOpenExrMultiLayerMultiViewOperation::deinit_execution()
/******************************** Stereo3D ******************************/
OutputStereoOperation::OutputStereoOperation(const RenderData *rd,
OutputStereoOperation::OutputStereoOperation(const Scene *scene,
const RenderData *rd,
const bNodeTree *tree,
DataType datatype,
ImageFormatData *format,
const char *path,
const char *name,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name,
const bool save_as_render)
: OutputSingleLayerOperation(rd,
tree,
datatype,
format,
path,
view_settings,
display_settings,
view_name,
save_as_render)
: OutputSingleLayerOperation(
scene, rd, tree, datatype, format, path, view_name, save_as_render)
{
BLI_strncpy(name_, name, sizeof(name_));
channels_ = get_datatype_size(datatype);
@ -317,7 +301,7 @@ void OutputStereoOperation::deinit_execution()
1,
channels_ * width * height,
buf,
format_->depth == R_IMF_CHAN_DEPTH_16);
format_.depth == R_IMF_CHAN_DEPTH_16);
image_input_ = nullptr;
output_buffer_ = nullptr;
@ -332,7 +316,7 @@ void OutputStereoOperation::deinit_execution()
/* get rectf from EXR */
for (i = 0; i < 2; i++) {
float *rectf = IMB_exr_channel_rect(exrhandle, nullptr, name_, names[i]);
ibuf[i] = IMB_allocImBuf(width, height, format_->planes, 0);
ibuf[i] = IMB_allocImBuf(width, height, format_.planes, 0);
ibuf[i]->channels = channels_;
ibuf[i]->rect_float = rectf;
@ -340,24 +324,23 @@ void OutputStereoOperation::deinit_execution()
ibuf[i]->dither = rd_->dither_intensity;
/* do colormanagement in the individual views, so it doesn't need to do in the stereo */
IMB_colormanagement_imbuf_for_write(
ibuf[i], true, false, view_settings_, display_settings_, format_);
IMB_colormanagement_imbuf_for_write(ibuf[i], true, false, &format_);
IMB_prepare_write_ImBuf(IMB_isfloat(ibuf[i]), ibuf[i]);
}
/* create stereo buffer */
ibuf[2] = IMB_stereo3d_ImBuf(format_, ibuf[0], ibuf[1]);
ibuf[2] = IMB_stereo3d_ImBuf(&format_, ibuf[0], ibuf[1]);
BKE_image_path_from_imformat(filename,
path_,
BKE_main_blendfile_path_from_global(),
rd_->cfra,
format_,
&format_,
(rd_->scemode & R_EXTENSION) != 0,
true,
nullptr);
BKE_imbuf_write(ibuf[2], filename, format_);
BKE_imbuf_write(ibuf[2], filename, &format_);
/* imbuf knows which rects are not part of ibuf */
for (i = 0; i < 3; i++) {

View File

@ -18,13 +18,12 @@ namespace blender::compositor {
class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOperation {
private:
public:
OutputOpenExrSingleLayerMultiViewOperation(const RenderData *rd,
OutputOpenExrSingleLayerMultiViewOperation(const Scene *scene,
const RenderData *rd,
const bNodeTree *tree,
DataType datatype,
ImageFormatData *format,
const char *path,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name,
bool save_as_render);
@ -54,14 +53,13 @@ class OutputStereoOperation : public OutputSingleLayerOperation {
size_t channels_;
public:
OutputStereoOperation(const RenderData *rd,
OutputStereoOperation(const Scene *scene,
const RenderData *rd,
const bNodeTree *tree,
DataType datatype,
struct ImageFormatData *format,
const char *path,
const char *name,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name,
bool save_as_render);
void *get_handle(const char *filename);

View File

@ -200,16 +200,14 @@ static void write_buffer_rect(rcti *rect,
}
}
OutputSingleLayerOperation::OutputSingleLayerOperation(
const RenderData *rd,
const bNodeTree *tree,
DataType datatype,
ImageFormatData *format,
const char *path,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name,
const bool save_as_render)
OutputSingleLayerOperation::OutputSingleLayerOperation(const Scene *scene,
const RenderData *rd,
const bNodeTree *tree,
DataType datatype,
ImageFormatData *format,
const char *path,
const char *view_name,
const bool save_as_render)
{
rd_ = rd;
tree_ = tree;
@ -220,11 +218,9 @@ OutputSingleLayerOperation::OutputSingleLayerOperation(
datatype_ = datatype;
image_input_ = nullptr;
format_ = format;
BKE_image_format_init_for_write(&format_, scene, format);
BLI_strncpy(path_, path, sizeof(path_));
view_settings_ = view_settings;
display_settings_ = display_settings;
view_name_ = view_name;
save_as_render_ = save_as_render;
}
@ -245,7 +241,7 @@ void OutputSingleLayerOperation::deinit_execution()
if (this->get_width() * this->get_height() != 0) {
int size = get_datatype_size(datatype_);
ImBuf *ibuf = IMB_allocImBuf(this->get_width(), this->get_height(), format_->planes, 0);
ImBuf *ibuf = IMB_allocImBuf(this->get_width(), this->get_height(), format_.planes, 0);
char filename[FILE_MAX];
const char *suffix;
@ -254,8 +250,7 @@ void OutputSingleLayerOperation::deinit_execution()
ibuf->mall |= IB_rectfloat;
ibuf->dither = rd_->dither_intensity;
IMB_colormanagement_imbuf_for_write(
ibuf, save_as_render_, false, view_settings_, display_settings_, format_);
IMB_colormanagement_imbuf_for_write(ibuf, save_as_render_, false, &format_);
suffix = BKE_scene_multiview_view_suffix_get(rd_, view_name_);
@ -263,12 +258,12 @@ void OutputSingleLayerOperation::deinit_execution()
path_,
BKE_main_blendfile_path_from_global(),
rd_->cfra,
format_,
&format_,
(rd_->scemode & R_EXTENSION) != 0,
true,
suffix);
if (0 == BKE_imbuf_write(ibuf, filename, format_)) {
if (0 == BKE_imbuf_write(ibuf, filename, &format_)) {
printf("Cannot save Node File Output to %s\n", filename);
}
else {

View File

@ -20,27 +20,23 @@ class OutputSingleLayerOperation : public MultiThreadedOperation {
const RenderData *rd_;
const bNodeTree *tree_;
ImageFormatData *format_;
ImageFormatData format_;
char path_[FILE_MAX];
float *output_buffer_;
DataType datatype_;
SocketReader *image_input_;
const ColorManagedViewSettings *view_settings_;
const ColorManagedDisplaySettings *display_settings_;
const char *view_name_;
bool save_as_render_;
public:
OutputSingleLayerOperation(const RenderData *rd,
OutputSingleLayerOperation(const Scene *scene,
const RenderData *rd,
const bNodeTree *tree,
DataType datatype,
ImageFormatData *format,
const char *path,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name,
bool save_as_render);

View File

@ -1812,11 +1812,7 @@ static int image_save_options_init(Main *bmain,
}
/* color management */
BKE_color_managed_display_settings_copy(&opts->im_format.display_settings,
&scene->display_settings);
BKE_color_managed_view_settings_free(&opts->im_format.view_settings);
BKE_color_managed_view_settings_copy(&opts->im_format.view_settings, &scene->view_settings);
BKE_image_format_color_management_copy_from_scene(&opts->im_format, scene);
}
BKE_image_release_ibuf(ima, ibuf, lock);

View File

@ -18,6 +18,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_image_format.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
@ -274,28 +275,14 @@ static void compo_startjob(void *cjv,
/* 1 is do_previews */
if ((cj->scene->r.scemode & R_MULTIVIEW) == 0) {
ntreeCompositExecTree(cj->scene,
ntree,
&cj->scene->r,
false,
true,
&scene->view_settings,
&scene->display_settings,
"");
ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, "");
}
else {
LISTBASE_FOREACH (SceneRenderView *, srv, &scene->r.views) {
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) {
continue;
}
ntreeCompositExecTree(cj->scene,
ntree,
&cj->scene->r,
false,
true,
&scene->view_settings,
&scene->display_settings,
srv->name);
ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, srv->name);
}
}

View File

@ -19,6 +19,7 @@ extern "C" {
struct ColorManagedColorspaceSettings;
struct ColorManagedDisplaySettings;
struct ColorManagedViewSettings;
struct ColorManagedOutputSettings;
struct ColormanageProcessor;
struct EnumPropertyItem;
struct ImBuf;
@ -238,23 +239,10 @@ void IMB_colormanagement_imbuf_make_display_space(
* in image format write callback and if float_colorspace is not NULL, no color
* space transformation should be applied on this buffer.
*/
struct ImBuf *IMB_colormanagement_imbuf_for_write(
struct ImBuf *ibuf,
bool save_as_render,
bool allocate_result,
const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
const struct ImageFormatData *image_format_data);
void IMB_colormanagement_buffer_make_display_space(
float *buffer,
unsigned char *display_buffer,
int width,
int height,
int channels,
float dither,
const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings);
struct ImBuf *IMB_colormanagement_imbuf_for_write(struct ImBuf *ibuf,
bool save_as_render,
bool allocate_result,
const struct ImageFormatData *image_format);
/** \} */

View File

@ -2431,15 +2431,12 @@ void IMB_colormanagement_imbuf_make_display_space(
ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf,
bool save_as_render,
bool allocate_result,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const ImageFormatData *image_format_data)
const ImageFormatData *imf)
{
ImBuf *colormanaged_ibuf = ibuf;
bool do_colormanagement;
bool is_movie = BKE_imtype_is_movie(image_format_data->imtype);
bool requires_linear_float = BKE_imtype_requires_linear_float(image_format_data->imtype);
bool do_alpha_under = image_format_data->planes != R_IMF_PLANES_RGBA;
const bool is_movie = BKE_imtype_is_movie(imf->imtype);
const bool requires_linear_float = BKE_imtype_requires_linear_float(imf->imtype);
const bool do_alpha_under = imf->planes != R_IMF_PLANES_RGBA;
if (ibuf->rect_float && ibuf->rect &&
(ibuf->userflags & (IB_DISPLAY_BUFFER_INVALID | IB_RECT_INVALID)) != 0) {
@ -2447,7 +2444,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf,
ibuf->userflags &= ~(IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID);
}
do_colormanagement = save_as_render && (is_movie || !requires_linear_float);
const bool do_colormanagement = save_as_render && (is_movie || !requires_linear_float);
if (do_colormanagement || do_alpha_under) {
if (allocate_result) {
@ -2509,8 +2506,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf,
* should be pretty safe since this image buffer is supposed to be used for
* saving only and ftype would be overwritten a bit later by BKE_imbuf_write
*/
colormanaged_ibuf->ftype = BKE_imtype_to_ftype(image_format_data->imtype,
&colormanaged_ibuf->foptions);
colormanaged_ibuf->ftype = BKE_imtype_to_ftype(imf->imtype, &colormanaged_ibuf->foptions);
/* if file format isn't able to handle float buffer itself,
* we need to allocate byte buffer and store color managed
@ -2525,15 +2521,15 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf,
/* perform color space conversions */
colormanagement_imbuf_make_display_space(
colormanaged_ibuf, view_settings, display_settings, make_byte);
colormanaged_ibuf, &imf->view_settings, &imf->display_settings, make_byte);
if (colormanaged_ibuf->rect_float) {
/* float buffer isn't linear anymore,
* image format write callback should check for this flag and assume
* no space conversion should happen if ibuf->float_colorspace != NULL
*/
colormanaged_ibuf->float_colorspace = display_transform_get_colorspace(view_settings,
display_settings);
colormanaged_ibuf->float_colorspace = display_transform_get_colorspace(
&imf->view_settings, &imf->display_settings);
}
}
@ -2544,45 +2540,6 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf,
return colormanaged_ibuf;
}
void IMB_colormanagement_buffer_make_display_space(
float *buffer,
unsigned char *display_buffer,
int width,
int height,
int channels,
float dither,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings)
{
ColormanageProcessor *cm_processor;
size_t float_buffer_size = ((size_t)width) * height * channels * sizeof(float);
float *display_buffer_float = MEM_mallocN(float_buffer_size, "byte_buffer_make_display_space");
/* TODO(sergey): Convert float directly to byte buffer. */
memcpy(display_buffer_float, buffer, float_buffer_size);
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
processor_transform_apply_threaded(
NULL, display_buffer_float, width, height, channels, cm_processor, true, false);
IMB_buffer_byte_from_float(display_buffer,
display_buffer_float,
channels,
dither,
IB_PROFILE_SRGB,
IB_PROFILE_SRGB,
true,
width,
height,
width,
width);
MEM_freeN(display_buffer_float);
IMB_colormanagement_processor_free(cm_processor);
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -25,7 +25,9 @@
#ifdef RNA_RUNTIME
# include "BKE_image.h"
# include "BKE_image_format.h"
# include "BKE_main.h"
# include "BKE_scene.h"
# include <errno.h>
# include "IMB_colormanagement.h"
@ -68,19 +70,23 @@ static void rna_Image_save_render(
else {
ImBuf *write_ibuf;
write_ibuf = IMB_colormanagement_imbuf_for_write(
ibuf, true, true, &scene->view_settings, &scene->display_settings, &scene->r.im_format);
ImageFormatData image_format;
BKE_image_format_init_for_write(&image_format, scene, NULL);
write_ibuf->planes = scene->r.im_format.planes;
write_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &image_format);
write_ibuf->planes = image_format.planes;
write_ibuf->dither = scene->r.dither_intensity;
if (!BKE_imbuf_write(write_ibuf, path, &scene->r.im_format)) {
if (!BKE_imbuf_write(write_ibuf, path, &image_format)) {
BKE_reportf(reports, RPT_ERROR, "Could not write image: %s, '%s'", strerror(errno), path);
}
if (write_ibuf != ibuf) {
IMB_freeImBuf(write_ibuf);
}
BKE_image_format_free(&image_format);
}
BKE_image_release_ibuf(image, ibuf, lock);

View File

@ -143,8 +143,6 @@ void ntreeCompositExecTree(struct Scene *scene,
struct RenderData *rd,
int rendering,
int do_previews,
const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
const char *view_name);
/**

View File

@ -206,14 +206,12 @@ void ntreeCompositExecTree(Scene *scene,
RenderData *rd,
int rendering,
int do_preview,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
const char *view_name)
{
#ifdef WITH_COMPOSITOR
COM_execute(rd, scene, ntree, rendering, view_settings, display_settings, view_name);
COM_execute(rd, scene, ntree, rendering, view_name);
#else
UNUSED_VARS(scene, ntree, rd, rendering, view_settings, display_settings, view_name);
UNUSED_VARS(scene, ntree, rd, rendering, view_name);
#endif
UNUSED_VARS(do_preview);

View File

@ -1212,14 +1212,8 @@ static void do_render_compositor(Render *re)
RenderView *rv;
for (rv = re->result->views.first; rv; rv = rv->next) {
ntreeCompositExecTree(re->pipeline_scene_eval,
ntree,
&re->r,
true,
G.background == 0,
&re->scene->view_settings,
&re->scene->display_settings,
rv->name);
ntreeCompositExecTree(
re->pipeline_scene_eval, ntree, &re->r, true, G.background == 0, rv->name);
}
ntree->stats_draw = NULL;
@ -1960,17 +1954,19 @@ bool RE_WriteRenderViewsMovie(ReportList *reports,
return false;
}
ImageFormatData image_format;
BKE_image_format_init_for_write(&image_format, scene, NULL);
const bool is_mono = BLI_listbase_count_at_most(&rr->views, 2) < 2;
const float dither = scene->r.dither_intensity;
if (is_mono || (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
if (is_mono || (image_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
int view_id;
for (view_id = 0; view_id < totvideos; view_id++) {
const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &rd->im_format, dither, view_id);
IMB_colormanagement_imbuf_for_write(
ibuf, true, false, &scene->view_settings, &scene->display_settings, &scene->r.im_format);
IMB_colormanagement_imbuf_for_write(ibuf, true, false, &image_format);
ok &= mh->append_movie(movie_ctx_arr[view_id],
rd,
@ -1992,21 +1988,16 @@ bool RE_WriteRenderViewsMovie(ReportList *reports,
ImBuf *ibuf_arr[3] = {NULL};
int i;
BLI_assert((totvideos == 1) && (scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D));
BLI_assert((totvideos == 1) && (image_format.views_format == R_IMF_VIEWS_STEREO_3D));
for (i = 0; i < 2; i++) {
int view_id = BLI_findstringindex(&rr->views, names[i], offsetof(RenderView, name));
ibuf_arr[i] = RE_render_result_rect_to_ibuf(rr, &rd->im_format, dither, view_id);
IMB_colormanagement_imbuf_for_write(ibuf_arr[i],
true,
false,
&scene->view_settings,
&scene->display_settings,
&scene->r.im_format);
IMB_colormanagement_imbuf_for_write(ibuf_arr[i], true, false, &image_format);
}
ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]);
ibuf_arr[2] = IMB_stereo3d_ImBuf(&image_format, ibuf_arr[0], ibuf_arr[1]);
ok = mh->append_movie(movie_ctx_arr[0],
rd,
@ -2024,6 +2015,8 @@ bool RE_WriteRenderViewsMovie(ReportList *reports,
}
}
BKE_image_format_free(&image_format);
return ok;
}