FileDocCategorySizeDatePackage
ColorSpace.javaAPI DocJava SE 5 API18766Fri Aug 26 14:56:46 BST 2005java.awt.color

ColorSpace.java

/*
 * @(#)ColorSpace.java	1.39 03/12/19
 *
 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/**********************************************************************
 **********************************************************************
 **********************************************************************
 *** 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 sun.awt.color.CMM;


/**
 * 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.
 * <p>
 * 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.
 * <p>
 * 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 <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
 * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
 * </A>.
 * <p>
 * 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.
 * <p>
 * The CS_CIEXYZ space used by the toCIEXYZ/fromCIEXYZ methods can be
 * described as follows:
<pre>

      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).

</pre>
 *
 * <p>
 * @see ICC_ColorSpace
 * @version 10 Feb 1997
 */



public abstract class ColorSpace implements java.io.Serializable {

    static final long serialVersionUID = -409452704308689724L;

    private int type;
    private int numComponents;

    // 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.
     */
    public static final int TYPE_XYZ = 0;

    /**
     * Any of the family of Lab color spaces.
     */
    public static final int TYPE_Lab = 1;

    /**
     * Any of the family of Luv color spaces.
     */
    public static final int TYPE_Luv = 2;

    /**
     * Any of the family of YCbCr color spaces.
     */
    public static final int TYPE_YCbCr = 3;

    /**
     * Any of the family of Yxy color spaces.
     */
    public static final int TYPE_Yxy = 4;

    /**
     * Any of the family of RGB color spaces.
     */
    public static final int TYPE_RGB = 5;

    /**
     * Any of the family of GRAY color spaces.
     */
    public static final int TYPE_GRAY = 6;

    /**
     * Any of the family of HSV color spaces.
     */
    public static final int TYPE_HSV = 7;

    /**
     * Any of the family of HLS color spaces.
     */
    public static final int TYPE_HLS = 8;

    /**
     * Any of the family of CMYK color spaces.
     */
    public static final int TYPE_CMYK = 9;

    /**
     * Any of the family of CMY color spaces.
     */
    public static final int TYPE_CMY = 11;

    /**
     * Generic 2 component color spaces.
     */
    public static final int TYPE_2CLR = 12;

    /**
     * Generic 3 component color spaces.
     */
    public static final int TYPE_3CLR = 13;

    /**
     * Generic 4 component color spaces.
     */
    public static final int TYPE_4CLR = 14;

    /**
     * Generic 5 component color spaces.
     */
    public static final int TYPE_5CLR = 15;

    /**
     * Generic 6 component color spaces.
     */
    public static final int TYPE_6CLR = 16;

    /**
     * Generic 7 component color spaces.
     */
    public static final int TYPE_7CLR = 17;

    /**
     * Generic 8 component color spaces.
     */
    public static final int TYPE_8CLR = 18;

    /**
     * Generic 9 component color spaces.
     */
    public static final int TYPE_9CLR = 19;

    /**
     * Generic 10 component color spaces.
     */
    public static final int TYPE_ACLR = 20;

    /**
     * Generic 11 component color spaces.
     */
    public static final int TYPE_BCLR = 21;

    /**
     * Generic 12 component color spaces.
     */
    public static final int TYPE_CCLR = 22;

    /**
     * Generic 13 component color spaces.
     */
    public static final int TYPE_DCLR = 23;

    /**
     * Generic 14 component color spaces.
     */
    public static final int TYPE_ECLR = 24;

    /**
     * Generic 15 component color spaces.
     */
    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">
     * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
     * </A>.
     */
    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.
     */
    public static final int CS_LINEAR_RGB = 1004;

    /**
     * The CIEXYZ conversion color space defined above.
     */
    public static final int CS_CIEXYZ = 1001;

    /**
     * The Photo YCC conversion color space.
     */
    public static final int CS_PYCC = 1002;

    /**
     * The built-in linear gray scale color space.
     */
    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 <CODE>ColorSpace</CODE> 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 <CODE>ColorSpace</CODE> 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:
            if (sRGBspace == null) {
                ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB);
                sRGBspace = new ICC_ColorSpace (theProfile);
            }

            theColorSpace = sRGBspace;
            break;
        
        case CS_CIEXYZ:
            if (XYZspace == null) {
                ICC_Profile theProfile = ICC_Profile.getInstance (CS_CIEXYZ);
                XYZspace = new ICC_ColorSpace (theProfile);
            }

            theColorSpace = XYZspace;
            break;
        
        case CS_PYCC:
            if (PYCCspace == null) {
                ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC);
                PYCCspace = new ICC_ColorSpace (theProfile);
            }

            theColorSpace = PYCCspace;
            break;
        

        case CS_GRAY:
            if (GRAYspace == null) {
                ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY);
                GRAYspace = new ICC_ColorSpace (theProfile);
             CMM.GRAYspace = GRAYspace;   // to allow access from
                                          // java.awt.ColorModel
            }

            theColorSpace = GRAYspace;
            break;
        

        case CS_LINEAR_RGB:
            if (LINEAR_RGBspace == null) {
                ICC_Profile theProfile = ICC_Profile.getInstance(CS_LINEAR_RGB);
                LINEAR_RGBspace = new ICC_ColorSpace (theProfile);
             CMM.LINEAR_RGBspace = LINEAR_RGBspace;   // to allow access from
                                                      // java.awt.ColorModel
            }

            theColorSpace = LINEAR_RGBspace;
            break;
        

        default:
            throw new IllegalArgumentException ("Unknown color space");
        }
        
        return theColorSpace;
    }


    /**
     * Returns true if the ColorSpace is CS_sRGB.
     * @return <CODE>true</CODE> if this is a <CODE>CS_sRGB</CODE> color 
     *         space, <code>false</code> 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.
     * <p>
     * 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 <code>toCIEXYZ</code>
     * method of this color space to first convert from the input 
     * color space to the CS_CIEXYZ color space, and then use the 
     * <code>fromCIEXYZ</code> 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.
     * <p>
     * @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.
     * <p>
     * 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 <code>toCIEXYZ</code>
     * 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
     * <code>fromCIEXYZ</code> 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.
     * <p>
     * @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.
     * <p>
     * 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
     * <code>ICC_ColorSpace</code> for further information.
     * <p>
     * @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.
     * <p>
     * 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
     * <code>ICC_ColorSpace</code> for further information.
     * <p>
     * @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 
     *         <CODE>ColorSpace</CODE>
     */
    public int getType() {
        return type;
    }

    /**
     * Returns the number of components of this ColorSpace.
     * @return The number of components in this <CODE>ColorSpace</CODE>.
     */
    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 <code>idx</code> 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);
        }
        return new String("Unnamed color component("+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);
    }
}