diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-10-12 17:42:34 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-12-13 21:25:46 +0300 |
commit | f527ce5b2f5bb300a7fe55db33d1e3a4da8051c7 (patch) | |
tree | df1226d253b2a7c2e66cba75b37f9ec0a475c288 | |
parent | 6601a89650f92454aa57bc01bedebd4086f6d98d (diff) |
Color management: add OCIO aware utility functions for transform to/from XYZ.
-rw-r--r-- | intern/opencolorio/fallback_impl.cc | 7 | ||||
-rw-r--r-- | intern/opencolorio/ocio_capi.cc | 5 | ||||
-rw-r--r-- | intern/opencolorio/ocio_capi.h | 8 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl.cc | 27 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl.h | 3 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_math_color.h | 5 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_color.c | 81 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_colormanagement.h | 5 | ||||
-rw-r--r-- | source/blender/imbuf/intern/IMB_colormanagement_intern.h | 2 | ||||
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 38 | ||||
-rw-r--r-- | source/blender/imbuf/intern/colormanagement_inline.c | 10 |
11 files changed, 101 insertions, 90 deletions
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 87629422013..7bf8134b41c 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -333,6 +333,13 @@ void FallbackImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr * /*config*/, rgb[2] = 0.0722f; } +void FallbackImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr * /*config*/, + float xyz_to_rgb[3][3]) +{ + /* Default to ITU-BT.709. */ + memcpy(xyz_to_rgb, OCIO_XYZ_TO_LINEAR_SRGB, sizeof(OCIO_XYZ_TO_LINEAR_SRGB)); +} + int FallbackImpl::configGetNumLooks(OCIO_ConstConfigRcPtr * /*config*/) { return 0; diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc index 7a0b9faa5fc..25e1b31630c 100644 --- a/intern/opencolorio/ocio_capi.cc +++ b/intern/opencolorio/ocio_capi.cc @@ -137,6 +137,11 @@ void OCIO_configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb) impl->configGetDefaultLumaCoefs(config, rgb); } +void OCIO_configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config, float xyz_to_rgb[3][3]) +{ + impl->configGetXYZtoRGB(config, xyz_to_rgb); +} + int OCIO_configGetNumLooks(OCIO_ConstConfigRcPtr *config) { return impl->configGetNumLooks(config); diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 52a86727902..5bed24d64b1 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -54,6 +54,13 @@ OCIO_DECLARE_HANDLE(OCIO_ExponentTransformRcPtr); OCIO_DECLARE_HANDLE(OCIO_MatrixTransformRcPtr); OCIO_DECLARE_HANDLE(OCIO_ConstLookRcPtr); +/* Standard XYZ to linear sRGB transform, for fallback. */ +static const float OCIO_XYZ_TO_LINEAR_SRGB[3][3] = { + {3.2404542f, -0.9692660f, 0.0556434f}, + {-1.5371385f, 1.8760108f, -0.2040259f}, + {-0.4985314f, 0.0415560f, 1.0572252f}}; + + /* This structure is used to pass curve mapping settings from * blender's DNA structure stored in view transform settings * to a generic OpenColorIO C-API. @@ -141,6 +148,7 @@ const char *OCIO_configGetView(OCIO_ConstConfigRcPtr *config, const char *displa const char *OCIO_configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view); void OCIO_configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb); +void OCIO_configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config, float xyz_to_rgb[3][3]); int OCIO_configGetNumLooks(OCIO_ConstConfigRcPtr *config); const char *OCIO_configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index); diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index 4c9115af810..ac167692647 100644 --- a/intern/opencolorio/ocio_impl.cc +++ b/intern/opencolorio/ocio_impl.cc @@ -419,6 +419,33 @@ void OCIOImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *r } } +void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rgb[3][3]) +{ + ConstConfigRcPtr config = (*(ConstConfigRcPtr *) config_); + + /* Default to ITU-BT.709 in case no appropriate transform found. */ + memcpy(xyz_to_rgb, OCIO_XYZ_TO_LINEAR_SRGB, sizeof(OCIO_XYZ_TO_LINEAR_SRGB)); + + /* Auto estimate from XYZ and scene_linear roles, assumed to be a linear transform. */ + if(config->hasRole("XYZ") && config->hasRole("scene_linear")) { + ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear"); + if(to_rgb_processor) { + xyz_to_rgb[0][0] = 1.0f; + xyz_to_rgb[0][1] = 0.0f; + xyz_to_rgb[0][2] = 0.0f; + xyz_to_rgb[1][0] = 0.0f; + xyz_to_rgb[1][1] = 1.0f; + xyz_to_rgb[1][2] = 0.0f; + xyz_to_rgb[2][0] = 0.0f; + xyz_to_rgb[2][1] = 0.0f; + xyz_to_rgb[2][2] = 1.0f; + to_rgb_processor->applyRGB(xyz_to_rgb[0]); + to_rgb_processor->applyRGB(xyz_to_rgb[1]); + to_rgb_processor->applyRGB(xyz_to_rgb[2]); + } + } +} + int OCIOImpl::configGetNumLooks(OCIO_ConstConfigRcPtr *config) { try { diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h index f086bbb1a26..4e844584bca 100644 --- a/intern/opencolorio/ocio_impl.h +++ b/intern/opencolorio/ocio_impl.h @@ -59,6 +59,7 @@ public: virtual const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view) = 0; virtual void configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb) = 0; + virtual void configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config, float xyz_to_rgb[3][3]) = 0; virtual int configGetNumLooks(OCIO_ConstConfigRcPtr *config) = 0; virtual const char *configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index) = 0; @@ -148,6 +149,7 @@ public: const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view); void configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb); + void configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config, float xyz_to_rgb[3][3]); int configGetNumLooks(OCIO_ConstConfigRcPtr *config); const char *configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index); @@ -238,6 +240,7 @@ public: const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view); void configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr *config, float *rgb); + void configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config, float xyz_to_rgb[3][3]); int configGetNumLooks(OCIO_ConstConfigRcPtr *config); const char *configGetLookNameByIndex(OCIO_ConstConfigRcPtr *config, int index); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 3653191232c..7fe890edeec 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -64,7 +64,6 @@ void hsl_to_rgb_v(const float hcl[3], float r_rgb[3]); void hex_to_rgb(char *hexcol, float *r, float *g, float *b); void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb, int colorspace); void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace); -void xyz_to_rgb(float x, float y, float z, float *r, float *g, float *b, int colorspace); void cpack_to_rgb(unsigned int col, float *r, float *g, float *b); /***************** Conversion from RGB ********************/ @@ -79,8 +78,6 @@ void rgb_to_hsl_compat(float r, float g, float b, float *lh, float *ls, float *l void rgb_to_hsl_compat_v(const float rgb[3], float r_hsl[3]); void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv); void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3]); -void rgb_to_lab(float r, float g, float b, float *ll, float *la, float *lb); -void rgb_to_xyz(float r, float g, float b, float *x, float *y, float *z); unsigned int rgb_to_cpack(float r, float g, float b); unsigned int hsv_to_cpack(float h, float s, float v); @@ -131,8 +128,6 @@ void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4]); void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3]); void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4]); -void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b); - MINLINE float rgb_to_grayscale(const float rgb[3]); MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]); diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 9399646bedf..09a5762e4e0 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -357,29 +357,6 @@ void hsv_clamp_v(float hsv[3], float v_max) CLAMP(hsv[2], 0.0f, v_max); } -/*http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html */ - -void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b, int colorspace) -{ - switch (colorspace) { - case BLI_XYZ_SMPTE: - *r = (3.50570f * xc) + (-1.73964f * yc) + (-0.544011f * zc); - *g = (-1.06906f * xc) + (1.97781f * yc) + (0.0351720f * zc); - *b = (0.0563117f * xc) + (-0.196994f * yc) + (1.05005f * zc); - break; - case BLI_XYZ_REC709_SRGB: - *r = (3.240476f * xc) + (-1.537150f * yc) + (-0.498535f * zc); - *g = (-0.969256f * xc) + (1.875992f * yc) + (0.041556f * zc); - *b = (0.055648f * xc) + (-0.204043f * yc) + (1.057311f * zc); - break; - case BLI_XYZ_CIE: - *r = (2.28783848734076f * xc) + (-0.833367677835217f * yc) + (-0.454470795871421f * zc); - *g = (-0.511651380743862f * xc) + (1.42275837632178f * yc) + (0.0888930017552939f * zc); - *b = (0.00572040983140966f * xc) + (-0.0159068485104036f * yc) + (1.0101864083734f * zc); - break; - } -} - /** * We define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so. * for that reason it is sensitive for endianness... with this function it works correctly. @@ -618,64 +595,6 @@ void BLI_init_srgb_conversion(void) BLI_color_to_srgb_table[i] = (unsigned short)(b * 0x100); } } -static float inverse_srgb_companding(float v) -{ - if (v > 0.04045f) { - return powf((v + 0.055f) / 1.055f, 2.4f); - } - else { - return v / 12.92f; - } -} - -/** - * \note Does sRGB to linear conversion - */ -void rgb_to_xyz(float r, float g, float b, float *x, float *y, float *z) -{ - r = inverse_srgb_companding(r) * 100.0f; - g = inverse_srgb_companding(g) * 100.0f; - b = inverse_srgb_companding(b) * 100.0f; - - *x = r * 0.412453f + g * 0.357580f + b * 0.180423f; - *y = r * 0.212671f + g * 0.715160f + b * 0.072169f; - *z = r * 0.019334f + g * 0.119193f + b * 0.950227f; -} - -static float xyz_to_lab_component(float v) -{ - const float eps = 0.008856f; - const float k = 903.3f; - - if (v > eps) { - return powf(v, 1.0f / 3.0f); - } - else { - return (k * v + 16.0f) / 116.0f; - } -} - -void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b) -{ - const float xr = x / 95.047f; - const float yr = y / 100.0f; - const float zr = z / 108.883f; - - const float fx = xyz_to_lab_component(xr); - const float fy = xyz_to_lab_component(yr); - const float fz = xyz_to_lab_component(zr); - - *l = 116.0f * fy - 16.0f; - *a = 500.0f * (fx - fy); - *b = 200.0f * (fy - fz); -} - -void rgb_to_lab(float r, float g, float b, float *ll, float *la, float *lb) -{ - float x, y, z; - rgb_to_xyz(r, g, b, &x, &y, &z); - xyz_to_lab(x, y, z, ll, la, lb); -} /* ****************************** blackbody ******************************** */ diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 29e54158f4b..437a699208b 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -71,6 +71,8 @@ const char *IMB_colormanagement_get_rect_colorspace(struct ImBuf *ibuf); BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3]); BLI_INLINE unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char[3]); +BLI_INLINE void IMB_colormangement_xyz_to_rgb(float rgb[3], const float xyz[3]); +BLI_INLINE void IMB_colormangement_rgb_to_xyz(float xyz[3], const float rgb[3]); /* ** Color space transformation functions ** */ void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, @@ -99,6 +101,9 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in 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_srgb_v3(float pixel[3]); +void IMB_colormanagement_srgb_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/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 84e0bd6c599..ee3d207a8db 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -42,6 +42,8 @@ struct OCIO_ConstProcessorRcPtr; struct ImBuf; extern float imbuf_luma_coefficients[3]; +extern float imbuf_xyz_to_rgb[3][3]; +extern float imbuf_rgb_to_xyz[3][3]; #define MAX_COLORSPACE_NAME 64 #define MAX_COLORSPACE_DESCRIPTION 512 diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index f2244b6ab5c..395bb90d686 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -93,10 +93,12 @@ static int global_tot_display = 0; static int global_tot_view = 0; static int global_tot_looks = 0; -/* Set to ITU-BT.709 / sRGB primaries weight. Brute force stupid, but only - * option with no colormanagement in place. - */ -float imbuf_luma_coefficients[3] = { 0.2126f, 0.7152f, 0.0722f }; +/* Luma coefficients and XYZ to RGB to be initialized by OCIO. */ +float imbuf_luma_coefficients[3] = {0.0f}; +float imbuf_xyz_to_rgb[3][3] = {{0.0f}}; +float imbuf_rgb_to_xyz[3][3] = {{0.0f}}; +float imbuf_xyz_to_linear_srgb[3][3] = {{0.0f}}; +float imbuf_linear_srgb_to_xyz[3][3] = {{0.0f}}; /* lock used by pre-cached processors getters, so processor wouldn't * be created several times @@ -563,6 +565,10 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config) /* Load luminance coefficients. */ OCIO_configGetDefaultLumaCoefs(config, imbuf_luma_coefficients); + OCIO_configGetXYZtoRGB(config, imbuf_xyz_to_rgb); + invert_m3_m3(imbuf_rgb_to_xyz, imbuf_xyz_to_rgb); + copy_m3_m3(imbuf_xyz_to_linear_srgb, OCIO_XYZ_TO_LINEAR_SRGB); + invert_m3_m3(imbuf_linear_srgb_to_xyz, imbuf_xyz_to_linear_srgb); } static void colormanage_free_config(void) @@ -1927,6 +1933,14 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in } } +/* Conversion between color picking role. Typically we would expect such a + * 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. + */ void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]) { if (!global_color_picking_state.processor_to && !global_color_picking_state.failed) { @@ -1975,6 +1989,22 @@ void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]) } } +/* Conversion between sRGB, for rare cases like hex color or copy/pasting + * between UI theme and scene linear colors. */ +void IMB_colormanagement_scene_linear_to_srgb_v3(float pixel[3]) +{ + mul_m3_v3(imbuf_rgb_to_xyz, pixel); + mul_m3_v3(imbuf_xyz_to_linear_srgb, pixel); + linearrgb_to_srgb_v3_v3(pixel, pixel); +} + +void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3]) +{ + srgb_to_linearrgb_v3_v3(pixel, pixel); + mul_m3_v3(imbuf_linear_srgb_to_xyz, pixel); + mul_m3_v3(imbuf_xyz_to_rgb, 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 diff --git a/source/blender/imbuf/intern/colormanagement_inline.c b/source/blender/imbuf/intern/colormanagement_inline.c index 4a55f8f86ae..37ef8779f58 100644 --- a/source/blender/imbuf/intern/colormanagement_inline.c +++ b/source/blender/imbuf/intern/colormanagement_inline.c @@ -62,4 +62,14 @@ unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char rgb[3]) return unit_float_to_uchar_clamp(val); } +void IMB_colormangement_xyz_to_rgb(float rgb[3], const float xyz[3]) +{ + mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, xyz); +} + +void IMB_colormangement_rgb_to_xyz(float xyz[3], const float rgb[3]) +{ + mul_v3_m3v3(xyz, imbuf_rgb_to_xyz, rgb); +} + #endif /* __IMB_COLORMANAGEMENT_INLINE_H__ */ |