From 1fdaf5862feab049d6e8e60cd5f1469a17b9cda5 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 21 Jul 2014 09:26:39 +0200 Subject: Optimisation to rgb <-> hsv/l conversion Basically avoid redundant computations. Gives ~1-4% speedup in the compositor depending on the use case. For more info see: http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv Reviewers: psy-fi, sergey Subscribers: campbellbarton Differential Revision: https://developer.blender.org/D596 --- source/blender/blenlib/intern/math_color.c | 180 ++++++----------------------- 1 file changed, 36 insertions(+), 144 deletions(-) (limited to 'source/blender/blenlib/intern/math_color.c') diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 57a48bb5fa8..3dd8aab18d7 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -37,112 +37,38 @@ void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b) { - if (s != 0.0f) { - float i, f, p; - h = (h - floorf(h)) * 6.0f; - - i = floorf(h); - f = h - i; - - /* avoid computing q/t when not needed */ - p = (v * (1.0f - s)); -#define q (v * (1.0f - (s * f))) -#define t (v * (1.0f - (s * (1.0f - f)))) - - /* faster to compare floats then int conversion */ - if (i < 1.0f) { - *r = v; - *g = t; - *b = p; - } - else if (i < 2.0f) { - *r = q; - *g = v; - *b = p; - } - else if (i < 3.0f) { - *r = p; - *g = v; - *b = t; - } - else if (i < 4.0f) { - *r = p; - *g = q; - *b = v; - } - else if (i < 5.0f) { - *r = t; - *g = p; - *b = v; - } - else { - *r = v; - *g = p; - *b = q; - } + float nr, ng, nb; -#undef q -#undef t + nr = fabsf(h * 6.0f - 3.0f) - 1.0f; + ng = 2.0f - fabsf(h * 6.0f - 2.0f); + nb = 2.0f - fabsf(h * 6.0f - 4.0f); - } - else { - *r = v; - *g = v; - *b = v; - } + CLAMP(nr, 0.0f, 1.0f); + CLAMP(nb, 0.0f, 1.0f); + CLAMP(ng, 0.0f, 1.0f); + + *r = ((nr - 1.0f) * s + 1.0f) * v; + *g = ((ng - 1.0f) * s + 1.0f) * v; + *b = ((nb - 1.0f) * s + 1.0f) * v; } -/* HSL to rgb conversion from https://en.wikipedia.org/wiki/HSL_and_HSV */ void hsl_to_rgb(float h, float s, float l, float *r, float *g, float *b) { - float i, f, c; - h = (h - floorf(h)) * 6.0f; - c = (l > 0.5f) ? (2.0f * (1.0f - l) * s) : (2.0f * l * s); - i = floorf(h); - f = h - i; + float nr, ng, nb, chroma; -#define x2 (c * f) -#define x1 (c * (1.0f - f)) + nr = fabsf(h * 6.0f - 3.0f) - 1.0f; + ng = 2.0f - fabsf(h * 6.0f - 2.0f); + nb = 2.0f - fabsf(h * 6.0f - 4.0f); - /* faster to compare floats then int conversion */ - if (i < 1.0f) { - *r = c; - *g = x2; - *b = 0; - } - else if (i < 2.0f) { - *r = x1; - *g = c; - *b = 0; - } - else if (i < 3.0f) { - *r = 0; - *g = c; - *b = x2; - } - else if (i < 4.0f) { - *r = 0; - *g = x1; - *b = c; - } - else if (i < 5.0f) { - *r = x2; - *g = 0; - *b = c; - } - else { - *r = c; - *g = 0; - *b = x1; - } + CLAMP(nr, 0.0f, 1.0f); + CLAMP(nb, 0.0f, 1.0f); + CLAMP(ng, 0.0f, 1.0f); -#undef x1 -#undef x2 + chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s; - f = l - 0.5f * c; - *r += f; - *g += f; - *b += f; + *r = (nr - 0.5f) * chroma + l; + *g = (ng - 0.5f) * chroma + l; + *b = (nb - 0.5f) * chroma + l; } /* convenience function for now */ @@ -284,57 +210,23 @@ void hex_to_rgb(char *hexcol, float *r, float *g, float *b) void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv) { - float h, s, v; - float cmax, cmin; - - cmax = r; - cmin = r; - cmax = (g > cmax ? g : cmax); - cmin = (g < cmin ? g : cmin); - cmax = (b > cmax ? b : cmax); - cmin = (b < cmin ? b : cmin); - - v = cmax; /* value */ - if (cmax != 0.0f) { - float cdelta; - - cdelta = cmax - cmin; - s = cdelta / cmax; - - if (s != 0.0f) { - float rc, gc, bc; - - rc = (cmax - r) / cdelta; - gc = (cmax - g) / cdelta; - bc = (cmax - b) / cdelta; - - if (r == cmax) { - h = bc - gc; - if (h < 0.0f) { - h += 6.0f; - } - } - else if (g == cmax) { - h = 2.0f + rc - bc; - } - else { - h = 4.0f + gc - rc; - } - - h *= (1.0f / 6.0f); - } - else { - h = 0.0f; - } + float k = 0.0f; + float chroma; + + if (g < b) { + SWAP(float, g, b); + k = -1.0f; } - else { - h = 0.0f; - s = 0.0f; + if (r < g) { + SWAP(float, r, g); + k = -2.0f * 6e-1f - k; } - *lh = h; - *ls = s; - *lv = v; + chroma = r - min_ff(g, b); + + *lh = fabsf(k + (g - b) / (6.0f * chroma + 1e-20f)); + *ls = chroma / (r + 1e-20f); + *lv = r; } /* convenience function for now */ -- cgit v1.2.3 From 25fab54e092fb453e418ed1c895c739f4c5d03c8 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 21 Jul 2014 12:33:49 +0200 Subject: Fix errors in hsv calculation from recent optimization patch. Code was different from original here, result was apparent in color picker wedge position. --- source/blender/blenlib/intern/math_color.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source/blender/blenlib/intern/math_color.c') diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 3dd8aab18d7..eb9e36bcbf4 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -212,17 +212,20 @@ void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv) { float k = 0.0f; float chroma; + float min_gb; if (g < b) { SWAP(float, g, b); k = -1.0f; } + min_gb = b; if (r < g) { SWAP(float, r, g); - k = -2.0f * 6e-1f - k; + k = -2.0f / 6.0f - k; + min_gb = min_ff(g, b); } - chroma = r - min_ff(g, b); + chroma = r - min_gb; *lh = fabsf(k + (g - b) / (6.0f * chroma + 1e-20f)); *ls = chroma / (r + 1e-20f); -- cgit v1.2.3 From 74758576fc9c1220563c86ce47a17c51d08a6d4f Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 30 Jul 2014 11:00:59 +0200 Subject: Cleanup: general cleanup in BLI_math code (mostly, use 'const' where possible, true/false for booleans, format for float litterals). --- source/blender/blenlib/intern/math_color.c | 31 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'source/blender/blenlib/intern/math_color.c') diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index eb9e36bcbf4..828a84da6e1 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -113,7 +113,7 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb) void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace) { float sr, sg, sb; - float y = 128.f, cr = 128.f, cb = 128.f; + float y = 128.0f, cr = 128.0f, cb = 128.0f; sr = 255.0f * r; sg = 255.0f * g; @@ -152,7 +152,7 @@ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, in /* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */ void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace) { - float r = 128.f, g = 128.f, b = 128.f; + float r = 128.0f, g = 128.0f, b = 128.0f; switch (colorspace) { case BLI_YCC_ITU_BT601: @@ -269,8 +269,8 @@ void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll) void rgb_to_hsl_compat(float r, float g, float b, float *lh, float *ls, float *ll) { - float orig_s = *ls; - float orig_h = *lh; + const float orig_s = *ls; + const float orig_h = *lh; rgb_to_hsl(r, g, b, lh, ls, ll); @@ -302,8 +302,8 @@ void rgb_to_hsl_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) { - float orig_h = *lh; - float orig_s = *ls; + const float orig_h = *lh; + const float orig_s = *ls; rgb_to_hsv(r, g, b, lh, ls, lv); @@ -598,11 +598,12 @@ static float index_to_float(const unsigned short i) void BLI_init_srgb_conversion(void) { - static int initialized = 0; + static bool initialized = false; unsigned int i, b; - if (initialized) return; - initialized = 1; + if (initialized) + return; + initialized = true; /* Fill in the lookup table to convert floats to bytes: */ for (i = 0; i < 0x10000; i++) { @@ -657,13 +658,13 @@ static float xyz_to_lab_component(float v) void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b) { - float xr = x / 95.047f; - float yr = y / 100.0f; - float zr = z / 108.883f; + const float xr = x / 95.047f; + const float yr = y / 100.0f; + const float zr = z / 108.883f; - float fx = xyz_to_lab_component(xr); - float fy = xyz_to_lab_component(yr); - float fz = xyz_to_lab_component(zr); + 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); -- cgit v1.2.3