/* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ /********************************************************************** ********************************************************************** ********************************************************************** *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** *** As an unpublished work pursuant to Title 17 of the United *** *** States Code. All rights reserved. *** ********************************************************************** ********************************************************************** **********************************************************************/ package java.awt.color; import java.lang.annotation.Native; import sun.java2d.cmm.PCMM; import sun.java2d.cmm.CMSManager; /** * This abstract class is used to serve as a color space tag to identify the * specific color space of a Color object or, via a ColorModel object, * of an Image, a BufferedImage, or a GraphicsDevice. It contains * methods that transform colors in a specific color space to/from sRGB * and to/from a well-defined CIEXYZ color space. *

* For purposes of the methods in this class, colors are represented as * arrays of color components represented as floats in a normalized range * defined by each ColorSpace. For many ColorSpaces (e.g. sRGB), this * range is 0.0 to 1.0. However, some ColorSpaces have components whose * values have a different range. Methods are provided to inquire per * component minimum and maximum normalized values. *

* Several variables are defined for purposes of referring to color * space types (e.g. TYPE_RGB, TYPE_XYZ, etc.) and to refer to specific * color spaces (e.g. CS_sRGB and CS_CIEXYZ). * sRGB is a proposed standard RGB color space. For more information, * see * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html * . *

* The purpose of the methods to transform to/from the well-defined * CIEXYZ color space is to support conversions between any two color * spaces at a reasonably high degree of accuracy. It is expected that * particular implementations of subclasses of ColorSpace (e.g. * ICC_ColorSpace) will support high performance conversion based on * underlying platform color management systems. *

* The CS_CIEXYZ space used by the toCIEXYZ/fromCIEXYZ methods can be * described as follows:


      CIEXYZ
      viewing illuminance: 200 lux
      viewing white point: CIE D50
      media white point: "that of a perfectly reflecting diffuser" -- D50
      media black point: 0 lux or 0 Reflectance
      flare: 1 percent
      surround: 20percent of the media white point
      media description: reflection print (i.e., RLAB, Hunt viewing media)
      note: For developers creating an ICC profile for this conversion
            space, the following is applicable.  Use a simple Von Kries
            white point adaptation folded into the 3X3 matrix parameters
            and fold the flare and surround effects into the three
            one-dimensional lookup tables (assuming one uses the minimal
            model for monitors).

* *

* @see ICC_ColorSpace */ public abstract class ColorSpace implements java.io.Serializable { static final long serialVersionUID = -409452704308689724L; private int type; private int numComponents; private transient String [] compName = null; // Cache of singletons for the predefined color spaces. private static ColorSpace sRGBspace; private static ColorSpace XYZspace; private static ColorSpace PYCCspace; private static ColorSpace GRAYspace; private static ColorSpace LINEAR_RGBspace; /** * Any of the family of XYZ color spaces. */ @Native public static final int TYPE_XYZ = 0; /** * Any of the family of Lab color spaces. */ @Native public static final int TYPE_Lab = 1; /** * Any of the family of Luv color spaces. */ @Native public static final int TYPE_Luv = 2; /** * Any of the family of YCbCr color spaces. */ @Native public static final int TYPE_YCbCr = 3; /** * Any of the family of Yxy color spaces. */ @Native public static final int TYPE_Yxy = 4; /** * Any of the family of RGB color spaces. */ @Native public static final int TYPE_RGB = 5; /** * Any of the family of GRAY color spaces. */ @Native public static final int TYPE_GRAY = 6; /** * Any of the family of HSV color spaces. */ @Native public static final int TYPE_HSV = 7; /** * Any of the family of HLS color spaces. */ @Native public static final int TYPE_HLS = 8; /** * Any of the family of CMYK color spaces. */ @Native public static final int TYPE_CMYK = 9; /** * Any of the family of CMY color spaces. */ @Native public static final int TYPE_CMY = 11; /** * Generic 2 component color spaces. */ @Native public static final int TYPE_2CLR = 12; /** * Generic 3 component color spaces. */ @Native public static final int TYPE_3CLR = 13; /** * Generic 4 component color spaces. */ @Native public static final int TYPE_4CLR = 14; /** * Generic 5 component color spaces. */ @Native public static final int TYPE_5CLR = 15; /** * Generic 6 component color spaces. */ @Native public static final int TYPE_6CLR = 16; /** * Generic 7 component color spaces. */ @Native public static final int TYPE_7CLR = 17; /** * Generic 8 component color spaces. */ @Native public static final int TYPE_8CLR = 18; /** * Generic 9 component color spaces. */ @Native public static final int TYPE_9CLR = 19; /** * Generic 10 component color spaces. */ @Native public static final int TYPE_ACLR = 20; /** * Generic 11 component color spaces. */ @Native public static final int TYPE_BCLR = 21; /** * Generic 12 component color spaces. */ @Native public static final int TYPE_CCLR = 22; /** * Generic 13 component color spaces. */ @Native public static final int TYPE_DCLR = 23; /** * Generic 14 component color spaces. */ @Native public static final int TYPE_ECLR = 24; /** * Generic 15 component color spaces. */ @Native public static final int TYPE_FCLR = 25; /** * The sRGB color space defined at * * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html * . */ @Native public static final int CS_sRGB = 1000; /** * A built-in linear RGB color space. This space is based on the * same RGB primaries as CS_sRGB, but has a linear tone reproduction curve. */ @Native public static final int CS_LINEAR_RGB = 1004; /** * The CIEXYZ conversion color space defined above. */ @Native public static final int CS_CIEXYZ = 1001; /** * The Photo YCC conversion color space. */ @Native public static final int CS_PYCC = 1002; /** * The built-in linear gray scale color space. */ @Native public static final int CS_GRAY = 1003; /** * Constructs a ColorSpace object given a color space type * and the number of components. * @param type one of the ColorSpace type constants * @param numcomponents the number of components in the color space */ protected ColorSpace (int type, int numcomponents) { this.type = type; this.numComponents = numcomponents; } /** * Returns a ColorSpace representing one of the specific * predefined color spaces. * @param colorspace a specific color space identified by one of * the predefined class constants (e.g. CS_sRGB, CS_LINEAR_RGB, * CS_CIEXYZ, CS_GRAY, or CS_PYCC) * @return the requested ColorSpace object */ // NOTE: This method may be called by privileged threads. // DO NOT INVOKE CLIENT CODE ON THIS THREAD! public static ColorSpace getInstance (int colorspace) { ColorSpace theColorSpace; switch (colorspace) { case CS_sRGB: synchronized(ColorSpace.class) { if (sRGBspace == null) { ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB); sRGBspace = new ICC_ColorSpace (theProfile); } theColorSpace = sRGBspace; } break; case CS_CIEXYZ: synchronized(ColorSpace.class) { if (XYZspace == null) { ICC_Profile theProfile = ICC_Profile.getInstance (CS_CIEXYZ); XYZspace = new ICC_ColorSpace (theProfile); } theColorSpace = XYZspace; } break; case CS_PYCC: synchronized(ColorSpace.class) { if (PYCCspace == null) { ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC); PYCCspace = new ICC_ColorSpace (theProfile); } theColorSpace = PYCCspace; } break; case CS_GRAY: synchronized(ColorSpace.class) { if (GRAYspace == null) { ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY); GRAYspace = new ICC_ColorSpace (theProfile); /* to allow access from java.awt.ColorModel */ CMSManager.GRAYspace = GRAYspace; } theColorSpace = GRAYspace; } break; case CS_LINEAR_RGB: synchronized(ColorSpace.class) { if (LINEAR_RGBspace == null) { ICC_Profile theProfile = ICC_Profile.getInstance(CS_LINEAR_RGB); LINEAR_RGBspace = new ICC_ColorSpace (theProfile); /* to allow access from java.awt.ColorModel */ CMSManager.LINEAR_RGBspace = LINEAR_RGBspace; } theColorSpace = LINEAR_RGBspace; } break; default: throw new IllegalArgumentException ("Unknown color space"); } return theColorSpace; } /** * Returns true if the ColorSpace is CS_sRGB. * @return true if this is a CS_sRGB color * space, false if it is not */ public boolean isCS_sRGB () { /* REMIND - make sure we know sRGBspace exists already */ return (this == sRGBspace); } /** * Transforms a color value assumed to be in this ColorSpace * into a value in the default CS_sRGB color space. *

* This method transforms color values using algorithms designed * to produce the best perceptual match between input and output * colors. In order to do colorimetric conversion of color values, * you should use the toCIEXYZ * method of this color space to first convert from the input * color space to the CS_CIEXYZ color space, and then use the * fromCIEXYZ method of the CS_sRGB color space to * convert from CS_CIEXYZ to the output color space. * See {@link #toCIEXYZ(float[]) toCIEXYZ} and * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. *

* @param colorvalue a float array with length of at least the number * of components in this ColorSpace * @return a float array of length 3 * @throws ArrayIndexOutOfBoundsException if array length is not * at least the number of components in this ColorSpace */ public abstract float[] toRGB(float[] colorvalue); /** * Transforms a color value assumed to be in the default CS_sRGB * color space into this ColorSpace. *

* This method transforms color values using algorithms designed * to produce the best perceptual match between input and output * colors. In order to do colorimetric conversion of color values, * you should use the toCIEXYZ * method of the CS_sRGB color space to first convert from the input * color space to the CS_CIEXYZ color space, and then use the * fromCIEXYZ method of this color space to * convert from CS_CIEXYZ to the output color space. * See {@link #toCIEXYZ(float[]) toCIEXYZ} and * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. *

* @param rgbvalue a float array with length of at least 3 * @return a float array with length equal to the number of * components in this ColorSpace * @throws ArrayIndexOutOfBoundsException if array length is not * at least 3 */ public abstract float[] fromRGB(float[] rgbvalue); /** * Transforms a color value assumed to be in this ColorSpace * into the CS_CIEXYZ conversion color space. *

* This method transforms color values using relative colorimetry, * as defined by the International Color Consortium standard. This * means that the XYZ values returned by this method are represented * relative to the D50 white point of the CS_CIEXYZ color space. * This representation is useful in a two-step color conversion * process in which colors are transformed from an input color * space to CS_CIEXYZ and then to an output color space. This * representation is not the same as the XYZ values that would * be measured from the given color value by a colorimeter. * A further transformation is necessary to compute the XYZ values * that would be measured using current CIE recommended practices. * See the {@link ICC_ColorSpace#toCIEXYZ(float[]) toCIEXYZ} method of * ICC_ColorSpace for further information. *

* @param colorvalue a float array with length of at least the number * of components in this ColorSpace * @return a float array of length 3 * @throws ArrayIndexOutOfBoundsException if array length is not * at least the number of components in this ColorSpace. */ public abstract float[] toCIEXYZ(float[] colorvalue); /** * Transforms a color value assumed to be in the CS_CIEXYZ conversion * color space into this ColorSpace. *

* This method transforms color values using relative colorimetry, * as defined by the International Color Consortium standard. This * means that the XYZ argument values taken by this method are represented * relative to the D50 white point of the CS_CIEXYZ color space. * This representation is useful in a two-step color conversion * process in which colors are transformed from an input color * space to CS_CIEXYZ and then to an output color space. The color * values returned by this method are not those that would produce * the XYZ value passed to the method when measured by a colorimeter. * If you have XYZ values corresponding to measurements made using * current CIE recommended practices, they must be converted to D50 * relative values before being passed to this method. * See the {@link ICC_ColorSpace#fromCIEXYZ(float[]) fromCIEXYZ} method of * ICC_ColorSpace for further information. *

* @param colorvalue a float array with length of at least 3 * @return a float array with length equal to the number of * components in this ColorSpace * @throws ArrayIndexOutOfBoundsException if array length is not * at least 3 */ public abstract float[] fromCIEXYZ(float[] colorvalue); /** * Returns the color space type of this ColorSpace (for example * TYPE_RGB, TYPE_XYZ, ...). The type defines the * number of components of the color space and the interpretation, * e.g. TYPE_RGB identifies a color space with three components - red, * green, and blue. It does not define the particular color * characteristics of the space, e.g. the chromaticities of the * primaries. * * @return the type constant that represents the type of this * ColorSpace */ public int getType() { return type; } /** * Returns the number of components of this ColorSpace. * @return The number of components in this ColorSpace. */ public int getNumComponents() { return numComponents; } /** * Returns the name of the component given the component index. * * @param idx the component index * @return the name of the component at the specified index * @throws IllegalArgumentException if idx is * less than 0 or greater than numComponents - 1 */ 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); } if (compName == null) { switch (type) { case ColorSpace.TYPE_XYZ: compName = new String[] {"X", "Y", "Z"}; break; case ColorSpace.TYPE_Lab: compName = new String[] {"L", "a", "b"}; break; case ColorSpace.TYPE_Luv: compName = new String[] {"L", "u", "v"}; break; case ColorSpace.TYPE_YCbCr: compName = new String[] {"Y", "Cb", "Cr"}; break; case ColorSpace.TYPE_Yxy: compName = new String[] {"Y", "x", "y"}; break; case ColorSpace.TYPE_RGB: compName = new String[] {"Red", "Green", "Blue"}; break; case ColorSpace.TYPE_GRAY: compName = new String[] {"Gray"}; break; case ColorSpace.TYPE_HSV: compName = new String[] {"Hue", "Saturation", "Value"}; break; case ColorSpace.TYPE_HLS: compName = new String[] {"Hue", "Lightness", "Saturation"}; break; case ColorSpace.TYPE_CMYK: compName = new String[] {"Cyan", "Magenta", "Yellow", "Black"}; break; case ColorSpace.TYPE_CMY: compName = new String[] {"Cyan", "Magenta", "Yellow"}; break; default: String [] tmp = new String[numComponents]; for (int i = 0; i < tmp.length; i++) { tmp[i] = "Unnamed color component(" + i + ")"; } compName = tmp; } } return compName[idx]; } /** * Returns the minimum normalized color component value for the * specified component. The default implementation in this abstract * class returns 0.0 for all components. Subclasses should override * this method if necessary. * * @param component the component index * @return the minimum normalized component value * @throws IllegalArgumentException if component is less than 0 or * greater than numComponents - 1 * @since 1.4 */ public float getMinValue(int component) { if ((component < 0) || (component > numComponents - 1)) { throw new IllegalArgumentException( "Component index out of range: " + component); } return 0.0f; } /** * Returns the maximum normalized color component value for the * specified component. The default implementation in this abstract * class returns 1.0 for all components. Subclasses should override * this method if necessary. * * @param component the component index * @return the maximum normalized component value * @throws IllegalArgumentException if component is less than 0 or * greater than numComponents - 1 * @since 1.4 */ public float getMaxValue(int component) { if ((component < 0) || (component > numComponents - 1)) { throw new IllegalArgumentException( "Component index out of range: " + component); } return 1.0f; } /* Returns true if cspace is the XYZspace. */ static boolean isCS_CIEXYZ(ColorSpace cspace) { return (cspace == XYZspace); } }