sharpyuv_csp.c 3.8 KB

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