<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">/*
 * @(#)ColorModel.java	1.68 00/02/02
 *
 * Copyright 1995-2000 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * This software is the proprietary information of Sun Microsystems, Inc.  
 * Use is subject to license terms.
 * 
 */

package java.awt.image;

import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.Toolkit;

/**
 * The &lt;code&gt;ColorModel&lt;/code&gt; abstract class encapsulates the
 * methods for translating a pixel value to color components 
 * (for example, red, green, and blue) and an alpha component.
 * In order to render an image to the screen, a printer, or another
 * image, pixel values must be converted to color and alpha components.
 * As arguments to or return values from methods of this class,
 * pixels are represented as 32-bit ints or as arrays of primitive types.
 * The number, order, and interpretation of color components for a 
 * &lt;code&gt;ColorModel&lt;/code&gt; is specified by its &lt;code&gt;ColorSpace&lt;/code&gt;.  
 * A &lt;code&gt;ColorModel&lt;/code&gt; used with pixel data that does not include
 * alpha information treats all pixels as opaque, which is an alpha
 * value of 1.0.
 * &lt;p&gt;
 * This &lt;code&gt;ColorModel&lt;/code&gt; class supports two representations of
 * pixel values.  A pixel value can be a single 32-bit int or an
 * array of primitive types.  The Java(tm) Platform 1.0 and 1.1 APIs
 * represented pixels as single &lt;code&gt;byte&lt;/code&gt; or single 
 * &lt;code&gt;int&lt;/code&gt; values.  For purposes of the &lt;code&gt;ColorModel&lt;/code&gt; 
 * class, pixel value arguments were passed as ints.  The Java(tm) 2
 * Platform API introduced additional classes for representing images.
 * With {@link BufferedImage} or {@link RenderedImage}
 * objects, based on {@link Raster} and {@link SampleModel} classes, pixel
 * values might not be conveniently representable as a single int.  
 * Consequently, &lt;code&gt;ColorModel&lt;/code&gt; now has methods that accept
 * pixel values represented as arrays of primitive types.  The primitive
 * type used by a particular &lt;code&gt;ColorModel&lt;/code&gt; object is called its
 * transfer type.
 * &lt;p&gt;
 * &lt;code&gt;ColorModel&lt;/code&gt; objects used with images for which pixel values
 * are not conveniently representable as a single int throw an
 * {@link IllegalArgumentException} when methods taking a single int pixel
 * argument are called.  Subclasses of &lt;code&gt;ColorModel&lt;/code&gt; must
 * specify the conditions under which this occurs.  This does not
 * occur with {@link DirectColorModel} or {@link IndexColorModel} objects.
 * &lt;p&gt;
 * Currently, the transfer types supported by the Java 2D(tm) API are
 * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
 * The transfer type for a particular &lt;code&gt;ColorModel&lt;/code&gt; object is
 * specified when the object is created, either explicitly or by default.
 * All subclasses of &lt;code&gt;ColorModel&lt;/code&gt; must specify what the
 * possible transfer types are and how the number of elements in the
 * primitive arrays representing pixels is determined.
 * &lt;p&gt;
 * For &lt;code&gt;BufferedImages&lt;/code&gt;, the transfer type of its 
 * &lt;code&gt;Raster&lt;/code&gt; and of the &lt;code&gt;Raster&lt;/code&gt; object's
 * &lt;code&gt;SampleModel&lt;/code&gt; (available from the
 * &lt;code&gt;getTransferType&lt;/code&gt; methods of these classes) must match that
 * of the &lt;code&gt;ColorModel&lt;/code&gt;.  The number of elements in an array
 * representing a pixel for the &lt;code&gt;Raster&lt;/code&gt; and 
 * &lt;code&gt;SampleModel&lt;/code&gt; (available from the
 * &lt;code&gt;getNumDataElements&lt;/code&gt; methods of these classes) must match
 * that of the &lt;code&gt;ColorModel&lt;/code&gt;.
 * &lt;p&gt;
 * The algorithm used to convert from pixel values to color and alpha
 * components varies by subclass.  For example, there is not necessarily
 * a one-to-one correspondence between samples obtained from the
 * &lt;code&gt;SampleModel&lt;/code&gt; of a &lt;code&gt;BufferedImage&lt;/code&gt; object's
 * &lt;code&gt;Raster&lt;/code&gt; and color/alpha components.  Even when
 * there is such a correspondence, the number of bits in a sample is not
 * necessarily the same as the number of bits in the corresponding color/alpha
 * component.  Each subclass must specify how the translation from
 * pixel values to color/alpha components is done.
 * &lt;p&gt;
 * Methods in the &lt;code&gt;ColorModel&lt;/code&gt; class use two different
 * representations of color and alpha components.  In the unnormalized
 * form, each component is an unsigned integral value between 0 and
 * 2&lt;sup&gt;n&lt;/sup&gt; - 1, where n is the number of significant bits for a
 * particular component.  If pixel values for a particular 
 * &lt;code&gt;ColorModel&lt;/code&gt; represent color samples premultiplied by
 * the alpha sample, unnormalized color component values are
 * also premultiplied.  In the normalized form, each component is a 
 * &lt;code&gt;float&lt;/code&gt; value between 0.0 and 1.0.  Normalized color
 * component values are not premultiplied.
 *
 * @see IndexColorModel
 * @see ComponentColorModel
 * @see PackedColorModel
 * @see DirectColorModel
 * @see java.awt.Image
 * @see BufferedImage
 * @see RenderedImage
 * @see java.awt.color.ColorSpace
 * @see SampleModel
 * @see Raster
 * @see DataBuffer
 * @version 10 Feb 1997
 */
public abstract class ColorModel implements Transparency{
    private long pData;		// Placeholder for data for native functions

    /**
     * The total number of bits in the pixel.
     */
    protected int pixel_bits;
    int nBits[];
    int transparency = Transparency.TRANSLUCENT;
    boolean supportsAlpha = true;
    boolean isAlphaPremultiplied = false;
    int numComponents = -1;
    int numColorComponents = -1;
    ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
    int colorSpaceType = ColorSpace.TYPE_RGB;
    int maxBits;
    boolean is_sRGB = true;

    /**
     * Data type of the array used to represent pixel values.
     */
    protected int transferType;

    /**
     * This is copied from java.awt.Toolkit since we need the library
     * loaded in java.awt.image also:
     *
     * WARNING: This is a temporary workaround for a problem in the
     * way the AWT loads native libraries. A number of classes in the
     * AWT package have a native method, initIDs(), which initializes
     * the JNI field and method ids used in the native portion of
     * their implementation.
     *
     * Since the use and storage of these ids is done by the
     * implementation libraries, the implementation of these method is
     * provided by the particular AWT implementations
     * (for example, "Toolkit"s/Peer), such as Motif, Win32 or Tiny. The
     * problem is that this means that the native libraries must be
     * loaded by the java.* classes, which do not necessarily know the
     * names of the libraries to load. A better way of doing this
     * would be to provide a separate library which defines java.awt.*
     * initIDs, and exports the relevant symbols out to the
     * implementation libraries.
     * 
     * For now, we know it's done by the implementation, and we assume
     * that the name of the library is "awt".  -br.
     */
    private static boolean loaded = false;
    static void loadLibraries() {
	if (!loaded) {
	    java.security.AccessController.doPrivileged(
		  new sun.security.action.LoadLibraryAction("awt"));
	    loaded = true;
	}
    }
    private static native void initIDs();
    static {
	/* ensure that the proper libraries are loaded */
        loadLibraries();
	initIDs();
    }
    private static ColorModel RGBdefault;

    /**
     * Returns a &lt;code&gt;DirectColorModel&lt;/code&gt; that describes the default
     * format for integer RGB values used in many of the methods in the
     * AWT image interfaces for the convenience of the programmer.
     * The color space is the default {@link ColorSpace}, sRGB.
     * The format for the RGB values is an integer with 8 bits
     * each of alpha, red, green, and blue color components ordered
     * correspondingly from the most significant byte to the least
     * significant byte, as in:  0xAARRGGBB.  Color components are
     * not premultiplied by the alpha component.  This format does not
     * necessarily represent the native or the most efficient
     * &lt;code&gt;ColorModel&lt;/code&gt; for a particular device or for all images.
     * It is merely used as a common color model format.
     * @return a &lt;code&gt;DirectColorModel&lt;/code&gt;object describing default
     *		RGB values.
     */
    public static ColorModel getRGBdefault() {
	if (RGBdefault == null) {
	    RGBdefault = new DirectColorModel(32,
					      0x00ff0000,	// Red
					      0x0000ff00,	// Green
					      0x000000ff,	// Blue
					      0xff000000	// Alpha
					      );
	}
	return RGBdefault;
    }

    /**
     * Constructs a &lt;code&gt;ColorModel&lt;/code&gt; that translates pixels of the
     * specified number of bits to color/alpha components.  The color
     * space is the default RGB &lt;code&gt;ColorSpace&lt;/code&gt;, which is sRGB.
     * Pixel values are assumed to include alpha information.  If color
     * and alpha information are represented in the pixel value as
     * separate spatial bands, the color bands are assumed not to be
     * premultiplied with the alpha value. The transparency type is
     * java.awt.Transparency.TRANSLUCENT.  The transfer type will be the
     * smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 
     * or DataBuffer.TYPE_INT that can hold a single pixel 
     * (or DataBuffer.TYPE_UNDEFINED if bits is greater
     * than 32).  Since this constructor has no information about the
     * number of bits per color and alpha component, any subclass calling
     * this constructor should override any method that requires this
     * information.
     * @param bits the number of bits of a pixel
     * @throws IllegalArgumentException if the number
     * 		of bits in &lt;code&gt;bits&lt;/code&gt; is less than 1
     */
    public ColorModel(int bits) {
	pixel_bits = bits;
        if (bits &lt; 1) {
            throw new IllegalArgumentException("Number of bits must be &gt; 0");
        }
        numComponents = 4;
        numColorComponents = 3;
        maxBits = bits;
        // REMIND: make sure transferType is set correctly
        transferType = ColorModel.getDefaultTransferType(bits);
    }

    /**
     * Constructs a &lt;code&gt;ColorModel&lt;/code&gt; that translates pixel values
     * to color/alpha components.  Color components will be in the
     * specified &lt;code&gt;ColorSpace&lt;/code&gt;. &lt;code&gt;pixel_bits&lt;/code&gt; is the
     * number of bits in the pixel values.  The bits array
     * specifies the number of significant bits per color and alpha component.
     * Its length should be the number of components in the 
     * &lt;code&gt;ColorSpace&lt;/code&gt; if there is no alpha information in the
     * pixel values, or one more than this number if there is alpha
     * information.  &lt;code&gt;hasAlpha&lt;/code&gt; indicates whether or not alpha
     * information is present.  The &lt;code&gt;boolean&lt;/code&gt; 
     * &lt;code&gt;isAlphaPremultiplied&lt;/code&gt; specifies how to interpret pixel
     * values in which color and alpha information are represented as
     * separate spatial bands.  If the &lt;code&gt;boolean&lt;/code&gt;
     * is &lt;code&gt;true&lt;/code&gt;, color samples are assumed to have been
     * multiplied by the alpha sample.  The &lt;code&gt;transparency&lt;/code&gt; 
     * specifies what alpha values can be represented by this color model.
     * The transfer type is the type of primitive array used to represent
     * pixel values.  Note that the bits array contains the number of
     * significant bits per color/alpha component after the translation
     * from pixel values.  For example, for an
     * &lt;code&gt;IndexColorModel&lt;/code&gt; with &lt;code&gt;pixel_bits&lt;/code&gt; equal to
     * 16, the bits array might have four elements with each element set
     * to 8.
     * @param pixel_bits the number of bits in the pixel values
     * @param bits array that specifies the number of significant bits
     *		per color and alpha component
     * @param cspace the specified &lt;code&gt;ColorSpace&lt;/code&gt;
     * @param hasAlpha &lt;code&gt;true&lt;/code&gt; if alpha information is present;
     *		&lt;code&gt;false&lt;/code&gt; otherwise
     * @param isAlphaPremultiplied &lt;code&gt;true&lt;/code&gt; if color samples are
     *		assumed to be premultiplied by the alpha samples;
     *		&lt;code&gt;false&lt;/code&gt; otherwise
     * @param transparency what alpha values can be represented by this
     *		color model
     * @param transferType the type of the array used to represent pixel
     *		values
     * @throws IllegalArgumentException if the length of
     *		the bit array is less than the number of color or alpha
     *		components in this &lt;code&gt;ColorModel&lt;/code&gt;, or if the
     *          transparency is not a valid value.
     * @see java.awt.Transparency
     */
    protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
                         boolean hasAlpha,
                         boolean isAlphaPremultiplied,
                         int transparency,
                         int transferType) {
        colorSpace                = cspace;
        colorSpaceType            = cspace.getType();
        numColorComponents        = cspace.getNumComponents();
        numComponents             = numColorComponents + (hasAlpha ? 1 : 0);
        supportsAlpha             = hasAlpha;
        if (bits.length &lt; numComponents) {
            throw new IllegalArgumentException("Number of color/alpha "+
                                               "components should be "+
                                               numComponents+
                                               " but length of bits array is "+
                                               bits.length);
        }

        // 4186669
        if (transparency &lt; Transparency.OPAQUE ||
            transparency &gt; Transparency.TRANSLUCENT)
        {
            throw new IllegalArgumentException("Unknown transparency: "+
                                               transparency);
        }
        
        if (supportsAlpha == false) {
            this.isAlphaPremultiplied = false;
            this.transparency = Transparency.OPAQUE;
        }
        else {
            this.isAlphaPremultiplied = isAlphaPremultiplied;
            this.transparency         = transparency;
        }

        nBits = (int[]) bits.clone();
        this.pixel_bits = pixel_bits;
        if (pixel_bits &lt;= 0) {
            throw new IllegalArgumentException("Number of pixel bits must "+
                                               "be &gt; 0");
        }
        // Check for bits &lt; 0
        maxBits = 0;
        for (int i=0; i &lt; bits.length; i++) {
            if (bits[i] &lt;= 0) {
                throw new
                    IllegalArgumentException("Number of bits must be &gt; 0");
            }
            if (maxBits &lt; bits[i]) {
                maxBits = bits[i];
            }
        }

        // Save this since we always need to check if it is the default CS
        if (cspace != ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
            is_sRGB = false;
        }

        // Save the transfer type
        this.transferType = transferType;
    }

    /**
     * Returns whether or not alpha is supported in this 
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     * @return &lt;code&gt;true&lt;/code&gt; if alpha is supported in this
     * &lt;code&gt;ColorModel&lt;/code&gt;; &lt;code&gt;false&lt;/code&gt; otherwise.
     */
    final public boolean hasAlpha() {
        return supportsAlpha;
    }
    
    /**
     * Returns whether or not the alpha has been premultiplied in the
     * pixel values to be translated by this &lt;code&gt;ColorModel&lt;/code&gt;.  
     * If the boolean is &lt;code&gt;true&lt;/code&gt;, this &lt;code&gt;ColorModel&lt;/code&gt; 
     * is to be used to interpret pixel values in which color and alpha
     * information are represented as separate spatial bands, and color
     * samples are assumed to have been multiplied by the
     * alpha sample.
     * @return &lt;code&gt;true&lt;/code&gt; if the alpha values are premultiplied
     *		in the pixel values to be translated by this
     *		&lt;code&gt;ColorModel&lt;/code&gt;; &lt;code&gt;false&lt;/code&gt; otherwise.
     */
    final public boolean isAlphaPremultiplied() {
        return isAlphaPremultiplied;
    }

    /**
     * Returns the transfer type of this &lt;code&gt;ColorModel&lt;/code&gt;.
     * The transfer type is the type of primitive array used to represent
     * pixel values as arrays.
     * @return the transfer type.
     */
    final public int getTransferType() {
        return transferType;
    }
    
    /**
     * Returns the number of bits per pixel described by this 
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     * @return the number of bits per pixel.
     */
    public int getPixelSize() {
	return pixel_bits;
    }

    /**
     * Returns the number of bits for the specified color/alpha component.
     * Color components are indexed in the order specified by the 
     * &lt;code&gt;ColorSpace&lt;/code&gt;.  Typically, this order reflects the name
     * of the color space type. For example, for TYPE_RGB, index 0
     * corresponds to red, index 1 to green, and index 2
     * to blue.  If this &lt;code&gt;ColorModel&lt;/code&gt; supports alpha, the alpha
     * component corresponds to the index following the last color
     * component.
     * @param componentIdx the index of the color/alpha component
     * @return the number of bits for the color/alpha component at the
     *		specified index.
     * @throws ArrayIndexOutOfBoundsException if &lt;code&gt;componentIdx&lt;/code&gt; 
     *         is greater than the number of components or
     *         less than zero
     * @throws NullPointerException if the number of bits array is 
     *         &lt;code&gt;null&lt;/code&gt;
     */
    public int getComponentSize(int componentIdx) {
        // REMIND:
        if (nBits == null) {
            throw new NullPointerException("Number of bits array is null.");
        }
        
        return nBits[componentIdx];
    }
    
    /**
     * Returns an array of the number of bits per color/alpha component.  
     * The array contains the color components in the order specified by the
     * &lt;code&gt;ColorSpace&lt;/code&gt;, followed by the alpha component, if
     * present.
     * @return an array of the number of bits per color/alpha component
     */
    public int[] getComponentSize() {
        if (nBits != null) {
            return (int[]) nBits.clone();
        }

        return null;
    }

    /**
     * Returns the transparency.  Returns either OPAQUE, BITMASK,
     * or TRANSLUCENT.
     * @return the transparency of this &lt;code&gt;ColorModel&lt;/code&gt;.
     * @see Transparency#OPAQUE
     * @see Transparency#BITMASK
     * @see Transparency#TRANSLUCENT
     */
    public int getTransparency() {
        return transparency;
    }

    /**
     * Returns the number of components, including alpha, in this
     * &lt;code&gt;ColorModel&lt;/code&gt;.  This is equal to the number of color
     * components, optionally plus one, if there is an alpha component.
     * @return the number of components in this &lt;code&gt;ColorModel&lt;/code&gt;
     */
    public int getNumComponents() {
        return numComponents;
    }
    
    /**
     * Returns the number of color components in this
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     * This is the number of components returned by
     * {@link ColorSpace#getNumComponents}.
     * @return the number of color components in this
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     * @see ColorSpace#getNumComponents
     */
    public int getNumColorComponents() {
        return numColorComponents;
    }

    /**
     * Returns the red color component for the specified pixel, scaled
     * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
     * is done if necessary.  The pixel value is specified as an int.
     * An &lt;code&gt;IllegalArgumentException&lt;/code&gt; is thrown if pixel
     * values for this &lt;code&gt;ColorModel&lt;/code&gt; are not conveniently
     * representable as a single int.  The returned value is not a
     * pre-multiplied value.  For example, if the
     * alpha is premultiplied, this method divides it out before returning
     * the value.  If the alpha value is 0, the red value is 0.
     * @param pixel a specified pixel
     * @return the value of the red component of the specified pixel.
     */
    public abstract int getRed(int pixel);

    /**
     * Returns the green color component for the specified pixel, scaled
     * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
     * is done if necessary.  The pixel value is specified as an int.
     * An &lt;code&gt;IllegalArgumentException&lt;/code&gt; is thrown if pixel
     * values for this &lt;code&gt;ColorModel&lt;/code&gt; are not conveniently
     * representable as a single int.  The returned value is a non
     * pre-multiplied value.  For example, if the alpha is premultiplied,
     * this method divides it out before returning
     * the value.  If the alpha value is 0, the green value is 0.
     * @param pixel the specified pixel
     * @return the value of the green component of the specified pixel.
     */
    public abstract int getGreen(int pixel);

    /**
     * Returns the blue color component for the specified pixel, scaled
     * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
     * is done if necessary.  The pixel value is specified as an int.
     * An &lt;code&gt;IllegalArgumentException&lt;/code&gt; is thrown if pixel values
     * for this &lt;code&gt;ColorModel&lt;/code&gt; are not conveniently representable
     * as a single int.  The returned value is a non pre-multiplied
     * value, for example, if the alpha is premultiplied, this method
     * divides it out before returning the value.  If the alpha value is
     * 0, the blue value is 0.
     * @param pixel the specified pixel
     * @return the value of the blue component of the specified pixel.
     */
    public abstract int getBlue(int pixel);

    /**
     * Returns the alpha component for the specified pixel, scaled
     * from 0 to 255.  The pixel value is specified as an int.
     * An &lt;code&gt;IllegalArgumentException&lt;/code&gt; is thrown if pixel
     * values for this &lt;code&gt;ColorModel&lt;/code&gt; are not conveniently
     * representable as a single int.
     * @param pixel the specified pixel
     * @return the value of alpha component of the specified pixel. 
     */
    public abstract int getAlpha(int pixel);

    /**
     * Returns the color/alpha components of the pixel in the default
     * RGB color model format.  A color conversion is done if necessary.
     * The pixel value is specified as an int.
     * An &lt;code&gt;IllegalArgumentException&lt;/code&gt; thrown if pixel values
     * for this &lt;code&gt;ColorModel&lt;/code&gt; are not conveniently representable
     * as a single int.  The returned value is in a non
     * pre-multiplied format. For example, if the alpha is premultiplied,
     * this method divides it out of the color components.  If the alpha
     * value is 0, the color values are 0.
     * @param pixel the specified pixel
     * @return the RGB value of the color/alpha components of the 
     *		specified pixel.
     * @see ColorModel#getRGBdefault
     */
    public int getRGB(int pixel) {
	return (getAlpha(pixel) &lt;&lt; 24)
	    | (getRed(pixel) &lt;&lt; 16)
	    | (getGreen(pixel) &lt;&lt; 8)
	    | (getBlue(pixel) &lt;&lt; 0);
    }

    /**
     * Returns the red color component for the specified pixel, scaled
     * from 0 to 255 in the default RGB &lt;code&gt;ColorSpace&lt;/code&gt;, sRGB.  A
     * color conversion is done if necessary.  The pixel value is
     * specified by an array of data elements of type transferType passed
     * in as an object reference.  The returned value is a non
     * pre-multiplied value.  For example, if alpha is premultiplied,
     * this method divides it out before returning
     * the value.  If the alpha value is 0, the red value is 0.
     * If &lt;code&gt;inData&lt;/code&gt; is not a primitive array of type
     * transferType, a &lt;code&gt;ClassCastException&lt;/code&gt; is thrown.  An
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown if 
     * &lt;code&gt;inData&lt;/code&gt; is not large enough to hold a pixel value for
     * this &lt;code&gt;ColorModel&lt;/code&gt;.
     * If this &lt;code&gt;transferType&lt;/code&gt; is not supported, a       
     * &lt;code&gt;UnsupportedOperationException&lt;/code&gt; will be
     * thrown.  Since
     * &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class, any instance
     * must be an instance of a subclass.  Subclasses inherit the
     * implementation of this method and if they don't override it, this
     * method throws an exception if the subclass uses a
     * &lt;code&gt;transferType&lt;/code&gt; other than
     * &lt;code&gt;DataBuffer.TYPE_BYTE&lt;/code&gt;,
     * &lt;code&gt;DataBuffer.TYPE_USHORT&lt;/code&gt;, or 
     * &lt;code&gt;DataBuffer.TYPE_INT&lt;/code&gt;. 
     * @param inData an array of pixel values
     * @return the value of the red component of the specified pixel.
     * @throws ClassCastException if &lt;code&gt;inData&lt;/code&gt;
     * 	is not a primitive array of type &lt;code&gt;transferType&lt;/code&gt;
     * @throws ArrayIndexOutOfBoundsException if
     *	&lt;code&gt;inData&lt;/code&gt; is not large enough to hold a pixel value
     *	for this &lt;code&gt;ColorModel&lt;/code&gt;
     * @throws UnsupportedOperationException if this
     *	&lt;code&gt;tranferType&lt;/code&gt; is not supported by this
     *	&lt;code&gt;ColorModel&lt;/code&gt;
     */
    public int getRed(Object inData) {
        int pixel=0,length=0;
        switch (transferType) {
            case DataBuffer.TYPE_BYTE:
               byte bdata[] = (byte[])inData;
               pixel = bdata[0] &amp; 0xff;
               length = bdata.length;
            break;
            case DataBuffer.TYPE_USHORT:
               short sdata[] = (short[])inData;
               pixel = sdata[0] &amp; 0xffff;
               length = sdata.length;
            break;
            case DataBuffer.TYPE_INT:
               int idata[] = (int[])inData;
               pixel = idata[0];
               length = idata.length;
            break;
            default:
               throw new UnsupportedOperationException("This method has not been "+
                   "implemented for transferType " + transferType);
        }
        if (length == 1) {
            return getRed(pixel);
        }
        else {
            throw new UnsupportedOperationException
                ("This method is not supported by this color model");
        }
    }

    /**
     * Returns the green color component for the specified pixel, scaled
     * from 0 to 255 in the default RGB &lt;code&gt;ColorSpace&lt;/code&gt;, sRGB.  A
     * color conversion is done if necessary.  The pixel value is
     * specified by an array of data elements of type transferType passed
     * in as an object reference.  The returned value will be a non
     * pre-multiplied value.  For example, if the alpha is premultiplied,
     * this method divides it out before returning the value.  If the
     * alpha value is 0, the green value is 0.  If &lt;code&gt;inData&lt;/code&gt; is
     * not a primitive array of type transferType, a
     * &lt;code&gt;ClassCastException&lt;/code&gt; is thrown.  An
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown if 
     * &lt;code&gt;inData&lt;/code&gt; is not large enough to hold a pixel value for
     * this &lt;code&gt;ColorModel&lt;/code&gt;.
     * If this &lt;code&gt;transferType&lt;/code&gt; is not supported, a
     * &lt;code&gt;UnsupportedOperationException&lt;/code&gt; will be
     * thrown.  Since
     * &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class, any instance
     * must be an instance of a subclass.  Subclasses inherit the
     * implementation of this method and if they don't override it, this
     * method throws an exception if the subclass uses a
     * &lt;code&gt;transferType&lt;/code&gt; other than 
     * &lt;code&gt;DataBuffer.TYPE_BYTE&lt;/code&gt;, 
     * &lt;code&gt;DataBuffer.TYPE_USHORT&lt;/code&gt;, or  
     * &lt;code&gt;DataBuffer.TYPE_INT&lt;/code&gt;.
     * @param inData an array of pixel values
     * @return the value of the green component of the specified pixel.
     * @throws &lt;code&gt;ClassCastException&lt;/code&gt; if &lt;code&gt;inData&lt;/code&gt;
     *  is not a primitive array of type &lt;code&gt;transferType&lt;/code&gt;
     * @throws &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; if
     *  &lt;code&gt;inData&lt;/code&gt; is not large enough to hold a pixel value
     *  for this &lt;code&gt;ColorModel&lt;/code&gt;
     * @throws &lt;code&gt;UnsupportedOperationException&lt;/code&gt; if this
     *  &lt;code&gt;tranferType&lt;/code&gt; is not supported by this 
     *  &lt;code&gt;ColorModel&lt;/code&gt; 
     */
    public int getGreen(Object inData) {
        int pixel=0,length=0;
        switch (transferType) {
            case DataBuffer.TYPE_BYTE:
               byte bdata[] = (byte[])inData;
               pixel = bdata[0] &amp; 0xff;
               length = bdata.length;
            break;
            case DataBuffer.TYPE_USHORT:
               short sdata[] = (short[])inData;
               pixel = sdata[0] &amp; 0xffff;
               length = sdata.length;
            break;
            case DataBuffer.TYPE_INT:
               int idata[] = (int[])inData;
               pixel = idata[0];
               length = idata.length;
            break;
            default:
               throw new UnsupportedOperationException("This method has not been "+
                   "implemented for transferType " + transferType);
        }
        if (length == 1) {
            return getGreen(pixel);
        }
        else {
            throw new UnsupportedOperationException
                ("This method is not supported by this color model");
        }
    }
    
    /**
     * Returns the blue color component for the specified pixel, scaled
     * from 0 to 255 in the default RGB &lt;code&gt;ColorSpace&lt;/code&gt;, sRGB.  A
     * color conversion is done if necessary.  The pixel value is
     * specified by an array of data elements of type transferType passed
     * in as an object reference.  The returned value is a non
     * pre-multiplied value.  For example, if the alpha is premultiplied,
     * this method divides it out before returning the value.  If the
     * alpha value is 0, the blue value will be 0.  If 
     * &lt;code&gt;inData&lt;/code&gt; is not a primitive array of type transferType,
     * a &lt;code&gt;ClassCastException&lt;/code&gt; is thrown.  An
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is
     * thrown if &lt;code&gt;inData&lt;/code&gt; is not large enough to hold a pixel
     * value for this &lt;code&gt;ColorModel&lt;/code&gt;.
     * If this &lt;code&gt;transferType&lt;/code&gt; is not supported, a
     * &lt;code&gt;UnsupportedOperationException&lt;/code&gt; will be 
     * thrown.  Since
     * &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class, any instance
     * must be an instance of a subclass.  Subclasses inherit the
     * implementation of this method and if they don't override it, this
     * method throws an exception if the subclass uses a
     * &lt;code&gt;transferType&lt;/code&gt; other than 
     * &lt;code&gt;DataBuffer.TYPE_BYTE&lt;/code&gt;, 
     * &lt;code&gt;DataBuffer.TYPE_USHORT&lt;/code&gt;, or  
     * &lt;code&gt;DataBuffer.TYPE_INT&lt;/code&gt;.
     * @param inData an array of pixel values
     * @return the value of the blue component of the specified pixel.
     * @throws ClassCastException if &lt;code&gt;inData&lt;/code&gt;
     *  is not a primitive array of type &lt;code&gt;transferType&lt;/code&gt;
     * @throws ArrayIndexOutOfBoundsException if
     *  &lt;code&gt;inData&lt;/code&gt; is not large enough to hold a pixel value
     *  for this &lt;code&gt;ColorModel&lt;/code&gt;
     * @throws UnsupportedOperationException if this
     *  &lt;code&gt;tranferType&lt;/code&gt; is not supported by this 
     *  &lt;code&gt;ColorModel&lt;/code&gt; 
     */
    public int getBlue(Object inData) {
        int pixel=0,length=0;
        switch (transferType) {
            case DataBuffer.TYPE_BYTE:
               byte bdata[] = (byte[])inData;
               pixel = bdata[0] &amp; 0xff;
               length = bdata.length;
            break;
            case DataBuffer.TYPE_USHORT:
               short sdata[] = (short[])inData;
               pixel = sdata[0] &amp; 0xffff;
               length = sdata.length;
            break;
            case DataBuffer.TYPE_INT:
               int idata[] = (int[])inData;
               pixel = idata[0];
               length = idata.length;
            break;
            default:
               throw new UnsupportedOperationException("This method has not been "+
                   "implemented for transferType " + transferType);
        }
        if (length == 1) {
            return getBlue(pixel);
        }
        else {
            throw new UnsupportedOperationException
                ("This method is not supported by this color model");
        }
    }

    /**
     * Returns the alpha component for the specified pixel, scaled
     * from 0 to 255.  The pixel value is specified by an array of data
     * elements of type transferType passed in as an object reference.
     * If inData is not a primitive array of type transferType, a
     * &lt;code&gt;ClassCastException&lt;/code&gt; is thrown.  An
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown if 
     * &lt;code&gt;inData&lt;/code&gt; is not large enough to hold a pixel value for
     * this &lt;code&gt;ColorModel&lt;/code&gt;.
     * If this &lt;code&gt;transferType&lt;/code&gt; is not supported, a
     * &lt;code&gt;UnsupportedOperationException&lt;/code&gt; will be 
     * thrown.  Since
     * &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class, any instance
     * must be an instance of a subclass.  Subclasses inherit the
     * implementation of this method and if they don't override it, this
     * method throws an exception if the subclass uses a
     * &lt;code&gt;transferType&lt;/code&gt; other than 
     * &lt;code&gt;DataBuffer.TYPE_BYTE&lt;/code&gt;, 
     * &lt;code&gt;DataBuffer.TYPE_USHORT&lt;/code&gt;, or  
     * &lt;code&gt;DataBuffer.TYPE_INT&lt;/code&gt;.
     * @param inData the specified pixel
     * @return the alpha component of the specified pixel, scaled from
     * 0 to 255.
     * @throws ClassCastException if &lt;code&gt;inData&lt;/code&gt; 
     *  is not a primitive array of type &lt;code&gt;transferType&lt;/code&gt;
     * @throws ArrayIndexOutOfBoundsException if
     *  &lt;code&gt;inData&lt;/code&gt; is not large enough to hold a pixel value   
     *  for this &lt;code&gt;ColorModel&lt;/code&gt;
     * @throws UnsupportedOperationException if this
     *  &lt;code&gt;tranferType&lt;/code&gt; is not supported by this
     *  &lt;code&gt;ColorModel&lt;/code&gt;
     */
    public int getAlpha(Object inData) {
        int pixel=0,length=0;
        switch (transferType) {
            case DataBuffer.TYPE_BYTE:
               byte bdata[] = (byte[])inData;
               pixel = bdata[0] &amp; 0xff;
               length = bdata.length;
            break;
            case DataBuffer.TYPE_USHORT:
               short sdata[] = (short[])inData;
               pixel = sdata[0] &amp; 0xffff;
               length = sdata.length;
            break;
            case DataBuffer.TYPE_INT:
               int idata[] = (int[])inData;
               pixel = idata[0];
               length = idata.length;
            break;
            default:
               throw new UnsupportedOperationException("This method has not been "+
                   "implemented for transferType " + transferType);
        }
        if (length == 1) {
            return getAlpha(pixel);
        }
        else {
            throw new UnsupportedOperationException
                ("This method is not supported by this color model");
        }
    }

    /**
     * Returns the color/alpha components for the specified pixel in the
     * default RGB color model format.  A color conversion is done if
     * necessary.  The pixel value is specified by an array of data
     * elements of type transferType passed in as an object reference.
     * If inData is not a primitive array of type transferType, a
     * &lt;code&gt;ClassCastException&lt;/code&gt; is thrown.  An
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is
     * thrown if &lt;code&gt;inData&lt;/code&gt; is not large enough to hold a pixel
     * value for this &lt;code&gt;ColorModel&lt;/code&gt;.
     * The returned value will be in a non pre-multiplied format, i.e. if
     * the alpha is premultiplied, this method will divide it out of the
     * color components (if the alpha value is 0, the color values will be 0).
     * @param inData the specified pixel
     * @return the color and alpha components of the specified pixel.
     * @see ColorModel#getRGBdefault
     */
    public int getRGB(Object inData) {
        return (getAlpha(inData) &lt;&lt; 24)
            | (getRed(inData) &lt;&lt; 16)
            | (getGreen(inData) &lt;&lt; 8)
            | (getBlue(inData) &lt;&lt; 0);
    }

    /**
     * Returns a data element array representation of a pixel in this
     * &lt;code&gt;ColorModel&lt;/code&gt;, given an integer pixel representation in
     * the default RGB color model.
     * This array can then be passed to the 
     * {@link WritableRaster#setDataElements} method of
     * a {@link WritableRaster} object.  If the pixel variable is 
     * &lt;code&gt;null&lt;/code&gt;, a new array will be allocated.  If 
     * &lt;code&gt;pixel&lt;/code&gt; is not
     * &lt;code&gt;null&lt;/code&gt;, it must be a primitive array of type
     * &lt;code&gt;transferType&lt;/code&gt;; otherwise, a
     * &lt;code&gt;ClassCastException&lt;/code&gt; is thrown.  An
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown if 
     * &lt;code&gt;pixel&lt;/code&gt; is
     * not large enough to hold a pixel value for this
     * &lt;code&gt;ColorModel&lt;/code&gt;. The pixel array is returned.
     * If this &lt;code&gt;transferType&lt;/code&gt; is not supported, a
     * &lt;code&gt;UnsupportedOperationException&lt;/code&gt; will be 
     * thrown.  Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
     * any instance is an instance of a subclass.  Subclasses must
     * override this method since the implementation in this abstract
     * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
     * @param rgb the integer pixel representation in the default RGB
     * color model
     * @param pixel the specified pixel
     * @return an array representation of the specified pixel in this
     *	&lt;code&gt;ColorModel&lt;/code&gt;.
     * @throws ClassCastException if &lt;code&gt;pixel&lt;/code&gt;
     *  is not a primitive array of type &lt;code&gt;transferType&lt;/code&gt;
     * @throws ArrayIndexOutOfBoundsException if
     *  &lt;code&gt;pixel&lt;/code&gt; is not large enough to hold a pixel value
     *  for this &lt;code&gt;ColorModel&lt;/code&gt;
     * @throws UnsupportedOperationException if this
     *  method is not supported by this &lt;code&gt;ColorModel&lt;/code&gt; 
     * @see WritableRaster#setDataElements
     * @see SampleModel#setDataElements
     */
    public Object getDataElements(int rgb, Object pixel) {
        throw new UnsupportedOperationException
            ("This method is not supported by this color model.");
    }
    
    /**
     * Returns an array of unnormalized color/alpha components given a pixel 
     * in this &lt;code&gt;ColorModel&lt;/code&gt;.  The pixel value is specified as
     * an &lt;code&gt;int&lt;/code&gt;.  An &lt;code&gt;IllegalArgumentException&lt;/code&gt;
     * will be thrown if pixel values for this &lt;code&gt;ColorModel&lt;/code&gt; are
     * not conveniently representable as a single &lt;code&gt;int&lt;/code&gt;.
     * For example, this method can be used to retrieve the
     * components for a specific pixel value in a 
     * &lt;code&gt;DirectColorModel&lt;/code&gt;.  If the components array is 
     * &lt;code&gt;null&lt;/code&gt;, a new array will be allocated.  The
     * components array will be returned.  Color/alpha components are
     * stored in the components array starting at &lt;code&gt;offset&lt;/code&gt; 
     * (even if the array is allocated by this method).  An
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown if  the
     * components array is not &lt;code&gt;null&lt;/code&gt; and is not large
     * enough to hold all the color and alpha components (starting at offset).
     * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
     * any instance is an instance of a subclass.  Subclasses must   
     * override this method since the implementation in this abstract
     * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
     * @param pixel the specified pixel
     * @param components the array to receive the color and alpha
     * components of the specified pixel
     * @param offset the offset into the &lt;code&gt;components&lt;/code&gt; array at
     * which to start storing the color and alpha components
     * @return an array containing the color and alpha components of the
     * specified pixel starting at the specified offset.
     * @throws UnsupportedOperationException if this
     *		method is not supported by this &lt;code&gt;ColorModel&lt;/code&gt;
     */
    public int[] getComponents(int pixel, int[] components, int offset) {
        throw new UnsupportedOperationException
            ("This method is not supported by this color model.");
    }
    
    /**
     * Returns an array of unnormalized color/alpha components given a pixel
     * in this &lt;code&gt;ColorModel&lt;/code&gt;.  The pixel value is specified by
     * an array of data elements of type transferType passed in as an
     * object reference.  If &lt;code&gt;pixel&lt;/code&gt; is not a primitive array
     * of type transferType, a &lt;code&gt;ClassCastException&lt;/code&gt; is thrown.
     * An &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is
     * thrown if &lt;code&gt;pixel&lt;/code&gt; is not large enough to hold a pixel
     * value for this &lt;code&gt;ColorModel&lt;/code&gt;.
     * This method can be used to retrieve the components for a specific
     * pixel value in any &lt;code&gt;ColorModel&lt;/code&gt;.  If the components
     * array is &lt;code&gt;null&lt;/code&gt;, a new array will be allocated.  The
     * components array will be returned.  Color/alpha components are
     * stored in the &lt;code&gt;components&lt;/code&gt; array starting at 
     * &lt;code&gt;offset&lt;/code&gt; (even if the array is allocated by this
     * method).  An &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt;
     * is thrown if  the components array is not &lt;code&gt;null&lt;/code&gt; and is
     * not large enough to hold all the color and alpha components
     * (starting at &lt;code&gt;offset&lt;/code&gt;).
     * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
     * any instance is an instance of a subclass.  Subclasses must   
     * override this method since the implementation in this abstract
     * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
     * @param pixel the specified pixel
     * @param components an array that receives the color and alpha
     * components of the specified pixel
     * @param offset the index into the &lt;code&gt;components&lt;/code&gt; array at
     * which to begin storing the color and alpha components of the 
     * specified pixel
     * @return an array containing the color and alpha components of the
     * specified pixel starting at the specified offset.
     * @throws UnsupportedOperationException if this
     *		method is not supported by this &lt;code&gt;ColorModel&lt;/code&gt;
     */
    public int[] getComponents(Object pixel, int[] components, int offset) {
        throw new UnsupportedOperationException
            ("This method is not supported by this color model.");
    }

    /**
     * Returns an array of all of the color/alpha components in unnormalized
     * form, given a normalized component array.  Unnormalized components
     * are unsigned integral values between 0 and 2&lt;sup&gt;n&lt;/sup&gt; - 1, where
     * n is the number of bits for a particular component.  Normalized
     * components are float values between 0.0 and 1.0.  If the 
     * &lt;code&gt;components&lt;/code&gt; array is &lt;code&gt;null&lt;/code&gt;, a new array
     * will be allocated.  The &lt;code&gt;components&lt;/code&gt; array will
     * be returned.  Color/alpha components are stored in the 
     * &lt;code&gt;components&lt;/code&gt; array starting at &lt;code&gt;offset&lt;/code&gt; (even
     * if the array is allocated by this method). An
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown if the
     * &lt;code&gt;components&lt;/code&gt; array is not &lt;code&gt;null&lt;/code&gt; and is not
     * large enough to hold all the color and alpha
     * components (starting at &lt;code&gt;offset&lt;/code&gt;).  An
     * &lt;code&gt;IllegalArgumentException&lt;/code&gt; is thrown if the
     * &lt;code&gt;normComponents&lt;/code&gt; array is not large enough to hold
     * all the color and alpha components starting at
     * &lt;code&gt;normOffset&lt;/code&gt;.
     * @param normComponents an array containing normalized components
     * @param normOffset the offset into the &lt;code&gt;normComponents&lt;/code&gt; 
     * array at which to start retrieving normalized components
     * @param components an array that receives the components from
     * &lt;code&gt;normComponents&lt;/code&gt;
     * @param offset the index into &lt;code&gt;components&lt;/code&gt; at which to
     * begin storing normalized components from 
     * &lt;code&gt;normComponents&lt;/code&gt;
     * @return an array containing unnormalized color and alpha 
     * components.
     * @throws IllegalArgumentException if the length of 
     *          &lt;code&gt;normComponents&lt;/code&gt; minus &lt;code&gt;normOffset&lt;/code&gt;
     *          is less than &lt;code&gt;numComponents&lt;/code&gt;
     * @throws UnsupportedOperationException if the
     *          constructor of this &lt;code&gt;ColorModel&lt;/code&gt; called the
     *          &lt;code&gt;super(bits)&lt;/code&gt; constructor, but did not 
     *          override this method.  See the constructor, 
     *          {@link #ColorModel(int)}.
     */
    public int[] getUnnormalizedComponents(float[] normComponents,
                                           int normOffset,
                                           int[] components, int offset) {
        // Make sure that someone isn't using a custom color model
        // that called the super(bits) constructor.
        if (colorSpace == null) {
            throw new UnsupportedOperationException("This method is not supported "+
                                        "by this color model.");
        }

        if (nBits == null) {
            throw new UnsupportedOperationException ("This method is not supported.  "+
                                         "Unable to determine #bits per "+
                                         "component.");
        }
        if ((normComponents.length - normOffset) &lt; numComponents) {
            throw new
                IllegalArgumentException(
                        "Incorrect number of components.  Expecting "+
                        numComponents);
        }
        
        if (components == null) {
            components = new int[offset+numComponents];
        }

        if (supportsAlpha &amp;&amp; isAlphaPremultiplied) {
            float normAlpha = normComponents[normOffset+numColorComponents];
            for (int i=0; i &lt; numColorComponents; i++) {
                components[offset+i] = (int) (normComponents[normOffset+i]
                                              * ((1&lt;&lt;nBits[i]) - 1)
                                              * normAlpha + .5);
            }
            components[offset+numColorComponents] = (int)
                (normAlpha * (1&lt;&lt;nBits[numColorComponents] - 1) + .5);
        }
        else {
            for (int i=0; i &lt; numComponents; i++) {
                components[offset+i] = (int) (normComponents[normOffset+i]
                                              * ((1&lt;&lt;nBits[i]) - 1));
            }
        }
        
        return components;
    }

    /**
     * Returns an array of all of the color/alpha components in normalized
     * form, given an unnormalized component array.  Unnormalized components
     * are unsigned integral values between 0 and 2&lt;sup&gt;n&lt;/sup&gt; - 1, where
     * n is the number of bits for a particular component.  Normalized
     * components are float values between 0.0 and 1.0.  If the 
     * &lt;code&gt;normComponents&lt;/code&gt; array is &lt;code&gt;null&lt;/code&gt;, a new array
     * will be allocated.  The &lt;code&gt;normComponents&lt;/code&gt; array
     * will be returned.  Color/alpha components are stored in the
     * &lt;code&gt;normComponents&lt;/code&gt; array starting at
     * &lt;code&gt;normOffset&lt;/code&gt; (even if the array is allocated by this
     * method).  An &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown
     * if the &lt;code&gt;normComponents&lt;/code&gt; array is not &lt;code&gt;null&lt;/code&gt; 
     * and is not large enough to hold all the color and alpha components
     * (starting at &lt;code&gt;normOffset&lt;/code&gt;).  An
     * &lt;code&gt;IllegalArgumentException&lt;/code&gt; is thrown if the 
     * &lt;code&gt;components&lt;/code&gt; array is not large enough to hold all the
     * color and alpha components starting at &lt;code&gt;offset&lt;/code&gt;.
     * @param components an array containing unnormalized components
     * @param offset the offset into the &lt;code&gt;components&lt;/code&gt; array at
     * which to start retrieving unnormalized components
     * @param normComponents an array that receives the components from
     * &lt;code&gt;components&lt;/code&gt;
     * @param normOffset the index into &lt;code&gt;normComponents&lt;/code&gt; at
     * which to begin storing unnormalized components from
     * &lt;code&gt;components&lt;/code&gt;
     * @return an array containing normalized color and alpha 
     * components. 
     * @throws UnsupportedOperationException if the
     *          constructor of this &lt;code&gt;ColorModel&lt;/code&gt; called the
     *          &lt;code&gt;super(bits)&lt;/code&gt; constructor, but did not
     *          override this method.  See the constructor,
     *          {@link #ColorModel(int)}.
     * @throws UnsupportedOperationException if this method is unable
     *          to determine the number of bits per component
     */
    public float[] getNormalizedComponents(int[] components, int offset,
                                           float[] normComponents,
                                           int normOffset) {
        // Make sure that someone isn't using a custom color model
        // that called the super(bits) constructor.
        if (colorSpace == null) {
            throw new UnsupportedOperationException("This method is not supported by "+
                                        "this color model.");
        }
        if (nBits == null) {
            throw new UnsupportedOperationException ("This method is not supported.  "+
                                         "Unable to determine #bits per "+
                                         "component.");
        }
        
        if ((components.length - offset) &lt; numComponents) {
            throw new
                IllegalArgumentException(
                        "Incorrect number of components.  Expecting "+
                        numComponents);
        }
        
        if (normComponents == null) {
            normComponents = new float[numComponents+normOffset];
        }

        if (supportsAlpha &amp;&amp; isAlphaPremultiplied) {
            // Normalized coordinates are non premultiplied
            float normAlpha = (float)components[offset+numColorComponents];
            normAlpha /= ((1&lt;&lt;nBits[numColorComponents]) - 1.f);
            for (int i=0; i &lt; numColorComponents; i++) {
                normComponents[normOffset+i] =
                    ((float)components[offset+i]) /
                    (normAlpha * ((1&lt;&lt;nBits[i]) - 1.f));
            }
            normComponents[normOffset+numColorComponents] = normAlpha;
        }
        else {
            for (int i=0; i &lt; numComponents; i++) {
                normComponents[normOffset+i] =
                    (float) components[offset+i] / ((1&lt;&lt;nBits[i]) - 1.f);
            }
        }

        return normComponents;
    }

    /**
     * Returns a pixel value represented as an &lt;code&gt;int&lt;/code&gt; in this
     * &lt;code&gt;ColorModel&lt;/code&gt;, given an array of unnormalized color/alpha
     * components.  This method will throw an 
     * &lt;code&gt;IllegalArgumentException&lt;/code&gt; if pixel values for this
     * &lt;code&gt;ColorModel&lt;/code&gt; are not conveniently representable as a
     * single &lt;code&gt;int&lt;/code&gt;. An 
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown if  the
     * &lt;code&gt;components&lt;/code&gt; array is not large enough to hold all the
     * color and alpha components (starting at &lt;code&gt;offset&lt;/code&gt;).
     * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
     * any instance is an instance of a subclass.  Subclasses must
     * override this method since the implementation in this abstract
     * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
     * @param components an array of unnormalized color and alpha
     * components
     * @param offset the index into &lt;code&gt;components&lt;/code&gt; at which to
     * begin retrieving the color and alpha components
     * @return an &lt;code&gt;int&lt;/code&gt; pixel value in this
     * &lt;code&gt;ColorModel&lt;/code&gt; corresponding to the specified components.  
     * @throws IllegalArgumentException if
     * 	pixel values for this &lt;code&gt;ColorModel&lt;/code&gt; are not 
     * 	conveniently representable as a single &lt;code&gt;int&lt;/code&gt;
     * @throws ArrayIndexOutOfBoundsException if
     *  the &lt;code&gt;components&lt;/code&gt; array is not large enough to 
     *	hold all of the color and alpha components starting at
     *	&lt;code&gt;offset&lt;/code&gt; 
     * @throws UnsupportedOperationException if this
     * 	method is not supported by this &lt;code&gt;ColorModel&lt;/code&gt;
     */
    public int getDataElement(int[] components, int offset) {
        throw new UnsupportedOperationException("This method is not supported "+
                                    "by this color model.");
    }
    
    /**
     * Returns a data element array representation of a pixel in this
     * &lt;code&gt;ColorModel&lt;/code&gt;, given an array of unnormalized color/alpha
     * components.  This array can then be passed to the
     * &lt;code&gt;setDataElements&lt;/code&gt; method of a &lt;code&gt;WritableRaster&lt;/code&gt; 
     * object.  An &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown
     * if the &lt;code&gt;components&lt;/code&gt; array is not large enough to hold
     * all the color and alpha components (starting at
     * &lt;code&gt;offset&lt;/code&gt;).  If the &lt;code&gt;obj&lt;/code&gt; variable is
     * &lt;code&gt;null&lt;/code&gt;, a new array will be allocated.  If
     * &lt;code&gt;obj&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt;, it must be a primitive
     * array of type transferType; otherwise, a 
     * &lt;code&gt;ClassCastException&lt;/code&gt; is thrown.  An
     * &lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt; is thrown if 
     * &lt;code&gt;obj&lt;/code&gt; is not large enough to hold a pixel value for this
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
     * any instance is an instance of a subclass.  Subclasses must
     * override this method since the implementation in this abstract
     * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
     * @param components an array of unnormalized color and alpha
     * components
     * @param offset the index into &lt;code&gt;components&lt;/code&gt; at which to
     * begin retrieving color and alpha components
     * @param obj the &lt;code&gt;Object&lt;/code&gt; representing an array of color
     * and alpha components
     * @return an &lt;code&gt;Object&lt;/code&gt; representing an array of color and
     * alpha components.
     * @throws ClassCastException if &lt;code&gt;obj&lt;/code&gt;
     *  is not a primitive array of type &lt;code&gt;transferType&lt;/code&gt;
     * @throws ArrayIndexOutOfBoundsException if
     *  &lt;code&gt;obj&lt;/code&gt; is not large enough to hold a pixel value
     *  for this &lt;code&gt;ColorModel&lt;/code&gt; or the &lt;code&gt;components&lt;/code&gt;
     *	array is not large enough to hold all of the color and alpha
     *	components starting at &lt;code&gt;offset&lt;/code&gt; 
     * @throws UnsupportedOperationException if this 
     *  method is not supported by this &lt;code&gt;ColorModel&lt;/code&gt; 
     * @see WritableRaster#setDataElements
     * @see SampleModel#setDataElements
     */
    public Object getDataElements(int[] components, int offset, Object obj) {
        throw new UnsupportedOperationException("This method has not been implemented "+
                                    "for this color model.");
    }

    /**
     * Tests if the specified &lt;code&gt;Object&lt;/code&gt; is an instance of
     * &lt;code&gt;ColorModel&lt;/code&gt; and if it equals this
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     * @param obj the &lt;code&gt;Object&lt;/code&gt; to test for equality
     * @return &lt;code&gt;true&lt;/code&gt; if the specified &lt;code&gt;Object&lt;/code&gt;
     * is an instance of &lt;code&gt;ColorModel&lt;/code&gt; and equals this
     * &lt;code&gt;ColorModel&lt;/code&gt;; &lt;code&gt;false&lt;/code&gt; otherwise.
     */
    public boolean equals(Object obj) {
        if (!(obj instanceof ColorModel)) {
            return false;
        }
        ColorModel cm = (ColorModel) obj;
        
        if (this == cm) {
            return true;
        }
        if (supportsAlpha != cm.hasAlpha() ||
            isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
            pixel_bits != cm.getPixelSize() ||
            transparency != cm.getTransparency() ||
            numComponents != cm.getNumComponents())
        {
            return false;
        }
        int i;
        int[] nb = cm.getComponentSize();
        for (i=0; i &lt; numComponents; i++) {
            if (nBits[i] != nb[i]) {
                return false;
            }
        }

        return true;
    }

    /**
     * Returns the hash code for this ColorModel.
     *
     * @return    a hash code for this ColorModel.
     */
    public int hashCode() {
        
        int result = 0;

        result = (supportsAlpha ? 2 : 3) +
                 (isAlphaPremultiplied ? 4 : 5) +
                 pixel_bits * 6 +
                 transparency * 7 +
                 numComponents * 8;

	int i;
        for (i=0; i &lt; numComponents; i++) {
            result = result + nBits[i] * (i + 9);
        }

        return result;
    }
    
    /**
     * Returns the &lt;code&gt;ColorSpace&lt;/code&gt; associated with this 
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     * @return the &lt;code&gt;ColorSpace&lt;/code&gt; of this
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     */
    final public ColorSpace getColorSpace() {
        return colorSpace;
    }

    /**
     * Forces the raster data to match the state specified in the
     * &lt;code&gt;isAlphaPremultiplied&lt;/code&gt; variable, assuming the data is
     * currently correctly described by this &lt;code&gt;ColorModel&lt;/code&gt;.  It
     * may multiply or divide the color raster data by alpha, or do
     * nothing if the data is in the correct state.  If the data needs to
     * be coerced, this method will also return an instance of this
     * &lt;code&gt;ColorModel&lt;/code&gt; with the &lt;code&gt;isAlphaPremultiplied&lt;/code&gt; 
     * flag set appropriately.  This method will throw a
     * &lt;code&gt;UnsupportedOperationException&lt;/code&gt; if it is not supported
     * by this &lt;code&gt;ColorModel&lt;/code&gt;.
     * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
     * any instance is an instance of a subclass.  Subclasses must
     * override this method since the implementation in this abstract
     * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
     * @param raster the &lt;code&gt;WritableRaster&lt;/code&gt; data
     * @param isAlphaPremultiplied &lt;code&gt;true&lt;/code&gt; if the alpha is
     * premultiplied; &lt;code&gt;false&lt;/code&gt; otherwise
     * @return a &lt;code&gt;ColorModel&lt;/code&gt; object that represents the
     * coerced data.
     */
    public ColorModel coerceData (WritableRaster raster,
                                  boolean isAlphaPremultiplied) {
        throw new UnsupportedOperationException
            ("This method is not supported by this color model");
    }

    /**
      * Returns &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;raster&lt;/code&gt; is compatible
      * with this &lt;code&gt;ColorModel&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; if it is
      * not.
      * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
      * any instance is an instance of a subclass.  Subclasses must
      * override this method since the implementation in this abstract
      * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
      * @param raster the {@link Raster} object to test for compatibility
      * @return &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;raster&lt;/code&gt; is compatible
      * with this &lt;code&gt;ColorModel&lt;/code&gt;.
      * @throws UnsupportedOperationException if this
      *		method has not been implemented for this 
      *		&lt;code&gt;ColorModel&lt;/code&gt;
      */
    public boolean isCompatibleRaster(Raster raster) {
	throw new UnsupportedOperationException(
            "This method has not been implemented for this ColorModel.");
    }

    /**
     * Creates a &lt;code&gt;WritableRaster&lt;/code&gt; with the specified width and
     * height that has a data layout (&lt;code&gt;SampleModel&lt;/code&gt;) compatible
     * with this &lt;code&gt;ColorModel&lt;/code&gt;.
     * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
     * any instance is an instance of a subclass.  Subclasses must
     * override this method since the implementation in this abstract
     * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
     * @param w the width to apply to the new &lt;code&gt;WritableRaster&lt;/code&gt;
     * @param h the height to apply to the new &lt;code&gt;WritableRaster&lt;/code&gt;
     * @return a &lt;code&gt;WritableRaster&lt;/code&gt; object with the specified
     * width and height.  
     * @throws UnsupportedOperationException if this
     * 		method is not supported by this &lt;code&gt;ColorModel&lt;/code&gt;
     * @see WritableRaster
     * @see SampleModel
     */
    public WritableRaster createCompatibleWritableRaster(int w, int h) {
	throw new UnsupportedOperationException
            ("This method is not supported by this color model");
    }
    
    /**
     * Creates a &lt;code&gt;SampleModel&lt;/code&gt; with the specified width and
     * height that has a data layout compatible with this 
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
     * any instance is an instance of a subclass.  Subclasses must
     * override this method since the implementation in this abstract
     * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
     * @param w the width to apply to the new &lt;code&gt;SampleModel&lt;/code&gt;
     * @param h the height to apply to the new &lt;code&gt;SampleModel&lt;/code&gt;
     * @return a &lt;code&gt;SampleModel&lt;/code&gt; object with the specified
     * width and height.
     * @throws UnsupportedOperationException if this
     * 		method is not supported by this &lt;code&gt;ColorModel&lt;/code&gt;  
     * @see SampleModel
     */
    public SampleModel createCompatibleSampleModel(int w, int h) {
	throw new UnsupportedOperationException
            ("This method is not supported by this color model");
    }

    /** Checks if the &lt;code&gt;SampleModel&lt;/code&gt; is compatible with this
     * &lt;code&gt;ColorModel&lt;/code&gt;.
     * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class,
     * any instance is an instance of a subclass.  Subclasses must
     * override this method since the implementation in this abstract
     * class throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt;.
     * @param sm the specified &lt;code&gt;SampleModel&lt;/code&gt;
     * @return &lt;code&gt;true&lt;/code&gt; if the specified &lt;code&gt;SampleModel&lt;/code&gt;
     * is compatible with this &lt;code&gt;ColorModel&lt;/code&gt;; &lt;code&gt;false&lt;/code&gt;
     * otherwise.
     * @throws UnsupportedOperationException if this
     * 		method is not supported by this &lt;code&gt;ColorModel&lt;/code&gt;
     * @see SampleModel 
     */
    public boolean isCompatibleSampleModel(SampleModel sm) {
	throw new UnsupportedOperationException
            ("This method is not supported by this color model");
    }
    
    /**
     * Disposes of system resources associated with this 
     * &lt;code&gt;ColorModel&lt;/code&gt; once this &lt;code&gt;ColorModel&lt;/code&gt; is no
     * longer referenced.
     */
    public void finalize() {
    }


    /**
     * Returns a &lt;code&gt;Raster&lt;/code&gt; representing the alpha channel of an
     * image, extracted from the input &lt;code&gt;Raster&lt;/code&gt;, provided that
     * pixel values of this &lt;code&gt;ColorModel&lt;/code&gt; represent color and
     * alpha information as separate spatial bands (e.g.
     * {@link ComponentColorModel} and &lt;code&gt;DirectColorModel&lt;/code&gt;).
     * This method assumes that &lt;code&gt;Raster&lt;/code&gt; objects associated
     * with such a &lt;code&gt;ColorModel&lt;/code&gt; store the alpha band, if
     * present, as the last band of image data.  Returns &lt;code&gt;null&lt;/code&gt; 
     * if there is no separate spatial alpha channel associated with this
     * &lt;code&gt;ColorModel&lt;/code&gt;.  If this is an
     * &lt;code&gt;IndexColorModel&lt;/code&gt; which has alpha in the lookup table,
     * this method will return &lt;code&gt;null&lt;/code&gt; since
     * there is no spatially discrete alpha channel.
     * This method will create a new &lt;code&gt;Raster&lt;/code&gt; (but will share
     * the data array).
     * Since &lt;code&gt;ColorModel&lt;/code&gt; is an abstract class, any instance 
     * is an instance of a subclass.  Subclasses must override this 
     * method to get any behavior other than returning &lt;code&gt;null&lt;/code&gt;
     * because the implementation in this abstract class returns
     * &lt;code&gt;null&lt;/code&gt;.
     * @param raster the specified &lt;code&gt;Raster&lt;/code&gt;
     * @return a &lt;code&gt;Raster&lt;/code&gt; representing the alpha channel of
     * an image, obtained from the specified &lt;code&gt;Raster&lt;/code&gt;.
     */
    public WritableRaster getAlphaRaster(WritableRaster raster) {
        return null;
    }

    /**
     * Returns the &lt;code&gt;String&lt;/code&gt; representation of the contents of
     * this &lt;code&gt;ColorModel&lt;/code&gt;object.
     * @return a &lt;code&gt;String&lt;/code&gt; representing the contents of this
     * &lt;code&gt;ColorModel&lt;/code&gt; object.
     */
    public String toString() {
       return new String("ColorModel: #pixelBits = "+pixel_bits
                         + " numComponents = "+numComponents
                         + " color space = "+colorSpace
                         + " transparency = "+transparency
                         + " has alpha = "+supportsAlpha
                         + " isAlphaPre = "+isAlphaPremultiplied
                         );
    }

    static int getDefaultTransferType(int pixel_bits) {
        if (pixel_bits &lt;= 8) {
            return DataBuffer.TYPE_BYTE;
        } else if (pixel_bits &lt;= 16) {
            return DataBuffer.TYPE_USHORT;
        } else if (pixel_bits &lt;= 32) {
            return DataBuffer.TYPE_INT;
        } else {
            return DataBuffer.TYPE_UNDEFINED;
        }
    }

}
</pre></body></html>