Add partial Rec. 2020 support.
[movit] / gamma_compression_effect.cpp
1 #include <math.h>
2 #include <string.h>
3 #include <assert.h>
4
5 #include "gamma_compression_effect.h"
6 #include "util.h"
7
8 GammaCompressionEffect::GammaCompressionEffect()
9         : destination_curve(GAMMA_LINEAR)
10 {
11         register_int("destination_curve", (int *)&destination_curve);
12         memset(compression_curve, 0, sizeof(compression_curve));
13         register_1d_texture("compression_curve_tex", compression_curve, COMPRESSION_CURVE_SIZE);
14 }
15
16 std::string GammaCompressionEffect::output_fragment_shader()
17 {
18         if (destination_curve == GAMMA_LINEAR) {
19                 return read_file("identity.frag");
20         }
21         if (destination_curve == GAMMA_sRGB) {
22                 for (unsigned i = 0; i < COMPRESSION_CURVE_SIZE; ++i) {
23                         float x = i / (float)(COMPRESSION_CURVE_SIZE - 1);
24                         if (x < 0.0031308f) {
25                                 compression_curve[i] = 12.92f * x;
26                         } else {
27                                 compression_curve[i] = 1.055f * pow(x, 1.0f / 2.4f) - 0.055f;
28                         }
29                 }
30                 invalidate_1d_texture("compression_curve_tex");
31                 return read_file("gamma_compression_effect.frag");
32         }
33         if (destination_curve == GAMMA_REC_709 ||  // And Rec. 601, and 10-bit Rec. 2020.
34             destination_curve == GAMMA_REC_2020_12_BIT) {
35                 // Rec. 2020, page 3.
36                 float alpha, beta;
37                 if (destination_curve == GAMMA_REC_2020_12_BIT) {
38                         alpha = 1.0993f;
39                         beta = 0.0181f;
40                 } else {
41                         alpha = 1.099f;
42                         beta = 0.018f;
43                 }
44                 for (unsigned i = 0; i < COMPRESSION_CURVE_SIZE; ++i) {
45                         float x = i / (float)(COMPRESSION_CURVE_SIZE - 1);
46                         if (x < beta) {
47                                 compression_curve[i] = 4.5f * x;
48                         } else {
49                                 compression_curve[i] = alpha * pow(x, 0.45f) - (alpha - 1.0f);
50                         }
51                 }
52                 invalidate_1d_texture("compression_curve_tex");
53                 return read_file("gamma_compression_effect.frag");
54         }
55         assert(false);
56 }