- /*
 - * @(#)DirectColorModel.java 1.60 01/11/29
 - *
 - * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
 - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 - */
 - package java.awt.image;
 - import java.awt.color.ColorSpace;
 - import java.awt.Transparency;
 - /**
 - * A ColorModel class that works with pixel values which represent RGB
 - * color and alpha information as separate samples and which pack all
 - * samples for a single pixel into a single int, short, or byte quantity.
 - * This class can be used only with ColorSpaces of type ColorSpace.TYPE_RGB.
 - * There must be three color samples in the pixel values and there may
 - * be a single alpha sample. For those methods which use a primitive array
 - * pixel representation of type transferType, the array length is always
 - * one. Color and alpha samples are stored in the single element of the
 - * array in bits indicated by bit masks. Each bit mask must be contiguous
 - * and masks must not overlap. The same masks apply to the single int
 - * pixel representation used by other methods. The correspondence of
 - * masks and color/alpha samples is as follows. Masks are identified by
 - * indices running from 0 through 2, if no alpha is present, or 3. The
 - * first three indices refer to color samples; index 0 corresponds to red,
 - * index 1 to green, and index 2 to blue. Index 3 corresponds to the alpha
 - * sample, if present. The transfer types supported are DataBuffer.TYPE_BYTE,
 - * DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
 - * <p>
 - * The translation from pixel values to color/alpha components for
 - * display or processing purposes is a one-to-one correspondence of
 - * samples to components.
 - * A DirectColorModel is typically used with image data which uses masks
 - * to define packed samples. For example, a DirectColorModel can be used in
 - * conjunction with a SinglePixelPackedSampleModel to construct a
 - * BufferedImage. Normally the masks used by the SampleModel and the
 - * ColorModel would be the same. However, if they are different, the
 - * color interpretation of pixel data will be done according to the
 - * masks of the ColorModel.
 - * <p>
 - * A single int pixel representation is valid for all objects of this
 - * class, since it is always possible to represent pixel values used with
 - * this class in a single int. Therefore, methods which use this
 - * representation will not throw an IllegalArgumentException due to
 - * an invalid pixel value.
 - * <p>
 - * This color model is similar to an X11 TrueColor visual.
 - * The default RGB ColorModel specified by the ColorModel.getRGBdefault
 - * method is a DirectColorModel with the following parameters:
 - * <pre>
 - * Number of bits: 32
 - * Red mask: 0x00ff0000
 - * Green mask: 0x0000ff00
 - * Blue mask: 0x000000ff
 - * Alpha mask: 0xff000000
 - * Color space: sRGB
 - * isAlphaPremultiplied: False
 - * Transparency: Transparency.TRANSLUCENT
 - * transferType: DataBuffer.TYPE_INT
 - * </pre>
 - * <p>
 - * Many of the methods in this class are final. This is because the
 - * underlying native graphics code makes assumptions about the layout
 - * and operation of this class and those assumptions are reflected in
 - * the implementations of the methods here that are marked final. You
 - * can subclass this class for other reasons, but you cannot override
 - * or modify the behavior of those methods.
 - *
 - * @see ColorModel
 - * @see ColorSpace
 - * @see SinglePixelPackedSampleModel
 - * @see BufferedImage
 - * @see ColorModel#getRGBdefault
 - *
 - * @version 10 Feb 1997
 - */
 - public class DirectColorModel extends PackedColorModel {
 - private int red_mask;
 - private int green_mask;
 - private int blue_mask;
 - private int alpha_mask;
 - private int red_offset;
 - private int green_offset;
 - private int blue_offset;
 - private int alpha_offset;
 - private int red_scale;
 - private int green_scale;
 - private int blue_scale;
 - private int alpha_scale;
 - /**
 - * Constructs a DirectColorModel from the given masks specifying which
 - * bits in an int pixel representation contain the red, green and blue
 - * color samples. Pixel values do not contain alpha information, so
 - * all pixels will be treated as opaque (alpha = 1.0). All of the bits
 - * in each mask must be contiguous and fit in the specified number
 - * of least significant bits of an int pixel representation. The
 - * ColorSpace will be the default sRGB space. The
 - * transparency value will be Transparency.OPAQUE. The transfer type
 - * will be the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
 - * or DataBuffer.TYPE_INT that can hold a single pixel.
 - */
 - public DirectColorModel(int bits,
 - int rmask, int gmask, int bmask) {
 - this(bits, rmask, gmask, bmask, 0);
 - }
 - /**
 - * Constructs a DirectColorModel from the given masks specifying which
 - * bits in an int pixel representation contain the red, green and blue
 - * color samples and the alpha sample, if present. If amask is 0,
 - * pixel values do not contain alpha information, so all pixels will
 - * be treated as opaque (alpha = 1.0). All of the bits in each mask must
 - * be contiguous and fit in the specified number of least significant bits
 - * of an int pixel representation. Alpha, if present, will not be
 - * premultiplied. The ColorSpace will be the default sRGB space. The
 - * transparency value will be Transparency.OPAQUE, if no alpha is
 - * present, or Transparency.TRANSLUCENT otherwise. The transfer type
 - * will be the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
 - * or DataBuffer.TYPE_INT that can hold a single pixel.
 - */
 - public DirectColorModel(int bits, int rmask, int gmask,
 - int bmask, int amask) {
 - super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
 - bits, rmask, gmask, bmask, amask, false,
 - amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
 - ColorModel.getDefaultTransferType(bits));
 - setFields();
 - }
 - /**
 - * Constructs a DirectColorModel from the specified parameters.
 - * Color components will be in the specified ColorSpace, which must
 - * be of type ColorSpace.TYPE_RGB.
 - * The masks specify which bits in an int pixel representation contain
 - * the red, green and blue color samples and the alpha sample, if present.
 - * If amask is 0, pixel values do not contain alpha information, so
 - * all pixels will be treated as opaque (alpha = 1.0). All of the bits
 - * in each mask must be contiguous and fit in the specified number of
 - * least significant bits of an int pixel representation. If there
 - * is alpha, the boolean isAlphaPremultiplied specifies how to interpret
 - * color and alpha samples in pixel values. If the boolean is true, color
 - * samples are assumed to have been multiplied by the alpha sample.
 - * The transparency value will be Transparency.OPAQUE, if no alpha is
 - * present, or Transparency.TRANSLUCENT otherwise. The transfer type
 - * is the type of primitive array used to represent pixel values and
 - * must be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or
 - * DataBuffer.TYPE_INT.
 - */
 - public DirectColorModel(ColorSpace space, int bits, int rmask,
 - int gmask, int bmask, int amask,
 - boolean isAlphaPremultiplied,
 - int transferType) {
 - super (space, bits, rmask, gmask, bmask, amask,
 - isAlphaPremultiplied,
 - amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
 - transferType);
 - setFields();
 - }
 - /**
 - * Returns the mask indicating which bits in an int pixel representation
 - * contain the red color component.
 - */
 - final public int getRedMask() {
 - return maskArray[0];
 - }
 - /**
 - * Returns the mask indicating which bits in an int pixel representation
 - * contain the green color component.
 - */
 - final public int getGreenMask() {
 - return maskArray[1];
 - }
 - /**
 - * Returns the mask indicating which bits in an int pixel representation
 - * contain the blue color component.
 - */
 - final public int getBlueMask() {
 - return maskArray[2];
 - }
 - /**
 - * Returns the mask indicating which bits in an int pixel representation
 - * contain the alpha component.
 - */
 - final public int getAlphaMask() {
 - if (supportsAlpha) {
 - return maskArray[3];
 - } else {
 - return 0;
 - }
 - }
 - /**
 - * 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.
 - * The returned value will be a non pre-multiplied value, i.e. if the
 - * alpha is premultiplied, this method will divide it out before returning
 - * the value (if the alpha value is 0, the red value will be 0).
 - */
 - final public int getRed(int pixel) {
 - int r = ((pixel & maskArray[0]) >>> maskOffsets[0]);
 - if (scaleFactors[0] != 1.) {
 - r = (int)(r * scaleFactors[0]);
 - }
 - if (isAlphaPremultiplied) {
 - int a = getAlpha(pixel);
 - r = (a == 0) ? 0 : (r * 255/a);
 - if (r > 255) {
 - r = 255;
 - }
 - }
 - return r;
 - }
 - /**
 - * 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.
 - * The returned value will be a non pre-multiplied value, i.e. if the
 - * alpha is premultiplied, this method will divide it out before returning
 - * the value (if the alpha value is 0, the green value will be 0).
 - */
 - final public int getGreen(int pixel) {
 - int g = ((pixel & maskArray[1]) >>> maskOffsets[1]);
 - if (scaleFactors[1] != 1.) {
 - g = (int) (g * scaleFactors[1]);
 - }
 - if (isAlphaPremultiplied) {
 - int a = getAlpha(pixel);
 - g = (a == 0) ? 0 : (g * 255/a);
 - if (g > 255) {
 - g = 255;
 - }
 - }
 - return g;
 - }
 - /**
 - * 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.
 - * The returned value will be a non pre-multiplied value, i.e. if the
 - * alpha is premultiplied, this method will divide it out before returning
 - * the value (if the alpha value is 0, the blue value will be 0).
 - */
 - final public int getBlue(int pixel) {
 - int b = ((pixel & maskArray[2]) >>> maskOffsets[2]);
 - if (scaleFactors[2] != 1.) {
 - b = (int)(b * scaleFactors[2]);
 - }
 - if (isAlphaPremultiplied) {
 - int a = getAlpha(pixel);
 - b = (a == 0) ? 0 : (b * 255/a);
 - if (b > 255) {
 - b = 255;
 - }
 - }
 - return b;
 - }
 - /**
 - * Returns the alpha component for the specified pixel, scaled
 - * from 0 to 255. The pixel value is specified as an int.
 - */
 - final public int getAlpha(int pixel) {
 - if (!supportsAlpha) return 255;
 - int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
 - if (scaleFactors[3] != 1.) {
 - a = (int)(a * scaleFactors[3]);
 - }
 - return a;
 - }
 - /**
 - * 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.
 - * 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).
 - * @see ColorModel#getRGBdefault
 - */
 - final public int getRGB(int pixel) {
 - return (getAlpha(pixel) << 24)
 - | (getRed(pixel) << 16)
 - | (getGreen(pixel) << 8)
 - | (getBlue(pixel) << 0);
 - }
 - /**
 - * 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 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, i.e. if the
 - * alpha is premultiplied, this method will divide it out before returning
 - * the value (if the alpha value is 0, the red value will be 0).
 - * If inData is not a primitive array of type transferType, a
 - * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
 - * thrown if inData is not large enough to hold a pixel value for this
 - * ColorModel.
 - */
 - public int getRed(Object inData) {
 - int pixel=0;
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE:
 - byte bdata[] = (byte[])inData;
 - pixel = bdata[0] & 0xff;
 - break;
 - case DataBuffer.TYPE_USHORT:
 - short sdata[] = (short[])inData;
 - pixel = sdata[0] & 0xffff;
 - break;
 - case DataBuffer.TYPE_INT:
 - int idata[] = (int[])inData;
 - pixel = idata[0];
 - break;
 - default:
 - throw new UnsupportedOperationException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - return getRed(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 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, i.e. if the
 - * alpha is premultiplied, this method will divide it out before returning
 - * the value (if the alpha value is 0, the green value will be 0).
 - * If inData is not a primitive array of type transferType, a
 - * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
 - * thrown if inData is not large enough to hold a pixel value for this
 - * ColorModel.
 - */
 - public int getGreen(Object inData) {
 - int pixel=0;
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE:
 - byte bdata[] = (byte[])inData;
 - pixel = bdata[0] & 0xff;
 - break;
 - case DataBuffer.TYPE_USHORT:
 - short sdata[] = (short[])inData;
 - pixel = sdata[0] & 0xffff;
 - break;
 - case DataBuffer.TYPE_INT:
 - int idata[] = (int[])inData;
 - pixel = idata[0];
 - break;
 - default:
 - throw new UnsupportedOperationException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - return getGreen(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 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, i.e. if the
 - * alpha is premultiplied, this method will divide it out before returning
 - * the value (if the alpha value is 0, the blue value will be 0).
 - * If inData is not a primitive array of type transferType, a
 - * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
 - * thrown if inData is not large enough to hold a pixel value for this
 - * ColorModel.
 - */
 - public int getBlue(Object inData) {
 - int pixel=0;
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE:
 - byte bdata[] = (byte[])inData;
 - pixel = bdata[0] & 0xff;
 - break;
 - case DataBuffer.TYPE_USHORT:
 - short sdata[] = (short[])inData;
 - pixel = sdata[0] & 0xffff;
 - break;
 - case DataBuffer.TYPE_INT:
 - int idata[] = (int[])inData;
 - pixel = idata[0];
 - break;
 - default:
 - throw new UnsupportedOperationException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - return getBlue(pixel);
 - }
 - /**
 - * 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
 - * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
 - * thrown if inData is not large enough to hold a pixel value for this
 - * ColorModel.
 - */
 - public int getAlpha(Object inData) {
 - int pixel=0;
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE:
 - byte bdata[] = (byte[])inData;
 - pixel = bdata[0] & 0xff;
 - break;
 - case DataBuffer.TYPE_USHORT:
 - short sdata[] = (short[])inData;
 - pixel = sdata[0] & 0xffff;
 - break;
 - case DataBuffer.TYPE_INT:
 - int idata[] = (int[])inData;
 - pixel = idata[0];
 - break;
 - default:
 - throw new UnsupportedOperationException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - return getAlpha(pixel);
 - }
 - /**
 - * 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
 - * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
 - * thrown if inData is not large enough to hold a pixel value for this
 - * ColorModel.
 - * 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).
 - * @see ColorModel#getRGBdefault
 - */
 - public int getRGB(Object inData) {
 - int pixel=0;
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE:
 - byte bdata[] = (byte[])inData;
 - pixel = bdata[0] & 0xff;
 - break;
 - case DataBuffer.TYPE_USHORT:
 - short sdata[] = (short[])inData;
 - pixel = sdata[0] & 0xffff;
 - break;
 - case DataBuffer.TYPE_INT:
 - int idata[] = (int[])inData;
 - pixel = idata[0];
 - break;
 - default:
 - throw new UnsupportedOperationException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - return getRGB(pixel);
 - }
 - /**
 - * Returns a data element array representation of a pixel in this
 - * ColorModel, given an integer pixel representation in the
 - * default RGB color model.
 - * This array can then be passed to the setDataElements method of
 - * a WritableRaster object. If the pixel variable is null, a new
 - * array will be allocated. If pixel is not null, it must be
 - * a primitive array of type transferType; otherwise, a
 - * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
 - * thrown if pixel is not large enough to hold a pixel value for this
 - * ColorModel. The pixel array will be returned.
 - * @see WritableRaster#setDataElements
 - * @see SampleModel#setDataElements
 - */
 - public Object getDataElements(int rgb, Object pixel) {
 - //REMIND: maybe more efficient not to use int array for
 - //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
 - int i;
 - int intpixel[] = null;
 - if (transferType == DataBuffer.TYPE_INT &&
 - pixel != null) {
 - intpixel = (int[])pixel;
 - } else {
 - intpixel = new int[1];
 - }
 - ColorModel defaultCM = ColorModel.getRGBdefault();
 - if (this == defaultCM || equals(defaultCM)) {
 - intpixel[0] = rgb;
 - } else {
 - double normAlpha = 1.;
 - int c;
 - if (isAlphaPremultiplied) {
 - normAlpha = ((rgb>>24)&0xff)/255.;
 - }
 - double value;
 - int[] shifts = {16, 8, 0, 24};
 - int nbands = 3+(supportsAlpha ? 1 : 0);
 - intpixel[0] = 0;
 - for (i=0; i < nbands; i++) {
 - c = (int)(((rgb>>shifts[i])&0xff)*normAlphascaleFactors[i]);
 - intpixel[0] |= (c << maskOffsets[i]) & maskArray[i];
 - }
 - }
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE: {
 - byte bdata[];
 - if (pixel == null) {
 - bdata = new byte[1];
 - } else {
 - bdata = (byte[])pixel;
 - }
 - bdata[0] = (byte)(0xff&intpixel[0]);
 - return bdata;
 - }
 - case DataBuffer.TYPE_USHORT:{
 - short sdata[];
 - if (pixel == null) {
 - sdata = new short[1];
 - } else {
 - sdata = (short[])pixel;
 - }
 - sdata[0] = (short)(intpixel[0]&0xffff);
 - return sdata;
 - }
 - case DataBuffer.TYPE_INT:
 - return intpixel;
 - }
 - throw new UnsupportedOperationException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - /**
 - * Returns an array of unnormalized color/alpha components given a pixel
 - * in this ColorModel. The pixel value is specified as an int. If the
 - * components array is null, a new array will be allocated. The
 - * components array will be returned. Color/alpha components are
 - * stored in the components array starting at offset (even if the
 - * array is allocated by this method). An ArrayIndexOutOfBoundsException
 - * is thrown if the components array is not null and is not large
 - * enough to hold all the color and alpha components (starting at offset).
 - */
 - final public int[] getComponents(int pixel, int[] components, int offset) {
 - if (components == null) {
 - components = new int[offset+numComponents];
 - }
 - for (int i=0; i < numComponents; i++) {
 - components[offset+i] = (pixel & maskArray[i]) >>> maskOffsets[i];
 - }
 - return components;
 - }
 - /**
 - * Returns an array of unnormalized color/alpha components given a pixel
 - * in this ColorModel. The pixel value is specified by an array of
 - * data elements of type transferType passed in as an object reference.
 - * If pixel is not a primitive array of type transferType, a
 - * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
 - * thrown if pixel is not large enough to hold a pixel value for this
 - * ColorModel. If the components array is null, a new
 - * array will be allocated. The components array will be returned.
 - * Color/alpha components are
 - * stored in the components array starting at offset (even if the
 - * array is allocated by this method). An ArrayIndexOutOfBoundsException
 - * is thrown if the components array is not null and is not large
 - * enough to hold all the color and alpha components (starting at offset).
 - */
 - final public int[] getComponents(Object pixel, int[] components,
 - int offset) {
 - int intpixel=0;
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE:
 - byte bdata[] = (byte[])pixel;
 - intpixel = bdata[0] & 0xff;
 - break;
 - case DataBuffer.TYPE_USHORT:
 - short sdata[] = (short[])pixel;
 - intpixel = sdata[0] & 0xffff;
 - break;
 - case DataBuffer.TYPE_INT:
 - int idata[] = (int[])pixel;
 - intpixel = idata[0];
 - break;
 - default:
 - throw new UnsupportedOperationException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - return getComponents(intpixel, components, offset);
 - }
 - /**
 - * Creates a WritableRaster with the specified width and height that
 - * has a data layout (SampleModel) compatible with this ColorModel.
 - * @see WritableRaster
 - * @see SampleModel
 - */
 - final public WritableRaster createCompatibleWritableRaster (int w,
 - int h) {
 - int[] bandmasks;
 - if (supportsAlpha) {
 - bandmasks = new int[4];
 - bandmasks[3] = alpha_mask;
 - }
 - else {
 - bandmasks = new int[3];
 - }
 - bandmasks[0] = red_mask;
 - bandmasks[1] = green_mask;
 - bandmasks[2] = blue_mask;
 - if (pixel_bits > 16) {
 - return Raster.createPackedRaster(DataBuffer.TYPE_INT,
 - w,h,bandmasks,null);
 - }
 - else if (pixel_bits > 8) {
 - return Raster.createPackedRaster(DataBuffer.TYPE_USHORT,
 - w,h,bandmasks,null);
 - }
 - else {
 - return Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
 - w,h,bandmasks,null);
 - }
 - }
 - /**
 - * Returns a pixel value represented as an int in this ColorModel,
 - * given an array of unnormalized color/alpha components. An
 - * ArrayIndexOutOfBoundsException is thrown if the components array is
 - * not large enough to hold all the color and alpha components (starting
 - * at offset).
 - */
 - public int getDataElement(int[] components, int offset) {
 - int pixel = 0;
 - for (int i=0; i < numComponents; i++) {
 - pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
 - }
 - return pixel;
 - }
 - /**
 - * Returns a data element array representation of a pixel in this
 - * ColorModel, given an array of unnormalized color/alpha components.
 - * This array can then be passed to the setDataElements method of
 - * a WritableRaster object.
 - * An ArrayIndexOutOfBoundsException is thrown if the components array
 - * is not large enough to hold all the color and alpha components
 - * (starting at offset). If the obj variable is null, a new array
 - * will be allocated. If obj is not null, it must be a primitive array
 - * of type transferType; otherwise, a ClassCastException is thrown.
 - * An ArrayIndexOutOfBoundsException is thrown if obj is not large
 - * enough to hold a pixel value for this ColorModel.
 - * @see WritableRaster#setDataElements
 - * @see SampleModel#setDataElements
 - */
 - public Object getDataElements(int[] components, int offset, Object obj) {
 - int pixel = 0;
 - for (int i=0; i < numComponents; i++) {
 - pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
 - }
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE:
 - if (obj instanceof byte[]) {
 - byte bdata[] = (byte[])obj;
 - bdata[0] = (byte)(pixel&0xff);
 - return bdata;
 - } else {
 - byte bdata[] = {(byte)(pixel&0xff)};
 - return bdata;
 - }
 - case DataBuffer.TYPE_USHORT:
 - if (obj instanceof short[]) {
 - short sdata[] = (short[])obj;
 - sdata[0] = (short)(pixel&0xffff);
 - return sdata;
 - } else {
 - short sdata[] = {(short)(pixel&0xffff)};
 - return sdata;
 - }
 - case DataBuffer.TYPE_INT:
 - if (obj instanceof int[]) {
 - int idata[] = (int[])obj;
 - idata[0] = pixel;
 - return idata;
 - } else {
 - int idata[] = {pixel};
 - return idata;
 - }
 - default:
 - throw new ClassCastException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - }
 - /**
 - * Forces the Raster data to match the state specified in the
 - * isAlphaPremultiplied variable, assuming the data is currently
 - * correctly described by this ColorModel. 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 ColorModel with
 - * the isAlphaPremultiplied flag set appropriately.
 - */
 - final public ColorModel coerceData (WritableRaster raster,
 - boolean isAlphaPremultiplied)
 - {
 - if (!supportsAlpha ||
 - this.isAlphaPremultiplied() == isAlphaPremultiplied) {
 - return this;
 - }
 - int w = raster.getWidth();
 - int h = raster.getHeight();
 - int aIdx = numColorComponents;
 - float normAlpha;
 - int alphaScale = (1 << nBits[aIdx]) - 1;
 - int rminX = raster.getMinX();
 - int rY = raster.getMinY();
 - int rX;
 - int pixel[] = null;
 - if (isAlphaPremultiplied) {
 - // Must mean that we are currently not premultiplied so
 - // multiply by alpha
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE: {
 - for (int y = 0; y < h; y++, rY++) {
 - rX = rminX;
 - for (int x = 0; x < w; x++, rX++) {
 - pixel = raster.getPixel(rX, rY, pixel);
 - normAlpha = pixel[aIdx]/alphaScale;
 - if (normAlpha != 0.f) {
 - for (int c=0; c < aIdx; c++) {
 - pixel[c] = (int)(pixel[c]*normAlpha);
 - }
 - raster.setPixel(rX, rY, pixel);
 - }
 - }
 - }
 - }
 - break;
 - case DataBuffer.TYPE_USHORT: {
 - for (int y = 0; y < h; y++, rY++) {
 - rX = rminX;
 - for (int x = 0; x < w; x++, rX++) {
 - pixel = raster.getPixel(rX, rY, pixel);
 - normAlpha = pixel[aIdx]/alphaScale;
 - if (normAlpha != 0.f) {
 - for (int c=0; c < aIdx; c++) {
 - pixel[c] = (int)(pixel[c]*normAlpha);
 - }
 - raster.setPixel(rX, rY, pixel);
 - }
 - }
 - }
 - }
 - break;
 - case DataBuffer.TYPE_INT: {
 - for (int y = 0; y < h; y++, rY++) {
 - rX = rminX;
 - for (int x = 0; x < w; x++, rX++) {
 - pixel = raster.getPixel(rX, rY, pixel);
 - normAlpha = pixel[aIdx]/alphaScale;
 - if (normAlpha != 0.f) {
 - for (int c=0; c < aIdx; c++) {
 - pixel[c] = (int)(pixel[c]*normAlpha);
 - }
 - raster.setPixel(rX, rY, pixel);
 - }
 - }
 - }
 - }
 - break;
 - default:
 - throw new UnsupportedOperationException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - }
 - else {
 - // We are premultiplied and want to divide it out
 - switch (transferType) {
 - case DataBuffer.TYPE_BYTE: {
 - for (int y = 0; y < h; y++, rY++) {
 - rX = rminX;
 - for (int x = 0; x < w; x++, rX++) {
 - pixel = raster.getPixel(rX, rY, pixel);
 - normAlpha = pixel[aIdx]/alphaScale;
 - if (normAlpha != 0) {
 - for (int c=0; c < aIdx; c++) {
 - pixel[c] /= normAlpha;
 - }
 - }
 - raster.setPixel(rX, rY, pixel);
 - }
 - }
 - }
 - break;
 - case DataBuffer.TYPE_USHORT: {
 - for (int y = 0; y < h; y++, rY++) {
 - rX = rminX;
 - for (int x = 0; x < w; x++, rX++) {
 - pixel = raster.getPixel(rX, rY, pixel);
 - normAlpha = pixel[aIdx]/alphaScale;
 - if (normAlpha != 0) {
 - for (int c=0; c < aIdx; c++) {
 - pixel[c] /= normAlpha;
 - }
 - }
 - raster.setPixel(rX, rY, pixel);
 - }
 - }
 - }
 - break;
 - case DataBuffer.TYPE_INT: {
 - for (int y = 0; y < h; y++, rY++) {
 - rX = rminX;
 - for (int x = 0; x < w; x++, rX++) {
 - pixel = raster.getPixel(rX, rY, pixel);
 - normAlpha = pixel[aIdx]/alphaScale;
 - if (normAlpha != 0) {
 - for (int c=0; c < aIdx; c++) {
 - pixel[c] /= normAlpha;
 - }
 - }
 - raster.setPixel(rX, rY, pixel);
 - }
 - }
 - }
 - break;
 - default:
 - throw new UnsupportedOperationException("This method has not been "+
 - "implemented for transferType " + transferType);
 - }
 - }
 - // Return a new color model
 - return new DirectColorModel(colorSpace, pixel_bits, maskArray[0],
 - maskArray[1], maskArray[2], maskArray[3],
 - isAlphaPremultiplied,
 - transferType);
 - }
 - /**
 - * Returns true if raster is compatible with this ColorModel and
 - * false if it is not.
 - */
 - public boolean isCompatibleRaster(Raster raster) {
 - SampleModel sm = raster.getSampleModel();
 - SinglePixelPackedSampleModel spsm;
 - if (sm instanceof SinglePixelPackedSampleModel) {
 - spsm = (SinglePixelPackedSampleModel) sm;
 - }
 - else {
 - return false;
 - }
 - if (spsm.getNumBands() != getNumComponents()) {
 - return false;
 - }
 - boolean flag = true;
 - int[] bitMasks = spsm.getBitMasks();
 - int[] bitSizes = spsm.getSampleSize();
 - int[] bitOffsets = spsm.getBitOffsets();
 - int totalBitSize = 0;
 - /*if[Linux]
 - int testBitSize=0;
 - end[Linux]*/
 - for(int i=0; i<bitSizes.length; i++) {
 - if (bitSizes[i]+bitOffsets[i] > totalBitSize) {
 - totalBitSize = bitSizes[i]+bitOffsets[i];
 - }
 - }
 - for (int i=0; i<numComponents; i++) {
 - if (bitMasks[i] != maskArray[i])
 - flag = false;
 - /*if[Linux]
 - testBitSize+=bitSizes[i];
 - end[Linux]*/
 - }
 - return ( (raster.getTransferType() == transferType) &&
 - /*if[Linux]
 - (totalBitSize == testBitSize ) && flag );
 - else[Linux]*/
 - (totalBitSize == pixel_bits ) && flag );
 - /*end[Linux]*/
 - }
 - private void setFields() {
 - // Set the private fields
 - // REMIND: Get rid of these from the native code
 - red_mask = maskArray[0];
 - red_offset = maskOffsets[0];
 - green_mask = maskArray[1];
 - green_offset = maskOffsets[1];
 - blue_mask = maskArray[2];
 - blue_offset = maskOffsets[2];
 - if (nBits[0] < 8) {
 - red_scale = (1 << nBits[0]) - 1;
 - }
 - if (nBits[1] < 8) {
 - green_scale = (1 << nBits[1]) - 1;
 - }
 - if (nBits[2] < 8) {
 - blue_scale = (1 << nBits[2]) - 1;
 - }
 - if (supportsAlpha) {
 - alpha_mask = maskArray[3];
 - alpha_offset = maskOffsets[3];
 - if (nBits[3] < 8) {
 - alpha_scale = (1 << nBits[3]) - 1;
 - }
 - }
 - }
 - /**
 - * Returns a <code>String</code> that represents this
 - * <code>DirectColorModel</code>.
 - * @return a <code>String</code> representing this
 - * <code>DirectColorModel</code>.
 - */
 - public String toString() {
 - return new String("DirectColorModel: rmask="
 - +Integer.toHexString(red_mask)+" gmask="
 - +Integer.toHexString(green_mask)+" bmask="
 - +Integer.toHexString(blue_mask)+" amask="
 - +Integer.toHexString(alpha_mask));
 - }
 - }