avutil/color_utils: Add basic transfer functions for each AVColorTransferCharacteristic
[ffmpeg.git] / libavutil / color_utils.c
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
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 }