1 // Unit tests for ColorspaceConversionEffect.
5 #include "colorspace_conversion_effect.h"
6 #include "gtest/gtest.h"
9 TEST(ColorspaceConversionEffectTest, Reversible) {
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,
18 float temp_data[4 * 6], out_data[4 * 6];
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);
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);
29 expect_equal(data, out_data, 4, 6);
32 TEST(ColorspaceConversionEffectTest, sRGB_Primaries) {
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,
40 float out_data[4 * 5];
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);
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]);
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]);
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]);
65 // Convert the primaries from XYZ to xyz, and compare to the references
66 // given by Rec. 709 (which are shared with sRGB).
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]);
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]);
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]);
90 TEST(ColorspaceConversionEffectTest, Rec601_525_Primaries) {
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,
98 float out_data[4 * 5];
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);
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]);
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]);
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]);
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]);
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]);
140 TEST(ColorspaceConversionEffectTest, Rec601_625_Primaries) {
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,
148 float out_data[4 * 5];
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);
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]);
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]);
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]);
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]);
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]);
190 TEST(ColorspaceConversionEffectTest, Rec2020_Primaries) {
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,
198 float out_data[4 * 5];
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);
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]);
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]);
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]);
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]);
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]);
240 TEST(ColorspaceConversionEffectTest, sRGBToRec601_525) {
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,
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
253 float expected_data[] = {
254 // Black should stay black.
255 0.0f, 0.0f, 0.0f, 1.0f,
257 // White should stay white (both use the D65 white point).
258 1.0f, 1.0f, 1.0f, 1.0f,
260 // sRGB red is slightly out-of-gamut for Rec. 601/525.
261 1.064f, -0.020f, 0.0f, 1.0f,
264 -0.055f, 1.036f, 0.004f, 1.0f,
266 // The blues are much closer; it _is_ still out-of-gamut,
267 // but not actually more saturated (farther from the
269 -0.010f, -0.017f, 0.994f, 1.0f,
271 // Cyan is a mix of green and blue. Note: The alpha is kept.
272 -0.065f, 1.0195f, 0.998f, 0.5f,
274 float out_data[4 * 6];
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);
279 expect_equal(expected_data, out_data, 4, 6);