diff options
-rw-r--r-- | release/datafiles/colormanagement/config.ocio | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 21 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_draw.c | 5 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 46 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 9 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_region_color_picker.c | 134 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 88 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_colormanagement.h | 3 | ||||
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 66 |
9 files changed, 199 insertions, 175 deletions
diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index bba5958769d..411af8ebdf2 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -34,7 +34,7 @@ roles: default_sequencer: sRGB # Color spaces for color picking and texture painting (not internally supported yet) - color_picking: Raw + color_picking: sRGB texture_paint: Raw # Non-color data diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 39dcdda5ee8..2a4dfc210b0 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2992,19 +2992,20 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh block->evil_C = (void *)C; /* XXX */ if (scn) { - block->color_profile = true; - /* store display device name, don't lookup for transformations yet * block could be used for non-color displays where looking up for transformation * would slow down redraw, so only lookup for actual transform when it's indeed * needed */ - BLI_strncpy(block->display_device, scn->display_settings.display_device, sizeof(block->display_device)); + STRNCPY(block->display_device, scn->display_settings.display_device); /* copy to avoid crash when scene gets deleted with ui still open */ block->unit = MEM_mallocN(sizeof(scn->unit), "UI UnitSettings"); memcpy(block->unit, &scn->unit, sizeof(scn->unit)); } + else { + STRNCPY(block->display_device, IMB_colormanagement_display_get_default_name()); + } BLI_strncpy(block->name, name, sizeof(block->name)); @@ -3295,20 +3296,6 @@ void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3]) IMB_colormanagement_display_to_scene_linear_v3(pixel, display); } -void ui_block_cm_to_display_space_range(uiBlock *block, float *min, float *max) -{ - struct ColorManagedDisplay *display = ui_block_cm_display_get(block); - float pixel[3]; - - copy_v3_fl(pixel, *min); - IMB_colormanagement_scene_linear_to_display_v3(pixel, display); - *min = min_fff(UNPACK3(pixel)); - - copy_v3_fl(pixel, *max); - IMB_colormanagement_scene_linear_to_display_v3(pixel, display); - *max = max_fff(UNPACK3(pixel)); -} - static uiBut *ui_but_alloc(const eButType type) { switch (type) { diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index ef9a69cd1dd..f1ada343faa 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -1404,15 +1404,12 @@ static void ui_draw_colorband_handle( void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect) { - struct ColorManagedDisplay *display = NULL; + struct ColorManagedDisplay *display = ui_block_cm_display_get(but->block); uint pos_id, col_id; ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin); if (coba == NULL) return; - if (but->block->color_profile) - display = ui_block_cm_display_get(but->block); - float x1 = rect->xmin; float sizex = rect->xmax - x1; float sizey = BLI_rcti_size_y(rect); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 3a3259e8d1f..3949c1e2d50 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -5440,7 +5440,6 @@ static bool ui_numedit_but_HSVCUBE( float x, y; float mx_fl, my_fl; bool changed = true; - bool use_display_colorspace = ui_but_is_colorpicker_display_space(but); ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift); @@ -5454,9 +5453,7 @@ static bool ui_numedit_but_HSVCUBE( #endif ui_but_v3_get(but, rgb); - - if (use_display_colorspace) - ui_block_cm_to_display_space_v3(but->block, rgb); + ui_scene_linear_to_color_picker_space(but, rgb); ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv); @@ -5469,8 +5466,7 @@ static bool ui_numedit_but_HSVCUBE( /* calculate original hsv again */ copy_v3_v3(rgb, data->origvec); - if (use_display_colorspace) - ui_block_cm_to_display_space_v3(but->block, rgb); + ui_scene_linear_to_color_picker_space(but, rgb); copy_v3_v3(hsvo, hsv); @@ -5518,9 +5514,6 @@ static bool ui_numedit_but_HSVCUBE( { /* vertical 'value' strip */ float min = but->softmin, max = but->softmax; - if (use_display_colorspace) { - ui_block_cm_to_display_space_range(but->block, &min, &max); - } /* exception only for value strip - use the range set in but->min/max */ hsv[2] = y * (max - min) + min; break; @@ -5537,9 +5530,7 @@ static bool ui_numedit_but_HSVCUBE( } ui_color_picker_to_rgb_HSVCUBE_v(but, hsv, rgb); - - if (use_display_colorspace) - ui_block_cm_to_scene_linear_v3(but->block, rgb); + ui_color_picker_to_scene_linear_space(but, rgb); /* clamp because with color conversion we can exceed range [#34295] */ if (but->a1 == UI_GRAD_V_ALT) { @@ -5565,13 +5556,9 @@ static void ui_ndofedit_but_HSVCUBE( const float hsv_v_max = max_ff(hsv[2], but->softmax); float rgb[3]; float sensitivity = (shift ? 0.15f : 0.3f) * ndof->dt; - bool use_display_colorspace = ui_but_is_colorpicker_display_space(but); ui_but_v3_get(but, rgb); - - if (use_display_colorspace) - ui_block_cm_to_display_space_v3(but->block, rgb); - + ui_scene_linear_to_color_picker_space(but, rgb); ui_rgb_to_color_picker_HSVCUBE_compat_v(but, rgb, hsv); switch ((int)but->a1) { @@ -5620,9 +5607,7 @@ static void ui_ndofedit_but_HSVCUBE( hsv_clamp_v(hsv, hsv_v_max); ui_color_picker_to_rgb_HSVCUBE_v(but, hsv, rgb); - - if (use_display_colorspace) - ui_block_cm_to_scene_linear_v3(but->block, rgb); + ui_color_picker_to_scene_linear_space(but, rgb); copy_v3_v3(data->vec, rgb); ui_but_v3_set(but, data->vec); @@ -5737,7 +5722,6 @@ static bool ui_numedit_but_HSVCIRCLE( float rgb[3]; ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; - bool use_display_colorspace = ui_but_is_colorpicker_display_space(but); ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift); @@ -5760,9 +5744,7 @@ static bool ui_numedit_but_HSVCIRCLE( BLI_rcti_rctf_copy(&rect, &but->rect); ui_but_v3_get(but, rgb); - if (use_display_colorspace) - ui_block_cm_to_display_space_v3(but->block, rgb); - + ui_scene_linear_to_color_picker_space(but, rgb); ui_rgb_to_color_picker_compat_v(rgb, hsv); /* exception, when using color wheel in 'locked' value state: @@ -5784,9 +5766,7 @@ static bool ui_numedit_but_HSVCIRCLE( /* calculate original hsv again */ copy_v3_v3(hsvo, hsv); copy_v3_v3(rgbo, data->origvec); - if (use_display_colorspace) - ui_block_cm_to_display_space_v3(but->block, rgbo); - + ui_scene_linear_to_color_picker_space(but, rgbo); ui_rgb_to_color_picker_compat_v(rgbo, hsvo); /* and original position */ @@ -5812,9 +5792,7 @@ static bool ui_numedit_but_HSVCIRCLE( normalize_v3_length(rgb, but->a2); } - if (use_display_colorspace) - ui_block_cm_to_scene_linear_v3(but->block, rgb); - + ui_color_picker_to_scene_linear_space(but, rgb); ui_but_v3_set(but, rgb); data->draglastx = mx; @@ -5831,14 +5809,12 @@ static void ui_ndofedit_but_HSVCIRCLE( { ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; - bool use_display_colorspace = ui_but_is_colorpicker_display_space(but); float rgb[3]; float phi, r /*, sqr */ /* UNUSED */, v[2]; float sensitivity = (shift ? 0.06f : 0.3f) * ndof->dt; ui_but_v3_get(but, rgb); - if (use_display_colorspace) - ui_block_cm_to_display_space_v3(but->block, rgb); + ui_scene_linear_to_color_picker_space(but, rgb); ui_rgb_to_color_picker_compat_v(rgb, hsv); /* Convert current color on hue/sat disc to circular coordinates phi, r */ @@ -5889,9 +5865,7 @@ static void ui_ndofedit_but_HSVCIRCLE( normalize_v3_length(data->vec, but->a2); } - if (use_display_colorspace) - ui_block_cm_to_scene_linear_v3(but->block, data->vec); - + ui_color_picker_to_scene_linear_space(but, data->vec); ui_but_v3_set(but, data->vec); } #endif /* WITH_INPUT_NDOF */ diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 7e8653bfc56..0ab92a633ad 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -439,7 +439,7 @@ struct uiBlock { struct UnitSettings *unit; /* unit system, used a lot for numeric buttons so include here rather then fetching through the scene every time. */ ColorPickerData color_pickers; /* XXX, only accessed by color picker templates */ - bool color_profile; /* color profile for correcting linear colors for display */ + bool is_color_gamma_picker; /* Block for color picker with gamma baked in. */ char display_device[64]; /* display device name used to display this block, * used by color widgets to transform colors from/to scene linear @@ -477,7 +477,6 @@ extern void ui_hsvcircle_vals_from_pos( const float mx, const float my); extern void ui_hsvcircle_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xpos, float *ypos); extern void ui_hsvcube_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xp, float *yp); -bool ui_but_is_colorpicker_display_space(struct uiBut *but); extern void ui_but_string_get_ex( uiBut *but, char *str, const size_t maxlen, @@ -516,7 +515,6 @@ extern void ui_block_bounds_calc(uiBlock *block); extern struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block); void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]); void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3]); -void ui_block_cm_to_display_space_range(uiBlock *block, float *min, float *max); /* interface_regions.c */ @@ -611,6 +609,11 @@ void ui_rgb_to_color_picker_v(const float rgb[3], float r_cp[3]); void ui_color_picker_to_rgb_v(const float r_cp[3], float rgb[3]); void ui_color_picker_to_rgb(float r_cp0, float r_cp1, float r_cp2, float *r, float *g, float *b); +bool ui_but_is_color_gamma(uiBut *but); + +void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3]); +void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3]); + uiBlock *ui_block_func_COLOR(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but); ColorPicker *ui_block_colorpicker_create(struct uiBlock *block); diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c index a99bcb2b73c..7c2afaf1a92 100644 --- a/source/blender/editors/interface/interface_region_color_picker.c +++ b/source/blender/editors/interface/interface_region_color_picker.c @@ -111,6 +111,36 @@ void ui_color_picker_to_rgb(float r_cp0, float r_cp1, float r_cp2, float *r, flo } } +/* Returns true if the button is for a color with gamma baked in, + * or if it's a color picker for such a button. */ +bool ui_but_is_color_gamma(uiBut *but) +{ + if (but->rnaprop) { + if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { + return true; + } + } + + return but->block->is_color_gamma_picker; +} + +void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3]) +{ + /* Map to color picking space for HSV values and HSV cube/circle, + * assuming it is more perceptually linear then the scene linear + * space for intuitive color picking. */ + if (!ui_but_is_color_gamma(but)) { + IMB_colormanagement_scene_linear_to_color_picking_v3(rgb); + } +} + +void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3]) +{ + if (!ui_but_is_color_gamma(but)) { + IMB_colormanagement_color_picking_to_scene_linear_v3(rgb); + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -132,28 +162,18 @@ void ui_but_hsv_set(uiBut *but) /* Updates all buttons who share the same color picker as the one passed * also used by small picker, be careful with name checks below... */ static void ui_update_color_picker_buts_rgb( - uiBlock *block, ColorPicker *cpicker, const float rgb[3], bool is_display_space) + uiBut *from_but, uiBlock *block, ColorPicker *cpicker, const float rgb[3]) { uiBut *bt; float *hsv = cpicker->color_data; - struct ColorManagedDisplay *display = NULL; - /* this is to keep the H and S value when V is equal to zero - * and we are working in HSV mode, of course! - */ - if (is_display_space) { - ui_rgb_to_color_picker_compat_v(rgb, hsv); - } - else { - /* we need to convert to display space to use hsv, because hsv is stored in display space */ - float rgb_display[3]; - copy_v3_v3(rgb_display, rgb); - ui_block_cm_to_display_space_v3(block, rgb_display); - ui_rgb_to_color_picker_compat_v(rgb_display, hsv); + /* Convert from RGB to HSV in perceptually linear space. */ + float tmp[3]; + copy_v3_v3(tmp, rgb); + if (from_but) { + ui_scene_linear_to_color_picker_space(from_but, tmp); } - - if (block->color_profile) - display = ui_block_cm_display_get(block); + ui_rgb_to_color_picker_compat_v(tmp, hsv); /* this updates button strings, is hackish... but button pointers are on stack of caller function */ for (bt = block->buttons.first; bt; bt = bt->next) { @@ -177,9 +197,9 @@ static void ui_update_color_picker_buts_rgb( copy_v3_v3(rgb_gamma, rgb); - if (display) { + if (!block->is_color_gamma_picker) { /* make a display version, for Hex code */ - IMB_colormanagement_scene_linear_to_display_v3(rgb_gamma, display); + ui_block_cm_to_display_space_v3(block, rgb_gamma); } if (rgb_gamma[0] > 1.0f) rgb_gamma[0] = modf(rgb_gamma[0], &intpart); @@ -230,7 +250,7 @@ static void ui_colorpicker_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(a if (prop) { RNA_property_float_get_array(&ptr, prop, rgb); ui_update_color_picker_buts_rgb( - but->block, but->custom_data, rgb, (RNA_property_subtype(prop) == PROP_COLOR_GAMMA)); + but, but->block, but->custom_data, rgb); } if (popup) @@ -244,16 +264,13 @@ static void ui_color_wheel_rna_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(a float rgb[3]; ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; - bool use_display_colorspace = ui_but_is_colorpicker_display_space(but); ui_color_picker_to_rgb_v(hsv, rgb); - /* hsv is saved in display space so convert back */ - if (use_display_colorspace) { - ui_block_cm_to_scene_linear_v3(but->block, rgb); - } + /* hsv is saved in perceptually linear space so convert back */ + ui_color_picker_to_scene_linear_space(but, rgb); - ui_update_color_picker_buts_rgb(but->block, cpicker, rgb, !use_display_colorspace); + ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb); if (popup) popup->menuretval = UI_RETURN_UPDATE; @@ -270,12 +287,12 @@ static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexc hex_to_rgb(hexcol, rgb, rgb + 1, rgb + 2); /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */ - if (but->block->color_profile) { + if (!but->block->is_color_gamma_picker) { /* so we need to linearise it for Blender */ ui_block_cm_to_scene_linear_v3(but->block, rgb); } - ui_update_color_picker_buts_rgb(but->block, cpicker, rgb, false); + ui_update_color_picker_buts_rgb(NULL, but->block, cpicker, rgb); if (popup) popup->menuretval = UI_RETURN_UPDATE; @@ -378,37 +395,22 @@ static void ui_colorpicker_square(uiBlock *block, PointerRNA *ptr, PropertyRNA * /* a HS circle, V slider, rgb/hsv/hex sliders */ static void ui_block_colorpicker( - uiBlock *block, float rgba[4], PointerRNA *ptr, PropertyRNA *prop, bool show_picker) + uiBlock *block, uiBut *from_but, float rgba[4], bool show_picker) { static short colormode = 0; /* temp? 0=rgb, 1=hsv, 2=hex */ uiBut *bt; int width, butwidth; - static char tip[50]; static char hexcol[128]; - float rgb_gamma[3]; - unsigned char rgb_gamma_uchar[3]; float softmin, softmax, hardmin, hardmax, step, precision; int yco; ColorPicker *cpicker = ui_block_colorpicker_create(block); float *hsv = cpicker->color_data; + PointerRNA *ptr = &from_but->rnapoin; + PropertyRNA *prop = from_but->rnaprop; width = PICKER_TOTAL_W; butwidth = width - 1.5f * UI_UNIT_X; - /* existence of profile means storage is in linear color space, with display correction */ - /* XXX That tip message is not use anywhere! */ - if (!block->color_profile) { - BLI_strncpy(tip, N_("Value in Display Color Space"), sizeof(tip)); - copy_v3_v3(rgb_gamma, rgba); - } - else { - BLI_strncpy(tip, N_("Value in Linear RGB Color Space"), sizeof(tip)); - - /* make a display version, for Hex code */ - copy_v3_v3(rgb_gamma, rgba); - ui_block_cm_to_display_space_v3(block, rgb_gamma); - } - /* sneaky way to check for alpha */ rgba[3] = FLT_MAX; @@ -416,6 +418,11 @@ static void ui_block_colorpicker( RNA_property_float_range(ptr, prop, &hardmin, &hardmax); RNA_property_float_get_array(ptr, prop, rgba); + float rgb_perceptual[3]; + copy_v3_v3(rgb_perceptual, rgba); + ui_scene_linear_to_color_picker_space(from_but, rgb_perceptual); + ui_rgb_to_color_picker_v(rgb_perceptual, hsv); + /* when the softmax isn't defined in the RNA, * using very large numbers causes sRGB/linear round trip to fail. */ if (softmax == FLT_MAX) { @@ -539,6 +546,19 @@ static void ui_block_colorpicker( rgba[3] = 1.0f; } + /* Hex color is in display space. This should actually be sRGB without any view + * transform, as most other applications would expect this. */ + float rgb_gamma[3]; + unsigned char rgb_gamma_uchar[3]; + + if (block->is_color_gamma_picker) { + copy_v3_v3(rgb_gamma, rgba); + } + else { + copy_v3_v3(rgb_gamma, rgba); + ui_block_cm_to_display_space_v3(block, rgb_gamma); + } + rgb_float_to_uchar(rgb_gamma_uchar, rgb_gamma); BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((uint), rgb_gamma_uchar, )); @@ -552,8 +572,6 @@ static void ui_block_colorpicker( block, UI_BTYPE_LABEL, 0, IFACE_("(Gamma Corrected)"), 0, yco - UI_UNIT_Y, butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); - ui_rgb_to_color_picker_v(rgb_gamma, hsv); - ui_colorpicker_hide_reveal(block, colormode); } @@ -576,24 +594,18 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *blo float rgb[3]; ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; - bool use_display_colorspace = ui_but_is_colorpicker_display_space(but); ui_but_v3_get(but, rgb); - - if (use_display_colorspace) - ui_block_cm_to_display_space_v3(block, rgb); - + ui_scene_linear_to_color_picker_space(but, rgb); ui_rgb_to_color_picker_compat_v(rgb, hsv); hsv[2] = clamp_f(hsv[2] + add, 0.0f, 1.0f); - ui_color_picker_to_rgb_v(hsv, rgb); - - if (use_display_colorspace) - ui_block_cm_to_scene_linear_v3(block, rgb); + ui_color_picker_to_rgb_v(hsv, rgb); + ui_color_picker_to_scene_linear_space(but, rgb); ui_but_v3_set(but, rgb); - ui_update_color_picker_buts_rgb(block, cpicker, rgb, !use_display_colorspace); + ui_update_color_picker_buts_rgb(but, block, cpicker, rgb); if (popup) popup->menuretval = UI_RETURN_UPDATE; @@ -612,8 +624,8 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ block = UI_block_begin(C, handle->region, __func__, UI_EMBOSS); - if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { - block->color_profile = false; + if (ui_but_is_color_gamma(but)) { + block->is_color_gamma_picker = true; } if (but->block) { @@ -626,7 +638,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ copy_v3_v3(handle->retvec, but->editvec); - ui_block_colorpicker(block, handle->retvec, &but->rnapoin, but->rnaprop, show_picker); + ui_block_colorpicker(block, but, handle->retvec, show_picker); block->flag = UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT; UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index f9a96803661..fd34ac8f140 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2581,23 +2581,16 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f; ColorPicker *cpicker = but->custom_data; - const float *hsv_ptr = cpicker->color_data; - float rgb[3], hsvo[3], hsv[3], col[3], colcent[3]; - bool color_profile = ui_but_is_colorpicker_display_space(but); + float rgb[3], hsv[3], rgb_center[3]; + bool is_color_gamma = ui_but_is_color_gamma(but); - /* color */ - ui_but_v3_get(but, rgb); - - /* since we use compat functions on both 'hsv' and 'hsvo', they need to be initialized */ - hsvo[0] = hsv[0] = hsv_ptr[0]; - hsvo[1] = hsv[1] = hsv_ptr[1]; - hsvo[2] = hsv[2] = hsv_ptr[2]; - - if (color_profile) - ui_block_cm_to_display_space_v3(but->block, rgb); + /* Initialize for compatibility. */ + copy_v3_v3(hsv, cpicker->color_data); + /* Compute current hue. */ + ui_but_v3_get(but, rgb); + ui_scene_linear_to_color_picker_space(but, rgb); ui_rgb_to_color_picker_compat_v(rgb, hsv); - copy_v3_v3(hsvo, hsv); CLAMP(hsv[2], 0.0f, 1.0f); /* for display only */ @@ -2611,7 +2604,13 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * hsv[2] = 0.5f; } - ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2); + const float hsv_center[3] = {0.0f, 0.0f, hsv[2]}; + ui_color_picker_to_rgb_v(hsv_center, rgb_center); + ui_scene_linear_to_color_picker_space(but, rgb_center); + + if (!is_color_gamma) { + ui_block_cm_to_display_space_v3(but->block, rgb_center); + } GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -2620,19 +2619,27 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); immBegin(GPU_PRIM_TRI_FAN, tot + 2); - immAttr3fv(color, colcent); + immAttr3fv(color, rgb_center); immVertex2f(pos, centx, centy); float ang = 0.0f; for (int a = 0; a <= tot; a++, ang += radstep) { float si = sinf(ang); float co = cosf(ang); + float hsv_ang[3]; + float rgb_ang[3]; - ui_hsvcircle_vals_from_pos(hsv, hsv + 1, rect, centx + co * radius, centy + si * radius); + ui_hsvcircle_vals_from_pos(hsv_ang, hsv_ang + 1, rect, centx + co * radius, centy + si * radius); + hsv_ang[2] = hsv[2]; - ui_color_picker_to_rgb_v(hsv, col); + ui_color_picker_to_rgb_v(hsv_ang, rgb_ang); + ui_color_picker_to_scene_linear_space(but, rgb_ang); - immAttr3fv(color, col); + if (!is_color_gamma) { + ui_block_cm_to_display_space_v3(but->block, rgb_ang); + } + + immAttr3fv(color, rgb_ang); immVertex2f(pos, centx + co * radius, centy + si * radius); } immEnd(); @@ -2656,8 +2663,13 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * GPU_line_smooth(false); /* cursor */ + copy_v3_v3(hsv, cpicker->color_data); + ui_but_v3_get(but, rgb); + ui_scene_linear_to_color_picker_space(but, rgb); + ui_rgb_to_color_picker_compat_v(rgb, hsv); + float xpos, ypos; - ui_hsvcircle_pos_from_vals(but, rect, hsvo, &xpos, &ypos); + ui_hsvcircle_pos_from_vals(but, rect, hsv, &xpos, &ypos); ui_hsv_cursor(xpos, ypos); } @@ -2812,18 +2824,6 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons immUnbindProgram(); } -bool ui_but_is_colorpicker_display_space(uiBut *but) -{ - bool color_profile = but->block->color_profile; - - if (but->rnaprop) { - if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = false; - } - - return color_profile; -} - void ui_hsvcube_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float *xp, float *yp) { float x = 0.0f, y = 0.0f; @@ -2865,15 +2865,12 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect) ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; float hsv_n[3]; - bool use_display_colorspace = ui_but_is_colorpicker_display_space(but); + /* Initialize for compatibility. */ copy_v3_v3(hsv_n, hsv); ui_but_v3_get(but, rgb); - - if (use_display_colorspace) - ui_block_cm_to_display_space_v3(but->block, rgb); - + ui_scene_linear_to_color_picker_space(but, rgb); rgb_to_hsv_compat_v(rgb, hsv_n); ui_draw_gradient(rect, hsv_n, but->a1, 1.0f); @@ -2901,15 +2898,9 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect) const float rad = wcol->roundness * BLI_rcti_size_x(rect); float x, y; float rgb[3], hsv[3], v; - bool color_profile = but->block->color_profile; - - if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = false; ui_but_v3_get(but, rgb); - - if (color_profile) - ui_block_cm_to_display_space_v3(but->block, rgb); + ui_scene_linear_to_color_picker_space(but, rgb); if (but->a1 == UI_GRAD_L_ALT) rgb_to_hsl_v(rgb, hsv); @@ -2920,9 +2911,6 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect) /* map v from property range to [0,1] */ if (but->a1 == UI_GRAD_V_ALT) { float min = but->softmin, max = but->softmax; - if (color_profile) { - ui_block_cm_to_display_space_range(but->block, &min, &max); - } v = (v - min) / (max - min); } @@ -3378,16 +3366,12 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat { uiWidgetBase wtb; float rad, col[4]; - bool color_profile = but->block->color_profile; col[3] = 1.0f; if (but->rnaprop) { BLI_assert(but->rnaindex == -1); - if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = false; - if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) { col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3); } @@ -3415,7 +3399,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat round_box_edges(&wtb, roundboxalign, rect, rad); } - if (color_profile) + if (!ui_but_is_color_gamma(but)) ui_block_cm_to_display_space_v3(but->block, col); rgba_float_to_uchar((unsigned char *)wcol->inner, col); diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 8c903af2420..29e54158f4b 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -96,6 +96,9 @@ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], struct Co void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, bool predivide); +void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]); +void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]); + void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], struct ColorManagedDisplay *display); void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], struct ColorManagedDisplay *display); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 5d0e59e1788..f2244b6ab5c 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -130,7 +130,14 @@ static struct global_glsl_state { /* Container for GLSL state needed for OCIO module. */ struct OCIO_GLSLDrawState *ocio_glsl_state; struct OCIO_GLSLDrawState *transform_ocio_glsl_state; -} global_glsl_state; +} global_glsl_state = {NULL}; + +static struct global_color_picking_state { + /* Cached processor for color picking conversion. */ + OCIO_ConstProcessorRcPtr *processor_to; + OCIO_ConstProcessorRcPtr *processor_from; + bool failed; +} global_color_picking_state = {NULL}; /*********************** Color managed cache *************************/ @@ -699,6 +706,15 @@ void colormanagement_exit(void) if (global_glsl_state.transform_ocio_glsl_state) OCIO_freeOGLState(global_glsl_state.transform_ocio_glsl_state); + if (global_color_picking_state.processor_to) + OCIO_processorRelease(global_color_picking_state.processor_to); + + if (global_color_picking_state.processor_from) + OCIO_processorRelease(global_color_picking_state.processor_from); + + memset(&global_glsl_state, 0, sizeof(global_glsl_state)); + memset(&global_color_picking_state, 0, sizeof(global_color_picking_state)); + colormanage_free_config(); } @@ -1911,6 +1927,54 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in } } +void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]) +{ + if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) { + /* Create processor if none exists. */ + BLI_mutex_lock(&processor_lock); + + if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) { + global_color_picking_state.processor_to = + create_colorspace_transform_processor(global_role_scene_linear, + global_role_color_picking); + + if (!global_color_picking_state.processor_to) { + global_color_picking_state.failed = true; + } + } + + BLI_mutex_unlock(&processor_lock); + } + + if (global_color_picking_state.processor_to) { + OCIO_processorApplyRGB(global_color_picking_state.processor_to, pixel); + } +} + +void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]) +{ + if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) { + /* Create processor if none exists. */ + BLI_mutex_lock(&processor_lock); + + if (!global_color_picking_state.processor_from && !global_color_picking_state.failed) { + global_color_picking_state.processor_from = + create_colorspace_transform_processor(global_role_color_picking, + global_role_scene_linear); + + if (!global_color_picking_state.processor_from) { + global_color_picking_state.failed = true; + } + } + + BLI_mutex_unlock(&processor_lock); + } + + if (global_color_picking_state.processor_from) { + OCIO_processorApplyRGB(global_color_picking_state.processor_from, pixel); + } +} + /* convert pixel from scene linear to display space using default view * used by performance-critical areas such as color-related widgets where we want to reduce * amount of per-widget allocations |