Coverage Report

Created: 2022-08-24 06:15

/src/libheif/libheif/nclx.cc
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * HEIF codec.
3
 * Copyright (c) 2020 struktur AG, Dirk Farin <farin@struktur.de>
4
 *
5
 * This file is part of libheif.
6
 *
7
 * libheif is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation, either version 3 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * libheif is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libheif.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
22
#include "nclx.h"
23
24
25
heif::primaries::primaries(float gx, float gy, float bx, float by, float rx, float ry, float wx, float wy)
26
0
{
27
0
  defined = true;
28
0
  redX = rx;
29
0
  redY = ry;
30
0
  greenX = gx;
31
0
  greenY = gy;
32
0
  blueX = bx;
33
0
  blueY = by;
34
0
  whiteX = wx;
35
0
  whiteY = wy;
36
0
}
37
38
39
heif::primaries heif::get_colour_primaries(uint16_t primaries_idx)
40
0
{
41
0
  switch (primaries_idx) {
42
0
    case 1:
43
0
      return {0.300f, 0.600f, 0.150f, 0.060f, 0.640f, 0.330f, 0.3127f, 0.3290f};
44
0
    case 4:
45
0
      return {0.21f, 0.71f, 0.14f, 0.08f, 0.67f, 0.33f, 0.310f, 0.316f};
46
0
    case 5:
47
0
      return {0.29f, 0.60f, 0.15f, 0.06f, 0.64f, 0.33f, 0.3127f, 0.3290f};
48
0
    case 6:
49
0
    case 7:
50
0
      return {0.310f, 0.595f, 0.155f, 0.070f, 0.630f, 0.340f, 0.3127f, 0.3290f};
51
0
    case 8:
52
0
      return {0.243f, 0.692f, 0.145f, 0.049f, 0.681f, 0.319f, 0.310f, 0.316f};
53
0
    case 9:
54
0
      return {0.170f, 0.797f, 0.131f, 0.046f, 0.708f, 0.292f, 0.3127f, 0.3290f};
55
0
    case 10:
56
0
      return {0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.333333f, 0.33333f};
57
0
    case 11:
58
0
      return {0.265f, 0.690f, 0.150f, 0.060f, 0.680f, 0.320f, 0.314f, 0.351f};
59
0
    case 12:
60
0
      return {0.265f, 0.690f, 0.150f, 0.060f, 0.680f, 0.320f, 0.3127f, 0.3290f};
61
0
    case 22:
62
0
      return {0.295f, 0.605f, 0.155f, 0.077f, 0.630f, 0.340f, 0.3127f, 0.3290f};
63
0
    default:
64
0
      return {};
65
0
  }
66
0
}
67
68
69
heif::Kr_Kb heif::get_Kr_Kb(uint16_t matrix_coefficients_idx, uint16_t primaries_idx)
70
0
{
71
0
  Kr_Kb result;
72
73
0
  if (matrix_coefficients_idx == 12 ||
74
0
      matrix_coefficients_idx == 13) {
75
76
0
    primaries p = get_colour_primaries(primaries_idx);
77
0
    float zr = 1 - (p.redX + p.redY);
78
0
    float zg = 1 - (p.greenX + p.greenY);
79
0
    float zb = 1 - (p.blueX + p.blueY);
80
0
    float zw = 1 - (p.whiteX + p.whiteY);
81
82
0
    float denom = p.whiteY * (p.redX * (p.greenY * zb - p.blueY * zg) + p.greenX * (p.blueY * zr - p.redY * zb) +
83
0
                              p.blueX * (p.redY * zg - p.greenY * zr));
84
85
0
    if (denom == 0.0f) {
86
0
      return result;
87
0
    }
88
89
0
    result.Kr = (p.redY * (p.whiteX * (p.greenY * zb - p.blueY * zg) + p.whiteY * (p.blueX * zg - p.greenX * zb) +
90
0
                           zw * (p.greenX * p.blueY - p.blueX * p.greenY))) / denom;
91
0
    result.Kb = (p.blueY * (p.whiteX * (p.redY * zg - p.greenY * zr) + p.whiteY * (p.greenX * zr - p.redX * zg) +
92
0
                            zw * (p.redX * p.greenY - p.greenX * p.redY))) / denom;
93
0
  }
94
0
  else
95
0
    switch (matrix_coefficients_idx) {
96
0
      case 1:
97
0
        result.Kr = 0.2126f;
98
0
        result.Kb = 0.0722f;
99
0
        break;
100
0
      case 4:
101
0
        result.Kr = 0.30f;
102
0
        result.Kb = 0.11f;
103
0
        break;
104
0
      case 5:
105
0
      case 6:
106
0
        result.Kr = 0.299f;
107
0
        result.Kb = 0.114f;
108
0
        break;
109
0
      case 7:
110
0
        result.Kr = 0.212f;
111
0
        result.Kb = 0.087f;
112
0
        break;
113
0
      case 9:
114
0
      case 10:
115
0
        result.Kr = 0.2627f;
116
0
        result.Kb = 0.0593f;
117
0
        break;
118
0
      default:;
119
0
    }
120
121
0
  return result;
122
0
}
123
124
125
heif::YCbCr_to_RGB_coefficients heif::YCbCr_to_RGB_coefficients::defaults()
126
0
{
127
0
  YCbCr_to_RGB_coefficients coeffs;
128
0
  coeffs.defined = true;
129
0
  coeffs.r_cr = 1.402f;
130
0
  coeffs.g_cb = -0.344136f;
131
0
  coeffs.g_cr = -0.714136f;
132
0
  coeffs.b_cb = 1.772f;
133
0
  return coeffs;
134
0
}
135
136
heif::YCbCr_to_RGB_coefficients
137
heif::get_YCbCr_to_RGB_coefficients(uint16_t matrix_coefficients_idx, uint16_t primaries_idx)
138
0
{
139
0
  YCbCr_to_RGB_coefficients coeffs;
140
141
0
  Kr_Kb k = get_Kr_Kb(matrix_coefficients_idx, primaries_idx);
142
143
0
  if (k.Kb != 0 || k.Kr != 0) { // both will be != 0 when valid
144
0
    coeffs.defined = true;
145
0
    coeffs.r_cr = 2 * (-k.Kr + 1);
146
0
    coeffs.g_cb = 2 * k.Kb * (-k.Kb + 1) / (k.Kb + k.Kr - 1);
147
0
    coeffs.g_cr = 2 * k.Kr * (-k.Kr + 1) / (k.Kb + k.Kr - 1);
148
0
    coeffs.b_cb = 2 * (-k.Kb + 1);
149
0
  }
150
0
  else {
151
0
    coeffs = YCbCr_to_RGB_coefficients::defaults();
152
0
  }
153
154
0
  return coeffs;
155
0
}
156
157
158
heif::RGB_to_YCbCr_coefficients
159
heif::get_RGB_to_YCbCr_coefficients(uint16_t matrix_coefficients_idx, uint16_t primaries_idx)
160
0
{
161
0
  RGB_to_YCbCr_coefficients coeffs;
162
163
0
  Kr_Kb k = get_Kr_Kb(matrix_coefficients_idx, primaries_idx);
164
165
0
  if (k.Kb != 0 || k.Kr != 0) { // both will be != 0 when valid
166
0
    coeffs.defined = true;
167
0
    coeffs.c[0][0] = k.Kr;
168
0
    coeffs.c[0][1] = 1 - k.Kr - k.Kb;
169
0
    coeffs.c[0][2] = k.Kb;
170
0
    coeffs.c[1][0] = -k.Kr / (1 - k.Kb) / 2;
171
0
    coeffs.c[1][1] = -(1 - k.Kr - k.Kb) / (1 - k.Kb) / 2;
172
0
    coeffs.c[1][2] = 0.5f;
173
0
    coeffs.c[2][0] = 0.5f;
174
0
    coeffs.c[2][1] = -(1 - k.Kr - k.Kb) / (1 - k.Kr) / 2;
175
0
    coeffs.c[2][2] = -k.Kb / (1 - k.Kr) / 2;
176
0
  }
177
0
  else {
178
0
    coeffs = RGB_to_YCbCr_coefficients::defaults();
179
0
  }
180
181
0
  return coeffs;
182
0
}
183
184
185
heif::RGB_to_YCbCr_coefficients heif::RGB_to_YCbCr_coefficients::defaults()
186
0
{
187
0
  RGB_to_YCbCr_coefficients coeffs;
188
0
  coeffs.defined = true;
189
190
0
  coeffs.c[0][0] = 0.299f;
191
0
  coeffs.c[0][1] = 0.587f;
192
0
  coeffs.c[0][2] = 0.114f;
193
0
  coeffs.c[1][0] = -0.168735f;
194
0
  coeffs.c[1][1] = -0.331264f;
195
0
  coeffs.c[1][2] = 0.5f;
196
0
  coeffs.c[2][0] = 0.5f;
197
0
  coeffs.c[2][1] = -0.418688f;
198
0
  coeffs.c[2][2] = -0.081312f;
199
200
0
  return coeffs;
201
0
}
202