Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
52868 views
1
/*
2
* Copyright (c) 2015 Kevin Wheatley <[email protected]>
3
*
4
* This file is part of FFmpeg.
5
*
6
* FFmpeg is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* FFmpeg is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with FFmpeg; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
#include <stddef.h>
22
#include <math.h>
23
24
#include "libavutil/color_utils.h"
25
#include "libavutil/pixfmt.h"
26
27
double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc)
28
{
29
double gamma;
30
switch (trc) {
31
case AVCOL_TRC_BT709:
32
case AVCOL_TRC_SMPTE170M:
33
case AVCOL_TRC_SMPTE240M:
34
case AVCOL_TRC_BT1361_ECG:
35
case AVCOL_TRC_BT2020_10:
36
case AVCOL_TRC_BT2020_12:
37
/* these share a segmented TRC, but gamma 1.961 is a close
38
approximation, and also more correct for decoding content */
39
gamma = 1.961;
40
break;
41
case AVCOL_TRC_GAMMA22:
42
case AVCOL_TRC_IEC61966_2_1:
43
gamma = 2.2;
44
break;
45
case AVCOL_TRC_GAMMA28:
46
gamma = 2.8;
47
break;
48
case AVCOL_TRC_LINEAR:
49
gamma = 1.0;
50
break;
51
default:
52
gamma = 0.0; // Unknown value representation
53
}
54
return gamma;
55
}
56
57
#define BT709_alpha 1.099296826809442
58
#define BT709_beta 0.018053968510807
59
60
static double avpriv_trc_bt709(double Lc)
61
{
62
const double a = BT709_alpha;
63
const double b = BT709_beta;
64
65
return (0.0 > Lc) ? 0.0
66
: ( b > Lc) ? 4.500 * Lc
67
: a * pow(Lc, 0.45) - (a - 1.0);
68
}
69
70
static double avpriv_trc_gamma22(double Lc)
71
{
72
return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2);
73
}
74
75
static double avpriv_trc_gamma28(double Lc)
76
{
77
return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8);
78
}
79
80
static double avpriv_trc_smpte240M(double Lc)
81
{
82
const double a = 1.1115;
83
const double b = 0.0228;
84
85
return (0.0 > Lc) ? 0.0
86
: ( b > Lc) ? 4.000 * Lc
87
: a * pow(Lc, 0.45) - (a - 1.0);
88
}
89
90
static double avpriv_trc_linear(double Lc)
91
{
92
return Lc;
93
}
94
95
static double avpriv_trc_log(double Lc)
96
{
97
return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0;
98
}
99
100
static double avpriv_trc_log_sqrt(double Lc)
101
{
102
// sqrt(10) / 1000
103
return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5;
104
}
105
106
static double avpriv_trc_iec61966_2_4(double Lc)
107
{
108
const double a = BT709_alpha;
109
const double b = BT709_beta;
110
111
return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0)
112
: ( b > Lc) ? 4.500 * Lc
113
: a * pow( Lc, 0.45) - (a - 1.0);
114
}
115
116
static double avpriv_trc_bt1361(double Lc)
117
{
118
const double a = BT709_alpha;
119
const double b = BT709_beta;
120
121
return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0
122
: ( b > Lc) ? 4.500 * Lc
123
: a * pow( Lc, 0.45) - (a - 1.0);
124
}
125
126
static double avpriv_trc_iec61966_2_1(double Lc)
127
{
128
const double a = 1.055;
129
const double b = 0.0031308;
130
131
return (0.0 > Lc) ? 0.0
132
: ( b > Lc) ? 12.92 * Lc
133
: a * pow(Lc, 1.0 / 2.4) - (a - 1.0);
134
}
135
136
static double avpriv_trc_smpte_st2084(double Lc)
137
{
138
const double c1 = 3424.0 / 4096.0; // c3-c2 + 1
139
const double c2 = 32.0 * 2413.0 / 4096.0;
140
const double c3 = 32.0 * 2392.0 / 4096.0;
141
const double m = 128.0 * 2523.0 / 4096.0;
142
const double n = 0.25 * 2610.0 / 4096.0;
143
const double L = Lc / 10000.0;
144
const double Ln = pow(L, n);
145
146
return (0.0 > Lc) ? 0.0
147
: pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m);
148
149
}
150
151
static double avpriv_trc_smpte_st428_1(double Lc)
152
{
153
return (0.0 > Lc) ? 0.0
154
: pow(48.0 * Lc / 52.37, 1.0 / 2.6);
155
}
156
157
avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)
158
{
159
avpriv_trc_function func = NULL;
160
switch (trc) {
161
case AVCOL_TRC_BT709:
162
case AVCOL_TRC_SMPTE170M:
163
case AVCOL_TRC_BT2020_10:
164
case AVCOL_TRC_BT2020_12:
165
func = avpriv_trc_bt709;
166
break;
167
168
case AVCOL_TRC_GAMMA22:
169
func = avpriv_trc_gamma22;
170
break;
171
case AVCOL_TRC_GAMMA28:
172
func = avpriv_trc_gamma28;
173
break;
174
175
case AVCOL_TRC_SMPTE240M:
176
func = avpriv_trc_smpte240M;
177
break;
178
179
case AVCOL_TRC_LINEAR:
180
func = avpriv_trc_linear;
181
break;
182
183
case AVCOL_TRC_LOG:
184
func = avpriv_trc_log;
185
break;
186
187
case AVCOL_TRC_LOG_SQRT:
188
func = avpriv_trc_log_sqrt;
189
break;
190
191
case AVCOL_TRC_IEC61966_2_4:
192
func = avpriv_trc_iec61966_2_4;
193
break;
194
195
case AVCOL_TRC_BT1361_ECG:
196
func = avpriv_trc_bt1361;
197
break;
198
199
case AVCOL_TRC_IEC61966_2_1:
200
func = avpriv_trc_iec61966_2_1;
201
break;
202
203
case AVCOL_TRC_SMPTEST2084:
204
func = avpriv_trc_smpte_st2084;
205
break;
206
207
case AVCOL_TRC_SMPTEST428_1:
208
func = avpriv_trc_smpte_st428_1;
209
break;
210
211
case AVCOL_TRC_RESERVED0:
212
case AVCOL_TRC_UNSPECIFIED:
213
case AVCOL_TRC_RESERVED:
214
default:
215
break;
216
}
217
return func;
218
}
219
220