1 // Unit tests for ColorspaceConversionEffect.
5 #include "colorspace_conversion_effect.h"
6 #include "gtest/gtest.h"
11 TEST(ColorspaceConversionEffectTest, Reversible) {
13 0.0f, 0.0f, 0.0f, 1.0f,
14 1.0f, 1.0f, 1.0f, 1.0f,
15 1.0f, 0.0f, 0.0f, 1.0f,
16 0.0f, 1.0f, 0.0f, 1.0f,
17 0.0f, 0.0f, 1.0f, 1.0f,
18 0.0f, 1.0f, 1.0f, 0.5f,
20 float temp_data[4 * 6], out_data[4 * 6];
23 EffectChainTester tester(data, 1, 6, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
24 tester.run(temp_data, GL_RGBA, COLORSPACE_REC_601_525, GAMMA_LINEAR);
27 EffectChainTester tester(temp_data, 1, 6, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_REC_601_525, GAMMA_LINEAR);
28 tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
31 expect_equal(data, out_data, 4, 6);
34 TEST(ColorspaceConversionEffectTest, sRGB_Primaries) {
36 0.0f, 0.0f, 0.0f, 1.0f,
37 1.0f, 1.0f, 1.0f, 1.0f,
38 1.0f, 0.0f, 0.0f, 1.0f,
39 0.0f, 1.0f, 0.0f, 1.0f,
40 0.0f, 0.0f, 1.0f, 1.0f,
42 float out_data[4 * 5];
44 EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
45 tester.run(out_data, GL_RGBA, COLORSPACE_XYZ, GAMMA_LINEAR);
47 // Black should stay black.
48 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 0]);
49 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 1]);
50 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 2]);
51 EXPECT_FLOAT_EQ(1.0f, out_data[0 * 4 + 3]);
53 // White point should be D65.
54 // XYZ values from http://en.wikipedia.org/wiki/CIE_Standard_Illuminant_D65.
55 EXPECT_NEAR(0.9505, out_data[1 * 4 + 0], 1e-3);
56 EXPECT_NEAR(1.0000, out_data[1 * 4 + 1], 1e-3);
57 EXPECT_NEAR(1.0889, out_data[1 * 4 + 2], 1e-3);
58 EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
60 float white_xyz_sum = out_data[1 * 4 + 0] + out_data[1 * 4 + 1] + out_data[1 * 4 + 2];
61 float white_x = out_data[1 * 4 + 0] / white_xyz_sum;
62 float white_y = out_data[1 * 4 + 1] / white_xyz_sum;
63 EXPECT_NEAR(0.3127, white_x, 1e-3);
64 EXPECT_NEAR(0.3290, white_y, 1e-3);
65 EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
67 // Convert the primaries from XYZ to xyz, and compare to the references
68 // given by Rec. 709 (which are shared with sRGB).
70 float red_xyz_sum = out_data[2 * 4 + 0] + out_data[2 * 4 + 1] + out_data[2 * 4 + 2];
71 float red_x = out_data[2 * 4 + 0] / red_xyz_sum;
72 float red_y = out_data[2 * 4 + 1] / red_xyz_sum;
73 EXPECT_NEAR(0.640, red_x, 1e-3);
74 EXPECT_NEAR(0.330, red_y, 1e-3);
75 EXPECT_FLOAT_EQ(1.0f, out_data[2 * 4 + 3]);
77 float green_xyz_sum = out_data[3 * 4 + 0] + out_data[3 * 4 + 1] + out_data[3 * 4 + 2];
78 float green_x = out_data[3 * 4 + 0] / green_xyz_sum;
79 float green_y = out_data[3 * 4 + 1] / green_xyz_sum;
80 EXPECT_NEAR(0.300, green_x, 1e-3);
81 EXPECT_NEAR(0.600, green_y, 1e-3);
82 EXPECT_FLOAT_EQ(1.0f, out_data[3 * 4 + 3]);
84 float blue_xyz_sum = out_data[4 * 4 + 0] + out_data[4 * 4 + 1] + out_data[4 * 4 + 2];
85 float blue_x = out_data[4 * 4 + 0] / blue_xyz_sum;
86 float blue_y = out_data[4 * 4 + 1] / blue_xyz_sum;
87 EXPECT_NEAR(0.150, blue_x, 1e-3);
88 EXPECT_NEAR(0.060, blue_y, 1e-3);
89 EXPECT_FLOAT_EQ(1.0f, out_data[4 * 4 + 3]);
92 TEST(ColorspaceConversionEffectTest, Rec601_525_Primaries) {
94 0.0f, 0.0f, 0.0f, 1.0f,
95 1.0f, 1.0f, 1.0f, 1.0f,
96 1.0f, 0.0f, 0.0f, 1.0f,
97 0.0f, 1.0f, 0.0f, 1.0f,
98 0.0f, 0.0f, 1.0f, 1.0f,
100 float out_data[4 * 5];
102 EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_REC_601_525, GAMMA_LINEAR);
103 tester.run(out_data, GL_RGBA, COLORSPACE_XYZ, GAMMA_LINEAR);
105 // Black should stay black.
106 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 0]);
107 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 1]);
108 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 2]);
109 EXPECT_FLOAT_EQ(1.0f, out_data[0 * 4 + 3]);
111 // Convert the primaries from XYZ to xyz, and compare to the references
112 // given by Rec. 601.
113 float white_xyz_sum = out_data[1 * 4 + 0] + out_data[1 * 4 + 1] + out_data[1 * 4 + 2];
114 float white_x = out_data[1 * 4 + 0] / white_xyz_sum;
115 float white_y = out_data[1 * 4 + 1] / white_xyz_sum;
116 EXPECT_NEAR(0.3127, white_x, 1e-3);
117 EXPECT_NEAR(0.3290, white_y, 1e-3);
118 EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
120 float red_xyz_sum = out_data[2 * 4 + 0] + out_data[2 * 4 + 1] + out_data[2 * 4 + 2];
121 float red_x = out_data[2 * 4 + 0] / red_xyz_sum;
122 float red_y = out_data[2 * 4 + 1] / red_xyz_sum;
123 EXPECT_NEAR(0.630, red_x, 1e-3);
124 EXPECT_NEAR(0.340, red_y, 1e-3);
125 EXPECT_FLOAT_EQ(1.0f, out_data[2 * 4 + 3]);
127 float green_xyz_sum = out_data[3 * 4 + 0] + out_data[3 * 4 + 1] + out_data[3 * 4 + 2];
128 float green_x = out_data[3 * 4 + 0] / green_xyz_sum;
129 float green_y = out_data[3 * 4 + 1] / green_xyz_sum;
130 EXPECT_NEAR(0.310, green_x, 1e-3);
131 EXPECT_NEAR(0.595, green_y, 1e-3);
132 EXPECT_FLOAT_EQ(1.0f, out_data[3 * 4 + 3]);
134 float blue_xyz_sum = out_data[4 * 4 + 0] + out_data[4 * 4 + 1] + out_data[4 * 4 + 2];
135 float blue_x = out_data[4 * 4 + 0] / blue_xyz_sum;
136 float blue_y = out_data[4 * 4 + 1] / blue_xyz_sum;
137 EXPECT_NEAR(0.155, blue_x, 1e-3);
138 EXPECT_NEAR(0.070, blue_y, 1e-3);
139 EXPECT_FLOAT_EQ(1.0f, out_data[4 * 4 + 3]);
142 TEST(ColorspaceConversionEffectTest, Rec601_625_Primaries) {
144 0.0f, 0.0f, 0.0f, 1.0f,
145 1.0f, 1.0f, 1.0f, 1.0f,
146 1.0f, 0.0f, 0.0f, 1.0f,
147 0.0f, 1.0f, 0.0f, 1.0f,
148 0.0f, 0.0f, 1.0f, 1.0f,
150 float out_data[4 * 5];
152 EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_REC_601_625, GAMMA_LINEAR);
153 tester.run(out_data, GL_RGBA, COLORSPACE_XYZ, GAMMA_LINEAR);
155 // Black should stay black.
156 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 0]);
157 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 1]);
158 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 2]);
159 EXPECT_FLOAT_EQ(1.0f, out_data[0 * 4 + 3]);
161 // Convert the primaries from XYZ to xyz, and compare to the references
162 // given by Rec. 601.
163 float white_xyz_sum = out_data[1 * 4 + 0] + out_data[1 * 4 + 1] + out_data[1 * 4 + 2];
164 float white_x = out_data[1 * 4 + 0] / white_xyz_sum;
165 float white_y = out_data[1 * 4 + 1] / white_xyz_sum;
166 EXPECT_NEAR(0.3127, white_x, 1e-3);
167 EXPECT_NEAR(0.3290, white_y, 1e-3);
168 EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
170 float red_xyz_sum = out_data[2 * 4 + 0] + out_data[2 * 4 + 1] + out_data[2 * 4 + 2];
171 float red_x = out_data[2 * 4 + 0] / red_xyz_sum;
172 float red_y = out_data[2 * 4 + 1] / red_xyz_sum;
173 EXPECT_NEAR(0.640, red_x, 1e-3);
174 EXPECT_NEAR(0.330, red_y, 1e-3);
175 EXPECT_FLOAT_EQ(1.0f, out_data[2 * 4 + 3]);
177 float green_xyz_sum = out_data[3 * 4 + 0] + out_data[3 * 4 + 1] + out_data[3 * 4 + 2];
178 float green_x = out_data[3 * 4 + 0] / green_xyz_sum;
179 float green_y = out_data[3 * 4 + 1] / green_xyz_sum;
180 EXPECT_NEAR(0.290, green_x, 1e-3);
181 EXPECT_NEAR(0.600, green_y, 1e-3);
182 EXPECT_FLOAT_EQ(1.0f, out_data[3 * 4 + 3]);
184 float blue_xyz_sum = out_data[4 * 4 + 0] + out_data[4 * 4 + 1] + out_data[4 * 4 + 2];
185 float blue_x = out_data[4 * 4 + 0] / blue_xyz_sum;
186 float blue_y = out_data[4 * 4 + 1] / blue_xyz_sum;
187 EXPECT_NEAR(0.150, blue_x, 1e-3);
188 EXPECT_NEAR(0.060, blue_y, 1e-3);
189 EXPECT_FLOAT_EQ(1.0f, out_data[4 * 4 + 3]);
192 TEST(ColorspaceConversionEffectTest, Rec2020_Primaries) {
194 0.0f, 0.0f, 0.0f, 1.0f,
195 1.0f, 1.0f, 1.0f, 1.0f,
196 1.0f, 0.0f, 0.0f, 1.0f,
197 0.0f, 1.0f, 0.0f, 1.0f,
198 0.0f, 0.0f, 1.0f, 1.0f,
200 float out_data[4 * 5];
202 EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_REC_2020, GAMMA_LINEAR);
203 tester.run(out_data, GL_RGBA, COLORSPACE_XYZ, GAMMA_LINEAR);
205 // Black should stay black.
206 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 0]);
207 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 1]);
208 EXPECT_FLOAT_EQ(0.0f, out_data[0 * 4 + 2]);
209 EXPECT_FLOAT_EQ(1.0f, out_data[0 * 4 + 3]);
211 // Convert the primaries from XYZ to xyz, and compare to the references
212 // given by Rec. 2020.
213 float white_xyz_sum = out_data[1 * 4 + 0] + out_data[1 * 4 + 1] + out_data[1 * 4 + 2];
214 float white_x = out_data[1 * 4 + 0] / white_xyz_sum;
215 float white_y = out_data[1 * 4 + 1] / white_xyz_sum;
216 EXPECT_NEAR(0.3127, white_x, 1e-3);
217 EXPECT_NEAR(0.3290, white_y, 1e-3);
218 EXPECT_FLOAT_EQ(1.0f, out_data[1 * 4 + 3]);
220 float red_xyz_sum = out_data[2 * 4 + 0] + out_data[2 * 4 + 1] + out_data[2 * 4 + 2];
221 float red_x = out_data[2 * 4 + 0] / red_xyz_sum;
222 float red_y = out_data[2 * 4 + 1] / red_xyz_sum;
223 EXPECT_NEAR(0.708, red_x, 1e-3);
224 EXPECT_NEAR(0.292, red_y, 1e-3);
225 EXPECT_FLOAT_EQ(1.0f, out_data[2 * 4 + 3]);
227 float green_xyz_sum = out_data[3 * 4 + 0] + out_data[3 * 4 + 1] + out_data[3 * 4 + 2];
228 float green_x = out_data[3 * 4 + 0] / green_xyz_sum;
229 float green_y = out_data[3 * 4 + 1] / green_xyz_sum;
230 EXPECT_NEAR(0.170, green_x, 1e-3);
231 EXPECT_NEAR(0.797, green_y, 1e-3);
232 EXPECT_FLOAT_EQ(1.0f, out_data[3 * 4 + 3]);
234 float blue_xyz_sum = out_data[4 * 4 + 0] + out_data[4 * 4 + 1] + out_data[4 * 4 + 2];
235 float blue_x = out_data[4 * 4 + 0] / blue_xyz_sum;
236 float blue_y = out_data[4 * 4 + 1] / blue_xyz_sum;
237 EXPECT_NEAR(0.131, blue_x, 1e-3);
238 EXPECT_NEAR(0.046, blue_y, 1e-3);
239 EXPECT_FLOAT_EQ(1.0f, out_data[4 * 4 + 3]);
242 TEST(ColorspaceConversionEffectTest, sRGBToRec601_525) {
244 0.0f, 0.0f, 0.0f, 1.0f,
245 1.0f, 1.0f, 1.0f, 1.0f,
246 1.0f, 0.0f, 0.0f, 1.0f,
247 0.0f, 1.0f, 0.0f, 1.0f,
248 0.0f, 0.0f, 1.0f, 1.0f,
249 0.0f, 1.0f, 1.0f, 0.5f,
252 // I have to admit that most of these come from the code itself;
253 // however, they do make sense if you look at the two gamuts
255 float expected_data[] = {
256 // Black should stay black.
257 0.0f, 0.0f, 0.0f, 1.0f,
259 // White should stay white (both use the D65 white point).
260 1.0f, 1.0f, 1.0f, 1.0f,
262 // sRGB red is slightly out-of-gamut for Rec. 601/525.
263 1.064f, -0.020f, 0.0f, 1.0f,
266 -0.055f, 1.036f, 0.004f, 1.0f,
268 // The blues are much closer; it _is_ still out-of-gamut,
269 // but not actually more saturated (farther from the
271 -0.010f, -0.017f, 0.994f, 1.0f,
273 // Cyan is a mix of green and blue. Note: The alpha is kept.
274 -0.065f, 1.0195f, 0.998f, 0.5f,
276 float out_data[4 * 6];
278 EffectChainTester tester(data, 1, 6, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
279 tester.run(out_data, GL_RGBA, COLORSPACE_REC_601_525, GAMMA_LINEAR);
281 expect_equal(expected_data, out_data, 4, 6);