Path: blob/21.2-virgl/src/gallium/auxiliary/vl/vl_csc.c
4565 views
/**************************************************************************1*2* Copyright 2009 Younes Manton.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include "util/u_math.h"28#include "util/u_debug.h"2930#include "vl_csc.h"3132/*33* Color space conversion formulas34*35* To convert YCbCr to RGB,36* vec4 ycbcr, rgb37* mat44 csc38* rgb = csc * ycbcr39*40* To calculate the color space conversion matrix csc with ProcAmp adjustments,41* mat44 csc, cstd, procamp, bias42* csc = cstd * (procamp * bias)43*44* Where cstd is a matrix corresponding to one of the color standards (BT.601, BT.709, etc)45* adjusted for the kind of YCbCr -> RGB mapping wanted (1:1, full),46* bias is a matrix corresponding to the kind of YCbCr -> RGB mapping wanted (1:1, full)47*48* To calculate procamp,49* mat44 procamp, hue, saturation, brightness, contrast50* procamp = brightness * (saturation * (contrast * hue))51* Alternatively,52* procamp = saturation * (brightness * (contrast * hue))53*54* contrast55* [ c, 0, 0, 0]56* [ 0, c, 0, 0]57* [ 0, 0, c, 0]58* [ 0, 0, 0, 1]59*60* brightness61* [ 1, 0, 0, b/c]62* [ 0, 1, 0, 0]63* [ 0, 0, 1, 0]64* [ 0, 0, 0, 1]65*66* saturation67* [ 1, 0, 0, 0]68* [ 0, s, 0, 0]69* [ 0, 0, s, 0]70* [ 0, 0, 0, 1]71*72* hue73* [ 1, 0, 0, 0]74* [ 0, cos(h), sin(h), 0]75* [ 0, -sin(h), cos(h), 0]76* [ 0, 0, 0, 1]77*78* procamp79* [ c, 0, 0, b]80* [ 0, c*s*cos(h), c*s*sin(h), 0]81* [ 0, -c*s*sin(h), c*s*cos(h), 0]82* [ 0, 0, 0, 1]83*84* bias85* [ 1, 0, 0, ybias]86* [ 0, 1, 0, cbbias]87* [ 0, 0, 1, crbias]88* [ 0, 0, 0, 1]89*90* csc91* [ c*cstd[ 0], c*cstd[ 1]*s*cos(h) - c*cstd[ 2]*s*sin(h), c*cstd[ 2]*s*cos(h) + c*cstd[ 1]*s*sin(h), cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 2]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]92* [ c*cstd[ 4], c*cstd[ 5]*s*cos(h) - c*cstd[ 6]*s*sin(h), c*cstd[ 6]*s*cos(h) + c*cstd[ 5]*s*sin(h), cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 6]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]93* [ c*cstd[ 8], c*cstd[ 9]*s*cos(h) - c*cstd[10]*s*sin(h), c*cstd[10]*s*cos(h) + c*cstd[ 9]*s*sin(h), cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[10]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]94* [ c*cstd[12], c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h), c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h), cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]95*/9697/*98* Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:99* Y is in [16,235], Cb and Cr are in [16,240]100* R, G, and B are in [16,235]101*/102static const vl_csc_matrix bt_601 =103{104{ 1.0f, 0.0f, 1.371f, 0.0f, },105{ 1.0f, -0.336f, -0.698f, 0.0f, },106{ 1.0f, 1.732f, 0.0f, 0.0f, }107};108109/*110* Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:111* Y is in [16,235], Cb and Cr are in [16,240]112* R, G, and B are in [16,235]113*/114static const vl_csc_matrix bt_709 =115{116{ 1.0f, 0.0f, 1.540f, 0.0f, },117{ 1.0f, -0.183f, -0.459f, 0.0f, },118{ 1.0f, 1.816f, 0.0f, 0.0f, }119};120121/*122* Converts SMPTE 240M YCbCr pixels to RGB pixels where:123* Y is in [16,235], Cb and Cr are in [16,240]124* R, G, and B are in [16,235]125*/126static const vl_csc_matrix smpte240m =127{128{ 1.0f, 0.0f, 1.541f, 0.0f, },129{ 1.0f, -0.221f, -0.466f, 0.0f, },130{ 1.0f, 1.785f, 0.0f, 0.0f, }131};132133static const vl_csc_matrix bt_709_rev = {134{ 0.183f, 0.614f, 0.062f, 0.0625f},135{-0.101f, -0.338f, 0.439f, 0.5f },136{ 0.439f, -0.399f, -0.040f, 0.5f }137};138139static const vl_csc_matrix identity =140{141{ 1.0f, 0.0f, 0.0f, 0.0f, },142{ 0.0f, 1.0f, 0.0f, 0.0f, },143{ 0.0f, 0.0f, 1.0f, 0.0f, }144};145146const struct vl_procamp vl_default_procamp = {1470.0f, /* brightness */1481.0f, /* contrast */1491.0f, /* saturation */1500.0f /* hue */151};152153void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,154struct vl_procamp *procamp,155bool full_range,156vl_csc_matrix *matrix)157{158float cbbias = -128.0f/255.0f;159float crbias = -128.0f/255.0f;160161const struct vl_procamp *p = procamp ? procamp : &vl_default_procamp;162float c = p->contrast;163float s = p->saturation;164float b = p->brightness;165float h = p->hue;166float x, y;167168const vl_csc_matrix *cstd;169170if (full_range) {171c *= 1.164f; /* Adjust for the y range */172b *= 1.164f; /* Adjust for the y range */173b -= c * 16.0f / 255.0f; /* Adjust for the y bias */174}175176/* Parameter substitutions */177x = c * s * cosf(h);178y = c * s * sinf(h);179180assert(matrix);181182switch (cs) {183case VL_CSC_COLOR_STANDARD_BT_601:184cstd = &bt_601;185break;186case VL_CSC_COLOR_STANDARD_BT_709:187cstd = &bt_709;188break;189case VL_CSC_COLOR_STANDARD_SMPTE_240M:190cstd = &smpte240m;191break;192case VL_CSC_COLOR_STANDARD_BT_709_REV:193memcpy(matrix, bt_709_rev, sizeof(vl_csc_matrix));194return;195case VL_CSC_COLOR_STANDARD_IDENTITY:196default:197assert(cs == VL_CSC_COLOR_STANDARD_IDENTITY);198memcpy(matrix, identity, sizeof(vl_csc_matrix));199return;200}201202(*matrix)[0][0] = c * (*cstd)[0][0];203(*matrix)[0][1] = (*cstd)[0][1] * x - (*cstd)[0][2] * y;204(*matrix)[0][2] = (*cstd)[0][2] * x + (*cstd)[0][1] * y;205(*matrix)[0][3] = (*cstd)[0][3] + (*cstd)[0][0] * b +206(*cstd)[0][1] * (x * cbbias + y * crbias) +207(*cstd)[0][2] * (x * crbias - y * cbbias);208209(*matrix)[1][0] = c * (*cstd)[1][0];210(*matrix)[1][1] = (*cstd)[1][1] * x - (*cstd)[1][2] * y;211(*matrix)[1][2] = (*cstd)[1][2] * x + (*cstd)[1][1] * y;212(*matrix)[1][3] = (*cstd)[1][3] + (*cstd)[1][0] * b +213(*cstd)[1][1] * (x * cbbias + y * crbias) +214(*cstd)[1][2] * (x * crbias - y * cbbias);215216(*matrix)[2][0] = c * (*cstd)[2][0];217(*matrix)[2][1] = (*cstd)[2][1] * x - (*cstd)[2][2] * y;218(*matrix)[2][2] = (*cstd)[2][2] * x + (*cstd)[2][1] * y;219(*matrix)[2][3] = (*cstd)[2][3] + (*cstd)[2][0] * b +220(*cstd)[2][1] * (x * cbbias + y * crbias) +221(*cstd)[2][2] * (x * crbias - y * cbbias);222}223224225