Color Management: Fix wrong use of display color space

* PROP_COLOR_GAMMA is sRGB, not display space
* Hex colors are always sRGB
* Image byte buffers are in byte_buffer.colorspace

Fixes for sequencer text, image painting, render stamp and tooltips.
The default display space is sRGB, so this change will not be noticed
in most files.

Ref #144911

Pull Request: https://projects.blender.org/blender/blender/pulls/144565
This commit is contained in:
Brecht Van Lommel
2025-08-14 22:25:52 +02:00
parent 24308a9f21
commit 235fdc6356
21 changed files with 249 additions and 429 deletions

View File

@@ -32,9 +32,9 @@ struct ResultBLF;
struct rcti;
namespace blender::ocio {
class Display;
class ColorSpace;
} // namespace blender::ocio
using ColorManagedDisplay = blender::ocio::Display;
using ColorSpace = blender::ocio::ColorSpace;
int BLF_init();
void BLF_exit();
@@ -350,12 +350,8 @@ void BLF_shadow_offset(int fontid, int x, int y);
* The image is assumed to have 4 color channels (RGBA) per pixel.
* When done, call this function with null buffer pointers.
*/
void BLF_buffer(int fontid,
float *fbuf,
unsigned char *cbuf,
int w,
int h,
const ColorManagedDisplay *display);
void BLF_buffer(
int fontid, float *fbuf, unsigned char *cbuf, int w, int h, const ColorSpace *colorspace);
/**
* Opaque structure used to push/pop values set by the #BLF_buffer function.
@@ -379,7 +375,7 @@ void BLF_buffer_state_free(BLFBufferState *buffer_state);
/**
* Set the color to be used for text.
*/
void BLF_buffer_col(int fontid, const float rgba[4]) ATTR_NONNULL(2);
void BLF_buffer_col(int fontid, const float srgb_color[4]) ATTR_NONNULL(2);
/**
* Draw the string into the buffer, this function draw in both buffer,

View File

@@ -944,8 +944,7 @@ void BLF_shadow_offset(int fontid, int x, int y)
}
}
void BLF_buffer(
int fontid, float *fbuf, uchar *cbuf, int w, int h, const ColorManagedDisplay *display)
void BLF_buffer(int fontid, float *fbuf, uchar *cbuf, int w, int h, const ColorSpace *colorspace)
{
FontBLF *font = blf_get(fontid);
@@ -954,7 +953,7 @@ void BLF_buffer(
font->buf_info.cbuf = cbuf;
font->buf_info.dims[0] = w;
font->buf_info.dims[1] = h;
font->buf_info.display = display;
font->buf_info.colorspace = colorspace;
}
}
@@ -1004,12 +1003,12 @@ void BLF_buffer_state_free(BLFBufferState *buffer_state)
MEM_delete(buffer_state);
}
void BLF_buffer_col(int fontid, const float rgba[4])
void BLF_buffer_col(int fontid, const float srgb_color[4])
{
FontBLF *font = blf_get(fontid);
if (font) {
copy_v4_v4(font->buf_info.col_init, rgba);
copy_v4_v4(font->buf_info.col_init, srgb_color);
}
}
@@ -1017,14 +1016,19 @@ void blf_draw_buffer__start(FontBLF *font)
{
FontBufInfoBLF *buf_info = &font->buf_info;
rgba_float_to_uchar(buf_info->col_char, buf_info->col_init);
/* This will be written to scene linear image buffer, so convert to that. */
IMB_colormanagement_srgb_to_scene_linear_v3(buf_info->col_float, buf_info->col_init);
buf_info->col_float[3] = buf_info->col_init[3];
if (buf_info->display) {
copy_v4_v4(buf_info->col_float, buf_info->col_init);
IMB_colormanagement_display_to_scene_linear_v3(buf_info->col_float, buf_info->display);
/* Convert to the colorspace of the byte image buffer, assumed sRGB if not specified. */
if (buf_info->colorspace) {
float col_char[4];
copy_v4_v4(col_char, buf_info->col_float);
IMB_colormanagement_scene_linear_to_colorspace_v3(col_char, buf_info->colorspace);
rgba_float_to_uchar(buf_info->col_char, col_char);
}
else {
srgb_to_linearrgb_v4(buf_info->col_float, buf_info->col_init);
rgba_float_to_uchar(buf_info->col_char, buf_info->col_init);
}
}
void blf_draw_buffer__end() {}

View File

