Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2009 Younes Manton.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include "util/u_math.h"
  29. #include "util/u_debug.h"
  30.  
  31. #include "vl_csc.h"
  32.  
  33. /*
  34.  * Color space conversion formulas
  35.  *
  36.  * To convert YCbCr to RGB,
  37.  *    vec4  ycbcr, rgb
  38.  *    mat44 csc
  39.  *    rgb = csc * ycbcr
  40.  *
  41.  * To calculate the color space conversion matrix csc with ProcAmp adjustments,
  42.  *    mat44 csc, cstd, procamp, bias
  43.  *    csc = cstd * (procamp * bias)
  44.  *
  45.  * Where cstd is a matrix corresponding to one of the color standards (BT.601, BT.709, etc)
  46.  * adjusted for the kind of YCbCr -> RGB mapping wanted (1:1, full),
  47.  * bias is a matrix corresponding to the kind of YCbCr -> RGB mapping wanted (1:1, full)
  48.  *
  49.  * To calculate procamp,
  50.  *    mat44 procamp, hue, saturation, brightness, contrast
  51.  *    procamp = brightness * (saturation * (contrast * hue))
  52.  * Alternatively,
  53.  *    procamp = saturation * (brightness * (contrast * hue))
  54.  *
  55.  * contrast
  56.  * [ c, 0, 0, 0]
  57.  * [ 0, c, 0, 0]
  58.  * [ 0, 0, c, 0]
  59.  * [ 0, 0, 0, 1]
  60.  *
  61.  * brightness
  62.  * [ 1, 0, 0, b]
  63.  * [ 0, 1, 0, 0]
  64.  * [ 0, 0, 1, 0]
  65.  * [ 0, 0, 0, 1]
  66.  *
  67.  * saturation
  68.  * [ 1, 0, 0, 0]
  69.  * [ 0, s, 0, 0]
  70.  * [ 0, 0, s, 0]
  71.  * [ 0, 0, 0, 1]
  72.  *
  73.  * hue
  74.  * [ 1,       0,      0, 0]
  75.  * [ 0,  cos(h), sin(h), 0]
  76.  * [ 0, -sin(h), cos(h), 0]
  77.  * [ 0,       0,      0, 1]
  78.  *
  79.  * procamp
  80.  * [ c,           0,          0, b]
  81.  * [ 0,  c*s*cos(h), c*s*sin(h), 0]
  82.  * [ 0, -c*s*sin(h), c*s*cos(h), 0]
  83.  * [ 0,           0,          0, 1]
  84.  *
  85.  * bias
  86.  * [ 1, 0, 0,  ybias]
  87.  * [ 0, 1, 0, cbbias]
  88.  * [ 0, 0, 1, crbias]
  89.  * [ 0, 0, 0,      1]
  90.  *
  91.  * csc
  92.  * [ 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))]
  93.  * [ 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))]
  94.  * [ 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))]
  95.  * [ 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))]
  96.  */
  97.  
  98. /*
  99.  * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
  100.  * Y is in [16,235], Cb and Cr are in [16,240]
  101.  * R, G, and B are in [16,235]
  102.  */
  103. static const vl_csc_matrix bt_601 =
  104. {
  105.    { 1.0f,  0.0f,    1.371f, 0.0f, },
  106.    { 1.0f, -0.336f, -0.698f, 0.0f, },
  107.    { 1.0f,  1.732f,  0.0f,   0.0f, }
  108. };
  109.  
  110. /*
  111.  * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
  112.  * Y is in [16,235], Cb and Cr are in [16,240]
  113.  * R, G, and B are in [0,255]
  114.  */
  115. static const vl_csc_matrix bt_601_full =
  116. {
  117.    { 1.164f,  0.0f,    1.596f, 0.0f, },
  118.    { 1.164f, -0.391f, -0.813f, 0.0f, },
  119.    { 1.164f,  2.018f,  0.0f,   0.0f, }
  120. };
  121.  
  122. /*
  123.  * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
  124.  * Y is in [16,235], Cb and Cr are in [16,240]
  125.  * R, G, and B are in [16,235]
  126.  */
  127. static const vl_csc_matrix bt_709 =
  128. {
  129.    { 1.0f,  0.0f,    1.540f, 0.0f, },
  130.    { 1.0f, -0.183f, -0.459f, 0.0f, },
  131.    { 1.0f,  1.816f,  0.0f,   0.0f, }
  132. };
  133.  
  134. /*
  135.  * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
  136.  * Y is in [16,235], Cb and Cr are in [16,240]
  137.  * R, G, and B are in [0,255]
  138.  */
  139. static const vl_csc_matrix bt_709_full =
  140. {
  141.    { 1.164f,  0.0f,    1.793f, 0.0f, },
  142.    { 1.164f, -0.213f, -0.534f, 0.0f, },
  143.    { 1.164f,  2.115f,  0.0f,   0.0f, }
  144. };
  145.  
  146. static const vl_csc_matrix smpte240m =
  147. {
  148.    { 1.0f,  0.0f,    1.582f, 0.0f, },
  149.    { 1.0f, -0.228f, -0.478f, 0.0f, },
  150.    { 1.0f,  1.833f,  0.0f,   0.0f, }
  151. };
  152.  
  153. static const vl_csc_matrix smpte240m_full =
  154. {
  155.    { 1.164f,  0.0f,    1.794f, 0.0f, },
  156.    { 1.164f, -0.258f, -0.543f, 0.0f, },
  157.    { 1.164f,  2.079f,  0.0f,   0.0f, }
  158. };
  159.  
  160. static const vl_csc_matrix identity =
  161. {
  162.    { 1.0f, 0.0f, 0.0f, 0.0f, },
  163.    { 0.0f, 1.0f, 0.0f, 0.0f, },
  164.    { 0.0f, 0.0f, 1.0f, 0.0f, }
  165. };
  166.  
  167. const struct vl_procamp vl_default_procamp = {
  168.    0.0f,  /* brightness */
  169.    1.0f,  /* contrast   */
  170.    1.0f,  /* saturation */
  171.    0.0f   /* hue        */
  172. };
  173.  
  174. void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,
  175.                        struct vl_procamp *procamp,
  176.                        bool full_range,
  177.                        vl_csc_matrix *matrix)
  178. {
  179.    float ybias = full_range ? -16.0f/255.0f : 0.0f;
  180.    float cbbias = -128.0f/255.0f;
  181.    float crbias = -128.0f/255.0f;
  182.  
  183.    const struct vl_procamp *p = procamp ? procamp : &vl_default_procamp;
  184.    float c = p->contrast;
  185.    float s = p->saturation;
  186.    float b = p->brightness;
  187.    float h = p->hue;
  188.  
  189.    const vl_csc_matrix *cstd;
  190.  
  191.    assert(matrix);
  192.  
  193.    switch (cs) {
  194.       case VL_CSC_COLOR_STANDARD_BT_601:
  195.          cstd = full_range ? &bt_601_full : &bt_601;
  196.          break;
  197.       case VL_CSC_COLOR_STANDARD_BT_709:
  198.          cstd = full_range ? &bt_709_full : &bt_709;
  199.          break;
  200.       case VL_CSC_COLOR_STANDARD_SMPTE_240M:
  201.          cstd = full_range ? &smpte240m_full : &smpte240m;
  202.          break;
  203.       case VL_CSC_COLOR_STANDARD_IDENTITY:
  204.       default:
  205.          assert(cs == VL_CSC_COLOR_STANDARD_IDENTITY);
  206.          memcpy(matrix, identity, sizeof(vl_csc_matrix));
  207.          return;
  208.    }
  209.  
  210.    (*matrix)[0][0] = c * (*cstd)[0][0];
  211.    (*matrix)[0][1] = c * (*cstd)[0][1] * s * cosf(h) - c * (*cstd)[0][2] * s * sinf(h);
  212.    (*matrix)[0][2] = c * (*cstd)[0][2] * s * cosf(h) + c * (*cstd)[0][1] * s * sinf(h);
  213.    (*matrix)[0][3] = (*cstd)[0][3] + (*cstd)[0][0] * (b + c * ybias) +
  214.                      (*cstd)[0][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) +
  215.                      (*cstd)[0][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h));
  216.  
  217.    (*matrix)[1][0] = c * (*cstd)[1][0];
  218.    (*matrix)[1][1] = c * (*cstd)[1][1] * s * cosf(h) - c * (*cstd)[1][2] * s * sinf(h);
  219.    (*matrix)[1][2] = c * (*cstd)[1][2] * s * cosf(h) + c * (*cstd)[1][1] * s * sinf(h);
  220.    (*matrix)[1][3] = (*cstd)[1][3] + (*cstd)[1][0] * (b + c * ybias) +
  221.                      (*cstd)[1][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) +
  222.                      (*cstd)[1][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h));
  223.  
  224.    (*matrix)[2][0] = c * (*cstd)[2][0];
  225.    (*matrix)[2][1] = c * (*cstd)[2][1] * s * cosf(h) - c * (*cstd)[2][2] * s * sinf(h);
  226.    (*matrix)[2][2] = c * (*cstd)[2][2] * s * cosf(h) + c * (*cstd)[2][1] * s * sinf(h);
  227.    (*matrix)[2][3] = (*cstd)[2][3] + (*cstd)[2][0] * (b + c * ybias) +
  228.                      (*cstd)[2][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) +
  229.                      (*cstd)[2][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h));
  230. }
  231.