From 128506eeb1a2d87393061b4c9783289a5e4b3275 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Sun, 29 Apr 2018 18:00:45 -0400 Subject: BLI Color: YUV to/from rgb colorspace option This commit does two things: - Adds an option to do the calculation in different color spaces (BT601 or BT709). - Changes the default caluclation from legacy BT601 to BT709. This affects several areas: - UI areas (mainly scopes) - ViewLevelsNode - Several other nodes that use `COM_ConvertOperation.h` --- source/blender/blenkernel/intern/colortools.c | 2 +- source/blender/blenlib/BLI_math_color.h | 9 ++++-- source/blender/blenlib/intern/math_color.c | 37 +++++++++++++++++----- .../operations/COM_CalculateMeanOperation.cpp | 2 +- .../COM_CalculateStandardDeviationOperation.cpp | 2 +- .../compositor/operations/COM_ConvertOperation.cpp | 4 +-- source/blender/editors/interface/interface_draw.c | 2 +- source/blender/editors/space_image/image_draw.c | 6 ++-- tests/gtests/blenlib/BLI_math_color_test.cc | 4 +-- 9 files changed, 46 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 0fe429312db..e7fa4cee587 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1034,7 +1034,7 @@ static void save_sample_line(Scopes *scopes, const int idx, const float fx, cons float yuv[3]; /* vectorscope*/ - rgb_to_yuv(rgb[0], rgb[1], rgb[2], &yuv[0], &yuv[1], &yuv[2]); + rgb_to_yuv(rgb[0], rgb[1], rgb[2], &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709); scopes->vecscope[idx + 0] = yuv[1]; scopes->vecscope[idx + 1] = yuv[2]; diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 34fc52c12c0..72d29164988 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -51,6 +51,10 @@ extern "C" { #define BLI_YCC_ITU_BT709 1 #define BLI_YCC_JFIF_0_255 2 +/* YUV */ +#define BLI_YUV_ITU_BT601 0 +#define BLI_YUV_ITU_BT709 1 + /******************* Conversion to RGB ********************/ void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b); @@ -58,14 +62,14 @@ void hsv_to_rgb_v(const float hsv[3], float r_rgb[3]); void hsl_to_rgb(float h, float c, float l, float *r, float *g, float *b); 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); +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 ********************/ -void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv); +void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv, int colorspace); void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace); void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv); void rgb_to_hsv_v(const float rgb[3], float r_hsv[3]); @@ -164,4 +168,3 @@ void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *o #endif #endif /* __BLI_MATH_COLOR_H__ */ - diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 6d7d24c79c3..a091595bc6c 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -83,24 +83,45 @@ void hsl_to_rgb_v(const float hsl[3], float r_rgb[3]) hsl_to_rgb(hsl[0], hsl[1], hsl[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]); } -void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv) +void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv, int colorspace) { float y, u, v; - y = 0.299f * r + 0.587f * g + 0.114f * b; - u = -0.147f * r - 0.289f * g + 0.436f * b; - v = 0.615f * r - 0.515f * g - 0.100f * b; + + switch (colorspace) { + case BLI_YUV_ITU_BT601: + y = 0.299f * r + 0.587f * g + 0.114f * b; + u = -0.147f * r - 0.289f * g + 0.436f * b; + v = 0.615f * r - 0.515f * g - 0.100f * b; + break; + case BLI_YUV_ITU_BT709: + default: + y = 0.2126f * r + 0.7152f * g + 0.0722f * b; + u = -0.09991f * r - 0.33609f * g + 0.436f * b; + v = 0.615f * r - 0.55861f * g - 0.05639f * b; + break; + } *ly = y; *lu = u; *lv = v; } -void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb) +void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb, int colorspace) { float r, g, b; - r = y + 1.140f * v; - g = y - 0.394f * u - 0.581f * v; - b = y + 2.032f * u; + + switch (colorspace) { + case BLI_YUV_ITU_BT601: + r = y + 1.140f * v; + g = y - 0.394f * u - 0.581f * v; + b = y + 2.032f * u; + break; + case BLI_YUV_ITU_BT709: + r = y + 1.28033f * v; + g = y - 0.21482f * u - 0.38059f * v; + b = y + 2.12798f * u; + break; + } *lr = r; *lg = g; diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp index d26dcd17750..ecbc7a9a93d 100644 --- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp @@ -121,7 +121,7 @@ void CalculateMeanOperation::calculateMean(MemoryBuffer *tile) case 5: { float yuv[3]; - rgb_to_yuv(buffer[offset], buffer[offset + 1], buffer[offset + 2], &yuv[0], &yuv[1], &yuv[2]); + rgb_to_yuv(buffer[offset], buffer[offset + 1], buffer[offset + 2], &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709); sum += yuv[0]; break; } diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp index 6b238e53d7b..56b402f2b3b 100644 --- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp @@ -87,7 +87,7 @@ void *CalculateStandardDeviationOperation::initializeTileData(rcti *rect) case 5: /* luminance */ { float yuv[3]; - rgb_to_yuv(buffer[offset], buffer[offset + 1], buffer[offset + 2], &yuv[0], &yuv[1], &yuv[2]); + rgb_to_yuv(buffer[offset], buffer[offset + 1], buffer[offset + 2], &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709); sum += (yuv[0] - mean) * (yuv[0] - mean); break; } diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cpp b/source/blender/compositor/operations/COM_ConvertOperation.cpp index 8b8e8408208..327015c1139 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertOperation.cpp @@ -241,7 +241,7 @@ void ConvertRGBToYUVOperation::executePixelSampled(float output[4], float x, flo { float inputColor[4]; this->m_inputOperation->readSampled(inputColor, x, y, sampler); - rgb_to_yuv(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]); + rgb_to_yuv(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], BLI_YUV_ITU_BT709); output[3] = inputColor[3]; } @@ -258,7 +258,7 @@ void ConvertYUVToRGBOperation::executePixelSampled(float output[4], float x, flo { float inputColor[4]; this->m_inputOperation->readSampled(inputColor, x, y, sampler); - yuv_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]); + yuv_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], BLI_YUV_ITU_BT709); output[3] = inputColor[3]; } diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 9a05c12e00a..7583dc654bb 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -831,7 +831,7 @@ static void vectorscope_draw_target(float centerx, float centery, float diam, co float tangle = 0.f, tampli; float dangle, dampli, dangle2, dampli2; - rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v); + rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v, BLI_YUV_ITU_BT709); if (u > 0 && v >= 0) tangle = atanf(v / u); else if (u > 0 && v < 0) tangle = atanf(v / u) + 2.0f * (float)M_PI; else if (u < 0) tangle = atanf(v / u) + (float)M_PI; diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 4d4beb07f00..594938b82aa 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -360,11 +360,11 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d if (channels == 1) { if (fp) { rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val); - rgb_to_yuv(fp[0], fp[0], fp[0], &lum, &u, &v); + rgb_to_yuv(fp[0], fp[0], fp[0], &lum, &u, &v, BLI_YUV_ITU_BT709); } else if (cp) { rgb_to_hsv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &hue, &sat, &val); - rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &lum, &u, &v); + rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &lum, &u, &v, BLI_YUV_ITU_BT709); } BLI_snprintf(str, sizeof(str), "V:%-.4f", val); @@ -379,7 +379,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d } else if (channels >= 3) { rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val); - rgb_to_yuv(finalcol[0], finalcol[1], finalcol[2], &lum, &u, &v); + rgb_to_yuv(finalcol[0], finalcol[1], finalcol[2], &lum, &u, &v, BLI_YUV_ITU_BT709); BLI_snprintf(str, sizeof(str), "H:%-.4f", hue); BLF_position(blf_mono_font, dx, dy, 0); diff --git a/tests/gtests/blenlib/BLI_math_color_test.cc b/tests/gtests/blenlib/BLI_math_color_test.cc index 2118822a9d8..8989e6740a5 100644 --- a/tests/gtests/blenlib/BLI_math_color_test.cc +++ b/tests/gtests/blenlib/BLI_math_color_test.cc @@ -27,9 +27,9 @@ TEST(math_color, RGBToYUVRoundtrip) float orig_rgb[3] = {0.1f, 0.2f, 0.3f}; float yuv[3], rgb[3]; rgb_to_yuv(orig_rgb[0], orig_rgb[1], orig_rgb[2], - &yuv[0], &yuv[1], &yuv[2]); + &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709); yuv_to_rgb(yuv[0], yuv[1], yuv[2], - &rgb[0], &rgb[1], &rgb[2]); + &rgb[0], &rgb[1], &rgb[2], BLI_YUV_ITU_BT709); EXPECT_V3_NEAR(orig_rgb, rgb, 1e-4); } -- cgit v1.2.3