@@ -35,9 +35,9 @@ class VertBuf;
struct GPUVertBufRaw;
namespace blender::ocio {
class Display;
class ColorSpace;
} // namespace blender::ocio
using ColorManagedDisplay = blender::ocio::Display;
using ColorSpace = blender::ocio::ColorSpace;
#include FT_MULTIPLE_MASTERS_H /* Variable font support. */
@@ -230,8 +230,8 @@ struct FontBufInfoBLF {
/** Buffer size, keep signed so comparisons with negative values work. */
int dims[2];
/** Display device used for color management. */
const ColorManagedDisplay *display;
/** Colorspace of the byte buffer (float is scene linear). */
const ColorSpace *colorspace;
/** The color, the alphas is get from the glyph! (color is sRGB space). */
float col_init[4];

View File

@@ -17,6 +17,11 @@ namespace blender::gpu {
class Texture;
} // namespace blender::gpu
namespace blender::ocio {
class ColorSpace;
} // namespace blender::ocio
using ColorSpace = blender::ocio::ColorSpace;
struct rcti;
struct Depsgraph;
struct ID;
@@ -113,10 +118,7 @@ void BKE_stamp_data_free(StampData *stamp_data);
void BKE_image_stamp_buf(Scene *scene,
Object *camera,
const StampData *stamp_data_template,
unsigned char *rect,
float *rectf,
int width,
int height);
ImBuf *ibuf);
bool BKE_imbuf_alpha_test(ImBuf *ibuf);
bool BKE_imbuf_write_stamp(const Scene *scene,
const RenderResult *rr,

View File

@@ -2001,18 +2001,13 @@ static void stampdata_from_template(StampData *stamp_data,
void BKE_image_stamp_buf(Scene *scene,
Object *camera,
const StampData *stamp_data_template,
uchar *rect,
float *rectf,
int width,
int height)
ImBuf *ibuf)
{
StampData stamp_data;
int w, h, pad;
int x, y, y_ofs;
int h_fixed;
const int mono = blf_mono_font_render; /* XXX */
const ColorManagedDisplay *display;
const char *display_device;
/* vars for calculating wordwrap */
struct {
@@ -2035,13 +2030,10 @@ void BKE_image_stamp_buf(Scene *scene,
#define BUFF_MARGIN_X 2
#define BUFF_MARGIN_Y 1
if (!rect && !rectf) {
if (!ibuf->byte_buffer.data && !ibuf->float_buffer.data) {
return;
}
display_device = scene->display_settings.display_device;
display = IMB_colormanagement_display_get_named(display_device);
bool do_prefix = (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0;
if (stamp_data_template == nullptr) {
stampdata(scene, camera, &stamp_data, do_prefix, true);
@@ -2057,9 +2049,14 @@ void BKE_image_stamp_buf(Scene *scene,
/* set before return */
BLF_size(mono, scene->r.stamp_font_id);
BLF_wordwrap(mono, width - (BUFF_MARGIN_X * 2));
BLF_wordwrap(mono, ibuf->x - (BUFF_MARGIN_X * 2));
BLF_buffer(mono, rectf, rect, width, height, display);
BLF_buffer(mono,
ibuf->float_buffer.data,
ibuf->byte_buffer.data,
ibuf->x,
ibuf->y,
ibuf->byte_buffer.colorspace);
BLF_buffer_col(mono, scene->r.fg_stamp);
pad = BLF_width_max(mono);
@@ -2068,19 +2065,15 @@ void BKE_image_stamp_buf(Scene *scene,
y_ofs = -BLF_descender(mono);
x = 0;
y = height;
y = ibuf->y;
if (TEXT_SIZE_CHECK(stamp_data.file, w, h)) {
/* Top left corner */
y -= h;
/* also a little of space to the background. */
buf_rectfill_area(rect,
rectf,
width,
height,
IMB_rectfill_area(ibuf,
scene->r.bg_stamp,
display,
x - BUFF_MARGIN_X,
y - BUFF_MARGIN_Y,
w + BUFF_MARGIN_X,
@@ -2099,16 +2092,8 @@ void BKE_image_stamp_buf(Scene *scene,
y -= h;
/* and space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
scene->r.bg_stamp,
display,
0,
y - BUFF_MARGIN_Y,
w + BUFF_MARGIN_X,
y + h + BUFF_MARGIN_Y);
IMB_rectfill_area(
ibuf, scene->r.bg_stamp, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.date, sizeof(stamp_data.date));
@@ -2122,16 +2107,8 @@ void BKE_image_stamp_buf(Scene *scene,
y -= h;
/* and space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
scene->r.bg_stamp,
display,
0,
y - BUFF_MARGIN_Y,
w + BUFF_MARGIN_X,
y + h + BUFF_MARGIN_Y);
IMB_rectfill_area(
ibuf, scene->r.bg_stamp, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.rendertime, sizeof(stamp_data.rendertime));
@@ -2145,16 +2122,8 @@ void BKE_image_stamp_buf(Scene *scene,
y -= h;
/* and space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
scene->r.bg_stamp,
display,
0,
y - BUFF_MARGIN_Y,
w + BUFF_MARGIN_X,
y + h + BUFF_MARGIN_Y);
IMB_rectfill_area(
ibuf, scene->r.bg_stamp, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.memory, sizeof(stamp_data.memory));
@@ -2168,16 +2137,8 @@ void BKE_image_stamp_buf(Scene *scene,
y -= h;
/* and space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
scene->r.bg_stamp,
display,
0,
y - BUFF_MARGIN_Y,
w + BUFF_MARGIN_X,
y + h + BUFF_MARGIN_Y);
IMB_rectfill_area(
ibuf, scene->r.bg_stamp, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.hostname, sizeof(stamp_data.hostname));
@@ -2192,16 +2153,8 @@ void BKE_image_stamp_buf(Scene *scene,
y -= h;
/* and space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
scene->r.bg_stamp,
display,
0,
y - BUFF_MARGIN_Y,
w + BUFF_MARGIN_X,
y + h + BUFF_MARGIN_Y);
IMB_rectfill_area(
ibuf, scene->r.bg_stamp, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs + (h - h_fixed), 0.0);
BLF_draw_buffer(mono, stamp_data.note, sizeof(stamp_data.note));
@@ -2215,12 +2168,8 @@ void BKE_image_stamp_buf(Scene *scene,
if (TEXT_SIZE_CHECK(stamp_data.marker, w, h)) {
/* extra space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
IMB_rectfill_area(ibuf,
scene->r.bg_stamp,
display,
x - BUFF_MARGIN_X,
y - BUFF_MARGIN_Y,
w + BUFF_MARGIN_X,
@@ -2238,12 +2187,8 @@ void BKE_image_stamp_buf(Scene *scene,
if (TEXT_SIZE_CHECK(stamp_data.time, w, h)) {
/* extra space for background */
buf_rectfill_area(rect,
rectf,
width,
height,
IMB_rectfill_area(ibuf,
scene->r.bg_stamp,
display,
x - BUFF_MARGIN_X,
y,
x + w + BUFF_MARGIN_X,
@@ -2260,12 +2205,8 @@ void BKE_image_stamp_buf(Scene *scene,
if (TEXT_SIZE_CHECK(stamp_data.frame, w, h)) {
/* extra space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
IMB_rectfill_area(ibuf,
scene->r.bg_stamp,
display,
x - BUFF_MARGIN_X,
y - BUFF_MARGIN_Y,
x + w + BUFF_MARGIN_X,
@@ -2282,12 +2223,8 @@ void BKE_image_stamp_buf(Scene *scene,
if (TEXT_SIZE_CHECK(stamp_data.frame_range, w, h)) {
/* extra space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
IMB_rectfill_area(ibuf,
scene->r.bg_stamp,
display,
x - BUFF_MARGIN_X,
y - BUFF_MARGIN_Y,
x + w + BUFF_MARGIN_X,
@@ -2304,12 +2241,8 @@ void BKE_image_stamp_buf(Scene *scene,
if (TEXT_SIZE_CHECK(stamp_data.camera, w, h)) {
/* extra space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
IMB_rectfill_area(ibuf,
scene->r.bg_stamp,
display,
x - BUFF_MARGIN_X,
y - BUFF_MARGIN_Y,
x + w + BUFF_MARGIN_X,
@@ -2324,12 +2257,8 @@ void BKE_image_stamp_buf(Scene *scene,
if (TEXT_SIZE_CHECK(stamp_data.cameralens, w, h)) {
/* extra space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
IMB_rectfill_area(ibuf,
scene->r.bg_stamp,
display,
x - BUFF_MARGIN_X,
y - BUFF_MARGIN_Y,
x + w + BUFF_MARGIN_X,
@@ -2341,15 +2270,11 @@ void BKE_image_stamp_buf(Scene *scene,
if (TEXT_SIZE_CHECK(stamp_data.scene, w, h)) {
/* Bottom right corner, with an extra space because the BLF API is too strict! */
x = width - w - 2;
x = ibuf->x - w - 2;
/* extra space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
IMB_rectfill_area(ibuf,
scene->r.bg_stamp,
display,
x - BUFF_MARGIN_X,
y - BUFF_MARGIN_Y,
x + w + BUFF_MARGIN_X,
@@ -2363,16 +2288,12 @@ void BKE_image_stamp_buf(Scene *scene,
if (TEXT_SIZE_CHECK(stamp_data.strip, w, h)) {
/* Top right corner, with an extra space because the BLF API is too strict! */
x = width - w - pad;
y = height - h;
x = ibuf->x - w - pad;
y = ibuf->y - h;
/* extra space for background. */
buf_rectfill_area(rect,
rectf,
width,
height,
IMB_rectfill_area(ibuf,
scene->r.bg_stamp,
display,
x - BUFF_MARGIN_X,
y - BUFF_MARGIN_Y,
x + w + BUFF_MARGIN_X,

View File

@@ -302,10 +302,8 @@ static void checker_board_text(
BLF_size(mono, 54.0f); /* hard coded size! */
/* OCIO_TODO: using nullptr as display will assume using sRGB display
* this is correct since currently generated images are assumed to be in sRGB space,
* but this would probably needed to be fixed in some way
*/
/* Using nullptr will assume the byte buffer has sRGB colorspace, which currently
* matches the default colorspace of new images. */
BLF_buffer(mono, rect_float, rect, width, height, nullptr);
const float text_color[4] = {0.0, 0.0, 0.0, 1.0};

View File

@@ -313,11 +313,11 @@ static void eyedropper_grease_pencil_color_set(bContext *C,
float3 col_conv = eye->color;
/* Convert from linear rgb space to display space because palette and brush colors are in display
* space, and this conversion is needed to undo the conversion to linear performed by
* eyedropper_color_sample_fl. */
/* Convert from linear rgb space to sRGB space because palette and brush colors are in
* sRGB space, and this conversion is needed to undo the conversion to linear performed by
* eyedropper_color_sample_fl. */
if (eye->display && ELEM(eye->mode, EyeMode::Palette, EyeMode::Brush)) {
IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
IMB_colormanagement_scene_linear_to_srgb_v3(col_conv, col_conv);
}
switch (eye->mode) {

View File

@@ -805,34 +805,35 @@ static std::unique_ptr<uiTooltipData> ui_tooltip_data_from_tool(bContext *C,
static std::string ui_tooltip_color_string(const blender::float4 &color,
const blender::StringRefNull title,
const int max_title_len,
const bool show_alpha,
const bool show_hex = false)
{
const int align = max_title_len - title.size();
if (show_hex) {
uchar hex[4];
rgba_float_to_uchar(hex, color);
if (show_alpha) {
return fmt::format("{}: #{:02X}{:02X}{:02X}{:02X}",
TIP_(title),
return fmt::format("{}:{: <{}} #{:02X}{:02X}{:02X}{:02X}",
title,
"",
align,
int(hex[0]),
int(hex[1]),
int(hex[2]),
int(hex[3]));
}
return fmt::format(
"{}: #{:02X}{:02X}{:02X}", TIP_(title), int(hex[0]), int(hex[1]), int(hex[2]));
"{}:{: <{}} #{:02X}{:02X}{:02X}", title, "", align, int(hex[0]), int(hex[1]), int(hex[2]));
}
if (show_alpha) {
return fmt::format("{}: {:.3f} {:.3f} {:.3f} {:.3f}",
TIP_(title),
color[0],
color[1],
color[2],
color[3]);
return fmt::format("{}:{: <{}} {:.3f}", title, "", align, color[3]);
}
return fmt::format("{}: {:.3f} {:.3f} {:.3f}", TIP_(title), color[0], color[1], color[2]);
return fmt::format(
"{}:{: <{}} {:.3f} {:.3f} {:.3f}", title, "", align, color[0], color[1], color[2]);
};
void UI_tooltip_color_field_add(uiTooltipData &data,
@@ -842,25 +843,42 @@ void UI_tooltip_color_field_add(uiTooltipData &data,
const ColorManagedDisplay *display,
const uiTooltipColorID color_id)
{
blender::float4 color = original_color;
if (!is_gamma && display) {
IMB_colormanagement_scene_linear_to_display_v3(color, display);
blender::float4 scene_linear_color = original_color;
blender::float4 display_color = original_color;
blender::float4 srgb_color = original_color;
if (is_gamma) {
IMB_colormanagement_srgb_to_scene_linear_v3(scene_linear_color, scene_linear_color);
}
else {
IMB_colormanagement_scene_linear_to_display_v3(display_color, display);
IMB_colormanagement_scene_linear_to_srgb_v3(srgb_color, srgb_color);
}
const std::string hex_st = ui_tooltip_color_string(color, "Hex", has_alpha, true);
float hsv[4];
rgb_to_hsv_v(srgb_color, hsv);
hsv[3] = srgb_color[3];
const blender::StringRefNull hex_title = TIP_("Hex");
const blender::StringRefNull rgb_title = (is_gamma) ? TIP_("sRGB") : TIP_("Display RGB");
const blender::StringRefNull hsv_title = TIP_("HSV");
const blender::StringRefNull alpha_title = TIP_("Alpha");
const int max_title_len = std::max(
{hex_title.size(), rgb_title.size(), hsv_title.size(), alpha_title.size()});
const std::string hex_st = ui_tooltip_color_string(
srgb_color, hex_title, max_title_len, has_alpha, true);
const std::string rgba_st = ui_tooltip_color_string(
color, has_alpha ? "RGBA" : "RGB", has_alpha);
float hsva[4];
rgb_to_hsv_v(color, hsva);
hsva[3] = color[3];
const std::string hsva_st = ui_tooltip_color_string(hsva, has_alpha ? "HSVA" : "HSV", has_alpha);
display_color, rgb_title, max_title_len, false);
const std::string hsv_st = ui_tooltip_color_string(hsv, hsv_title, max_title_len, false);
const std::string alpha_st = ui_tooltip_color_string(
scene_linear_color, alpha_title, max_title_len, true);
const uiFontStyle *fs = &UI_style_get()->tooltip;
BLF_size(blf_mono_font, fs->points * UI_SCALE_FAC);
float w = BLF_width(blf_mono_font, hsva_st.c_str(), hsva_st.size());
float w = BLF_width(blf_mono_font, hsv_st.c_str(), hsv_st.size());
/* TODO: This clips wide gamut. Should make a float buffer and draw for display. */
uiTooltipImage image_data;
image_data.width = int(w);
image_data.height = int(w / (has_alpha ? 4.0f : 3.0f));
@@ -868,35 +886,38 @@ void UI_tooltip_color_field_add(uiTooltipData &data,
image_data.border = true;
image_data.premultiplied = false;
if (color[3] == 1.0f) {
if (scene_linear_color[3] == 1.0f) {
/* No transparency so draw the entire area solid without checkerboard. */
image_data.background = uiTooltipImageBackground::None;
IMB_rectfill_area(image_data.ibuf, color, 1, 1, image_data.width, image_data.height, display);
IMB_rectfill_area(
image_data.ibuf, scene_linear_color, 1, 1, image_data.width, image_data.height);
}
else {
image_data.background = uiTooltipImageBackground::Checkerboard_Fixed;
/* Draw one half with transparency. */
IMB_rectfill_area(image_data.ibuf,
color,
scene_linear_color,
image_data.width / 2,
1,
image_data.width,
image_data.height,
display);
image_data.height);
/* Draw the other half with a solid color. */
color[3] = 1.0f;
scene_linear_color[3] = 1.0f;
IMB_rectfill_area(
image_data.ibuf, color, 1, 1, image_data.width / 2, image_data.height, display);
image_data.ibuf, scene_linear_color, 1, 1, image_data.width / 2, image_data.height);
}
UI_tooltip_text_field_add(data, {}, {}, UI_TIP_STYLE_SPACER, color_id, false);
UI_tooltip_text_field_add(data, {}, {}, UI_TIP_STYLE_SPACER, color_id, false);
UI_tooltip_image_field_add(data, image_data);
UI_tooltip_text_field_add(data, {}, {}, UI_TIP_STYLE_SPACER, color_id, false);
UI_tooltip_text_field_add(data, hex_st, {}, UI_TIP_STYLE_MONO, color_id, false);
UI_tooltip_text_field_add(data, {}, {}, UI_TIP_STYLE_SPACER, color_id, false);
UI_tooltip_text_field_add(data, rgba_st, {}, UI_TIP_STYLE_MONO, color_id, false);
UI_tooltip_text_field_add(data, hsva_st, {}, UI_TIP_STYLE_MONO, color_id, false);
UI_tooltip_text_field_add(data, hsv_st, {}, UI_TIP_STYLE_MONO, color_id, false);
if (has_alpha) {
UI_tooltip_text_field_add(data, alpha_st, {}, UI_TIP_STYLE_MONO, color_id, false);
}
UI_tooltip_text_field_add(data, {}, {}, UI_TIP_STYLE_SPACER, color_id, false);
UI_tooltip_text_field_add(data, hex_st, {}, UI_TIP_STYLE_MONO, color_id, false);
/* Tooltip now owns a copy of the ImBuf, so we can delete ours. */
IMB_freeImBuf(image_data.ibuf);

View File

@@ -390,15 +390,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
if (ibuf_result != nullptr) {
if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) {
float *rectf = nullptr;
uchar *rect = nullptr;
if (ibuf_result->float_buffer.data) {
rectf = ibuf_result->float_buffer.data;
}
else {
rect = ibuf_result->byte_buffer.data;
}
BKE_image_stamp_buf(scene, camera, nullptr, rect, rectf, rr->rectx, rr->recty);
BKE_image_stamp_buf(scene, camera, nullptr, ibuf_result);
}
RE_render_result_rect_from_ibuf(rr, ibuf_result, oglrender->view_id);
IMB_freeImBuf(ibuf_result);

View File

@@ -366,11 +366,10 @@ bool paint_use_opacity_masking(const Paint *paint, const Brush *brush)
void paint_brush_color_get(const Paint *paint,
Brush *br,
std::optional<blender::float3> &initial_hsv_jitter,
bool color_correction,
bool invert,
float distance,
float pressure,
const ColorManagedDisplay *display,
bool is_data,
float r_color[3])
{
if (invert) {
@@ -396,7 +395,7 @@ void paint_brush_color_get(const Paint *paint,
}
}
/* Gradient / Color-band colors are not considered #PROP_COLOR_GAMMA.
* Brush colors are expected to be in sRGB though. */
* Brush colors are currently in sRGB though. */
IMB_colormanagement_scene_linear_to_srgb_v3(r_color, color_gr);
}
else if (color_jitter_settings) {
@@ -411,8 +410,8 @@ void paint_brush_color_get(const Paint *paint,
copy_v3_v3(r_color, BKE_brush_color_get(paint, br));
}
}
if (color_correction) {
IMB_colormanagement_display_to_scene_linear_v3(r_color, display);
if (!is_data) {
IMB_colormanagement_srgb_to_scene_linear_v3(r_color, r_color);
}
}

View File

@@ -12,12 +12,12 @@
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "BLI_bitmap.h"
#include "BLI_listbase.h"
#include "BLI_math_color.h"
#include "BLI_math_color_blend.h"
#include "BLI_stack.h"
#include "BLI_task.h"
@@ -51,8 +51,10 @@
/* Defines and Structs */
struct BrushPainterCache {
bool use_float; /* need float imbuf? */
bool use_color_correction; /* use color correction for float */
bool is_float; /* need float imbuf? */
bool is_data; /* is non-color data? */
bool is_srgb; /* is the byte colorspace sRGB? */
const ColorSpace *byte_colorspace;
bool invert;
bool is_texbrush;
@@ -161,12 +163,17 @@ static BrushPainter *brush_painter_2d_new(Scene *scene,
return painter;
}
static void brush_painter_2d_require_imbuf(
Brush *brush, ImagePaintTile *tile, bool use_float, bool use_color_correction, bool invert)
static void brush_painter_2d_require_imbuf(Brush *brush,
ImagePaintTile *tile,
bool is_float,
bool is_data,
bool is_srgb,
const ColorSpace *byte_colorspace,
bool invert)
{
BrushPainterCache *cache = &tile->cache;
if (cache->use_float != use_float) {
if (cache->is_float != is_float) {
if (cache->ibuf) {
IMB_freeImBuf(cache->ibuf);
}
@@ -181,8 +188,10 @@ static void brush_painter_2d_require_imbuf(
cache->lastdiameter = -1; /* force ibuf create in refresh */
}
cache->use_float = use_float;
cache->use_color_correction = use_float && use_color_correction;
cache->is_float = is_float;
cache->is_data = is_data;
cache->is_srgb = is_srgb;
cache->byte_colorspace = byte_colorspace;
cache->invert = invert;
cache->is_texbrush = (brush->mtex.tex &&
brush->image_brush_type == IMAGE_PAINT_BRUSH_TYPE_DRAW) ?
@@ -380,38 +389,39 @@ static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
static ImBuf *brush_painter_imbuf_new(
BrushPainter *painter, ImagePaintTile *tile, const int size, float pressure, float distance)
{
Scene *scene = painter->scene;
const Paint *paint = painter->paint;
Brush *brush = painter->brush;
BrushPainterCache *cache = &tile->cache;
const char *display_device = scene->display_settings.display_device;
const ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
rctf tex_mapping = painter->tex_mapping;
ImagePool *pool = painter->pool;
bool use_color_correction = cache->use_color_correction;
bool use_float = cache->use_float;
bool is_texbrush = cache->is_texbrush;
const bool is_float = cache->is_float;
const bool is_texbrush = cache->is_texbrush;
int x, y, thread = 0;
float brush_rgb[3];
/* allocate image buffer */
ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_float_data : IB_byte_data);
ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (is_float) ? IB_float_data : IB_byte_data);
/* get brush color */
if (brush->image_brush_type == IMAGE_PAINT_BRUSH_TYPE_DRAW) {
paint_brush_color_get(paint,
brush,
painter->initial_hsv_jitter,
use_color_correction,
cache->invert,
distance,
pressure,
display,
cache->is_data,
brush_rgb);
if (cache->is_srgb) {
IMB_colormanagement_scene_linear_to_srgb_v3(brush_rgb, brush_rgb);
}
else if (cache->byte_colorspace) {
IMB_colormanagement_scene_linear_to_colorspace_v3(brush_rgb, cache->byte_colorspace);
}
}
else {
brush_rgb[0] = 1.0f;
@@ -429,10 +439,13 @@ static ImBuf *brush_painter_imbuf_new(
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
const MTex *mtex = &brush->mtex;
BKE_brush_sample_tex_3d(painter->paint, brush, mtex, texco, rgba, thread, pool);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
if (cache->is_srgb) {
IMB_colormanagement_scene_linear_to_srgb_v3(rgba, rgba);
}
else if (cache->byte_colorspace) {
IMB_colormanagement_scene_linear_to_colorspace_v3(rgba, cache->byte_colorspace);
}
mul_v3_v3(rgba, brush_rgb);
}
else {
@@ -440,7 +453,7 @@ static ImBuf *brush_painter_imbuf_new(
rgba[3] = 1.0f;
}
if (use_float) {
if (is_float) {
/* write to float pixel */
float *dstf = ibuf->float_buffer.data + (y * size + x) * 4;
mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */
@@ -470,22 +483,17 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
int xt,
int yt)
{
Scene *scene = painter->scene;
const Paint *paint = painter->paint;
Brush *brush = painter->brush;
const MTex *mtex = &brush->mtex;
BrushPainterCache *cache = &tile->cache;
const char *display_device = scene->display_settings.display_device;
const ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
rctf tex_mapping = painter->tex_mapping;
ImagePool *pool = painter->pool;
bool use_color_correction = cache->use_color_correction;
bool use_float = cache->use_float;
bool is_texbrush = cache->is_texbrush;
bool use_texture_old = (oldtexibuf != nullptr);
const bool is_float = cache->is_float;
const bool is_texbrush = cache->is_texbrush;
const bool use_texture_old = (oldtexibuf != nullptr);
int x, y, thread = 0;
float brush_rgb[3];
@@ -498,12 +506,18 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
paint_brush_color_get(paint,
brush,
painter->initial_hsv_jitter,
use_color_correction,
cache->invert,
0.0f,
1.0f,
display,
cache->is_data,
brush_rgb);
if (cache->is_srgb) {
IMB_colormanagement_scene_linear_to_srgb_v3(brush_rgb, brush_rgb);
}
else if (cache->byte_colorspace) {
IMB_colormanagement_scene_linear_to_colorspace_v3(brush_rgb, cache->byte_colorspace);
}
}
else {
brush_rgb[0] = 1.0f;
@@ -521,10 +535,13 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
BKE_brush_sample_tex_3d(painter->paint, brush, mtex, texco, rgba, thread, pool);
/* TODO(sergey): Support texture paint color space. */
if (!use_float) {
IMB_colormanagement_scene_linear_to_display_v3(rgba, display);
if (cache->is_srgb) {
IMB_colormanagement_scene_linear_to_srgb_v3(rgba, rgba);
}
else if (cache->byte_colorspace) {
IMB_colormanagement_scene_linear_to_colorspace_v3(rgba, cache->byte_colorspace);
}
mul_v3_v3(rgba, brush_rgb);
}
else {
@@ -533,7 +550,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
}
}
if (use_float) {
if (is_float) {
/* handle float pixel */
float *bf = ibuf->float_buffer.data + (y * ibuf->x + x) * 4;
float *tf = texibuf->float_buffer.data + (y * texibuf->x + x) * 4;
@@ -601,7 +618,7 @@ static void brush_painter_imbuf_partial_update(BrushPainter *painter,
int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
/* create brush image buffer if it didn't exist yet */
imbflag = (cache->use_float) ? IB_float_data : IB_byte_data;
imbflag = (cache->is_float) ? IB_float_data : IB_byte_data;
if (!cache->ibuf) {
cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
}
@@ -1509,8 +1526,6 @@ void paint_2d_stroke(void *ps,
ImagePaintState *s = static_cast<ImagePaintState *>(ps);
BrushPainter *painter = s->painter;
const bool is_data = s->tiles[0].canvas->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
s->blend = s->brush->blend;
if (eraser) {
s->blend = IMB_BLEND_ERASE_ALPHA;
@@ -1573,13 +1588,23 @@ void paint_2d_stroke(void *ps,
ImBuf *ibuf = tile->canvas;
const bool is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
const bool is_float = (ibuf->float_buffer.data != nullptr);
const ColorSpace *byte_colorspace = (is_float || is_data) ? nullptr :
ibuf->byte_buffer.colorspace;
const bool is_srgb = (is_float || is_data) ?
false :
IMB_colormanagement_space_is_srgb(byte_colorspace);
/* OCIO_TODO: float buffers are now always linear, so always use color correction
* this should probably be changed when texture painting color space is supported
*/
brush_painter_2d_require_imbuf(painter->brush,
tile,
(ibuf->float_buffer.data != nullptr),
!is_data,
is_data,
is_srgb,
byte_colorspace,
painter->cache_invert);
brush_painter_2d_refresh_cache(s, painter, tile, new_coord, mval, pressure, distance, size);
@@ -1861,11 +1886,13 @@ void paint_2d_bucket_fill(const bContext *C,
/* First check if our image is float. If it is we should correct the color to be in linear space.
*/
if (!do_float) {
rgb_float_to_uchar((uchar *)&color_b, color);
blender::float3 ibuf_color = color;
IMB_colormanagement_scene_linear_to_colorspace_v3(ibuf_color, ibuf->byte_buffer.colorspace);
rgb_float_to_uchar((uchar *)&color_b, ibuf_color);
*(((char *)&color_b) + 3) = strength * 255;
}
else {
srgb_to_linearrgb_v3_v3(color_f, color);
copy_v3_v3(color_f, color);
color_f[3] = strength;
}
@@ -2110,7 +2137,7 @@ void paint_2d_gradient_fill(
}
BKE_colorband_evaluate(br->gradient, f, color_f);
linearrgb_to_srgb_v3_v3(color_f, color_f);
IMB_colormanagement_scene_linear_to_colorspace_v3(color_f, ibuf->byte_buffer.colorspace);
rgba_float_to_uchar((uchar *)&color_b, color_f);
((uchar *)&color_b)[3] *= brush_alpha;
IMB_blend_color_byte(ibuf->byte_buffer.data + 4 * (size_t(y_px) * ibuf->x + x_px),

View File

@@ -5787,18 +5787,11 @@ static void paint_proj_stroke_ps(const bContext * /*C*/,
paint_brush_color_get(paint,
brush,
ps_handle->initial_hsv_jitter,
false,
ps->mode == BRUSH_STROKE_INVERT,
distance,
pressure,
nullptr,
has_data_projection_paint_image(*ps),
ps->paint_color);
if (has_data_projection_paint_image(*ps)) {
copy_v3_v3(ps->paint_color_linear, ps->paint_color);
}
else {
srgb_to_linearrgb_v3_v3(ps->paint_color_linear, ps->paint_color);
}
}
else if (ps->brush_type == IMAGE_PAINT_BRUSH_TYPE_MASK) {
ps->stencil_value = brush->weight;

View File

@@ -347,12 +347,11 @@ void paint_proj_stroke_done(void *ps_handle_p);
void paint_brush_color_get(const Paint *paint,
Brush *br,
std::optional<blender::float3> &initial_hsv_jitter,
bool color_correction,
bool invert,
float distance,
float pressure,
const ColorManagedDisplay *display,
float r_color[3]);
bool is_data,
float r_color[3] /* In scene linear colorspace. */);
bool paint_use_opacity_masking(const Paint *paint, const Brush *brush);
void paint_brush_init_tex(Brush *brush);
void paint_brush_exit_tex(Brush *brush);

View File

@@ -251,7 +251,7 @@ void ED_image_draw_info(Scene *scene,
rgba, rgba, &scene->view_settings, &scene->display_settings);
}
SNPRINTF_UTF8(str, " | CM R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]);
SNPRINTF_UTF8(str, " | Display R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));

View File

@@ -416,7 +416,6 @@ class SocketTooltipBuilder {
this->build_tooltip_value_and_type_oneline(value_str, TIP_("Float Color"));
this->add_space();
this->add_text_field_mono(TIP_("Display:"), UI_TIP_LC_NORMAL);
bool is_gamma = false;
const ColorManagedDisplay *display = nullptr;
if (but_) {

View File

@@ -24,11 +24,6 @@ struct GSet;
struct ImageFormatData;
struct Stereo3dFormat;
namespace blender::ocio {
class Display;
} // namespace blender::ocio
using ColorManagedDisplay = blender::ocio::Display;
/**
* Module init/exit.
*/
@@ -470,53 +465,19 @@ void IMB_rectfill(ImBuf *drect, const float col[4]);
/**
* Blend pixels of image area with solid color.
*
* For images with `uchar` buffer use color matching image color-space.
* For images with float buffer use color display color-space.
* If display color-space can not be referenced, use color in SRGB color-space.
*
* \param ibuf: an image to be filled with color. It must be 4 channel image.
* \param col: RGBA color.
* \param x1, y1, x2, y2: (x1, y1) defines starting point of the rectangular area to be filled,
* (x2, y2) is the end point. Note that values are allowed to be loosely ordered, which means that
* x2 is allowed to be lower than x1, as well as y2 is allowed to be lower than y1. No matter the
* order the area between x1 and x2, and y1 and y2 is filled.
* \param display: color-space reference for display space.
* \param scene_linear_color: RGBA color in scene linear colorspace. For byte buffers, this is
* converted to the byte buffer colorspace.
* \param x1, y1, x2, y2: (x1, y1) defines starting point
* of the rectangular area to be filled, (x2, y2) is the end point. Note that values are allowed to
* be loosely ordered, which means that x2 is allowed to be lower than x1, as well as y2 is allowed
* to be lower than y1. No matter the order the area between x1 and x2, and y1 and y2 is filled.
* \param colorspace: color-space reference for display space.
*/
void IMB_rectfill_area(ImBuf *ibuf,
const float col[4],
int x1,
int y1,
int x2,
int y2,
const ColorManagedDisplay *display);
/**
* Replace pixels of image area with solid color.
* \param ibuf: an image to be filled with color. It must be 4 channel image.
* \param col: RGBA color, which is assigned directly to both byte (via scaling) and float buffers.
* \param x1, y1, x2, y2: (x1, y1) defines starting point of the rectangular area to be filled,
* (x2, y2) is the end point. Note that values are allowed to be loosely ordered, which means that
* x2 is allowed to be lower than x1, as well as y2 is allowed to be lower than y1. No matter the
* order the area between x1 and x2, and y1 and y2 is filled.
*/
void IMB_rectfill_area_replace(
const ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2);
void IMB_rectfill_area(
ImBuf *ibuf, const float scene_linear_color[4], int x1, int y1, int x2, int y2);
void IMB_rectfill_alpha(ImBuf *ibuf, float value);
/**
* This should not be here, really,
* we needed it for operating on render data, #IMB_rectfill_area calls it.
*/
void buf_rectfill_area(unsigned char *rect,
float *rectf,
int width,
int height,
const float col[4],
const ColorManagedDisplay *display,
int x1,
int y1,
int x2,
int y2);
/**
* Exported for image tools in blender, to quickly allocate 32 bits rect.
*/

View File

@@ -1008,65 +1008,19 @@ void IMB_rectfill(ImBuf *drect, const float col[4])
}
}
void IMB_rectfill_area_replace(
const ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2)
void IMB_rectfill_area(
ImBuf *ibuf, const float scene_linear_color[4], int x1, int y1, int x2, int y2)
{
/* Sanity checks. */
BLI_assert(ibuf->channels == 4);
if (ibuf->channels != 4) {
if (!ibuf) {
return;
}
int width = ibuf->x;
int height = ibuf->y;
CLAMP(x1, 0, width);
CLAMP(x2, 0, width);
CLAMP(y1, 0, height);
CLAMP(y2, 0, height);
uchar *rect = ibuf->byte_buffer.data;
float *rectf = ibuf->float_buffer.data;
const int width = ibuf->x;
const int height = ibuf->y;
if (x1 > x2) {
std::swap(x1, x2);
}
if (y1 > y2) {
std::swap(y1, y2);
}
if (x1 == x2 || y1 == y2) {
return;
}
const uchar col_char[4] = {
uchar(col[0] * 255), uchar(col[1] * 255), uchar(col[2] * 255), uchar(col[3] * 255)};
for (int y = y1; y < y2; y++) {
for (int x = x1; x < x2; x++) {
size_t offset = size_t(ibuf->x) * y * 4 + 4 * x;
if (ibuf->byte_buffer.data) {
uchar *rrect = ibuf->byte_buffer.data + offset;
memcpy(rrect, col_char, sizeof(uchar[4]));
}
if (ibuf->float_buffer.data) {
float *rrectf = ibuf->float_buffer.data + offset;
memcpy(rrectf, col, sizeof(float[4]));
}
}
}
}
void buf_rectfill_area(uchar *rect,
float *rectf,
int width,
int height,
const float col[4],
const ColorManagedDisplay *display,
int x1,
int y1,
int x2,
int y2)
{
if ((!rect && !rectf) || (!col) || col[3] == 0.0f) {
if ((!rect && !rectf) || scene_linear_color[3] == 0.0f) {
return;
}
@@ -1089,7 +1043,7 @@ void buf_rectfill_area(uchar *rect,
const int y_span = y2 - y1;
/* Alpha. */
const float a = col[3];
const float a = scene_linear_color[3];
/* Alpha inverted. */
const float ai = 1 - a;
/* Alpha, inverted, ai/255.0 - Convert char to float at the same time. */
@@ -1102,6 +1056,15 @@ void buf_rectfill_area(uchar *rect,
const int alphaint = unit_float_to_uchar_clamp(a);
float col[3];
copy_v3_v3(col, scene_linear_color);
if (ibuf->byte_buffer.colorspace) {
IMB_colormanagement_scene_linear_to_colorspace_v3(col, ibuf->byte_buffer.colorspace);
}
else {
IMB_colormanagement_scene_linear_to_srgb_v3(col, scene_linear_color);
}
if (a == 1.0f) {
chr = unit_float_to_uchar_clamp(col[0]);
chg = unit_float_to_uchar_clamp(col[1]);
@@ -1135,32 +1098,23 @@ void buf_rectfill_area(uchar *rect,
}
if (rectf) {
float col_conv[4];
float *pixel;
if (display) {
copy_v4_v4(col_conv, col);
IMB_colormanagement_display_to_scene_linear_v3(col_conv, display);
}
else {
srgb_to_linearrgb_v4(col_conv, col);
}
for (int j = 0; j < y_span; j++) {
pixel = rectf + (4 * (((size_t(y1) + j) * size_t(width)) + size_t(x1)));
for (int i = 0; i < x_span; i++) {
BLI_assert(pixel >= rectf && pixel < rectf + (4 * (size_t(width) * size_t(height))));
if (a == 1.0f) {
pixel[0] = col_conv[0];
pixel[1] = col_conv[1];
pixel[2] = col_conv[2];
pixel[0] = scene_linear_color[0];
pixel[1] = scene_linear_color[1];
pixel[2] = scene_linear_color[2];
pixel[3] = 1.0f;
}
else {
float alphatest;
pixel[0] = (col_conv[0] * a) + (pixel[0] * ai);
pixel[1] = (col_conv[1] * a) + (pixel[1] * ai);
pixel[2] = (col_conv[2] * a) + (pixel[2] * ai);
pixel[0] = (scene_linear_color[0] * a) + (pixel[0] * ai);
pixel[1] = (scene_linear_color[1] * a) + (pixel[1] * ai);
pixel[2] = (scene_linear_color[2] * a) + (pixel[2] * ai);
pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f;
}
pixel += 4;
@@ -1169,29 +1123,6 @@ void buf_rectfill_area(uchar *rect,
}
}
void IMB_rectfill_area(ImBuf *ibuf,
const float col[4],
int x1,
int y1,
int x2,
int y2,
const ColorManagedDisplay *display)
{
if (!ibuf) {
return;
}
buf_rectfill_area(ibuf->byte_buffer.data,
ibuf->float_buffer.data,
ibuf->x,
ibuf->y,
col,
display,
x1,
y1,
x2,
y2);
}
void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
{
size_t i;

View File

@@ -81,8 +81,8 @@ const EnumPropertyItem rna_enum_property_type_items[] = {
{PROP_FREQUENCY, "FREQUENCY", 0, "Frequency", ""}
#define RNA_ENUM_PROPERTY_SUBTYPE_NUMBER_ARRAY_ITEMS \
{PROP_COLOR, "COLOR", 0, "Linear Color", "Color in the linear space"}, \
{PROP_TRANSLATION, "TRANSLATION", 0, "Translation", "Color in the gamma corrected space"}, \
{PROP_COLOR, "COLOR", 0, "Linear Color", "Color in the scene linear working color space"}, \
{PROP_TRANSLATION, "TRANSLATION", 0, "Translation", ""}, \
{PROP_DIRECTION, "DIRECTION", 0, "Direction", ""}, \
{PROP_VELOCITY, "VELOCITY", 0, "Velocity", ""}, \
{PROP_ACCELERATION, "ACCELERATION", 0, "Acceleration", ""}, \
@@ -92,7 +92,7 @@ const EnumPropertyItem rna_enum_property_type_items[] = {
{PROP_AXISANGLE, "AXISANGLE", 0, "Axis-Angle", "Angle and axis to rotate around"}, \
{PROP_XYZ, "XYZ", 0, "XYZ", ""}, \
{PROP_XYZ_LENGTH, "XYZ_LENGTH", 0, "XYZ Length", ""}, \
{PROP_COLOR_GAMMA, "COLOR_GAMMA", 0, "Gamma-Corrected Color", ""}, \
{PROP_COLOR_GAMMA, "COLOR_GAMMA", 0, "sRGB Color", "Color in sRGB color space (mainly for user interface colors)"}, \
{PROP_COORDS, "COORDINATES", 0, "Coordinates", ""}, \
/* Boolean. */ \
{PROP_LAYER, "LAYER", 0, "Layer", ""}, \

View File

@@ -34,7 +34,6 @@
struct BPyBLFImBufContext {
PyObject_HEAD /* Required Python macro. */
PyObject *py_imbuf;
const ColorManagedDisplay *display;
int fontid;
BLFBufferState *buffer_state;
@@ -532,7 +531,7 @@ static PyObject *py_blf_bind_imbuf_enter(BPyBLFImBufContext *self)
ibuf->byte_buffer.data,
ibuf->x,
ibuf->y,
self->display);
ibuf->byte_buffer.colorspace);
self->buffer_state = buffer_state;
Py_RETURN_NONE;
@@ -654,7 +653,7 @@ static PyTypeObject BPyBLFImBufContext_Type = {
PyDoc_STRVAR(
/* Wrap. */
py_blf_bind_imbuf_doc,
".. method:: bind_imbuf(fontid, image, display_name=None)\n"
".. method:: bind_imbuf(fontid, image)\n"
"\n"
" Context manager to draw text into an image buffer instead of the GPU's context.\n"
"\n"
@@ -663,8 +662,6 @@ PyDoc_STRVAR(
" :type fontid: int\n"
" :arg imbuf: The image to draw into.\n"
" :type imbuf: :class:`imbuf.types.ImBuf`\n"
" :arg display_name: The color management display name to use or None.\n"
" :type display_name: str | None\n"
" :return: The BLF ImBuf context manager.\n"
" :rtype: BLFImBufContext\n");
@@ -697,32 +694,12 @@ static PyObject *py_blf_bind_imbuf(PyObject * /*self*/, PyObject *args, PyObject
return nullptr;
}
const ColorManagedDisplay *display = nullptr;
if (display_name) {
display = IMB_colormanagement_display_get_named(display_name);
if (UNLIKELY(display == nullptr)) {
std::string display_names_all;
display_names_all.reserve(1024);
const char *ex = nullptr;
/* 1 based index. */
for (int i = 1; (ex = IMB_colormanagement_display_get_indexed_name(i)); i++) {
if (i > 1) {
display_names_all += ", ";
}
display_names_all += ex;
}
PyErr_Format(PyExc_ValueError,
"bind_imbuf: color management \"%s\" not found in [%s]",
display_name,
display_names_all.c_str());
return nullptr;
}
}
/* Display name is ignored, it is only kept for backwards compatibility. This should
* always have been the image buffer byte colorspace rather than a display. */
BPyBLFImBufContext *ret = PyObject_GC_New(BPyBLFImBufContext, &BPyBLFImBufContext_Type);
ret->py_imbuf = Py_NewRef(py_imbuf);
ret->display = display;
ret->fontid = fontid;
ret->buffer_state = nullptr;

View File

@@ -1425,10 +1425,7 @@ static void renderresult_stampinfo(Render *re)
BKE_image_stamp_buf(re->scene,
ob_camera_eval,
(re->scene->r.stamp & R_STAMP_STRIPMETA) ? rres.stamp_data : nullptr,
rres.ibuf->byte_buffer.data,
rres.ibuf->float_buffer.data,
rres.rectx,
rres.recty);
rres.ibuf);
}
RE_ReleaseResultImage(re);

View File

@@ -575,7 +575,6 @@ static void text_draw(const char *text_ptr, const TextVarsRuntime *runtime, floa
static rcti draw_text_outline(const RenderData *context,
const TextVars *data,
const TextVarsRuntime *runtime,
const ColorManagedDisplay *display,
ImBuf *out)
{
/* Outline width of 1.0 maps to half of text line height. */
@@ -591,7 +590,12 @@ static rcti draw_text_outline(const RenderData *context,
/* Draw white text into temporary buffer. */
const size_t pixel_count = size_t(size.x) * size.y;
Array<uchar4> tmp_buf(pixel_count, uchar4(0));
BLF_buffer(runtime->font, nullptr, (uchar *)tmp_buf.data(), size.x, size.y, display);
BLF_buffer(runtime->font,
nullptr,
(uchar *)tmp_buf.data(),
size.x,
size.y,
out->byte_buffer.colorspace);
text_draw(data->text_ptr, runtime, float4(1.0f));
@@ -691,7 +695,8 @@ static rcti draw_text_outline(const RenderData *context,
}
}
});
BLF_buffer(runtime->font, nullptr, out->byte_buffer.data, size.x, size.y, display);
BLF_buffer(
runtime->font, nullptr, out->byte_buffer.data, size.x, size.y, out->byte_buffer.colorspace);
return outline_rect;
}
@@ -1027,8 +1032,6 @@ static ImBuf *do_text_effect(const RenderData *context,
ImBuf *out = prepare_effect_imbufs(context, nullptr, nullptr, false);
TextVars *data = static_cast<TextVars *>(strip->effectdata);
const char *display_device = context->scene->display_settings.display_device;
const ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
const FontFlags font_flags = ((data->flag & SEQ_TEXT_BOLD) ? BLF_BOLD : BLF_NONE) |
((data->flag & SEQ_TEXT_ITALIC) ? BLF_ITALIC : BLF_NONE);
@@ -1044,8 +1047,8 @@ static ImBuf *do_text_effect(const RenderData *context,
TextVarsRuntime *runtime = text_effect_calc_runtime(strip, font, {out->x, out->y});
data->runtime = runtime;
rcti outline_rect = draw_text_outline(context, data, runtime, display, out);
BLF_buffer(font, nullptr, out->byte_buffer.data, out->x, out->y, display);
rcti outline_rect = draw_text_outline(context, data, runtime, out);
BLF_buffer(font, nullptr, out->byte_buffer.data, out->x, out->y, out->byte_buffer.colorspace);
text_draw(data->text_ptr, runtime, data->color);
BLF_buffer(font, nullptr, nullptr, 0, 0, nullptr);
BLF_disable(font, font_flags);