]> git.sesse.net Git - movit/blob - colorspace_conversion_effect_test.cpp
Add a shared ResourcePool to share resources between EffectChains.
[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, Rec2020_Primaries) {
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         };
198         float out_data[4 * 5];
199
200         EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_REC_2020, GAMMA_LINEAR);
201         tester.run(out_data, GL_RGBA, COLORSPACE_XYZ, GAMMA_LINEAR);
202
203         // Black should stay black.
204         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 0]);
205         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 1]);
206         EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 2]);
207         EXPECT_FLOAT_EQ(1.0f, out_data[0 * 4 + 3]);
208
209         // Convert the primaries from XYZ to xyz, and compare to the references
210         // given by Rec. 2020.
211         float white_xyz_sum = out_data[1 * 4 + 0] + out_data[1 * 4 + 1] + out_data[1 * 4 + 2];
212         float white_x = out_data[1 * 4 + 0] / white_xyz_sum;
213         float white_y = out_data[1 * 4 + 1] / white_xyz_sum;
214         EXPECT_NEAR(0.3127, white_x, 1e-3);
215         EXPECT_NEAR(0.3290, white_y, 1e-3);
216         EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
217
218         float red_xyz_sum = out_data[2 * 4 + 0] + out_data[2 * 4 + 1] + out_data[2 * 4 + 2];
219         float red_x = out_data[2 * 4 + 0] / red_xyz_sum;
220         float red_y = out_data[2 * 4 + 1] / red_xyz_sum;
221         EXPECT_NEAR(0.708, red_x, 1e-3);
222         EXPECT_NEAR(0.292, red_y, 1e-3);
223         EXPECT_FLOAT_EQ(1.0f, out_data[2 * 4 + 3]);
224
225         float green_xyz_sum = out_data[3 * 4 + 0] + out_data[3 * 4 + 1] + out_data[3 * 4 + 2];
226         float green_x = out_data[3 * 4 + 0] / green_xyz_sum;
227         float green_y = out_data[3 * 4 + 1] / green_xyz_sum;
228         EXPECT_NEAR(0.170, green_x, 1e-3);
229         EXPECT_NEAR(0.797, green_y, 1e-3);
230         EXPECT_FLOAT_EQ(1.0f, out_data[3 * 4 + 3]);
231
232         float blue_xyz_sum = out_data[4 * 4 + 0] + out_data[4 * 4 + 1] + out_data[4 * 4 + 2];
233         float blue_x = out_data[4 * 4 + 0] / blue_xyz_sum;
234         float blue_y = out_data[4 * 4 + 1] / blue_xyz_sum;
235         EXPECT_NEAR(0.131, blue_x, 1e-3);
236         EXPECT_NEAR(0.046, blue_y, 1e-3);
237         EXPECT_FLOAT_EQ(1.0f, out_data[4 * 4 + 3]);
238 }
239
240 TEST(ColorspaceConversionEffectTest, sRGBToRec601_525) {
241         float data[] = {
242                 0.0f, 0.0f, 0.0f, 1.0f,
243                 1.0f, 1.0f, 1.0f, 1.0f,
244                 1.0f, 0.0f, 0.0f, 1.0f,
245                 0.0f, 1.0f, 0.0f, 1.0f,
246                 0.0f, 0.0f, 1.0f, 1.0f,
247                 0.0f, 1.0f, 1.0f, 0.5f,
248         };
249
250         // I have to admit that most of these come from the code itself;
251         // however, they do make sense if you look at the two gamuts
252         // in xy space.
253         float expected_data[] = {
254                 // Black should stay black.
255                 0.0f, 0.0f, 0.0f, 1.0f,
256
257                 // White should stay white (both use the D65 white point).
258                 1.0f, 1.0f, 1.0f, 1.0f,
259
260                 // sRGB red is slightly out-of-gamut for Rec. 601/525.
261                 1.064f, -0.020f, 0.0f, 1.0f,
262
263                 // Green too.
264                 -0.055f, 1.036f, 0.004f, 1.0f,
265
266                 // The blues are much closer; it _is_ still out-of-gamut,
267                 // but not actually more saturated (farther from the
268                 // white point).
269                 -0.010f, -0.017f, 0.994f, 1.0f,
270
271                 // Cyan is a mix of green and blue. Note: The alpha is kept.
272                 -0.065f, 1.0195f, 0.998f, 0.5f,
273         };
274         float out_data[4 * 6];
275
276         EffectChainTester tester(data, 1, 6, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
277         tester.run(out_data, GL_RGBA, COLORSPACE_REC_601_525, GAMMA_LINEAR);
278
279         expect_equal(expected_data, out_data, 4, 6);
280 }