• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 Google Inc. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 // -----------------------------------------------------------------------------
9 //
10 // Colorspace utilities.
11 
12 #include "sharpyuv/sharpyuv_csp.h"
13 
14 #include <assert.h>
15 #include <math.h>
16 #include <stddef.h>
17 
ToFixed16(float f)18 static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); }
19 
SharpYuvComputeConversionMatrix(const SharpYuvColorSpace * yuv_color_space,SharpYuvConversionMatrix * matrix)20 void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,
21                                      SharpYuvConversionMatrix* matrix) {
22   const float kr = yuv_color_space->kr;
23   const float kb = yuv_color_space->kb;
24   const float kg = 1.0f - kr - kb;
25   const float cr = 0.5f / (1.0f - kb);
26   const float cb = 0.5f / (1.0f - kr);
27 
28   const int shift = yuv_color_space->bit_depth - 8;
29 
30   const float denom = (float)((1 << yuv_color_space->bit_depth) - 1);
31   float scale_y = 1.0f;
32   float add_y = 0.0f;
33   float scale_u = cr;
34   float scale_v = cb;
35   float add_uv = (float)(128 << shift);
36   assert(yuv_color_space->bit_depth >= 8);
37 
38   if (yuv_color_space->range == kSharpYuvRangeLimited) {
39     scale_y *= (219 << shift) / denom;
40     scale_u *= (224 << shift) / denom;
41     scale_v *= (224 << shift) / denom;
42     add_y = (float)(16 << shift);
43   }
44 
45   matrix->rgb_to_y[0] = ToFixed16(kr * scale_y);
46   matrix->rgb_to_y[1] = ToFixed16(kg * scale_y);
47   matrix->rgb_to_y[2] = ToFixed16(kb * scale_y);
48   matrix->rgb_to_y[3] = ToFixed16(add_y);
49 
50   matrix->rgb_to_u[0] = ToFixed16(-kr * scale_u);
51   matrix->rgb_to_u[1] = ToFixed16(-kg * scale_u);
52   matrix->rgb_to_u[2] = ToFixed16((1 - kb) * scale_u);
53   matrix->rgb_to_u[3] = ToFixed16(add_uv);
54 
55   matrix->rgb_to_v[0] = ToFixed16((1 - kr) * scale_v);
56   matrix->rgb_to_v[1] = ToFixed16(-kg * scale_v);
57   matrix->rgb_to_v[2] = ToFixed16(-kb * scale_v);
58   matrix->rgb_to_v[3] = ToFixed16(add_uv);
59 }
60 
61 // Matrices are in YUV_FIX fixed point precision.
62 // WebP's matrix, similar but not identical to kRec601LimitedMatrix.
63 static const SharpYuvConversionMatrix kWebpMatrix = {
64   {16839, 33059, 6420, 16 << 16},
65   {-9719, -19081, 28800, 128 << 16},
66   {28800, -24116, -4684, 128 << 16},
67 };
68 // Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeLimited
69 static const SharpYuvConversionMatrix kRec601LimitedMatrix = {
70   {16829, 33039, 6416, 16 << 16},
71   {-9714, -19071, 28784, 128 << 16},
72   {28784, -24103, -4681, 128 << 16},
73 };
74 // Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeFull
75 static const SharpYuvConversionMatrix kRec601FullMatrix = {
76   {19595, 38470, 7471, 0},
77   {-11058, -21710, 32768, 128 << 16},
78   {32768, -27439, -5329, 128 << 16},
79 };
80 // Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeLimited
81 static const SharpYuvConversionMatrix kRec709LimitedMatrix = {
82   {11966, 40254, 4064, 16 << 16},
83   {-6596, -22189, 28784, 128 << 16},
84   {28784, -26145, -2639, 128 << 16},
85 };
86 // Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeFull
87 static const SharpYuvConversionMatrix kRec709FullMatrix = {
88   {13933, 46871, 4732, 0},
89   {-7509, -25259, 32768, 128 << 16},
90   {32768, -29763, -3005, 128 << 16},
91 };
92 
SharpYuvGetConversionMatrix(SharpYuvMatrixType matrix_type)93 const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
94     SharpYuvMatrixType matrix_type) {
95   switch (matrix_type) {
96     case kSharpYuvMatrixWebp:
97       return &kWebpMatrix;
98     case kSharpYuvMatrixRec601Limited:
99       return &kRec601LimitedMatrix;
100     case kSharpYuvMatrixRec601Full:
101       return &kRec601FullMatrix;
102     case kSharpYuvMatrixRec709Limited:
103       return &kRec709LimitedMatrix;
104     case kSharpYuvMatrixRec709Full:
105       return &kRec709FullMatrix;
106     case kSharpYuvMatrixNum:
107       return NULL;
108   }
109   return NULL;
110 }
111