sharpyuv_csp.c (4083B)
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 static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); } 21 22 void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space, 23 SharpYuvConversionMatrix* matrix) { 24 const float kr = yuv_color_space->kr; 25 const float kb = yuv_color_space->kb; 26 const float kg = 1.0f - kr - kb; 27 const float cb = 0.5f / (1.0f - kb); 28 const float cr = 0.5f / (1.0f - kr); 29 30 const int shift = yuv_color_space->bit_depth - 8; 31 32 const float denom = (float)((1 << yuv_color_space->bit_depth) - 1); 33 float scale_y = 1.0f; 34 float add_y = 0.0f; 35 float scale_u = cb; 36 float scale_v = cr; 37 float add_uv = (float)(128 << shift); 38 assert(yuv_color_space->bit_depth >= 8); 39 40 if (yuv_color_space->range == kSharpYuvRangeLimited) { 41 scale_y *= (219 << shift) / denom; 42 scale_u *= (224 << shift) / denom; 43 scale_v *= (224 << shift) / denom; 44 add_y = (float)(16 << shift); 45 } 46 47 matrix->rgb_to_y[0] = ToFixed16(kr * scale_y); 48 matrix->rgb_to_y[1] = ToFixed16(kg * scale_y); 49 matrix->rgb_to_y[2] = ToFixed16(kb * scale_y); 50 matrix->rgb_to_y[3] = ToFixed16(add_y); 51 52 matrix->rgb_to_u[0] = ToFixed16(-kr * scale_u); 53 matrix->rgb_to_u[1] = ToFixed16(-kg * scale_u); 54 matrix->rgb_to_u[2] = ToFixed16((1 - kb) * scale_u); 55 matrix->rgb_to_u[3] = ToFixed16(add_uv); 56 57 matrix->rgb_to_v[0] = ToFixed16((1 - kr) * scale_v); 58 matrix->rgb_to_v[1] = ToFixed16(-kg * scale_v); 59 matrix->rgb_to_v[2] = ToFixed16(-kb * scale_v); 60 matrix->rgb_to_v[3] = ToFixed16(add_uv); 61 } 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 SharpYuvMatrixType matrix_type) { 101 switch (matrix_type) { 102 case kSharpYuvMatrixWebp: 103 return &kWebpMatrix; 104 case kSharpYuvMatrixRec601Limited: 105 return &kRec601LimitedMatrix; 106 case kSharpYuvMatrixRec601Full: 107 return &kRec601FullMatrix; 108 case kSharpYuvMatrixRec709Limited: 109 return &kRec709LimitedMatrix; 110 case kSharpYuvMatrixRec709Full: 111 return &kRec709FullMatrix; 112 case kSharpYuvMatrixNum: 113 return NULL; 114 } 115 return NULL; 116 }