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:
@@ -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,
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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_) {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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", ""}, \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user