go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

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 }