/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 | } |