From 4c3fe3257de2cf9e00554c426aea676d57faea43 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 4 Mar 2016 11:49:31 +0100 Subject: [PATCH] gallium/vl: Simplify usage of full range matrices MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When looking at the full range matrices, it becomes obvious that the difference between the standard matrices and the full range matrices is that the full range matrices are multiplied by 1.164. Together with offsetting the y value with -16/255, this will scale and offset RGB with the desired quantities. However, the standard SMPTE 240M matrix seems to differ a bit since the U and V coefficients are only multiplied with 1.138 to get the full range matrix. This would actually alter the color somewhat so I figure that's an error. The full range matrix is consistent with Nvidia's VDPAU implementation. We can also incorporate the ybias in the brightness simplifying the calculation somewhat. Signed-off-by: Thomas Hellstrom Reviewed-by: Sinclair Yeh Reviewed-by: Christian König --- src/gallium/auxiliary/vl/vl_csc.c | 55 ++++++++++--------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/src/gallium/auxiliary/vl/vl_csc.c b/src/gallium/auxiliary/vl/vl_csc.c index 1587e6cf1df..d70ab14d323 100644 --- a/src/gallium/auxiliary/vl/vl_csc.c +++ b/src/gallium/auxiliary/vl/vl_csc.c @@ -107,18 +107,6 @@ static const vl_csc_matrix bt_601 = { 1.0f, 1.732f, 0.0f, 0.0f, } }; -/* - * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: - * Y is in [16,235], Cb and Cr are in [16,240] - * R, G, and B are in [0,255] - */ -static const vl_csc_matrix bt_601_full = -{ - { 1.164f, 0.0f, 1.596f, 0.0f, }, - { 1.164f, -0.391f, -0.813f, 0.0f, }, - { 1.164f, 2.018f, 0.0f, 0.0f, } -}; - /* * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: * Y is in [16,235], Cb and Cr are in [16,240] @@ -132,29 +120,15 @@ static const vl_csc_matrix bt_709 = }; /* - * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: + * Converts SMPTE 240M YCbCr pixels to RGB pixels where: * Y is in [16,235], Cb and Cr are in [16,240] - * R, G, and B are in [0,255] + * R, G, and B are in [16,235] */ -static const vl_csc_matrix bt_709_full = -{ - { 1.164f, 0.0f, 1.793f, 0.0f, }, - { 1.164f, -0.213f, -0.534f, 0.0f, }, - { 1.164f, 2.115f, 0.0f, 0.0f, } -}; - static const vl_csc_matrix smpte240m = { - { 1.0f, 0.0f, 1.582f, 0.0f, }, - { 1.0f, -0.228f, -0.478f, 0.0f, }, - { 1.0f, 1.833f, 0.0f, 0.0f, } -}; - -static const vl_csc_matrix smpte240m_full = -{ - { 1.164f, 0.0f, 1.794f, 0.0f, }, - { 1.164f, -0.258f, -0.543f, 0.0f, }, - { 1.164f, 2.079f, 0.0f, 0.0f, } + { 1.0f, 0.0f, 1.541f, 0.0f, }, + { 1.0f, -0.221f, -0.466f, 0.0f, }, + { 1.0f, 1.785f, 0.0f, 0.0f, } }; static const vl_csc_matrix identity = @@ -176,7 +150,6 @@ void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs, bool full_range, vl_csc_matrix *matrix) { - float ybias = full_range ? -16.0f/255.0f : 0.0f; float cbbias = -128.0f/255.0f; float crbias = -128.0f/255.0f; @@ -188,17 +161,23 @@ void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs, const vl_csc_matrix *cstd; + if (full_range) { + c *= 1.164f; /* Adjust for the y range */ + b *= 1.164f; /* Adjust for the y range */ + b -= c * 16.0f / 255.0f; /* Adjust for the y bias */ + } + assert(matrix); switch (cs) { case VL_CSC_COLOR_STANDARD_BT_601: - cstd = full_range ? &bt_601_full : &bt_601; + cstd = &bt_601; break; case VL_CSC_COLOR_STANDARD_BT_709: - cstd = full_range ? &bt_709_full : &bt_709; + cstd = &bt_709; break; case VL_CSC_COLOR_STANDARD_SMPTE_240M: - cstd = full_range ? &smpte240m_full : &smpte240m; + cstd = &smpte240m; break; case VL_CSC_COLOR_STANDARD_IDENTITY: default: @@ -210,21 +189,21 @@ void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs, (*matrix)[0][0] = c * (*cstd)[0][0]; (*matrix)[0][1] = c * (*cstd)[0][1] * s * cosf(h) - c * (*cstd)[0][2] * s * sinf(h); (*matrix)[0][2] = c * (*cstd)[0][2] * s * cosf(h) + c * (*cstd)[0][1] * s * sinf(h); - (*matrix)[0][3] = (*cstd)[0][3] + (*cstd)[0][0] * (b + c * ybias) + + (*matrix)[0][3] = (*cstd)[0][3] + (*cstd)[0][0] * b + (*cstd)[0][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) + (*cstd)[0][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h)); (*matrix)[1][0] = c * (*cstd)[1][0]; (*matrix)[1][1] = c * (*cstd)[1][1] * s * cosf(h) - c * (*cstd)[1][2] * s * sinf(h); (*matrix)[1][2] = c * (*cstd)[1][2] * s * cosf(h) + c * (*cstd)[1][1] * s * sinf(h); - (*matrix)[1][3] = (*cstd)[1][3] + (*cstd)[1][0] * (b + c * ybias) + + (*matrix)[1][3] = (*cstd)[1][3] + (*cstd)[1][0] * b + (*cstd)[1][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) + (*cstd)[1][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h)); (*matrix)[2][0] = c * (*cstd)[2][0]; (*matrix)[2][1] = c * (*cstd)[2][1] * s * cosf(h) - c * (*cstd)[2][2] * s * sinf(h); (*matrix)[2][2] = c * (*cstd)[2][2] * s * cosf(h) + c * (*cstd)[2][1] * s * sinf(h); - (*matrix)[2][3] = (*cstd)[2][3] + (*cstd)[2][0] * (b + c * ybias) + + (*matrix)[2][3] = (*cstd)[2][3] + (*cstd)[2][0] * b + (*cstd)[2][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) + (*cstd)[2][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h)); } -- 2.30.2