• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "common.h"
25 #include "libavutil/color_utils.h"
26 #include "libavutil/pixfmt.h"
27 
avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc)28 double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc)
29 {
30     double gamma;
31     switch (trc) {
32         case AVCOL_TRC_BT709:
33         case AVCOL_TRC_SMPTE170M:
34         case AVCOL_TRC_SMPTE240M:
35         case AVCOL_TRC_BT1361_ECG:
36         case AVCOL_TRC_BT2020_10:
37         case AVCOL_TRC_BT2020_12:
38             /* these share a segmented TRC, but gamma 1.961 is a close
39               approximation, and also more correct for decoding content */
40             gamma = 1.961;
41             break;
42         case AVCOL_TRC_GAMMA22:
43         case AVCOL_TRC_IEC61966_2_1:
44             gamma = 2.2;
45             break;
46         case AVCOL_TRC_GAMMA28:
47             gamma = 2.8;
48             break;
49         case AVCOL_TRC_LINEAR:
50             gamma = 1.0;
51             break;
52         default:
53             gamma = 0.0; // Unknown value representation
54     }
55     return gamma;
56 }
57 
58 #define BT709_alpha 1.099296826809442
59 #define BT709_beta 0.018053968510807
60 
avpriv_trc_bt709(double Lc)61 static double avpriv_trc_bt709(double Lc)
62 {
63     const double a = BT709_alpha;
64     const double b = BT709_beta;
65 
66     return (0.0 > Lc) ? 0.0
67          : (  b > Lc) ? 4.500 * Lc
68          :              a * pow(Lc, 0.45) - (a - 1.0);
69 }
70 
avpriv_trc_gamma22(double Lc)71 static double avpriv_trc_gamma22(double Lc)
72 {
73     return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2);
74 }
75 
avpriv_trc_gamma28(double Lc)76 static double avpriv_trc_gamma28(double Lc)
77 {
78     return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8);
79 }
80 
avpriv_trc_smpte240M(double Lc)81 static double avpriv_trc_smpte240M(double Lc)
82 {
83     const double a = 1.1115;
84     const double b = 0.0228;
85 
86     return (0.0 > Lc) ? 0.0
87          : (  b > Lc) ? 4.000 * Lc
88          :              a * pow(Lc, 0.45) - (a - 1.0);
89 }
90 
avpriv_trc_linear(double Lc)91 static double avpriv_trc_linear(double Lc)
92 {
93     return Lc;
94 }
95 
avpriv_trc_log(double Lc)96 static double avpriv_trc_log(double Lc)
97 {
98     return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0;
99 }
100 
avpriv_trc_log_sqrt(double Lc)101 static double avpriv_trc_log_sqrt(double Lc)
102 {
103     // sqrt(10) / 1000
104     return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5;
105 }
106 
avpriv_trc_iec61966_2_4(double Lc)107 static double avpriv_trc_iec61966_2_4(double Lc)
108 {
109     const double a = BT709_alpha;
110     const double b = BT709_beta;
111 
112     return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0)
113          : ( b >  Lc) ? 4.500 * Lc
114          :               a * pow( Lc, 0.45) - (a - 1.0);
115 }
116 
avpriv_trc_bt1361(double Lc)117 static double avpriv_trc_bt1361(double Lc)
118 {
119     const double a = BT709_alpha;
120     const double b = BT709_beta;
121 
122     return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0
123          : ( b >  Lc) ? 4.500 * Lc
124          :               a * pow( Lc, 0.45) - (a - 1.0);
125 }
126 
avpriv_trc_iec61966_2_1(double Lc)127 static double avpriv_trc_iec61966_2_1(double Lc)
128 {
129     const double a = 1.055;
130     const double b = 0.0031308;
131 
132     return (0.0 > Lc) ? 0.0
133          : (  b > Lc) ? 12.92 * Lc
134          :              a * pow(Lc, 1.0  / 2.4) - (a - 1.0);
135 }
136 
avpriv_trc_smpte_st2084(double Lc)137 static double avpriv_trc_smpte_st2084(double Lc)
138 {
139     const double c1 =         3424.0 / 4096.0; // c3-c2 + 1
140     const double c2 =  32.0 * 2413.0 / 4096.0;
141     const double c3 =  32.0 * 2392.0 / 4096.0;
142     const double m  = 128.0 * 2523.0 / 4096.0;
143     const double n  =  0.25 * 2610.0 / 4096.0;
144     const double L  = Lc / 10000.0;
145     const double Ln = pow(L, n);
146 
147     return (0.0 > Lc) ? 0.0
148          :              pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m);
149 
150 }
151 
avpriv_trc_smpte_st428_1(double Lc)152 static double avpriv_trc_smpte_st428_1(double Lc)
153 {
154     return (0.0 > Lc) ? 0.0
155          :              pow(48.0 * Lc / 52.37, 1.0 / 2.6);
156 }
157 
158 
avpriv_trc_arib_std_b67(double Lc)159 static double avpriv_trc_arib_std_b67(double Lc) {
160     // The function uses the definition from HEVC, which assumes that the peak
161     // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and
162     // using the definition from the ARIB STD-B67 spec)
163     const double a = 0.17883277;
164     const double b = 0.28466892;
165     const double c = 0.55991073;
166     return (0.0 > Lc) ? 0.0 :
167         (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c);
168 }
169 
avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)170 avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)
171 {
172     avpriv_trc_function func = NULL;
173     switch (trc) {
174         case AVCOL_TRC_BT709:
175         case AVCOL_TRC_SMPTE170M:
176         case AVCOL_TRC_BT2020_10:
177         case AVCOL_TRC_BT2020_12:
178             func = avpriv_trc_bt709;
179             break;
180 
181         case AVCOL_TRC_GAMMA22:
182             func = avpriv_trc_gamma22;
183             break;
184         case AVCOL_TRC_GAMMA28:
185             func = avpriv_trc_gamma28;
186             break;
187 
188         case AVCOL_TRC_SMPTE240M:
189             func = avpriv_trc_smpte240M;
190             break;
191 
192         case AVCOL_TRC_LINEAR:
193             func = avpriv_trc_linear;
194             break;
195 
196         case AVCOL_TRC_LOG:
197             func = avpriv_trc_log;
198             break;
199 
200         case AVCOL_TRC_LOG_SQRT:
201             func = avpriv_trc_log_sqrt;
202             break;
203 
204         case AVCOL_TRC_IEC61966_2_4:
205             func = avpriv_trc_iec61966_2_4;
206             break;
207 
208         case AVCOL_TRC_BT1361_ECG:
209             func = avpriv_trc_bt1361;
210             break;
211 
212         case AVCOL_TRC_IEC61966_2_1:
213             func = avpriv_trc_iec61966_2_1;
214             break;
215 
216         case AVCOL_TRC_SMPTEST2084:
217             func = avpriv_trc_smpte_st2084;
218             break;
219 
220         case AVCOL_TRC_SMPTEST428_1:
221             func = avpriv_trc_smpte_st428_1;
222             break;
223 
224         case AVCOL_TRC_ARIB_STD_B67:
225             func = avpriv_trc_arib_std_b67;
226             break;
227 
228         case AVCOL_TRC_RESERVED0:
229         case AVCOL_TRC_UNSPECIFIED:
230         case AVCOL_TRC_RESERVED:
231         default:
232             break;
233     }
234     return func;
235 }
236