Fix T58549, T56741: HSV color picker issues with Filmic view transform.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 13 Dec 2018 14:59:58 +0000 (15:59 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 13 Dec 2018 18:25:45 +0000 (19:25 +0100)
In 2d655d3 the color picker was changed to use display space HSV values.
This works ok for a simple sRGB EOTF, but fails with view transforms like
Filmic where display space V 1.0 maps to RGB 16.292.

Instead we now use the color_picking role from the OCIO config when
converting from RGB to HSV in the color picker. This role is set to sRGB
in the default OCIO config.

This color space fits the following requirements:

* It is approximately perceptually linear, so that the HSV numbers and
  the HSV cube/circle have an intuitive distribution.
* It has the same gamut as the scene linear color space.
* Color picking values 0..1 map to scene linear values in the 0..1 range,
  so that picked albedo values are energy conserving.

release/datafiles/colormanagement/config.ocio
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_draw.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_intern.h
source/blender/editors/interface/interface_region_color_picker.c
source/blender/editors/interface/interface_widgets.c
source/blender/imbuf/IMB_colormanagement.h
source/blender/imbuf/intern/colormanagement.c

index bba5958769d96a3444977aee415bc26b59f2a79d..411af8ebdf26583a217ad3cb9f99c5305828713a 100644 (file)
@@ -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
index 39dcdda5ee8e8d8e4c57c3800a6438785fe8a107..2a4dfc210b0ffbc98422efa952798812f521d46a 100644 (file)
@@ -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) {
index ef9a69cd1dda208db15af1c4ace7a78a07dd2d57..f1ada343faa313ec2b3fedbdaeb146da43d36702 100644 (file)
@@ -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);
index 3a3259e8d1f031f513042397b51b58ff27ac1bff..3949c1e2d5006ba155c7c7a48d848231cdea5ebc 100644 (file)
@@ -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 */
index 7e8653bfc5691f77ea4e3c3f997a6a22ad100f19..0ab92a633ad9aff625a7b37556c4462dba3f224e 100644 (file)
@@ -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);
 
index a99bcb2b73c1abb7c3647c60532dd150cc85650a..7c2afaf1a928c76553977dfdd7de378db903b1de 100644 (file)
@@ -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);
index f9a96803661ce8f7abe1eda0e0137def5d7f0dc6..fd34ac8f140f0c377f1c21acea91a8d3fd314295 100644 (file)
@@ -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);
index 8c903af2420cb57e438f78754d0d858c963855de..29e54158f4b90298d46a1508972d08a0862619ac 100644 (file)
@@ -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);
 
index 5d0e59e17881a718d6ae80d82416bd171164b5a3..f2244b6ab5cf8270d808b835dbe5d8120d447511 100644 (file)
@@ -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