| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package android.graphics.cts; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import android.graphics.ColorSpace; |
| import android.support.test.filters.SmallTest; |
| import android.support.test.runner.AndroidJUnit4; |
| |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.util.Arrays; |
| import java.util.function.DoubleUnaryOperator; |
| |
| @SmallTest |
| @RunWith(AndroidJUnit4.class) |
| public class ColorSpaceTest { |
| // Column-major RGB->XYZ transform matrix for the sRGB color space |
| private static final float[] SRGB_TO_XYZ = { |
| 0.412391f, 0.212639f, 0.019331f, |
| 0.357584f, 0.715169f, 0.119195f, |
| 0.180481f, 0.072192f, 0.950532f |
| }; |
| // Column-major XYZ->RGB transform matrix for the sRGB color space |
| private static final float[] XYZ_TO_SRGB = { |
| 3.240970f, -0.969244f, 0.055630f, |
| -1.537383f, 1.875968f, -0.203977f, |
| -0.498611f, 0.041555f, 1.056971f |
| }; |
| |
| // Column-major RGB->XYZ transform matrix for the sRGB color space and a D50 white point |
| private static final float[] SRGB_TO_XYZ_D50 = { |
| 0.4360747f, 0.2225045f, 0.0139322f, |
| 0.3850649f, 0.7168786f, 0.0971045f, |
| 0.1430804f, 0.0606169f, 0.7141733f |
| }; |
| |
| private static final float[] SRGB_PRIMARIES_xyY = |
| { 0.640f, 0.330f, 0.300f, 0.600f, 0.150f, 0.060f }; |
| private static final float[] SRGB_WHITE_POINT_xyY = { 0.3127f, 0.3290f }; |
| |
| private static final float[] SRGB_PRIMARIES_XYZ = { |
| 1.939394f, 1.000000f, 0.090909f, |
| 0.500000f, 1.000000f, 0.166667f, |
| 2.500000f, 1.000000f, 13.166667f |
| }; |
| private static final float[] SRGB_WHITE_POINT_XYZ = { 0.950456f, 1.000f, 1.089058f }; |
| |
| private static final DoubleUnaryOperator sIdentity = DoubleUnaryOperator.identity(); |
| |
| @Test |
| public void testNamedColorSpaces() { |
| for (ColorSpace.Named named : ColorSpace.Named.values()) { |
| ColorSpace colorSpace = ColorSpace.get(named); |
| assertNotNull(colorSpace.getName()); |
| assertNotNull(colorSpace); |
| assertEquals(named.ordinal(), colorSpace.getId()); |
| assertTrue(colorSpace.getComponentCount() >= 1); |
| assertTrue(colorSpace.getComponentCount() <= 4); |
| } |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testNullName() { |
| new ColorSpace.Rgb(null, new float[6], new float[2], sIdentity, sIdentity, 0.0f, 1.0f); |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testEmptyName() { |
| new ColorSpace.Rgb("", new float[6], new float[2], sIdentity, sIdentity, 0.0f, 1.0f); |
| } |
| |
| @Test |
| public void testName() { |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", new float[6], new float[2], |
| sIdentity, sIdentity, 0.0f, 1.0f); |
| assertEquals("Test", cs.getName()); |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testPrimariesLength() { |
| new ColorSpace.Rgb("Test", new float[7], new float[2], sIdentity, sIdentity, 0.0f, 1.0f); |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testWhitePointLength() { |
| new ColorSpace.Rgb("Test", new float[6], new float[1], sIdentity, sIdentity, 0.0f, 1.0f); |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testNullOETF() { |
| new ColorSpace.Rgb("Test", new float[6], new float[2], null, sIdentity, 0.0f, 1.0f); |
| } |
| |
| @Test |
| public void testOETF() { |
| DoubleUnaryOperator op = Math::sqrt; |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", new float[6], new float[2], |
| op, sIdentity, 0.0f, 1.0f); |
| assertEquals(0.5, cs.getOetf().applyAsDouble(0.25), 1e-5); |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testNullEOTF() { |
| new ColorSpace.Rgb("Test", new float[6], new float[2], sIdentity, null, 0.0f, 1.0f); |
| } |
| |
| @Test |
| public void testEOTF() { |
| DoubleUnaryOperator op = x -> x * x; |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", new float[6], new float[2], |
| sIdentity, op, 0.0f, 1.0f); |
| assertEquals(0.0625, cs.getEotf().applyAsDouble(0.25), 1e-5); |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testInvalidRange() { |
| new ColorSpace.Rgb("Test", new float[6], new float[2], sIdentity, sIdentity, 2.0f, 1.0f); |
| } |
| |
| @Test |
| public void testRanges() { |
| ColorSpace cs = ColorSpace.get(ColorSpace.Named.SRGB); |
| |
| float m1 = cs.getMinValue(0); |
| float m2 = cs.getMinValue(1); |
| float m3 = cs.getMinValue(2); |
| |
| assertEquals(0.0f, m1, 1e-9f); |
| assertEquals(0.0f, m2, 1e-9f); |
| assertEquals(0.0f, m3, 1e-9f); |
| |
| m1 = cs.getMaxValue(0); |
| m2 = cs.getMaxValue(1); |
| m3 = cs.getMaxValue(2); |
| |
| assertEquals(1.0f, m1, 1e-9f); |
| assertEquals(1.0f, m2, 1e-9f); |
| assertEquals(1.0f, m3, 1e-9f); |
| |
| cs = ColorSpace.get(ColorSpace.Named.CIE_LAB); |
| |
| m1 = cs.getMinValue(0); |
| m2 = cs.getMinValue(1); |
| m3 = cs.getMinValue(2); |
| |
| assertEquals(0.0f, m1, 1e-9f); |
| assertEquals(-128.0f, m2, 1e-9f); |
| assertEquals(-128.0f, m3, 1e-9f); |
| |
| m1 = cs.getMaxValue(0); |
| m2 = cs.getMaxValue(1); |
| m3 = cs.getMaxValue(2); |
| |
| assertEquals(100.0f, m1, 1e-9f); |
| assertEquals(128.0f, m2, 1e-9f); |
| assertEquals(128.0f, m3, 1e-9f); |
| |
| cs = ColorSpace.get(ColorSpace.Named.CIE_XYZ); |
| |
| m1 = cs.getMinValue(0); |
| m2 = cs.getMinValue(1); |
| m3 = cs.getMinValue(2); |
| |
| assertEquals(-2.0f, m1, 1e-9f); |
| assertEquals(-2.0f, m2, 1e-9f); |
| assertEquals(-2.0f, m3, 1e-9f); |
| |
| m1 = cs.getMaxValue(0); |
| m2 = cs.getMaxValue(1); |
| m3 = cs.getMaxValue(2); |
| |
| assertEquals(2.0f, m1, 1e-9f); |
| assertEquals(2.0f, m2, 1e-9f); |
| assertEquals(2.0f, m3, 1e-9f); |
| } |
| |
| @Test |
| public void testMat3x3() { |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_TO_XYZ, sIdentity, sIdentity); |
| |
| float[] rgbToXYZ = cs.getTransform(); |
| for (int i = 0; i < 9; i++) { |
| assertEquals(SRGB_TO_XYZ[i], rgbToXYZ[i], 1e-5f); |
| } |
| } |
| |
| @Test |
| public void testMat3x3Inverse() { |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_TO_XYZ, sIdentity, sIdentity); |
| |
| float[] xyzToRGB = cs.getInverseTransform(); |
| for (int i = 0; i < 9; i++) { |
| assertEquals(XYZ_TO_SRGB[i], xyzToRGB[i], 1e-5f); |
| } |
| } |
| |
| @Test |
| public void testMat3x3Primaries() { |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_TO_XYZ, sIdentity, sIdentity); |
| |
| float[] primaries = cs.getPrimaries(); |
| |
| assertNotNull(primaries); |
| assertEquals(6, primaries.length); |
| |
| assertEquals(SRGB_PRIMARIES_xyY[0], primaries[0], 1e-5f); |
| assertEquals(SRGB_PRIMARIES_xyY[1], primaries[1], 1e-5f); |
| assertEquals(SRGB_PRIMARIES_xyY[2], primaries[2], 1e-5f); |
| assertEquals(SRGB_PRIMARIES_xyY[3], primaries[3], 1e-5f); |
| assertEquals(SRGB_PRIMARIES_xyY[4], primaries[4], 1e-5f); |
| assertEquals(SRGB_PRIMARIES_xyY[5], primaries[5], 1e-5f); |
| } |
| |
| @Test |
| public void testMat3x3WhitePoint() { |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_TO_XYZ, sIdentity, sIdentity); |
| |
| float[] whitePoint = cs.getWhitePoint(); |
| |
| assertNotNull(whitePoint); |
| assertEquals(2, whitePoint.length); |
| |
| assertEquals(SRGB_WHITE_POINT_xyY[0], whitePoint[0], 1e-5f); |
| assertEquals(SRGB_WHITE_POINT_xyY[1], whitePoint[1], 1e-5f); |
| } |
| |
| @Test |
| public void testXYZFromPrimaries_xyY() { |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_PRIMARIES_xyY, SRGB_WHITE_POINT_xyY, |
| sIdentity, sIdentity, 0.0f, 1.0f); |
| |
| float[] rgbToXYZ = cs.getTransform(); |
| for (int i = 0; i < 9; i++) { |
| assertEquals(SRGB_TO_XYZ[i], rgbToXYZ[i], 1e-5f); |
| } |
| |
| float[] xyzToRGB = cs.getInverseTransform(); |
| for (int i = 0; i < 9; i++) { |
| assertEquals(XYZ_TO_SRGB[i], xyzToRGB[i], 1e-5f); |
| } |
| } |
| |
| @Test |
| public void testXYZFromPrimaries_XYZ() { |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", SRGB_PRIMARIES_XYZ, SRGB_WHITE_POINT_XYZ, |
| sIdentity, sIdentity, 0.0f, 1.0f); |
| |
| float[] primaries = cs.getPrimaries(); |
| |
| assertNotNull(primaries); |
| assertEquals(6, primaries.length); |
| |
| // SRGB_PRIMARIES_xyY only has 1e-3 of precision, match it |
| assertEquals(SRGB_PRIMARIES_xyY[0], primaries[0], 1e-3f); |
| assertEquals(SRGB_PRIMARIES_xyY[1], primaries[1], 1e-3f); |
| assertEquals(SRGB_PRIMARIES_xyY[2], primaries[2], 1e-3f); |
| assertEquals(SRGB_PRIMARIES_xyY[3], primaries[3], 1e-3f); |
| assertEquals(SRGB_PRIMARIES_xyY[4], primaries[4], 1e-3f); |
| assertEquals(SRGB_PRIMARIES_xyY[5], primaries[5], 1e-3f); |
| |
| float[] whitePoint = cs.getWhitePoint(); |
| |
| assertNotNull(whitePoint); |
| assertEquals(2, whitePoint.length); |
| |
| // SRGB_WHITE_POINT_xyY only has 1e-3 of precision, match it |
| assertEquals(SRGB_WHITE_POINT_xyY[0], whitePoint[0], 1e-3f); |
| assertEquals(SRGB_WHITE_POINT_xyY[1], whitePoint[1], 1e-3f); |
| |
| float[] rgbToXYZ = cs.getTransform(); |
| for (int i = 0; i < 9; i++) { |
| assertEquals(SRGB_TO_XYZ[i], rgbToXYZ[i], 1e-5f); |
| } |
| |
| float[] xyzToRGB = cs.getInverseTransform(); |
| for (int i = 0; i < 9; i++) { |
| assertEquals(XYZ_TO_SRGB[i], xyzToRGB[i], 1e-5f); |
| } |
| } |
| |
| @Test |
| public void testGetComponentCount() { |
| assertEquals(3, ColorSpace.get(ColorSpace.Named.SRGB).getComponentCount()); |
| assertEquals(3, ColorSpace.get(ColorSpace.Named.LINEAR_SRGB).getComponentCount()); |
| assertEquals(3, ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB).getComponentCount()); |
| assertEquals(3, ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB).getComponentCount()); |
| assertEquals(3, ColorSpace.get(ColorSpace.Named.DISPLAY_P3).getComponentCount()); |
| assertEquals(3, ColorSpace.get(ColorSpace.Named.CIE_LAB).getComponentCount()); |
| assertEquals(3, ColorSpace.get(ColorSpace.Named.CIE_XYZ).getComponentCount()); |
| } |
| |
| @Test |
| public void testIsSRGB() { |
| assertTrue(ColorSpace.get(ColorSpace.Named.SRGB).isSrgb()); |
| assertFalse(ColorSpace.get(ColorSpace.Named.LINEAR_SRGB).isSrgb()); |
| assertFalse(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB).isSrgb()); |
| assertFalse(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB).isSrgb()); |
| assertFalse(ColorSpace.get(ColorSpace.Named.DISPLAY_P3).isSrgb()); |
| assertFalse(ColorSpace.get(ColorSpace.Named.CIE_LAB).isSrgb()); |
| assertFalse(ColorSpace.get(ColorSpace.Named.CIE_XYZ).isSrgb()); |
| |
| ColorSpace.Rgb cs = new ColorSpace.Rgb("My sRGB", SRGB_TO_XYZ, |
| x -> Math.pow(x, 1.0f / 2.2f), x -> Math.pow(x, 2.2f)); |
| assertTrue(cs.isSrgb()); |
| } |
| |
| @Test |
| public void testIsWideGamut() { |
| assertFalse(ColorSpace.get(ColorSpace.Named.SRGB).isWideGamut()); |
| assertFalse(ColorSpace.get(ColorSpace.Named.BT709).isWideGamut()); |
| assertTrue(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB).isWideGamut()); |
| assertTrue(ColorSpace.get(ColorSpace.Named.DCI_P3).isWideGamut()); |
| assertTrue(ColorSpace.get(ColorSpace.Named.BT2020).isWideGamut()); |
| assertTrue(ColorSpace.get(ColorSpace.Named.ACES).isWideGamut()); |
| assertTrue(ColorSpace.get(ColorSpace.Named.CIE_LAB).isWideGamut()); |
| assertTrue(ColorSpace.get(ColorSpace.Named.CIE_XYZ).isWideGamut()); |
| } |
| |
| @Test |
| public void testWhitePoint() { |
| ColorSpace.Rgb cs = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); |
| |
| float[] whitePoint = cs.getWhitePoint(); |
| |
| assertNotNull(whitePoint); |
| assertEquals(2, whitePoint.length); |
| |
| // Make sure a copy is returned |
| Arrays.fill(whitePoint, Float.NaN); |
| assertArrayNotEquals(whitePoint, cs.getWhitePoint(), 1e-5f); |
| assertSame(whitePoint, cs.getWhitePoint(whitePoint)); |
| assertArrayEquals(whitePoint, cs.getWhitePoint(), 1e-5f); |
| } |
| |
| @Test |
| public void testPrimaries() { |
| ColorSpace.Rgb cs = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); |
| |
| float[] primaries = cs.getPrimaries(); |
| |
| assertNotNull(primaries); |
| assertEquals(6, primaries.length); |
| |
| // Make sure a copy is returned |
| Arrays.fill(primaries, Float.NaN); |
| assertArrayNotEquals(primaries, cs.getPrimaries(), 1e-5f); |
| assertSame(primaries, cs.getPrimaries(primaries)); |
| assertArrayEquals(primaries, cs.getPrimaries(), 1e-5f); |
| } |
| |
| @Test |
| public void testRGBtoXYZMatrix() { |
| ColorSpace.Rgb cs = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); |
| |
| float[] rgbToXYZ = cs.getTransform(); |
| |
| assertNotNull(rgbToXYZ); |
| assertEquals(9, rgbToXYZ.length); |
| |
| // Make sure a copy is returned |
| Arrays.fill(rgbToXYZ, Float.NaN); |
| assertArrayNotEquals(rgbToXYZ, cs.getTransform(), 1e-5f); |
| assertSame(rgbToXYZ, cs.getTransform(rgbToXYZ)); |
| assertArrayEquals(rgbToXYZ, cs.getTransform(), 1e-5f); |
| } |
| |
| @Test |
| public void testXYZtoRGBMatrix() { |
| ColorSpace.Rgb cs = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); |
| |
| float[] xyzToRGB = cs.getInverseTransform(); |
| |
| assertNotNull(xyzToRGB); |
| assertEquals(9, xyzToRGB.length); |
| |
| // Make sure a copy is returned |
| Arrays.fill(xyzToRGB, Float.NaN); |
| assertArrayNotEquals(xyzToRGB, cs.getInverseTransform(), 1e-5f); |
| assertSame(xyzToRGB, cs.getInverseTransform(xyzToRGB)); |
| assertArrayEquals(xyzToRGB, cs.getInverseTransform(), 1e-5f); |
| } |
| |
| @Test |
| public void testRGBtoXYZ() { |
| ColorSpace cs = ColorSpace.get(ColorSpace.Named.SRGB); |
| |
| float[] source = { 0.75f, 0.5f, 0.25f }; |
| float[] expected = { 0.3012f, 0.2679f, 0.0840f }; |
| |
| float[] r1 = cs.toXyz(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayNotEquals(source, r1, 1e-5f); |
| assertArrayEquals(expected, r1, 1e-3f); |
| |
| float[] r3 = { source[0], source[1], source[2] }; |
| assertSame(r3, cs.toXyz(r3)); |
| assertEquals(3, r3.length); |
| assertArrayEquals(r1, r3, 1e-5f); |
| } |
| |
| @Test |
| public void testXYZtoRGB() { |
| ColorSpace cs = ColorSpace.get(ColorSpace.Named.SRGB); |
| |
| float[] source = { 0.3012f, 0.2679f, 0.0840f }; |
| float[] expected = { 0.75f, 0.5f, 0.25f }; |
| |
| float[] r1 = cs.fromXyz(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayNotEquals(source, r1, 1e-5f); |
| assertArrayEquals(expected, r1, 1e-3f); |
| |
| float[] r3 = { source[0], source[1], source[2] }; |
| assertSame(r3, cs.fromXyz(r3)); |
| assertEquals(3, r3.length); |
| assertArrayEquals(r1, r3, 1e-5f); |
| } |
| |
| @Test |
| public void testConnect() { |
| ColorSpace.Connector connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.get(ColorSpace.Named.DCI_P3)); |
| |
| assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getSource()); |
| assertSame(ColorSpace.get(ColorSpace.Named.DCI_P3), connector.getDestination()); |
| assertSame(ColorSpace.RenderIntent.PERCEPTUAL, connector.getRenderIntent()); |
| |
| connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.get(ColorSpace.Named.SRGB)); |
| |
| assertSame(connector.getDestination(), connector.getSource()); |
| assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent()); |
| |
| connector = ColorSpace.connect(ColorSpace.get(ColorSpace.Named.DCI_P3)); |
| assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getDestination()); |
| |
| connector = ColorSpace.connect(ColorSpace.get(ColorSpace.Named.SRGB)); |
| assertSame(connector.getSource(), connector.getDestination()); |
| } |
| |
| @Test |
| public void testConnector() { |
| // Connect color spaces with same white points |
| ColorSpace.Connector connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.get(ColorSpace.Named.ADOBE_RGB)); |
| |
| float[] source = { 1.0f, 0.5f, 0.0f }; |
| float[] expected = { 0.8912f, 0.4962f, 0.1164f }; |
| |
| float[] r1 = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayNotEquals(source, r1, 1e-5f); |
| assertArrayEquals(expected, r1, 1e-3f); |
| |
| float[] r3 = { source[0], source[1], source[2] }; |
| assertSame(r3, connector.transform(r3)); |
| assertEquals(3, r3.length); |
| assertArrayEquals(r1, r3, 1e-5f); |
| |
| connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.ADOBE_RGB), |
| ColorSpace.get(ColorSpace.Named.SRGB)); |
| |
| float[] tmp = source; |
| source = expected; |
| expected = tmp; |
| |
| r1 = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayNotEquals(source, r1, 1e-5f); |
| assertArrayEquals(expected, r1, 1e-3f); |
| |
| r3 = new float[] { source[0], source[1], source[2] }; |
| assertSame(r3, connector.transform(r3)); |
| assertEquals(3, r3.length); |
| assertArrayEquals(r1, r3, 1e-5f); |
| } |
| |
| @Test |
| public void testAdaptedConnector() { |
| // Connect color spaces with different white points |
| ColorSpace.Connector connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.get(ColorSpace.Named.PRO_PHOTO_RGB)); |
| |
| float[] source = new float[] { 1.0f, 0.0f, 0.0f }; |
| float[] expected = new float[] { 0.70226f, 0.2757f, 0.1036f }; |
| |
| float[] r = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r); |
| assertEquals(3, r.length); |
| assertArrayNotEquals(source, r, 1e-5f); |
| assertArrayEquals(expected, r, 1e-4f); |
| } |
| |
| @Test |
| public void testAdaptedConnectorWithRenderIntent() { |
| // Connect a wider color space to a narrow color space |
| ColorSpace.Connector connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.DCI_P3), |
| ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.RenderIntent.RELATIVE); |
| |
| float[] source = { 0.9f, 0.9f, 0.9f }; |
| |
| float[] relative = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(relative); |
| assertEquals(3, relative.length); |
| assertArrayNotEquals(source, relative, 1e-5f); |
| assertArrayEquals(new float[] { 0.8862f, 0.8862f, 0.8862f }, relative, 1e-4f); |
| |
| connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.DCI_P3), |
| ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.RenderIntent.ABSOLUTE); |
| |
| float[] absolute = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(absolute); |
| assertEquals(3, absolute.length); |
| assertArrayNotEquals(source, absolute, 1e-5f); |
| assertArrayNotEquals(relative, absolute, 1e-5f); |
| assertArrayEquals(new float[] { 0.8475f, 0.9217f, 0.8203f }, absolute, 1e-4f); |
| } |
| |
| @Test |
| public void testIdentityConnector() { |
| ColorSpace.Connector connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.get(ColorSpace.Named.SRGB)); |
| |
| assertSame(connector.getSource(), connector.getDestination()); |
| assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent()); |
| |
| float[] source = new float[] { 0.11112f, 0.22227f, 0.444448f }; |
| |
| float[] r = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r); |
| assertEquals(3, r.length); |
| assertArrayEquals(source, r, 1e-5f); |
| } |
| |
| @Test |
| public void testConnectorTransformIdentity() { |
| ColorSpace.Connector connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.DCI_P3), |
| ColorSpace.get(ColorSpace.Named.DCI_P3)); |
| |
| float[] source = { 1.0f, 0.0f, 0.0f }; |
| float[] expected = { 1.0f, 0.0f, 0.0f }; |
| |
| float[] r1 = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayEquals(expected, r1, 1e-3f); |
| |
| float[] r3 = { source[0], source[1], source[2] }; |
| assertSame(r3, connector.transform(r3)); |
| assertEquals(3, r3.length); |
| assertArrayEquals(r1, r3, 1e-5f); |
| } |
| |
| @Test |
| public void testAdaptation() { |
| ColorSpace adapted = ColorSpace.adapt( |
| ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.ILLUMINANT_D50); |
| |
| float[] sRGBD50 = { |
| 0.43602175f, 0.22247513f, 0.01392813f, |
| 0.38510883f, 0.71690667f, 0.09710153f, |
| 0.14308129f, 0.06061824f, 0.71415880f |
| }; |
| |
| assertArrayEquals(sRGBD50, ((ColorSpace.Rgb) adapted).getTransform(), 1e-7f); |
| |
| adapted = ColorSpace.adapt( |
| ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.ILLUMINANT_D50, |
| ColorSpace.Adaptation.BRADFORD); |
| assertArrayEquals(sRGBD50, ((ColorSpace.Rgb) adapted).getTransform(), 1e-7f); |
| } |
| |
| @Test |
| public void testImplicitSRGBConnector() { |
| ColorSpace.Connector connector1 = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.DCI_P3)); |
| |
| assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector1.getDestination()); |
| |
| ColorSpace.Connector connector2 = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.DCI_P3), |
| ColorSpace.get(ColorSpace.Named.SRGB)); |
| |
| float[] source = { 0.6f, 0.9f, 0.7f }; |
| assertArrayEquals( |
| connector1.transform(source[0], source[1], source[2]), |
| connector2.transform(source[0], source[1], source[2]), 1e-7f); |
| } |
| |
| @Test |
| public void testLab() { |
| ColorSpace.Connector connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.CIE_LAB)); |
| |
| float[] source = { 100.0f, 0.0f, 0.0f }; |
| float[] expected = { 1.0f, 1.0f, 1.0f }; |
| |
| float[] r1 = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayEquals(expected, r1, 1e-3f); |
| |
| source = new float[] { 100.0f, 0.0f, 54.0f }; |
| expected = new float[] { 1.0f, 0.9925f, 0.5762f }; |
| |
| float[] r2 = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r2); |
| assertEquals(3, r2.length); |
| assertArrayEquals(expected, r2, 1e-3f); |
| |
| connector = ColorSpace.connect( |
| ColorSpace.get(ColorSpace.Named.CIE_LAB), ColorSpace.RenderIntent.ABSOLUTE); |
| |
| source = new float[] { 100.0f, 0.0f, 0.0f }; |
| expected = new float[] { 1.0f, 0.9910f, 0.8651f }; |
| |
| r1 = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayEquals(expected, r1, 1e-3f); |
| |
| source = new float[] { 100.0f, 0.0f, 54.0f }; |
| expected = new float[] { 1.0f, 0.9853f, 0.4652f }; |
| |
| r2 = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r2); |
| assertEquals(3, r2.length); |
| assertArrayEquals(expected, r2, 1e-3f); |
| } |
| |
| @Test |
| public void testXYZ() { |
| ColorSpace xyz = ColorSpace.get(ColorSpace.Named.CIE_XYZ); |
| |
| float[] source = { 0.32f, 0.43f, 0.54f }; |
| |
| float[] r1 = xyz.toXyz(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayEquals(source, r1, 1e-7f); |
| |
| float[] r2 = xyz.fromXyz(source[0], source[1], source[2]); |
| assertNotNull(r2); |
| assertEquals(3, r2.length); |
| assertArrayEquals(source, r2, 1e-7f); |
| |
| ColorSpace.Connector connector = |
| ColorSpace.connect(ColorSpace.get(ColorSpace.Named.CIE_XYZ)); |
| |
| float[] expected = { 0.2280f, 0.7541f, 0.8453f }; |
| |
| float[] r3 = connector.transform(source[0], source[1], source[2]); |
| assertNotNull(r3); |
| assertEquals(3, r3.length); |
| assertArrayEquals(expected, r3, 1e-3f); |
| } |
| |
| @Test |
| public void testIDs() { |
| // These cannot change |
| assertEquals(0, ColorSpace.get(ColorSpace.Named.SRGB).getId()); |
| assertEquals(-1, ColorSpace.MIN_ID); |
| assertEquals(63, ColorSpace.MAX_ID); |
| } |
| |
| @Test |
| public void testFromLinear() { |
| ColorSpace.Rgb colorSpace = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); |
| |
| float[] source = { 0.0f, 0.5f, 1.0f }; |
| float[] expected = { 0.0f, 0.7354f, 1.0f }; |
| |
| float[] r1 = colorSpace.fromLinear(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayEquals(expected, r1, 1e-3f); |
| |
| float[] r2 = { source[0], source[1], source[2] }; |
| assertSame(r2, colorSpace.fromLinear(r2)); |
| assertEquals(3, r2.length); |
| assertArrayEquals(r1, r2, 1e-5f); |
| } |
| |
| @Test |
| public void testToLinear() { |
| ColorSpace.Rgb colorSpace = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); |
| |
| float[] source = { 0.0f, 0.5f, 1.0f }; |
| float[] expected = new float[] { 0.0f, 0.2140f, 1.0f }; |
| |
| float[] r1 = colorSpace.toLinear(source[0], source[1], source[2]); |
| assertNotNull(r1); |
| assertEquals(3, r1.length); |
| assertArrayEquals(expected, r1, 1e-3f); |
| |
| float[] r2 = new float[] { source[0], source[1], source[2] }; |
| assertSame(r2, colorSpace.toLinear(r2)); |
| assertEquals(3, r2.length); |
| assertArrayEquals(r1, r2, 1e-5f); |
| } |
| |
| @Test |
| public void testTransferParameters() { |
| ColorSpace.Rgb colorSpace = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.SRGB); |
| assertNotNull(colorSpace.getTransferParameters()); |
| |
| colorSpace = (ColorSpace.Rgb) ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB); |
| assertNull(colorSpace.getTransferParameters()); |
| } |
| |
| @Test |
| public void testIdempotentTransferFunctions() { |
| Arrays.stream(ColorSpace.Named.values()) |
| .map(ColorSpace::get) |
| .filter(cs -> cs.getModel() == ColorSpace.Model.RGB) |
| .map(cs -> (ColorSpace.Rgb) cs) |
| .forEach(cs -> { |
| float[] source = { 0.0f, 0.5f, 1.0f }; |
| float[] r = cs.fromLinear(cs.toLinear(source[0], source[1], source[2])); |
| assertArrayEquals(source, r, 1e-3f); |
| }); |
| } |
| |
| @Test |
| public void testMatch() { |
| for (ColorSpace.Named named : ColorSpace.Named.values()) { |
| ColorSpace cs = ColorSpace.get(named); |
| if (cs.getModel() == ColorSpace.Model.RGB) { |
| ColorSpace.Rgb rgb = (ColorSpace.Rgb) cs; |
| // match() cannot match extended sRGB |
| if (rgb != ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB) && |
| rgb != ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB)) { |
| |
| // match() uses CIE XYZ D50 |
| rgb = (ColorSpace.Rgb) ColorSpace.adapt(rgb, ColorSpace.ILLUMINANT_D50); |
| assertSame(cs, |
| ColorSpace.match(rgb.getTransform(), rgb.getTransferParameters())); |
| } |
| } |
| } |
| |
| assertSame(ColorSpace.get(ColorSpace.Named.SRGB), |
| ColorSpace.match(SRGB_TO_XYZ_D50, new ColorSpace.Rgb.TransferParameters( |
| 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4))); |
| } |
| |
| |
| @SuppressWarnings("SameParameterValue") |
| private static void assertArrayNotEquals(float[] a, float[] b, float eps) { |
| for (int i = 0; i < a.length; i++) { |
| if (Float.compare(a[i], b[i]) == 0 || Math.abs(a[i] - b[i]) < eps) { |
| fail("Expected " + a[i] + ", received " + b[i]); |
| } |
| } |
| } |
| |
| private static void assertArrayEquals(float[] a, float[] b, float eps) { |
| for (int i = 0; i < a.length; i++) { |
| if (Float.compare(a[i], b[i]) != 0 && Math.abs(a[i] - b[i]) > eps) { |
| fail("Expected " + a[i] + ", received " + b[i]); |
| } |
| } |
| } |
| } |