]> git.sesse.net Git - movit/blob - colorspace_conversion_effect_test.cpp
Fix a bug where PaddingEffect could create assertion errors.
[movit] / colorspace_conversion_effect_test.cpp
1 // Unit tests for ColorspaceConversionEffect.
2
3 #include <GL/glew.h>
4
5 #include "colorspace_conversion_effect.h"
6 #include "gtest/gtest.h"
7 #include "test_util.h"
8
9 TEST(ColorspaceConversionEffectTest, Reversible) {
10         float data[] = {
11                 0.0f, 0.0f, 0.0f, 1.0f,
12                 1.0f, 1.0f, 1.0f, 1.0f,
13                 1.0f, 0.0f, 0.0f, 1.0f,
14                 0.0f, 1.0f, 0.0f, 1.0f,
15                 0.0f, 0.0f, 1.0f, 1.0f,
16                 0.0f, 1.0f, 1.0f, 0.5f,
17         };
18         float temp_data[4 * 6], out_data[4 * 6];
19
20         {
21                 EffectChainTester tester(data, 1, 6, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
22                 tester.run(temp_data, GL_RGBA, COLORSPACE_REC_601_525, GAMMA_LINEAR);
23         }
24         {
25                 EffectChainTester tester(temp_data, 1, 6, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_REC_601_525, GAMMA_LINEAR);
26                 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
27         }
28
29         expect_equal(data, out_data, 4, 6);
30 }
31
32 TEST(ColorspaceConversionEffectTest, sRGB_Primaries) {
33         float data[] = {
34                 0.0f, 0.0f, 0.0f, 1.0f,
35                 1.0f, 1.0f, 1.0f, 1.0f,
36                 1.0f, 0.0f, 0.0f, 1.0f,
37                 0.0f, 1.0f, 0.0f, 1.0f,
38                 0.0f, 0.0f, 1.0f, 1.0f,
39         };
40         float out_data[4 * 5];
41
42         EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
43         tester.run(out_data, GL_RGBA, COLORSPACE_XYZ, GAMMA_LINEAR);
44
45         // Black should stay black.
46         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 0]);
47         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 1]);
48         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 2]);
49         EXPECT_FLOAT_EQ(1.0f, out_data[0 * 4 + 3]);
50
51         // White point should be D65.
52         // XYZ values from http://en.wikipedia.org/wiki/CIE_Standard_Illuminant_D65.
53         EXPECT_NEAR(0.9505, out_data[1 * 4 + 0], 1e-3);
54         EXPECT_NEAR(1.0000, out_data[1 * 4 + 1], 1e-3);
55         EXPECT_NEAR(1.0889, out_data[1 * 4 + 2], 1e-3);
56         EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
57
58         float white_xyz_sum = out_data[1 * 4 + 0] + out_data[1 * 4 + 1] + out_data[1 * 4 + 2];
59         float white_x = out_data[1 * 4 + 0] / white_xyz_sum;
60         float white_y = out_data[1 * 4 + 1] / white_xyz_sum;
61         EXPECT_NEAR(0.3127, white_x, 1e-3);
62         EXPECT_NEAR(0.3290, white_y, 1e-3);
63         EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
64
65         // Convert the primaries from XYZ to xyz, and compare to the references
66         // given by Rec. 709 (which are shared with sRGB).
67
68         float red_xyz_sum = out_data[2 * 4 + 0] + out_data[2 * 4 + 1] + out_data[2 * 4 + 2];
69         float red_x = out_data[2 * 4 + 0] / red_xyz_sum;
70         float red_y = out_data[2 * 4 + 1] / red_xyz_sum;
71         EXPECT_NEAR(0.640, red_x, 1e-3);
72         EXPECT_NEAR(0.330, red_y, 1e-3);
73         EXPECT_FLOAT_EQ(1.0f, out_data[2 * 4 + 3]);
74
75         float green_xyz_sum = out_data[3 * 4 + 0] + out_data[3 * 4 + 1] + out_data[3 * 4 + 2];
76         float green_x = out_data[3 * 4 + 0] / green_xyz_sum;
77         float green_y = out_data[3 * 4 + 1] / green_xyz_sum;
78         EXPECT_NEAR(0.300, green_x, 1e-3);
79         EXPECT_NEAR(0.600, green_y, 1e-3);
80         EXPECT_FLOAT_EQ(1.0f, out_data[3 * 4 + 3]);
81
82         float blue_xyz_sum = out_data[4 * 4 + 0] + out_data[4 * 4 + 1] + out_data[4 * 4 + 2];
83         float blue_x = out_data[4 * 4 + 0] / blue_xyz_sum;
84         float blue_y = out_data[4 * 4 + 1] / blue_xyz_sum;
85         EXPECT_NEAR(0.150, blue_x, 1e-3);
86         EXPECT_NEAR(0.060, blue_y, 1e-3);
87         EXPECT_FLOAT_EQ(1.0f, out_data[4 * 4 + 3]);
88 }
89
90 TEST(ColorspaceConversionEffectTest, Rec601_525_Primaries) {
91         float data[] = {
92                 0.0f, 0.0f, 0.0f, 1.0f,
93                 1.0f, 1.0f, 1.0f, 1.0f,
94                 1.0f, 0.0f, 0.0f, 1.0f,
95                 0.0f, 1.0f, 0.0f, 1.0f,
96                 0.0f, 0.0f, 1.0f, 1.0f,
97         };
98         float out_data[4 * 5];
99
100         EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_REC_601_525, GAMMA_LINEAR);
101         tester.run(out_data, GL_RGBA, COLORSPACE_XYZ, GAMMA_LINEAR);
102
103         // Black should stay black.
104         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 0]);
105         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 1]);
106         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 2]);
107         EXPECT_FLOAT_EQ(1.0f, out_data[0 * 4 + 3]);
108
109         // Convert the primaries from XYZ to xyz, and compare to the references
110         // given by Rec. 601.
111         float white_xyz_sum = out_data[1 * 4 + 0] + out_data[1 * 4 + 1] + out_data[1 * 4 + 2];
112         float white_x = out_data[1 * 4 + 0] / white_xyz_sum;
113         float white_y = out_data[1 * 4 + 1] / white_xyz_sum;
114         EXPECT_NEAR(0.3127, white_x, 1e-3);
115         EXPECT_NEAR(0.3290, white_y, 1e-3);
116         EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
117
118         float red_xyz_sum = out_data[2 * 4 + 0] + out_data[2 * 4 + 1] + out_data[2 * 4 + 2];
119         float red_x = out_data[2 * 4 + 0] / red_xyz_sum;
120         float red_y = out_data[2 * 4 + 1] / red_xyz_sum;
121         EXPECT_NEAR(0.630, red_x, 1e-3);
122         EXPECT_NEAR(0.340, red_y, 1e-3);
123         EXPECT_FLOAT_EQ(1.0f, out_data[2 * 4 + 3]);
124
125         float green_xyz_sum = out_data[3 * 4 + 0] + out_data[3 * 4 + 1] + out_data[3 * 4 + 2];
126         float green_x = out_data[3 * 4 + 0] / green_xyz_sum;
127         float green_y = out_data[3 * 4 + 1] / green_xyz_sum;
128         EXPECT_NEAR(0.310, green_x, 1e-3);
129         EXPECT_NEAR(0.595, green_y, 1e-3);
130         EXPECT_FLOAT_EQ(1.0f, out_data[3 * 4 + 3]);
131
132         float blue_xyz_sum = out_data[4 * 4 + 0] + out_data[4 * 4 + 1] + out_data[4 * 4 + 2];
133         float blue_x = out_data[4 * 4 + 0] / blue_xyz_sum;
134         float blue_y = out_data[4 * 4 + 1] / blue_xyz_sum;
135         EXPECT_NEAR(0.155, blue_x, 1e-3);
136         EXPECT_NEAR(0.070, blue_y, 1e-3);
137         EXPECT_FLOAT_EQ(1.0f, out_data[4 * 4 + 3]);
138 }
139
140 TEST(ColorspaceConversionEffectTest, Rec601_625_Primaries) {
141         float data[] = {
142                 0.0f, 0.0f, 0.0f, 1.0f,
143                 1.0f, 1.0f, 1.0f, 1.0f,
144                 1.0f, 0.0f, 0.0f, 1.0f,
145                 0.0f, 1.0f, 0.0f, 1.0f,
146                 0.0f, 0.0f, 1.0f, 1.0f,
147         };
148         float out_data[4 * 5];
149
150         EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_REC_601_625, GAMMA_LINEAR);
151         tester.run(out_data, GL_RGBA, COLORSPACE_XYZ, GAMMA_LINEAR);
152
153         // Black should stay black.
154         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 0]);
155         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 1]);
156         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 2]);
157         EXPECT_FLOAT_EQ(1.0f, out_data[0 * 4 + 3]);
158
159         // Convert the primaries from XYZ to xyz, and compare to the references
160         // given by Rec. 601.
161         float white_xyz_sum = out_data[1 * 4 + 0] + out_data[1 * 4 + 1] + out_data[1 * 4 + 2];
162         float white_x = out_data[1 * 4 + 0] / white_xyz_sum;
163         float white_y = out_data[1 * 4 + 1] / white_xyz_sum;
164         EXPECT_NEAR(0.3127, white_x, 1e-3);
165         EXPECT_NEAR(0.3290, white_y, 1e-3);
166         EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
167
168         float red_xyz_sum = out_data[2 * 4 + 0] + out_data[2 * 4 + 1] + out_data[2 * 4 + 2];
169         float red_x = out_data[2 * 4 + 0] / red_xyz_sum;
170         float red_y = out_data[2 * 4 + 1] / red_xyz_sum;
171         EXPECT_NEAR(0.640, red_x, 1e-3);
172         EXPECT_NEAR(0.330, red_y, 1e-3);
173         EXPECT_FLOAT_EQ(1.0f, out_data[2 * 4 + 3]);
174
175         float green_xyz_sum = out_data[3 * 4 + 0] + out_data[3 * 4 + 1] + out_data[3 * 4 + 2];
176         float green_x = out_data[3 * 4 + 0] / green_xyz_sum;
177         float green_y = out_data[3 * 4 + 1] / green_xyz_sum;
178         EXPECT_NEAR(0.290, green_x, 1e-3);
179         EXPECT_NEAR(0.600, green_y, 1e-3);
180         EXPECT_FLOAT_EQ(1.0f, out_data[3 * 4 + 3]);
181
182         float blue_xyz_sum = out_data[4 * 4 + 0] + out_data[4 * 4 + 1] + out_data[4 * 4 + 2];
183         float blue_x = out_data[4 * 4 + 0] / blue_xyz_sum;
184         float blue_y = out_data[4 * 4 + 1] / blue_xyz_sum;
185         EXPECT_NEAR(0.150, blue_x, 1e-3);
186         EXPECT_NEAR(0.060, blue_y, 1e-3);
187         EXPECT_FLOAT_EQ(1.0f, out_data[4 * 4 + 3]);
188 }
189
190 TEST(ColorspaceConversionEffectTest, sRGBToRec601_525) {
191         float data[] = {
192                 0.0f, 0.0f, 0.0f, 1.0f,
193                 1.0f, 1.0f, 1.0f, 1.0f,
194                 1.0f, 0.0f, 0.0f, 1.0f,
195                 0.0f, 1.0f, 0.0f, 1.0f,
196                 0.0f, 0.0f, 1.0f, 1.0f,
197                 0.0f, 1.0f, 1.0f, 0.5f,
198         };
199
200         // I have to admit that most of these come from the code itself;
201         // however, they do make sense if you look at the two gamuts
202         // in xy space.
203         float expected_data[] = {
204                 // Black should stay black.
205                 0.0f, 0.0f, 0.0f, 1.0f,
206
207                 // White should stay white (both use the D65 white point).
208                 1.0f, 1.0f, 1.0f, 1.0f,
209
210                 // sRGB red is slightly out-of-gamut for Rec. 601/525.
211                 1.064f, -0.020f, 0.0f, 1.0f,
212
213                 // Green too.
214                 -0.055f, 1.036f, 0.004f, 1.0f,
215
216                 // The blues are much closer; it _is_ still out-of-gamut,
217                 // but not actually more saturated (farther from the
218                 // white point).
219                 -0.010f, -0.017f, 0.994f, 1.0f,
220
221                 // Cyan is a mix of green and blue. Note: The alpha is kept.
222                 -0.065f, 1.0195f, 0.998f, 0.5f,
223         };
224         float out_data[4 * 6];
225
226         EffectChainTester tester(data, 1, 6, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
227         tester.run(out_data, GL_RGBA, COLORSPACE_REC_601_525, GAMMA_LINEAR);
228
229         expect_equal(expected_data, out_data, 4, 6);
230 }