1 /*
2 * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com>
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
avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc)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
avpriv_trc_bt709(double Lc)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
avpriv_trc_gamma22(double Lc)70 static double avpriv_trc_gamma22(double Lc)
71 {
72 return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2);
73 }
74
avpriv_trc_gamma28(double Lc)75 static double avpriv_trc_gamma28(double Lc)
76 {
77 return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8);
78 }
79
avpriv_trc_smpte240M(double Lc)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
avpriv_trc_linear(double Lc)90 static double avpriv_trc_linear(double Lc)
91 {
92 return Lc;
93 }
94
avpriv_trc_log(double Lc)95 static double avpriv_trc_log(double Lc)
96 {
97 return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0;
98 }
99
avpriv_trc_log_sqrt(double Lc)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
avpriv_trc_iec61966_2_4(double Lc)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
avpriv_trc_bt1361(double Lc)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
avpriv_trc_iec61966_2_1(double Lc)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
avpriv_trc_smpte_st2084(double Lc)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
avpriv_trc_smpte_st428_1(double Lc)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_arib_std_b67(double Lc)158 static double avpriv_trc_arib_std_b67(double Lc) {
159 // The function uses the definition from HEVC, which assumes that the peak
160 // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and
161 // using the definition from the ARIB STD-B67 spec)
162 const double a = 0.17883277;
163 const double b = 0.28466892;
164 const double c = 0.55991073;
165 return (0.0 > Lc) ? 0.0 :
166 (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c);
167 }
168
avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)169 avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)
170 {
171 avpriv_trc_function func = NULL;
172 switch (trc) {
173 case AVCOL_TRC_BT709:
174 case AVCOL_TRC_SMPTE170M:
175 case AVCOL_TRC_BT2020_10:
176 case AVCOL_TRC_BT2020_12:
177 func = avpriv_trc_bt709;
178 break;
179
180 case AVCOL_TRC_GAMMA22:
181 func = avpriv_trc_gamma22;
182 break;
183 case AVCOL_TRC_GAMMA28:
184 func = avpriv_trc_gamma28;
185 break;
186
187 case AVCOL_TRC_SMPTE240M:
188 func = avpriv_trc_smpte240M;
189 break;
190
191 case AVCOL_TRC_LINEAR:
192 func = avpriv_trc_linear;
193 break;
194
195 case AVCOL_TRC_LOG:
196 func = avpriv_trc_log;
197 break;
198
199 case AVCOL_TRC_LOG_SQRT:
200 func = avpriv_trc_log_sqrt;
201 break;
202
203 case AVCOL_TRC_IEC61966_2_4:
204 func = avpriv_trc_iec61966_2_4;
205 break;
206
207 case AVCOL_TRC_BT1361_ECG:
208 func = avpriv_trc_bt1361;
209 break;
210
211 case AVCOL_TRC_IEC61966_2_1:
212 func = avpriv_trc_iec61966_2_1;
213 break;
214
215 case AVCOL_TRC_SMPTEST2084:
216 func = avpriv_trc_smpte_st2084;
217 break;
218
219 case AVCOL_TRC_SMPTEST428_1:
220 func = avpriv_trc_smpte_st428_1;
221 break;
222
223 case AVCOL_TRC_ARIB_STD_B67:
224 func = avpriv_trc_arib_std_b67;
225 break;
226
227 case AVCOL_TRC_RESERVED0:
228 case AVCOL_TRC_UNSPECIFIED:
229 case AVCOL_TRC_RESERVED:
230 default:
231 break;
232 }
233 return func;
234 }
235