8254370: Update the classes in the java.awt.color package

Reviewed-by: prr
This commit is contained in:
Sergey Bylokhov 2020-10-26 23:56:11 +00:00
parent 8ca59c9e2e
commit abdbbe3a79
6 changed files with 312 additions and 105 deletions

View file

@ -102,12 +102,12 @@ public abstract class ColorSpace implements Serializable {
/**
* One of the {@code ColorSpace} type constants.
*/
private int type;
private final int type;
/**
* The number of components in the color space.
*/
private int numComponents;
private final int numComponents;
private transient String [] compName = null;
// Cache of singletons for the predefined color spaces.
@ -242,6 +242,7 @@ public abstract class ColorSpace implements Serializable {
*/
@Native public static final int TYPE_FCLR = 25;
/**
* The sRGB color space defined at
* <a href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
@ -275,11 +276,11 @@ public abstract class ColorSpace implements Serializable {
* number of components.
*
* @param type one of the {@code ColorSpace} type constants
* @param numcomponents the number of components in the color space
* @param numComponents the number of components in the color space
*/
protected ColorSpace(int type, int numcomponents) {
protected ColorSpace(int type, int numComponents) {
this.type = type;
this.numComponents = numcomponents;
this.numComponents = numComponents;
}
/**
@ -508,11 +509,7 @@ public abstract class ColorSpace implements Serializable {
*/
public String getName (int idx) {
/* REMIND - handle common cases here */
if ((idx < 0) || (idx > numComponents - 1)) {
throw new IllegalArgumentException(
"Component index out of range: " + idx);
}
rangeCheck(idx);
if (compName == null) {
switch (type) {
case ColorSpace.TYPE_XYZ:
@ -573,10 +570,7 @@ public abstract class ColorSpace implements Serializable {
* @since 1.4
*/
public float getMinValue(int component) {
if ((component < 0) || (component > numComponents - 1)) {
throw new IllegalArgumentException(
"Component index out of range: " + component);
}
rangeCheck(component);
return 0.0f;
}
@ -592,17 +586,21 @@ public abstract class ColorSpace implements Serializable {
* @since 1.4
*/
public float getMaxValue(int component) {
if ((component < 0) || (component > numComponents - 1)) {
throw new IllegalArgumentException(
"Component index out of range: " + component);
}
rangeCheck(component);
return 1.0f;
}
/*
* Returns {@code true} if {@code cspace} is the XYZspace.
/**
* Checks that {@code component} is in range of the number of components.
*
* @param component the component index
* @throws IllegalArgumentException if component is less than 0 or greater
* than {@code numComponents - 1}
*/
static boolean isCS_CIEXYZ(ColorSpace cspace) {
return (cspace == XYZspace);
final void rangeCheck(int component) {
if (component < 0 || component > getNumComponents() - 1) {
throw new IllegalArgumentException(
"Component index out of range: " + component);
}
}
}

View file

@ -569,10 +569,7 @@ public class ICC_ColorSpace extends ColorSpace {
* @since 1.4
*/
public float getMinValue(int component) {
if ((component < 0) || (component > this.getNumComponents() - 1)) {
throw new IllegalArgumentException(
"Component index out of range: " + component);
}
rangeCheck(component);
return minVal[component];
}
@ -595,10 +592,7 @@ public class ICC_ColorSpace extends ColorSpace {
* @since 1.4
*/
public float getMaxValue(int component) {
if ((component < 0) || (component > this.getNumComponents() - 1)) {
throw new IllegalArgumentException(
"Component index out of range: " + component);
}
rangeCheck(component);
return maxVal[component];
}

View file

@ -115,10 +115,7 @@ public class ICC_ProfileGray extends ICC_Profile {
* single gamma value
*/
public float getGamma() {
float theGamma;
theGamma = super.getGamma(ICC_Profile.icSigGrayTRCTag);
return theGamma;
return getGamma(ICC_Profile.icSigGrayTRCTag);
}
/**
@ -140,10 +137,6 @@ public class ICC_ProfileGray extends ICC_Profile {
* table
*/
public short[] getTRC() {
short[] theTRC;
theTRC = super.getTRC(ICC_Profile.icSigGrayTRCTag);
return theTRC;
return getTRC(ICC_Profile.icSigGrayTRCTag);
}
}

View file

@ -143,22 +143,12 @@ public class ICC_ProfileRGB extends ICC_Profile {
* {@code greenColorantTag}, and {@code blueColorantTag}
*/
public float[][] getMatrix() {
float[][] theMatrix = new float[3][3];
float[] tmpMatrix;
tmpMatrix = getXYZTag(ICC_Profile.icSigRedColorantTag);
theMatrix[0][0] = tmpMatrix[0];
theMatrix[1][0] = tmpMatrix[1];
theMatrix[2][0] = tmpMatrix[2];
tmpMatrix = getXYZTag(ICC_Profile.icSigGreenColorantTag);
theMatrix[0][1] = tmpMatrix[0];
theMatrix[1][1] = tmpMatrix[1];
theMatrix[2][1] = tmpMatrix[2];
tmpMatrix = getXYZTag(ICC_Profile.icSigBlueColorantTag);
theMatrix[0][2] = tmpMatrix[0];
theMatrix[1][2] = tmpMatrix[1];
theMatrix[2][2] = tmpMatrix[2];
return theMatrix;
float[] red = getXYZTag(ICC_Profile.icSigRedColorantTag);
float[] green = getXYZTag(ICC_Profile.icSigGreenColorantTag);
float[] blue = getXYZTag(ICC_Profile.icSigBlueColorantTag);
return new float[][]{{red[0], green[0], blue[0]},
{red[1], green[1], blue[1]},
{red[2], green[2], blue[2]}};
}
/**
@ -181,33 +171,14 @@ public class ICC_ProfileRGB extends ICC_Profile {
* @param component the {@code ICC_ProfileRGB} constant that represents the
* component whose TRC you want to retrieve
* @return the gamma value as a float
* @throws IllegalArgumentException if the component is not
* {@code REDCOMPONENT}, {@code GREENCOMPONENT}, or
* {@code BLUECOMPONENT}
* @throws ProfileDataException if the profile does not specify the
* corresponding TRC as a single gamma value
*/
public float getGamma(int component) {
float theGamma;
int theSignature;
switch (component) {
case REDCOMPONENT:
theSignature = ICC_Profile.icSigRedTRCTag;
break;
case GREENCOMPONENT:
theSignature = ICC_Profile.icSigGreenTRCTag;
break;
case BLUECOMPONENT:
theSignature = ICC_Profile.icSigBlueTRCTag;
break;
default:
throw new IllegalArgumentException("Must be Red, Green, or Blue");
}
theGamma = super.getGamma(theSignature);
return theGamma;
return super.getGamma(toTag(component));
}
/**
@ -232,33 +203,32 @@ public class ICC_ProfileRGB extends ICC_Profile {
* component whose TRC you want to retrieve: {@code REDCOMPONENT},
* {@code GREENCOMPONENT}, or {@code BLUECOMPONENT}
* @return a short array representing the TRC
* @throws IllegalArgumentException if the component is not
* {@code REDCOMPONENT}, {@code GREENCOMPONENT}, or
* {@code BLUECOMPONENT}
* @throws ProfileDataException if the profile does not specify the
* corresponding TRC as a table
*/
public short[] getTRC(int component) {
short[] theTRC;
int theSignature;
switch (component) {
case REDCOMPONENT:
theSignature = ICC_Profile.icSigRedTRCTag;
break;
case GREENCOMPONENT:
theSignature = ICC_Profile.icSigGreenTRCTag;
break;
case BLUECOMPONENT:
theSignature = ICC_Profile.icSigBlueTRCTag;
break;
default:
throw new IllegalArgumentException("Must be Red, Green, or Blue");
return super.getTRC(toTag(component));
}
theTRC = super.getTRC(theSignature);
return theTRC;
/**
* Converts the {@code ICC_ProfileRGB} constant to the appropriate tag.
*
* @param component the {@code ICC_ProfileRGB} constant
* @return the tag signature
* @throws IllegalArgumentException if the component is not
* {@code REDCOMPONENT}, {@code GREENCOMPONENT}, or
* {@code BLUECOMPONENT}
*/
private static int toTag(int component) {
return switch (component) {
case REDCOMPONENT -> ICC_Profile.icSigRedTRCTag;
case GREENCOMPONENT -> ICC_Profile.icSigGreenTRCTag;
case BLUECOMPONENT -> ICC_Profile.icSigBlueTRCTag;
default -> throw new IllegalArgumentException(
"Must be Red, Green, or Blue");
};
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.color.ICC_ProfileGray;
import java.awt.color.ProfileDataException;
/**
* @test
* @bug 8254370
* @summary Tests basic ICC_ProfileGray functionality
*/
public final class ICC_ProfileGrayTest {
public static void main(String[] args) throws Exception {
ICC_Profile csProfile = ICC_Profile.getInstance(ColorSpace.CS_GRAY);
ICC_Profile dataProfile = ICC_Profile.getInstance(csProfile.getData());
ICC_Profile stringProfile = ICC_Profile.getInstance("GRAY.pf");
test(csProfile);
test(dataProfile);
test(stringProfile);
}
private static void test(ICC_Profile profile) {
// Gray profile should be implemented as ICC_ProfileGray and includes
// the mediaWhitePointTag and grayTRCTag tags
if (!(profile instanceof ICC_ProfileGray)
|| profile.getData(ICC_Profile.icSigMediaWhitePointTag) == null
|| profile.getData(ICC_Profile.icSigGrayTRCTag) == null) {
throw new RuntimeException("Wrong profile: " + profile);
}
ICC_ProfileGray gray = (ICC_ProfileGray) profile;
int length = gray.getMediaWhitePoint().length;
if (length != 3) {
throw new RuntimeException("Wrong data length: " + length);
}
// if getTRC() throws an exception then getGamma() should work
boolean trc = false;
try {
gray.getTRC();
trc = true;
System.out.println("getTRC() works fine");
} catch (ProfileDataException ignore) {
gray.getGamma();
}
// if getGamma() throws an exception then getTRC() should work
boolean gamma = false;
try {
gray.getGamma();
gamma = true;
System.out.println("getGamma() works fine");
} catch (ProfileDataException ignore) {
gray.getTRC();
}
if (gamma == trc) {
// only one should work
throw new RuntimeException("Only one operation should work");
}
}
}

View file

@ -0,0 +1,167 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.color.ICC_ProfileRGB;
import java.awt.color.ProfileDataException;
import java.util.Arrays;
/**
* @test
* @bug 8254370
* @summary Tests basic ICC_ProfileRGB functionality
*/
public final class ICC_ProfileRGBTest {
public static void main(String[] args) throws Exception {
ICC_Profile csProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
ICC_Profile dataProfile = ICC_Profile.getInstance(csProfile.getData());
ICC_Profile string2Profile = ICC_Profile.getInstance("sRGB.pf");
ICC_Profile string1Profile = ICC_Profile.getInstance("LINEAR_RGB.pf");
test(csProfile);
test(dataProfile);
test(string1Profile);
test(string2Profile);
}
private static void test(ICC_Profile profile) {
// RGB profile should be implemented as ICC_ProfileRGB and includes the
// redColorantTag, greenColorantTag, blueColorantTag, redTRCTag,
// greenTRCTag, blueTRCTag, mediaWhitePointTag tags
if (!(profile instanceof ICC_ProfileRGB)
|| profile.getData(ICC_Profile.icSigRedColorantTag) == null
|| profile.getData(ICC_Profile.icSigGreenColorantTag) == null
|| profile.getData(ICC_Profile.icSigBlueColorantTag) == null
|| profile.getData(ICC_Profile.icSigRedTRCTag) == null
|| profile.getData(ICC_Profile.icSigGreenTRCTag) == null
|| profile.getData(ICC_Profile.icSigBlueTRCTag) == null
|| profile.getData(ICC_Profile.icSigMediaWhitePointTag) == null)
{
throw new RuntimeException("Wrong profile: " + profile);
}
ICC_ProfileRGB rgb = (ICC_ProfileRGB) profile;
int length = rgb.getMediaWhitePoint().length;
if (length != 3) {
throw new RuntimeException("Wrong data length: " + length);
}
// if getTRC() throws an exception then getGamma() should work
boolean trc = false;
try {
rgb.getTRC(ICC_ProfileRGB.REDCOMPONENT);
rgb.getTRC(ICC_ProfileRGB.GREENCOMPONENT);
rgb.getTRC(ICC_ProfileRGB.BLUECOMPONENT);
trc = true;
System.out.println("getTRC() works fine");
} catch (ProfileDataException ignore) {
rgb.getGamma(ICC_ProfileRGB.REDCOMPONENT);
rgb.getGamma(ICC_ProfileRGB.GREENCOMPONENT);
rgb.getGamma(ICC_ProfileRGB.BLUECOMPONENT);
}
// if getGamma() throws an exception then getTRC() should work
boolean gamma = false;
try {
rgb.getGamma(ICC_ProfileRGB.REDCOMPONENT);
rgb.getGamma(ICC_ProfileRGB.GREENCOMPONENT);
rgb.getGamma(ICC_ProfileRGB.BLUECOMPONENT);
gamma = true;
System.out.println("getGamma() works fine");
} catch (ProfileDataException ignore) {
rgb.getTRC(ICC_ProfileRGB.REDCOMPONENT);
rgb.getTRC(ICC_ProfileRGB.GREENCOMPONENT);
rgb.getTRC(ICC_ProfileRGB.BLUECOMPONENT);
}
if (gamma == trc) {
// only one should work fine
throw new RuntimeException("Only one operation should work");
}
// IllegalArgumentException if the component is invalid
try {
rgb.getGamma(10);
throw new RuntimeException("IllegalArgumentException was expected");
} catch (IllegalArgumentException ignored) {}
try {
rgb.getGamma(-1);
throw new RuntimeException("IllegalArgumentException was expected");
} catch (IllegalArgumentException ignored) {}
try {
rgb.getTRC(10);
throw new RuntimeException("IllegalArgumentException was expected");
} catch (IllegalArgumentException ignored) {}
try {
rgb.getTRC(-1);
throw new RuntimeException("IllegalArgumentException was expected");
} catch (IllegalArgumentException ignored) {}
// Validates content of ICC_ProfileRGB.getMatrix()
float[][] matrix = rgb.getMatrix(); // current implementation
float[][] old = getMatrix(rgb); // old implementation
if (!Arrays.deepEquals(matrix, old)) {
System.err.println("Expected: " + Arrays.deepToString(old));
System.err.println("Actual: " + Arrays.deepToString(matrix));
throw new RuntimeException("Wrong matrix");
}
}
/**
* Old implementation of ICC_ProfileRGB.getMatrix().
*/
private static float[][] getMatrix(ICC_ProfileRGB profile) {
float[] tmpMatrix = getXYZTag(profile, ICC_Profile.icSigRedColorantTag);
float[][] theMatrix = new float[3][3];
theMatrix[0][0] = tmpMatrix[0];
theMatrix[1][0] = tmpMatrix[1];
theMatrix[2][0] = tmpMatrix[2];
tmpMatrix = getXYZTag(profile, ICC_Profile.icSigGreenColorantTag);
theMatrix[0][1] = tmpMatrix[0];
theMatrix[1][1] = tmpMatrix[1];
theMatrix[2][1] = tmpMatrix[2];
tmpMatrix = getXYZTag(profile, ICC_Profile.icSigBlueColorantTag);
theMatrix[0][2] = tmpMatrix[0];
theMatrix[1][2] = tmpMatrix[1];
theMatrix[2][2] = tmpMatrix[2];
return theMatrix;
}
private static float[] getXYZTag(ICC_ProfileRGB profile, int theTagSignature) {
byte[] theData = profile.getData(theTagSignature);
float[] theXYZNumber = new float[3];
for (int i1 = 0, i2 = profile.icXYZNumberX; i1 < 3; i1++, i2 += 4) {
int theS15Fixed16 = intFromBigEndian(theData, i2);
theXYZNumber [i1] = theS15Fixed16 / 65536.0f;
}
return theXYZNumber;
}
static int intFromBigEndian(byte[] array, int index) {
return (((array[index] & 0xff) << 24) |
((array[index+1] & 0xff) << 16) |
((array[index+2] & 0xff) << 8) |
(array[index+3] & 0xff));
}
}