/src/libwebp/sharpyuv/sharpyuv_csp.c
Line  | Count  | Source (jump to first uncovered line)  | 
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  |  |  | 
18  |  | #include "sharpyuv/sharpyuv.h"  | 
19  |  |  | 
20  | 0  | static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); } | 
21  |  |  | 
22  |  | void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,  | 
23  | 0  |                                      SharpYuvConversionMatrix* matrix) { | 
24  | 0  |   const float kr = yuv_color_space->kr;  | 
25  | 0  |   const float kb = yuv_color_space->kb;  | 
26  | 0  |   const float kg = 1.0f - kr - kb;  | 
27  | 0  |   const float cb = 0.5f / (1.0f - kb);  | 
28  | 0  |   const float cr = 0.5f / (1.0f - kr);  | 
29  |  | 
  | 
30  | 0  |   const int shift = yuv_color_space->bit_depth - 8;  | 
31  |  | 
  | 
32  | 0  |   const float denom = (float)((1 << yuv_color_space->bit_depth) - 1);  | 
33  | 0  |   float scale_y = 1.0f;  | 
34  | 0  |   float add_y = 0.0f;  | 
35  | 0  |   float scale_u = cb;  | 
36  | 0  |   float scale_v = cr;  | 
37  | 0  |   float add_uv = (float)(128 << shift);  | 
38  | 0  |   assert(yuv_color_space->bit_depth >= 8);  | 
39  |  |  | 
40  | 0  |   if (yuv_color_space->range == kSharpYuvRangeLimited) { | 
41  | 0  |     scale_y *= (219 << shift) / denom;  | 
42  | 0  |     scale_u *= (224 << shift) / denom;  | 
43  | 0  |     scale_v *= (224 << shift) / denom;  | 
44  | 0  |     add_y = (float)(16 << shift);  | 
45  | 0  |   }  | 
46  |  | 
  | 
47  | 0  |   matrix->rgb_to_y[0] = ToFixed16(kr * scale_y);  | 
48  | 0  |   matrix->rgb_to_y[1] = ToFixed16(kg * scale_y);  | 
49  | 0  |   matrix->rgb_to_y[2] = ToFixed16(kb * scale_y);  | 
50  | 0  |   matrix->rgb_to_y[3] = ToFixed16(add_y);  | 
51  |  | 
  | 
52  | 0  |   matrix->rgb_to_u[0] = ToFixed16(-kr * scale_u);  | 
53  | 0  |   matrix->rgb_to_u[1] = ToFixed16(-kg * scale_u);  | 
54  | 0  |   matrix->rgb_to_u[2] = ToFixed16((1 - kb) * scale_u);  | 
55  | 0  |   matrix->rgb_to_u[3] = ToFixed16(add_uv);  | 
56  |  | 
  | 
57  | 0  |   matrix->rgb_to_v[0] = ToFixed16((1 - kr) * scale_v);  | 
58  | 0  |   matrix->rgb_to_v[1] = ToFixed16(-kg * scale_v);  | 
59  | 0  |   matrix->rgb_to_v[2] = ToFixed16(-kb * scale_v);  | 
60  | 0  |   matrix->rgb_to_v[3] = ToFixed16(add_uv);  | 
61  | 0  | }  | 
62  |  |  | 
63  |  | // Matrices are in YUV_FIX fixed point precision.  | 
64  |  | // WebP's matrix, similar but not identical to kRec601LimitedMatrix  | 
65  |  | // Derived using the following formulas:  | 
66  |  | // Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16  | 
67  |  | // U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128  | 
68  |  | // V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128  | 
69  |  | static const SharpYuvConversionMatrix kWebpMatrix = { | 
70  |  |   {16839, 33059, 6420, 16 << 16}, | 
71  |  |   {-9719, -19081, 28800, 128 << 16}, | 
72  |  |   {28800, -24116, -4684, 128 << 16}, | 
73  |  | };  | 
74  |  | // Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeLimited  | 
75  |  | static const SharpYuvConversionMatrix kRec601LimitedMatrix = { | 
76  |  |   {16829, 33039, 6416, 16 << 16}, | 
77  |  |   {-9714, -19071, 28784, 128 << 16}, | 
78  |  |   {28784, -24103, -4681, 128 << 16}, | 
79  |  | };  | 
80  |  | // Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeFull  | 
81  |  | static const SharpYuvConversionMatrix kRec601FullMatrix = { | 
82  |  |   {19595, 38470, 7471, 0}, | 
83  |  |   {-11058, -21710, 32768, 128 << 16}, | 
84  |  |   {32768, -27439, -5329, 128 << 16}, | 
85  |  | };  | 
86  |  | // Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeLimited  | 
87  |  | static const SharpYuvConversionMatrix kRec709LimitedMatrix = { | 
88  |  |   {11966, 40254, 4064, 16 << 16}, | 
89  |  |   {-6596, -22189, 28784, 128 << 16}, | 
90  |  |   {28784, -26145, -2639, 128 << 16}, | 
91  |  | };  | 
92  |  | // Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeFull  | 
93  |  | static const SharpYuvConversionMatrix kRec709FullMatrix = { | 
94  |  |   {13933, 46871, 4732, 0}, | 
95  |  |   {-7509, -25259, 32768, 128 << 16}, | 
96  |  |   {32768, -29763, -3005, 128 << 16}, | 
97  |  | };  | 
98  |  |  | 
99  |  | const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(  | 
100  | 0  |     SharpYuvMatrixType matrix_type) { | 
101  | 0  |   switch (matrix_type) { | 
102  | 0  |     case kSharpYuvMatrixWebp:  | 
103  | 0  |       return &kWebpMatrix;  | 
104  | 0  |     case kSharpYuvMatrixRec601Limited:  | 
105  | 0  |       return &kRec601LimitedMatrix;  | 
106  | 0  |     case kSharpYuvMatrixRec601Full:  | 
107  | 0  |       return &kRec601FullMatrix;  | 
108  | 0  |     case kSharpYuvMatrixRec709Limited:  | 
109  | 0  |       return &kRec709LimitedMatrix;  | 
110  | 0  |     case kSharpYuvMatrixRec709Full:  | 
111  | 0  |       return &kRec709FullMatrix;  | 
112  | 0  |     case kSharpYuvMatrixNum:  | 
113  | 0  |       return NULL;  | 
114  | 0  |   }  | 
115  | 0  |   return NULL;  | 
116  | 0  | }  |