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

source code of qtimageformats/src/3rdparty/libwebp/sharpyuv/sharpyuv_csp.c