1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.graphics.cts; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertNull; 22 import static org.junit.Assert.assertSame; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 26 import android.graphics.ColorSpace; 27 import android.hardware.DataSpace; 28 import android.platform.test.annotations.RequiresFlagsEnabled; 29 import android.platform.test.flag.junit.CheckFlagsRule; 30 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 31 import android.util.Log; 32 33 import androidx.test.filters.SmallTest; 34 35 import com.android.graphics.flags.Flags; 36 37 import junitparams.JUnitParamsRunner; 38 import junitparams.Parameters; 39 40 import org.junit.Rule; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 44 import java.util.Arrays; 45 import java.util.HashSet; 46 import java.util.function.DoubleUnaryOperator; 47 48 @SmallTest 49 @RunWith(JUnitParamsRunner.class) 50 public class ColorSpaceTest { 51 52 @Rule 53 public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); 54 55 // Column-major RGB->XYZ transform matrix for the sRGB color space 56 private static final float[] SRGB_TO_XYZ = { 57 0.412391f, 0.212639f, 0.019331f, 58 0.357584f, 0.715169f, 0.119195f, 59 0.180481f, 0.072192f, 0.950532f 60 }; 61 // Column-major XYZ->RGB transform matrix for the sRGB color space 62 private static final float[] XYZ_TO_SRGB = { 63 3.240970f, -0.969244f, 0.055630f, 64 -1.537383f, 1.875968f, -0.203977f, 65 -0.498611f, 0.041555f, 1.056971f 66 }; 67 68 // Column-major RGB->XYZ transform matrix for the sRGB color space and a D50 white point 69 private static final float[] SRGB_TO_XYZ_D50 = { 70 0.4360747f, 0.2225045f, 0.0139322f, 71 0.3850649f, 0.7168786f, 0.0971045f, 72 0.1430804f, 0.0606169f, 0.7141733f 73 }; 74 75 private static final float[] SRGB_PRIMARIES_xyY = 76 { 0.640f, 0.330f, 0.300f, 0.600f, 0.150f, 0.060f }; 77 private static final float[] SRGB_WHITE_POINT_xyY = { 0.3127f, 0.3290f }; 78 79 private static final float[] SRGB_PRIMARIES_XYZ = { 80 1.939394f, 1.000000f, 0.090909f, 81 0.500000f, 1.000000f, 0.166667f, 82 2.500000f, 1.000000f, 13.166667f 83 }; 84 private static final float[] SRGB_WHITE_POINT_XYZ = { 0.950456f, 1.000f, 1.089058f }; 85 86 private static final DoubleUnaryOperator sIdentity = DoubleUnaryOperator.identity(); 87 88 private static final HashSet<ColorSpace.Named> ALLOWED_NAMED_COLORSPACES = 89 new HashSet<>(Arrays.asList( 90 ColorSpace.Named.SRGB, 91 ColorSpace.Named.LINEAR_SRGB, 92 ColorSpace.Named.EXTENDED_SRGB, 93 ColorSpace.Named.LINEAR_EXTENDED_SRGB, 94 ColorSpace.Named.BT709, 95 ColorSpace.Named.BT2020, 96 ColorSpace.Named.DCI_P3, 97 ColorSpace.Named.DISPLAY_P3, 98 ColorSpace.Named.NTSC_1953, 99 ColorSpace.Named.SMPTE_C, 100 ColorSpace.Named.ADOBE_RGB, 101 ColorSpace.Named.PRO_PHOTO_RGB, 102 ColorSpace.Named.ACES, 103 ColorSpace.Named.ACESCG, 104 ColorSpace.Named.CIE_XYZ, 105 ColorSpace.Named.CIE_LAB, 106 ColorSpace.Named.BT2020_HLG, 107 ColorSpace.Named.BT2020_PQ)); 108 static { 109 if (Flags.okLabColorspace()) { 110 ALLOWED_NAMED_COLORSPACES.add(ColorSpace.Named.OK_LAB); 111 } 112 113 if (Flags.displayBt2020Colorspace()) { 114 ALLOWED_NAMED_COLORSPACES.add(ColorSpace.Named.DISPLAY_BT2020); 115 } 116 } 117 118 @Test testNamedColorSpaces()119 public void testNamedColorSpaces() { 120 for (ColorSpace.Named named : ALLOWED_NAMED_COLORSPACES) { 121 ColorSpace colorSpace = ColorSpace.get(named); 122 Log.v("ResolvedColorSpace", "ColorSpace: " + colorSpace); 123 assertNotNull(colorSpace.getName()); 124 assertNotNull(colorSpace); 125 assertEquals(named.ordinal(), colorSpace.getId()); 126 assertTrue(colorSpace.getComponentCount() >= 1); 127 assertTrue(colorSpace.getComponentCount() <= 4); 128 } 129 } 130 131 @Test(expected = IllegalArgumentException.class) testNullName()132 public void testNullName() { 133 new ColorSpace.Rgb(null, new float[6], new float[2], sIdentity, sIdentity, 0.0f, 1.0f); 134 } 135 136 @Test(expected = IllegalArgumentException.class) testEmptyName()137 public void testEmptyName() { 138 new ColorSpace.Rgb("", new float[6], new float[2], sIdentity, sIdentity, 0.0f, 1.0f); 139 } 140 141 @Test testName()142 public void testName() { 143 ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", new float[6], new float[2], 144 sIdentity, sIdentity, 0.0f, 1.0f); 145 assertEquals("Test", cs.getName()); 146 } 147 148 @Test(expected = IllegalArgumentException.class) testPrimariesLength()149 public void testPrimariesLength() { 150 new ColorSpace.Rgb("Test", new float[7], new float[2], sIdentity, sIdentity, 0.0f, 1.0f); 151 } 152 153 @Test(expected = IllegalArgumentException.class) testWhitePointLength()154 public void testWhitePointLength() { 155 new ColorSpace.Rgb("Test", new float[6], new float[1], sIdentity, sIdentity, 0.0f, 1.0f); 156 } 157 158 @Test(expected = IllegalArgumentException.class) testNullOETF()159 public void testNullOETF() { 160 new ColorSpace.Rgb("Test", new float[6], new float[2], null, sIdentity, 0.0f, 1.0f); 161 } 162 163 @Test testOETF()164 public void testOETF() { 165 DoubleUnaryOperator op = Math::sqrt; 166 ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", new float[6], new float[2], 167 op, sIdentity, 0.0f, 1.0f); 168 assertEquals(0.5, cs.getOetf().applyAsDouble(0.25), 1e-5); 169 } 170 171 @Test(expected = IllegalArgumentException.class) testNullEOTF()172 public void testNullEOTF() { 173 new ColorSpace.Rgb("Test", new float[6], new float[2], sIdentity, null, 0.0f, 1.0f); 174 } 175 176 @Test testEOTF()177 public void testEOTF() { 178 DoubleUnaryOperator op = x -> x * x; 179 ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", new float[6], new float[2], 180 sIdentity, op, 0.0f, 1.0f); 181 assertEquals(0.0625, cs.getEotf().applyAsDouble(0.25), 1e-5); 182 } 183 184 @Test(expected = IllegalArgumentException.class) testInvalidRange()185 public void testInvalidRange() { 186 new ColorSpace.Rgb("Test", new float[6], new float[2], sIdentity, sIdentity, 2.0f, 1.0f); 187 } 188 189 @Test testRanges()190 public void testRanges() { 191 ColorSpace cs = ColorSpace.get(ColorSpace.Named.SRGB); 192 193 float m1 = cs.getMinValue(0); 194 float m2 = cs.getMinValue(1); 195 float m3 = cs.getMinValue(2); 196 197 assertEquals(0.0f, m1, 1e-9f); 198 assertEquals(0.0f, m2, 1e-9f); 199 assertEquals(0.0f, m3, 1e-9f); 200 201 m1 = cs.getMaxValue(0); 202 m2 = cs.getMaxValue(1); 203 m3 = cs.getMaxValue(2); 204 205 assertEquals(1.0f, m1, 1e-9f); 206 assertEquals(1.0f, m2, 1e-9f); 207 assertEquals(1.0f, m3, 1e-9f); 208 209 cs = ColorSpace.get(ColorSpace.Named.CIE_LAB); 210 211 m1 = cs.getMinValue(0); 212 m2 = cs.getMinValue(1); 213 m3 = cs.getMinValue(2); 214 215 assertEquals(0.0f, m1, 1e-9f); 216 assertEquals(-128.0f, m2, 1e-9f); 217 assertEquals(-128.0f, m3, 1e-9f); 218 219 m1 = cs.getMaxValue(0); 220 m2 = cs.getMaxValue(1); 221 m3 = cs.getMaxValue(2); 222 223 assertEquals(100.0f, m1, 1e-9f); 224 assertEquals(128.0f, m2, 1e-9f); 225 assertEquals(128.0f, m3, 1e-9f); 226 227 cs = ColorSpace.get(ColorSpace.Named.CIE_XYZ); 228 229 m1 = cs.getMinValue(0); 230 m2 = cs.getMinValue(1); 231 m3 = cs.getMinValue(2); 232 233 assertEquals(-2.0f, m1, 1e-9f); 234 assertEquals(-2.0f, m2, 1e-9f); 235 assertEquals(-2.0f, m3, 1e-9f); 236 237 m1 = cs.getMaxValue(0); 238 m2 = cs.getMaxValue(1); 239 m3 = cs.getMaxValue(2); 240 241 assertEquals(2.0f, m1, 1e-9f); 242 assertEquals(2.0f, m2, 1e-9f); 243 assertEquals(2.0f, m3, 1e-9f); 244 245 if (Flags.okLabColorspace()) { 246 cs = ColorSpace.get(ColorSpace.Named.OK_LAB); 247 248 m1 = cs.getMinValue(0); 249 m2 = cs.getMinValue(1); 250 m3 = cs.getMinValue(2); 251 252 assertEquals(0f, m1, 1e-9f); 253 assertEquals(-0.5f, m2, 1e-9f); 254 assertEquals(-0.5f, m3, 1e-9f); 255 256 m1 = cs.getMaxValue(0); 257 m2 = cs.getMaxValue(1); 258 m3 = cs.getMaxValue(2); 259 260 assertEquals(1f, m1, 1e-9f); 261 assertEquals(0.5f, m2, 1e-9f); 262 assertEquals(0.5f, m3, 1e-9f); 263 } 264 } 265 266 @Test testMat3x3()267 public void testMat3x3() { 268 ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_TO_XYZ, sIdentity, sIdentity); 269 270 float[] rgbToXYZ = cs.getTransform(); 271 for (int i = 0; i < 9; i++) { 272 assertEquals(SRGB_TO_XYZ[i], rgbToXYZ[i], 1e-5f); 273 } 274 } 275 276 @Test testMat3x3Inverse()277 public void testMat3x3Inverse() { 278 ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_TO_XYZ, sIdentity, sIdentity); 279 280 float[] xyzToRGB = cs.getInverseTransform(); 281 for (int i = 0; i < 9; i++) { 282 assertEquals(XYZ_TO_SRGB[i], xyzToRGB[i], 1e-5f); 283 } 284 } 285 286 @Test testMat3x3Primaries()287 public void testMat3x3Primaries() { 288 ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_TO_XYZ, sIdentity, sIdentity); 289 290 float[] primaries = cs.getPrimaries(); 291 292 assertNotNull(primaries); 293 assertEquals(6, primaries.length); 294 295 assertEquals(SRGB_PRIMARIES_xyY[0], primaries[0], 1e-5f); 296 assertEquals(SRGB_PRIMARIES_xyY[1], primaries[1], 1e-5f); 297 assertEquals(SRGB_PRIMARIES_xyY[2], primaries[2], 1e-5f); 298 assertEquals(SRGB_PRIMARIES_xyY[3], primaries[3], 1e-5f); 299 assertEquals(SRGB_PRIMARIES_xyY[4], primaries[4], 1e-5f); 300 assertEquals(SRGB_PRIMARIES_xyY[5], primaries[5], 1e-5f); 301 } 302 303 @Test testMat3x3WhitePoint()304 public void testMat3x3WhitePoint() { 305 ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_TO_XYZ, sIdentity, sIdentity); 306 307 float[] whitePoint = cs.getWhitePoint(); 308 309 assertNotNull(whitePoint); 310 assertEquals(2, whitePoint.length); 311 312 assertEquals(SRGB_WHITE_POINT_xyY[0], whitePoint[0], 1e-5f); 313 assertEquals(SRGB_WHITE_POINT_xyY[1], whitePoint[1], 1e-5f); 314 } 315 316 @Test testXYZFromPrimaries_xyY()317 public void testXYZFromPrimaries_xyY() { 318 ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_PRIMARIES_xyY, SRGB_WHITE_POINT_xyY, 319 sIdentity, sIdentity, 0.0f, 1.0f); 320 321 float[] rgbToXYZ = cs.getTransform(); 322 for (int i = 0; i < 9; i++) { 323 assertEquals(SRGB_TO_XYZ[i], rgbToXYZ[i], 1e-5f); 324 } 325 326 float[] xyzToRGB = cs.getInverseTransform(); 327 for (int i = 0; i < 9; i++) { 328 assertEquals(XYZ_TO_SRGB[i], xyzToRGB[i], 1e-5f); 329 } 330 } 331 332 @Test testXYZFromPrimaries_XYZ()333 public void testXYZFromPrimaries_XYZ() { 334 ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_PRIMARIES_XYZ, SRGB_WHITE_POINT_XYZ, 335 sIdentity, sIdentity, 0.0f, 1.0f); 336 337 float[] primaries = cs.getPrimaries(); 338 339 assertNotNull(primaries); 340 assertEquals(6, primaries.length); 341 342 // SRGB_PRIMARIES_xyY only has 1e-3 of precision, match it 343 assertEquals(SRGB_PRIMARIES_xyY[0], primaries[0], 1e-3f); 344 assertEquals(SRGB_PRIMARIES_xyY[1], primaries[1], 1e-3f); 345 assertEquals(SRGB_PRIMARIES_xyY[2], primaries[2], 1e-3f); 346 assertEquals(SRGB_PRIMARIES_xyY[3], primaries[3], 1e-3f); 347 assertEquals(SRGB_PRIMARIES_xyY[4], primaries[4], 1e-3f); 348 assertEquals(SRGB_PRIMARIES_xyY[5], primaries[5], 1e-3f); 349 350 float[] whitePoint = cs.getWhitePoint(); 351 352 assertNotNull(whitePoint); 353 assertEquals(2, whitePoint.length); 354 355 // SRGB_WHITE_POINT_xyY only has 1e-3 of precision, match it 356 assertEquals(SRGB_WHITE_POINT_xyY[0], whitePoint[0], 1e-3f); 357 assertEquals(SRGB_WHITE_POINT_xyY[1], whitePoint[1], 1e-3f); 358 359 float[] rgbToXYZ = cs.getTransform(); 360 for (int i = 0; i < 9; i++) { 361 assertEquals(SRGB_TO_XYZ[i], rgbToXYZ[i], 1e-5f); 362 } 363 364 float[] xyzToRGB = cs.getInverseTransform(); 365 for (int i = 0; i < 9; i++) { 366 assertEquals(XYZ_TO_SRGB[i], xyzToRGB[i], 1e-5f); 367 } 368 } 369 370 @Test testGetComponentCount()371 public void testGetComponentCount() { 372 assertEquals(3, ColorSpace.get(ColorSpace.Named.SRGB).getComponentCount()); 373 assertEquals(3, ColorSpace.get(ColorSpace.Named.LINEAR_SRGB).getComponentCount()); 374 assertEquals(3, ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB).getComponentCount()); 375 assertEquals(3, ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB).getComponentCount()); 376 assertEquals(3, ColorSpace.get(ColorSpace.Named.DISPLAY_P3).getComponentCount()); 377 assertEquals(3, ColorSpace.get(ColorSpace.Named.CIE_LAB).getComponentCount()); 378 assertEquals(3, ColorSpace.get(ColorSpace.Named.CIE_XYZ).getComponentCount()); 379 if (Flags.okLabColorspace()) { 380 assertEquals(3, ColorSpace.get(ColorSpace.Named.OK_LAB).getComponentCount()); 381 } 382 } 383 384 @Test testIsSRGB()385 public void testIsSRGB() { 386 for (ColorSpace.Named e : ColorSpace.Named.values()) { 387 ColorSpace colorSpace = ColorSpace.get(e); 388 // ColorSpace.get is guaranteed to return non-null. So if this is queried with 389 // a ColorSpace that is flagged, this falls back to return SRGB as a default. 390 // The values method of an enum will always return the full set of enum values 391 // regardless if they are flagged out or not 392 boolean isSrgbFallback = !ALLOWED_NAMED_COLORSPACES.contains(e); 393 if (e == ColorSpace.Named.SRGB || isSrgbFallback) { 394 assertTrue(colorSpace.isSrgb()); 395 } else { 396 assertFalse("Incorrectly treating " + e + " as SRGB!", 397 colorSpace.isSrgb()); 398 } 399 } 400 401 ColorSpace.Rgb cs = new ColorSpace.Rgb("Almost sRGB", SRGB_TO_XYZ, 402 x -> Math.pow(x, 1.0f / 2.2f), x -> Math.pow(x, 2.2f)); 403 assertFalse(cs.isSrgb()); 404 } 405 406 @Test testIsWideGamut()407 public void testIsWideGamut() { 408 assertFalse(ColorSpace.get(ColorSpace.Named.SRGB).isWideGamut()); 409 assertFalse(ColorSpace.get(ColorSpace.Named.BT709).isWideGamut()); 410 assertTrue(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB).isWideGamut()); 411 assertTrue(ColorSpace.get(ColorSpace.Named.DCI_P3).isWideGamut()); 412 assertTrue(ColorSpace.get(ColorSpace.Named.BT2020).isWideGamut()); 413 assertTrue(ColorSpace.get(ColorSpace.Named.ACES).isWideGamut()); 414 assertTrue(ColorSpace.get(ColorSpace.Named.CIE_LAB).isWideGamut()); 415 assertTrue(ColorSpace.get(ColorSpace.Named.CIE_XYZ).isWideGamut()); 416 if (Flags.okLabColorspace()) { 417 assertTrue(ColorSpace.get(ColorSpace.Named.OK_LAB).isWideGamut()); 418 } 419 } 420 421 @Test testWhitePoint()422 public void testWhitePoint() { 423 ColorSpace.Rgb cs = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); 424 425 float[] whitePoint = cs.getWhitePoint(); 426 427 assertNotNull(whitePoint); 428 assertEquals(2, whitePoint.length); 429 430 // Make sure a copy is returned 431 Arrays.fill(whitePoint, Float.NaN); 432 assertArrayNotEquals(whitePoint, cs.getWhitePoint(), 1e-5f); 433 assertSame(whitePoint, cs.getWhitePoint(whitePoint)); 434 assertArrayEquals(whitePoint, cs.getWhitePoint(), 1e-5f); 435 } 436 437 @Test testPrimaries()438 public void testPrimaries() { 439 ColorSpace.Rgb cs = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); 440 441 float[] primaries = cs.getPrimaries(); 442 443 assertNotNull(primaries); 444 assertEquals(6, primaries.length); 445 446 // Make sure a copy is returned 447 Arrays.fill(primaries, Float.NaN); 448 assertArrayNotEquals(primaries, cs.getPrimaries(), 1e-5f); 449 assertSame(primaries, cs.getPrimaries(primaries)); 450 assertArrayEquals(primaries, cs.getPrimaries(), 1e-5f); 451 } 452 453 @Test testRGBtoXYZMatrix()454 public void testRGBtoXYZMatrix() { 455 ColorSpace.Rgb cs = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); 456 457 float[] rgbToXYZ = cs.getTransform(); 458 459 assertNotNull(rgbToXYZ); 460 assertEquals(9, rgbToXYZ.length); 461 462 // Make sure a copy is returned 463 Arrays.fill(rgbToXYZ, Float.NaN); 464 assertArrayNotEquals(rgbToXYZ, cs.getTransform(), 1e-5f); 465 assertSame(rgbToXYZ, cs.getTransform(rgbToXYZ)); 466 assertArrayEquals(rgbToXYZ, cs.getTransform(), 1e-5f); 467 } 468 469 @Test testXYZtoRGBMatrix()470 public void testXYZtoRGBMatrix() { 471 ColorSpace.Rgb cs = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); 472 473 float[] xyzToRGB = cs.getInverseTransform(); 474 475 assertNotNull(xyzToRGB); 476 assertEquals(9, xyzToRGB.length); 477 478 // Make sure a copy is returned 479 Arrays.fill(xyzToRGB, Float.NaN); 480 assertArrayNotEquals(xyzToRGB, cs.getInverseTransform(), 1e-5f); 481 assertSame(xyzToRGB, cs.getInverseTransform(xyzToRGB)); 482 assertArrayEquals(xyzToRGB, cs.getInverseTransform(), 1e-5f); 483 } 484 485 @Test testRGBtoXYZ()486 public void testRGBtoXYZ() { 487 ColorSpace cs = ColorSpace.get(ColorSpace.Named.SRGB); 488 489 float[] source = { 0.75f, 0.5f, 0.25f }; 490 float[] expected = { 0.3012f, 0.2679f, 0.0840f }; 491 492 float[] r1 = cs.toXyz(source[0], source[1], source[2]); 493 assertNotNull(r1); 494 assertEquals(3, r1.length); 495 assertArrayNotEquals(source, r1, 1e-5f); 496 assertArrayEquals(expected, r1, 1e-3f); 497 498 float[] r3 = { source[0], source[1], source[2] }; 499 assertSame(r3, cs.toXyz(r3)); 500 assertEquals(3, r3.length); 501 assertArrayEquals(r1, r3, 1e-5f); 502 } 503 504 @Test testXYZtoRGB()505 public void testXYZtoRGB() { 506 ColorSpace cs = ColorSpace.get(ColorSpace.Named.SRGB); 507 508 float[] source = { 0.3012f, 0.2679f, 0.0840f }; 509 float[] expected = { 0.75f, 0.5f, 0.25f }; 510 511 float[] r1 = cs.fromXyz(source[0], source[1], source[2]); 512 assertNotNull(r1); 513 assertEquals(3, r1.length); 514 assertArrayNotEquals(source, r1, 1e-5f); 515 assertArrayEquals(expected, r1, 1e-3f); 516 517 float[] r3 = { source[0], source[1], source[2] }; 518 assertSame(r3, cs.fromXyz(r3)); 519 assertEquals(3, r3.length); 520 assertArrayEquals(r1, r3, 1e-5f); 521 } 522 523 @Test testConnect()524 public void testConnect() { 525 ColorSpace.Connector connector = ColorSpace.connect( 526 ColorSpace.get(ColorSpace.Named.SRGB), 527 ColorSpace.get(ColorSpace.Named.DCI_P3)); 528 529 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getSource()); 530 assertSame(ColorSpace.get(ColorSpace.Named.DCI_P3), connector.getDestination()); 531 assertSame(ColorSpace.RenderIntent.PERCEPTUAL, connector.getRenderIntent()); 532 533 connector = ColorSpace.connect( 534 ColorSpace.get(ColorSpace.Named.SRGB), 535 ColorSpace.get(ColorSpace.Named.SRGB)); 536 537 assertSame(connector.getDestination(), connector.getSource()); 538 assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent()); 539 540 connector = ColorSpace.connect(ColorSpace.get(ColorSpace.Named.DCI_P3)); 541 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getDestination()); 542 543 connector = ColorSpace.connect(ColorSpace.get(ColorSpace.Named.SRGB)); 544 assertSame(connector.getSource(), connector.getDestination()); 545 } 546 547 @Test testConnector()548 public void testConnector() { 549 // Connect color spaces with same white points 550 ColorSpace.Connector connector = ColorSpace.connect( 551 ColorSpace.get(ColorSpace.Named.SRGB), 552 ColorSpace.get(ColorSpace.Named.ADOBE_RGB)); 553 554 float[] source = { 1.0f, 0.5f, 0.0f }; 555 float[] expected = { 0.8912f, 0.4962f, 0.1164f }; 556 557 float[] r1 = connector.transform(source[0], source[1], source[2]); 558 assertNotNull(r1); 559 assertEquals(3, r1.length); 560 assertArrayNotEquals(source, r1, 1e-5f); 561 assertArrayEquals(expected, r1, 1e-3f); 562 563 float[] r3 = { source[0], source[1], source[2] }; 564 assertSame(r3, connector.transform(r3)); 565 assertEquals(3, r3.length); 566 assertArrayEquals(r1, r3, 1e-5f); 567 568 connector = ColorSpace.connect( 569 ColorSpace.get(ColorSpace.Named.ADOBE_RGB), 570 ColorSpace.get(ColorSpace.Named.SRGB)); 571 572 float[] tmp = source; 573 source = expected; 574 expected = tmp; 575 576 r1 = connector.transform(source[0], source[1], source[2]); 577 assertNotNull(r1); 578 assertEquals(3, r1.length); 579 assertArrayNotEquals(source, r1, 1e-5f); 580 assertArrayEquals(expected, r1, 1e-3f); 581 582 r3 = new float[] { source[0], source[1], source[2] }; 583 assertSame(r3, connector.transform(r3)); 584 assertEquals(3, r3.length); 585 assertArrayEquals(r1, r3, 1e-5f); 586 } 587 588 @Test testAdaptedConnector()589 public void testAdaptedConnector() { 590 // Connect color spaces with different white points 591 ColorSpace.Connector connector = ColorSpace.connect( 592 ColorSpace.get(ColorSpace.Named.SRGB), 593 ColorSpace.get(ColorSpace.Named.PRO_PHOTO_RGB)); 594 595 float[] source = new float[] { 1.0f, 0.0f, 0.0f }; 596 float[] expected = new float[] { 0.70226f, 0.2757f, 0.1036f }; 597 598 float[] r = connector.transform(source[0], source[1], source[2]); 599 assertNotNull(r); 600 assertEquals(3, r.length); 601 assertArrayNotEquals(source, r, 1e-5f); 602 assertArrayEquals(expected, r, 1e-4f); 603 } 604 605 @Test testAdaptedConnectorWithRenderIntent()606 public void testAdaptedConnectorWithRenderIntent() { 607 // Connect a wider color space to a narrow color space 608 ColorSpace.Connector connector = ColorSpace.connect( 609 ColorSpace.get(ColorSpace.Named.DCI_P3), 610 ColorSpace.get(ColorSpace.Named.SRGB), 611 ColorSpace.RenderIntent.RELATIVE); 612 613 float[] source = { 0.9f, 0.9f, 0.9f }; 614 615 float[] relative = connector.transform(source[0], source[1], source[2]); 616 assertNotNull(relative); 617 assertEquals(3, relative.length); 618 assertArrayNotEquals(source, relative, 1e-5f); 619 assertArrayEquals(new float[] { 0.8862f, 0.8862f, 0.8862f }, relative, 1e-4f); 620 621 connector = ColorSpace.connect( 622 ColorSpace.get(ColorSpace.Named.DCI_P3), 623 ColorSpace.get(ColorSpace.Named.SRGB), 624 ColorSpace.RenderIntent.ABSOLUTE); 625 626 float[] absolute = connector.transform(source[0], source[1], source[2]); 627 assertNotNull(absolute); 628 assertEquals(3, absolute.length); 629 assertArrayNotEquals(source, absolute, 1e-5f); 630 assertArrayNotEquals(relative, absolute, 1e-5f); 631 assertArrayEquals(new float[] { 0.8475f, 0.9217f, 0.8203f }, absolute, 1e-4f); 632 } 633 634 @Test testIdentityConnector()635 public void testIdentityConnector() { 636 ColorSpace.Connector connector = ColorSpace.connect( 637 ColorSpace.get(ColorSpace.Named.SRGB), 638 ColorSpace.get(ColorSpace.Named.SRGB)); 639 640 assertSame(connector.getSource(), connector.getDestination()); 641 assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent()); 642 643 float[] source = new float[] { 0.11112f, 0.22227f, 0.444448f }; 644 645 float[] r = connector.transform(source[0], source[1], source[2]); 646 assertNotNull(r); 647 assertEquals(3, r.length); 648 assertArrayEquals(source, r, 1e-5f); 649 } 650 651 @Test testConnectorTransformIdentity()652 public void testConnectorTransformIdentity() { 653 ColorSpace.Connector connector = ColorSpace.connect( 654 ColorSpace.get(ColorSpace.Named.DCI_P3), 655 ColorSpace.get(ColorSpace.Named.DCI_P3)); 656 657 float[] source = { 1.0f, 0.0f, 0.0f }; 658 float[] expected = { 1.0f, 0.0f, 0.0f }; 659 660 float[] r1 = connector.transform(source[0], source[1], source[2]); 661 assertNotNull(r1); 662 assertEquals(3, r1.length); 663 assertArrayEquals(expected, r1, 1e-3f); 664 665 float[] r3 = { source[0], source[1], source[2] }; 666 assertSame(r3, connector.transform(r3)); 667 assertEquals(3, r3.length); 668 assertArrayEquals(r1, r3, 1e-5f); 669 } 670 671 @Test testAdaptation()672 public void testAdaptation() { 673 ColorSpace adapted = ColorSpace.adapt( 674 ColorSpace.get(ColorSpace.Named.SRGB), 675 ColorSpace.ILLUMINANT_D50); 676 677 float[] sRGBD50 = { 678 0.43602175f, 0.22247513f, 0.01392813f, 679 0.38510883f, 0.71690667f, 0.09710153f, 680 0.14308129f, 0.06061824f, 0.71415880f 681 }; 682 683 assertArrayEquals(sRGBD50, ((ColorSpace.Rgb) adapted).getTransform(), 1e-7f); 684 685 adapted = ColorSpace.adapt( 686 ColorSpace.get(ColorSpace.Named.SRGB), 687 ColorSpace.ILLUMINANT_D50, 688 ColorSpace.Adaptation.BRADFORD); 689 assertArrayEquals(sRGBD50, ((ColorSpace.Rgb) adapted).getTransform(), 1e-7f); 690 } 691 692 @Test testImplicitSRGBConnector()693 public void testImplicitSRGBConnector() { 694 ColorSpace.Connector connector1 = ColorSpace.connect( 695 ColorSpace.get(ColorSpace.Named.DCI_P3)); 696 697 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector1.getDestination()); 698 699 ColorSpace.Connector connector2 = ColorSpace.connect( 700 ColorSpace.get(ColorSpace.Named.DCI_P3), 701 ColorSpace.get(ColorSpace.Named.SRGB)); 702 703 float[] source = { 0.6f, 0.9f, 0.7f }; 704 assertArrayEquals( 705 connector1.transform(source[0], source[1], source[2]), 706 connector2.transform(source[0], source[1], source[2]), 1e-7f); 707 } 708 709 @Test testLab()710 public void testLab() { 711 ColorSpace.Connector connector = ColorSpace.connect( 712 ColorSpace.get(ColorSpace.Named.CIE_LAB)); 713 714 float[] source = { 100.0f, 0.0f, 0.0f }; 715 float[] expected = { 1.0f, 1.0f, 1.0f }; 716 717 float[] r1 = connector.transform(source[0], source[1], source[2]); 718 assertNotNull(r1); 719 assertEquals(3, r1.length); 720 assertArrayEquals(expected, r1, 1e-3f); 721 722 source = new float[] { 100.0f, 0.0f, 54.0f }; 723 expected = new float[] { 1.0f, 0.9925f, 0.5762f }; 724 725 float[] r2 = connector.transform(source[0], source[1], source[2]); 726 assertNotNull(r2); 727 assertEquals(3, r2.length); 728 assertArrayEquals(expected, r2, 1e-3f); 729 730 connector = ColorSpace.connect( 731 ColorSpace.get(ColorSpace.Named.CIE_LAB), ColorSpace.RenderIntent.ABSOLUTE); 732 733 source = new float[] { 100.0f, 0.0f, 0.0f }; 734 expected = new float[] { 1.0f, 0.9910f, 0.8651f }; 735 736 r1 = connector.transform(source[0], source[1], source[2]); 737 assertNotNull(r1); 738 assertEquals(3, r1.length); 739 assertArrayEquals(expected, r1, 1e-3f); 740 741 source = new float[] { 100.0f, 0.0f, 54.0f }; 742 expected = new float[] { 1.0f, 0.9853f, 0.4652f }; 743 744 r2 = connector.transform(source[0], source[1], source[2]); 745 assertNotNull(r2); 746 assertEquals(3, r2.length); 747 assertArrayEquals(expected, r2, 1e-3f); 748 } 749 750 @RequiresFlagsEnabled(Flags.FLAG_OK_LAB_COLORSPACE) 751 @Test testOkLab()752 public void testOkLab() { 753 ColorSpace.Connector connector = ColorSpace.connect( 754 ColorSpace.get(ColorSpace.Named.OK_LAB)); 755 756 float[] source = { 100.0f, 0.0f, 0.0f }; 757 float[] expected = { 1.0f, 1.0f, 1.0f }; 758 759 float[] r1 = connector.transform(source[0], source[1], source[2]); 760 assertNotNull(r1); 761 assertEquals(3, r1.length); 762 assertArrayEquals(expected, r1, 1e-3f); 763 764 source = new float[] { 100.0f, 0.0f, 54.0f }; 765 expected = new float[] { 1.0f, 0.8137f, 0f }; 766 767 float[] r2 = connector.transform(source[0], source[1], source[2]); 768 assertNotNull(r2); 769 assertEquals(3, r2.length); 770 assertArrayEquals(expected, r2, 1e-3f); 771 772 connector = ColorSpace.connect( 773 ColorSpace.get(ColorSpace.Named.OK_LAB), ColorSpace.RenderIntent.ABSOLUTE); 774 775 source = new float[] { 100.0f, 0.0f, 0.0f }; 776 expected = new float[] { 1.0f, 0.9910f, 0.8651f }; 777 778 r1 = connector.transform(source[0], source[1], source[2]); 779 assertNotNull(r1); 780 assertEquals(3, r1.length); 781 assertArrayEquals(expected, r1, 1e-3f); 782 783 source = new float[] { 100.0f, 0.0f, 54.0f }; 784 expected = new float[] { 1.0f, 0.80465f, 0.0f }; 785 786 r2 = connector.transform(source[0], source[1], source[2]); 787 assertNotNull(r2); 788 assertEquals(3, r2.length); 789 assertArrayEquals(expected, r2, 1e-3f); 790 } 791 792 @Test testXYZ()793 public void testXYZ() { 794 ColorSpace xyz = ColorSpace.get(ColorSpace.Named.CIE_XYZ); 795 796 float[] source = { 0.32f, 0.43f, 0.54f }; 797 798 float[] r1 = xyz.toXyz(source[0], source[1], source[2]); 799 assertNotNull(r1); 800 assertEquals(3, r1.length); 801 assertArrayEquals(source, r1, 1e-7f); 802 803 float[] r2 = xyz.fromXyz(source[0], source[1], source[2]); 804 assertNotNull(r2); 805 assertEquals(3, r2.length); 806 assertArrayEquals(source, r2, 1e-7f); 807 808 ColorSpace.Connector connector = 809 ColorSpace.connect(ColorSpace.get(ColorSpace.Named.CIE_XYZ)); 810 811 float[] expected = { 0.2280f, 0.7541f, 0.8453f }; 812 813 float[] r3 = connector.transform(source[0], source[1], source[2]); 814 assertNotNull(r3); 815 assertEquals(3, r3.length); 816 assertArrayEquals(expected, r3, 1e-3f); 817 } 818 819 @Test testIDs()820 public void testIDs() { 821 // These cannot change 822 assertEquals(0, ColorSpace.get(ColorSpace.Named.SRGB).getId()); 823 assertEquals(-1, ColorSpace.MIN_ID); 824 assertEquals(63, ColorSpace.MAX_ID); 825 } 826 827 @Test testFromLinear()828 public void testFromLinear() { 829 ColorSpace.Rgb colorSpace = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); 830 831 float[] source = { 0.0f, 0.5f, 1.0f }; 832 float[] expected = { 0.0f, 0.7354f, 1.0f }; 833 834 float[] r1 = colorSpace.fromLinear(source[0], source[1], source[2]); 835 assertNotNull(r1); 836 assertEquals(3, r1.length); 837 assertArrayEquals(expected, r1, 1e-3f); 838 839 float[] r2 = { source[0], source[1], source[2] }; 840 assertSame(r2, colorSpace.fromLinear(r2)); 841 assertEquals(3, r2.length); 842 assertArrayEquals(r1, r2, 1e-5f); 843 } 844 845 @Test testToLinear()846 public void testToLinear() { 847 ColorSpace.Rgb colorSpace = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); 848 849 float[] source = { 0.0f, 0.5f, 1.0f }; 850 float[] expected = new float[] { 0.0f, 0.2140f, 1.0f }; 851 852 float[] r1 = colorSpace.toLinear(source[0], source[1], source[2]); 853 assertNotNull(r1); 854 assertEquals(3, r1.length); 855 assertArrayEquals(expected, r1, 1e-3f); 856 857 float[] r2 = new float[] { source[0], source[1], source[2] }; 858 assertSame(r2, colorSpace.toLinear(r2)); 859 assertEquals(3, r2.length); 860 assertArrayEquals(r1, r2, 1e-5f); 861 } 862 863 @Test testTransferParameters()864 public void testTransferParameters() { 865 ColorSpace.Rgb colorSpace = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); 866 assertNotNull(colorSpace.getTransferParameters()); 867 868 colorSpace = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB); 869 assertNotNull(colorSpace.getTransferParameters()); 870 871 colorSpace = new ColorSpace.Rgb("Almost sRGB", SRGB_TO_XYZ, 872 x -> Math.pow(x, 1.0f / 2.2f), x -> Math.pow(x, 2.2f)); 873 assertNull(colorSpace.getTransferParameters()); 874 } 875 876 @Test testIdempotentTransferFunctions()877 public void testIdempotentTransferFunctions() { 878 Arrays.stream(ColorSpace.Named.values()) 879 .map(ColorSpace::get) 880 .filter(cs -> cs.getModel() == ColorSpace.Model.RGB) 881 .map(cs -> (ColorSpace.Rgb) cs) 882 .forEach(cs -> { 883 float[] source = { 0.0f, 0.5f, 1.0f }; 884 float[] r = cs.fromLinear(cs.toLinear(source[0], source[1], source[2])); 885 assertArrayEquals(source, r, 1e-3f); 886 }); 887 } 888 889 @Test testMatch()890 public void testMatch() { 891 for (ColorSpace.Named named : ColorSpace.Named.values()) { 892 ColorSpace cs = ColorSpace.get(named); 893 if (cs.getModel() == ColorSpace.Model.RGB) { 894 ColorSpace.Rgb rgb = (ColorSpace.Rgb) cs; 895 // match() cannot match extended sRGB, BT2020_HLG, BT2020_PQ 896 if (rgb != ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB) 897 && rgb != ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB) 898 && rgb != ColorSpace.get(ColorSpace.Named.BT2020_HLG) 899 && rgb != ColorSpace.get(ColorSpace.Named.BT2020_PQ)) { 900 901 // match() uses CIE XYZ D50 902 rgb = (ColorSpace.Rgb) ColorSpace.adapt(rgb, ColorSpace.ILLUMINANT_D50); 903 assertSame(cs, 904 ColorSpace.match(rgb.getTransform(), rgb.getTransferParameters())); 905 } 906 } 907 } 908 909 assertSame(ColorSpace.get(ColorSpace.Named.SRGB), 910 ColorSpace.match(SRGB_TO_XYZ_D50, new ColorSpace.Rgb.TransferParameters( 911 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4))); 912 } 913 914 @Test(expected = IllegalArgumentException.class) 915 @Parameters({"0", "-1", "-50"}) testInvalidCct(int cct)916 public void testInvalidCct(int cct) { 917 ColorSpace.cctToXyz(cct); 918 } 919 920 @Test testCctToXyz()921 public void testCctToXyz() { 922 // Verify that range listed as meaningful by the API return float arrays as expected. 923 for (int i = 1667; i <= 25000; i++) { 924 float[] result = ColorSpace.cctToXyz(i); 925 assertNotNull(result); 926 assertEquals(3, result.length); 927 } 928 } 929 cctToXyzExpected()930 private static Object[] cctToXyzExpected() { 931 return new Object[] { 932 // ILLUMINANT_A 933 new Object[] { 2856, new float[] { 1.0970824f, 1.0f, 0.3568525f }}, 934 // ILLUMINANT_B 935 new Object[] { 4874, new float[] { 0.98355806f, 1.0f, 0.8376475f }}, 936 // ILLUMINANT_C 937 new Object[] { 6774, new float[] { 0.9680535f, 1.0f, 1.1603559f }}, 938 // ILLUMINANT_D50 939 new Object[] { 5003, new float[] { 0.9811904f, 1.0f, 0.86360276f }}, 940 // ILLUMINANT_D55 941 new Object[] { 5503, new float[] { 0.97444946f, 1.0f, 0.9582717f }}, 942 // ILLUMINANT_D60 943 new Object[] { 6004, new float[] { 0.9705604f, 1.0f, 1.0441511f }}, 944 // ILLUMINANT_D65 945 new Object[] { 6504, new float[] { 0.968573f, 1.0f, 1.1216444f }}, 946 // ILLUMINANT_D75 947 new Object[] { 7504, new float[] { 0.9679457f, 1.0f, 1.2551404f }}, 948 // ILLUMINANT_E 949 new Object[] { 5454, new float[] { 0.9749648f, 1.0f, 0.9494016f }}, 950 // Test a sample of values in the meaningful range according to the API. 951 new Object[] { 1667, new float[] { 1.4014802f, 1.0f, 0.08060435f }}, 952 new Object[] { 1668, new float[] { 1.4010513f, 1.0f, 0.08076303f }}, 953 new Object[] { 1700, new float[] { 1.3874257f, 1.0f, 0.08596305f }}, 954 new Object[] { 1701, new float[] { 1.3870035f, 1.0f, 0.08612958f }}, 955 new Object[] { 2020, new float[] { 1.2686056f, 1.0f, 0.14921218f }}, 956 new Object[] { 2102, new float[] { 1.2439337f, 1.0f, 0.1678791f }}, 957 new Object[] { 2360, new float[] { 1.1796018f, 1.0f, 0.2302558f }}, 958 new Object[] { 4688, new float[] { 0.9875373f, 1.0f, 0.79908675f }}, 959 new Object[] { 5797, new float[] { 0.97189087f, 1.0f, 1.0097121f }}, 960 new Object[] { 7625, new float[] { 0.96806175f, 1.0f, 1.2695707f }}, 961 new Object[] { 8222, new float[] { 0.9690009f, 1.0f, 1.3359972f }}, 962 new Object[] { 8330, new float[] { 0.9692224f, 1.0f, 1.3472213f }}, 963 new Object[] { 9374, new float[] { 0.9718307f, 1.0f, 1.4447508f }}, 964 new Object[] { 9604, new float[] { 0.97247595f, 1.0f, 1.4638413f }}, 965 new Object[] { 9894, new float[] { 0.9733059f, 1.0f, 1.4868189f }}, 966 new Object[] { 10764, new float[] { 0.97584003f, 1.0f, 1.5491791f }}, 967 new Object[] { 11735, new float[] { 0.97862047f, 1.0f, 1.6088297f }}, 968 new Object[] { 12819, new float[] { 0.98155034f, 1.0f, 1.6653923f }}, 969 new Object[] { 13607, new float[] { 0.98353446f, 1.0f, 1.7010691f }}, 970 new Object[] { 15185, new float[] { 0.98712224f, 1.0f, 1.7615601f }}, 971 new Object[] { 17474, new float[] { 0.9914801f, 1.0f, 1.8297766f }}, 972 new Object[] { 18788, new float[] { 0.9935937f, 1.0f, 1.8612393f }}, 973 new Object[] { 19119, new float[] { 0.99408686f, 1.0f, 1.8684553f }}, 974 new Object[] { 19174, new float[] { 0.99416786f, 1.0f, 1.8696303f }}, 975 new Object[] { 19437, new float[] { 0.9945476f, 1.0f, 1.8751476f }}, 976 new Object[] { 19533, new float[] { 0.99468416f, 1.0f, 1.8771234f }}, 977 new Object[] { 19548, new float[] { 0.99470526f, 1.0f, 1.8774294f }}, 978 new Object[] { 19762, new float[] { 0.995005f, 1.0f, 1.8817542f }}, 979 new Object[] { 19774, new float[] { 0.9950216f, 1.0f, 1.8819935f }}, 980 new Object[] { 20291, new float[] { 0.99572146f, 1.0f, 1.8920314f }}, 981 new Object[] { 23018, new float[] { 0.99893945f, 1.0f, 1.9371331f }}, 982 new Object[] { 23509, new float[] { 0.999445f, 1.0f, 1.9440757f }}, 983 new Object[] { 24761, new float[] { 1.0006485f, 1.0f, 1.9604537f }}, 984 985 }; 986 } 987 988 @Test 989 @Parameters(method = "cctToXyzExpected") testCctToXyzValues(int cct, float[] xyz)990 public void testCctToXyzValues(int cct, float[] xyz) { 991 float[] result = ColorSpace.cctToXyz(cct); 992 assertArrayEquals(xyz, result, 1e-3f); 993 } 994 chromaticAdaptationNullParameters()995 private static Object[] chromaticAdaptationNullParameters() { 996 return new Object[] { 997 new Object[] { null, ColorSpace.ILLUMINANT_D50, ColorSpace.ILLUMINANT_D60 }, 998 new Object[] { ColorSpace.Adaptation.BRADFORD, null, ColorSpace.ILLUMINANT_D60 }, 999 new Object[] { ColorSpace.Adaptation.BRADFORD, ColorSpace.ILLUMINANT_D60, null }, 1000 }; 1001 } 1002 1003 @Test(expected = NullPointerException.class) 1004 @Parameters(method = "chromaticAdaptationNullParameters") testChromaticAdaptationNullParameters(ColorSpace.Adaptation adaptation, float[] srcWhitePoint, float[] dstWhitePoint)1005 public void testChromaticAdaptationNullParameters(ColorSpace.Adaptation adaptation, 1006 float[] srcWhitePoint, float[] dstWhitePoint) { 1007 ColorSpace.chromaticAdaptation(adaptation, srcWhitePoint, dstWhitePoint); 1008 } 1009 chromaticAdaptationWrongSizedArrays()1010 private static Object[] chromaticAdaptationWrongSizedArrays() { 1011 return new Object[] { 1012 new Object[] { ColorSpace.Adaptation.BRADFORD, new float[] { 1.0f }, 1013 ColorSpace.ILLUMINANT_D60 }, 1014 new Object[] { ColorSpace.Adaptation.BRADFORD, ColorSpace.ILLUMINANT_D60, 1015 new float[] { 1.0f, 1.0f, 1.0f, 1.0f }}, 1016 }; 1017 } 1018 1019 @Test(expected = IllegalArgumentException.class) 1020 @Parameters(method = "chromaticAdaptationWrongSizedArrays") testChromaticAdaptationWrongSizedArrays(ColorSpace.Adaptation adaptation, float[] srcWhitePoint, float[] dstWhitePoint)1021 public void testChromaticAdaptationWrongSizedArrays(ColorSpace.Adaptation adaptation, 1022 float[] srcWhitePoint, float[] dstWhitePoint) { 1023 ColorSpace.chromaticAdaptation(adaptation, srcWhitePoint, dstWhitePoint); 1024 } 1025 1026 private static float[] sIdentityMatrix = new float[] { 1027 1.0f, 0.0f, 0.0f, 1028 0.0f, 1.0f, 0.0f, 1029 0.0f, 0.0f, 1.0f 1030 }; 1031 1032 @Test testChromaticAdaptation()1033 public void testChromaticAdaptation() { 1034 for (ColorSpace.Adaptation adaptation : ColorSpace.Adaptation.values()) { 1035 float[][] whitePoints = { 1036 ColorSpace.ILLUMINANT_A, 1037 ColorSpace.ILLUMINANT_B, 1038 ColorSpace.ILLUMINANT_C, 1039 ColorSpace.ILLUMINANT_D50, 1040 ColorSpace.ILLUMINANT_D55, 1041 ColorSpace.ILLUMINANT_D60, 1042 ColorSpace.ILLUMINANT_D65, 1043 ColorSpace.ILLUMINANT_D75, 1044 ColorSpace.ILLUMINANT_E, 1045 }; 1046 for (float[] srcWhitePoint : whitePoints) { 1047 for (float[] dstWhitePoint : whitePoints) { 1048 float[] result = ColorSpace.chromaticAdaptation(adaptation, srcWhitePoint, 1049 dstWhitePoint); 1050 assertNotNull(result); 1051 assertEquals(9, result.length); 1052 if (Arrays.equals(srcWhitePoint, dstWhitePoint)) { 1053 assertArrayEquals(sIdentityMatrix, result, 0f); 1054 } 1055 } 1056 } 1057 } 1058 } 1059 1060 @Test getDataSpaceFromColorSpace()1061 public void getDataSpaceFromColorSpace() { 1062 ColorSpace cs = ColorSpace.get(ColorSpace.Named.BT709); 1063 assertNotNull(cs); 1064 assertEquals(DataSpace.DATASPACE_BT709, cs.getDataSpace()); 1065 1066 cs = ColorSpace.get(ColorSpace.Named.ACES); 1067 assertEquals(DataSpace.DATASPACE_UNKNOWN, cs.getDataSpace()); 1068 } 1069 1070 @Test getColorSpaceFromDataSpace()1071 public void getColorSpaceFromDataSpace() { 1072 ColorSpace cs = ColorSpace.getFromDataSpace(DataSpace.DATASPACE_SRGB); 1073 assertNotNull(cs); 1074 assertEquals(DataSpace.DATASPACE_SRGB, cs.getDataSpace()); 1075 1076 assertNull(ColorSpace.getFromDataSpace(DataSpace.DATASPACE_JFIF)); 1077 } 1078 1079 @SuppressWarnings("SameParameterValue") assertArrayNotEquals(float[] a, float[] b, float eps)1080 private void assertArrayNotEquals(float[] a, float[] b, float eps) { 1081 for (int i = 0; i < a.length; i++) { 1082 if (Float.compare(a[i], b[i]) == 0 || Math.abs(a[i] - b[i]) < eps) { 1083 fail("Expected " + a[i] + ", received " + b[i]); 1084 } 1085 } 1086 } 1087 assertArrayEquals(float[] a, float[] b, float eps)1088 private void assertArrayEquals(float[] a, float[] b, float eps) { 1089 for (int i = 0; i < a.length; i++) { 1090 if (Float.compare(a[i], b[i]) != 0 && Math.abs(a[i] - b[i]) > eps) { 1091 fail("Expected " + a[i] + ", received " + b[i]); 1092 } 1093 } 1094 } 1095 } 1096