/* * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.awt.image; import java.awt.color.ColorSpace; import java.awt.Transparency; /** * The {@code DirectColorModel} class is a {@code ColorModel} * class that works with pixel values that represent RGB * color and alpha information as separate samples and that 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. * In addition, for each component of the ColorSpace, the minimum * normalized component value obtained via the {@code getMinValue()} * method of ColorSpace must be 0.0, and the maximum value obtained via * the {@code getMaxValue()} method must be 1.0 (these min/max * values are typical for RGB spaces). * There must be three color samples in the pixel values and there can * be a single alpha sample. For those methods that use a primitive array * pixel representation of type {@code transferType}, the array * length is always one. The transfer * types supported are DataBuffer.TYPE_BYTE, * DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT. * 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: * *

* 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 {@code DirectColorModel} is * typically used with image data which uses masks to define packed * samples. For example, a {@code DirectColorModel} can be used in * conjunction with a {@code SinglePixelPackedSampleModel} to * construct a {@link BufferedImage}. Normally the masks used by the * {@link SampleModel} and the {@code 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 * {@code ColorModel}. *

* 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 {@code IllegalArgumentException} * due to an invalid pixel value. *

* This color model is similar to an X11 TrueColor visual. * The default RGB ColorModel specified by the * {@link ColorModel#getRGBdefault() getRGBdefault} method is a * {@code DirectColorModel} with the following parameters: *

 * 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
 * 
*

* 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 * */ 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; private boolean is_LinearRGB; private int lRGBprecision; private byte[] tosRGB8LUT; private byte[] fromsRGB8LUT8; private short[] fromsRGB8LUT16; /** * Constructs a {@code DirectColorModel} from the specified masks * that indicate which bits in an {@code int} pixel representation * contain the red, green and blue color samples. As pixel values do not * contain alpha information, all pixels are treated as opaque, which * means that 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 {@code int} pixel representation. * The {@code ColorSpace} is the default sRGB space. The * transparency value is Transparency.OPAQUE. The transfer type * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, * or DataBuffer.TYPE_INT that can hold a single pixel. * @param bits the number of bits in the pixel values; for example, * the sum of the number of bits in the masks. * @param rmask specifies a mask indicating which bits in an * integer pixel contain the red component * @param gmask specifies a mask indicating which bits in an * integer pixel contain the green component * @param bmask specifies a mask indicating which bits in an * integer pixel contain the blue component * */ public DirectColorModel(int bits, int rmask, int gmask, int bmask) { this(bits, rmask, gmask, bmask, 0); } /** * Constructs a {@code DirectColorModel} from the specified masks * that indicate which bits in an {@code int} pixel representation * contain the red, green and blue color samples and the alpha sample, * if present. If {@code amask} is 0, pixel values do not contain * alpha information and all pixels are treated as opaque, which means * that 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 {@code int} pixel representation. Alpha, if present, is not * premultiplied. The {@code ColorSpace} is the default sRGB space. * The transparency value is Transparency.OPAQUE if no alpha is * present, or Transparency.TRANSLUCENT otherwise. The transfer type * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, * or DataBuffer.TYPE_INT that can hold a single pixel. * @param bits the number of bits in the pixel values; for example, * the sum of the number of bits in the masks. * @param rmask specifies a mask indicating which bits in an * integer pixel contain the red component * @param gmask specifies a mask indicating which bits in an * integer pixel contain the green component * @param bmask specifies a mask indicating which bits in an * integer pixel contain the blue component * @param amask specifies a mask indicating which bits in an * integer pixel contain the alpha component */ 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 {@code DirectColorModel} from the specified * parameters. Color components are in the specified * {@code ColorSpace}, which must be of type ColorSpace.TYPE_RGB * and have minimum normalized component values which are all 0.0 * and maximum values which are all 1.0. * The masks specify which bits in an {@code int} pixel * representation contain the red, green and blue color samples and * the alpha sample, if present. If {@code amask} is 0, pixel * values do not contain alpha information and all pixels are treated * as opaque, which means that 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 {@code int} pixel * representation. If there is alpha, the {@code boolean} * {@code isAlphaPremultiplied} specifies how to interpret * color and alpha samples in pixel values. If the {@code boolean} * is {@code true}, color samples are assumed to have been * multiplied by the alpha sample. The transparency value is * 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. * @param space the specified {@code ColorSpace} * @param bits the number of bits in the pixel values; for example, * the sum of the number of bits in the masks. * @param rmask specifies a mask indicating which bits in an * integer pixel contain the red component * @param gmask specifies a mask indicating which bits in an * integer pixel contain the green component * @param bmask specifies a mask indicating which bits in an * integer pixel contain the blue component * @param amask specifies a mask indicating which bits in an * integer pixel contain the alpha component * @param isAlphaPremultiplied {@code true} if color samples are * premultiplied by the alpha sample; {@code false} otherwise * @param transferType the type of array used to represent pixel values * @throws IllegalArgumentException if {@code space} is not a * TYPE_RGB space or if the min/max normalized component * values are not 0.0/1.0. */ 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); if (ColorModel.isLinearRGBspace(colorSpace)) { is_LinearRGB = true; if (maxBits <= 8) { lRGBprecision = 8; tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT(); fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT(); } else { lRGBprecision = 16; tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT(); fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT(); } } else if (!is_sRGB) { for (int i = 0; i < 3; i++) { // super constructor checks that space is TYPE_RGB // check here that min/max are all 0.0/1.0 if ((space.getMinValue(i) != 0.0f) || (space.getMaxValue(i) != 1.0f)) { throw new IllegalArgumentException( "Illegal min/max RGB component value"); } } } setFields(); } /** * Returns the mask indicating which bits in an {@code int} pixel * representation contain the red color component. * @return the mask, which indicates which bits of the {@code int} * pixel representation contain the red color sample. */ public final int getRedMask() { return maskArray[0]; } /** * Returns the mask indicating which bits in an {@code int} pixel * representation contain the green color component. * @return the mask, which indicates which bits of the {@code int} * pixel representation contain the green color sample. */ public final int getGreenMask() { return maskArray[1]; } /** * Returns the mask indicating which bits in an {@code int} pixel * representation contain the blue color component. * @return the mask, which indicates which bits of the {@code int} * pixel representation contain the blue color sample. */ public final int getBlueMask() { return maskArray[2]; } /** * Returns the mask indicating which bits in an {@code int} pixel * representation contain the alpha component. * @return the mask, which indicates which bits of the {@code int} * pixel representation contain the alpha sample. */ public final int getAlphaMask() { if (supportsAlpha) { return maskArray[3]; } else { return 0; } } /* * Given an int pixel in this ColorModel's ColorSpace, converts * it to the default sRGB ColorSpace and returns the R, G, and B * components as float values between 0.0 and 1.0. */ private float[] getDefaultRGBComponents(int pixel) { int[] components = getComponents(pixel, null, 0); float[] norm = getNormalizedComponents(components, 0, null, 0); // Note that getNormalizedComponents returns non-premultiplied values return colorSpace.toRGB(norm); } private int getsRGBComponentFromsRGB(int pixel, int idx) { int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]); if (isAlphaPremultiplied) { int a = ((pixel & maskArray[3]) >>> maskOffsets[3]); c = (a == 0) ? 0 : (int) (((c * scaleFactors[idx]) * 255.0f / (a * scaleFactors[3])) + 0.5f); } else if (scaleFactors[idx] != 1.0f) { c = (int) ((c * scaleFactors[idx]) + 0.5f); } return c; } private int getsRGBComponentFromLinearRGB(int pixel, int idx) { int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]); if (isAlphaPremultiplied) { float factor = (float) ((1 << lRGBprecision) - 1); int a = ((pixel & maskArray[3]) >>> maskOffsets[3]); c = (a == 0) ? 0 : (int) (((c * scaleFactors[idx]) * factor / (a * scaleFactors[3])) + 0.5f); } else if (nBits[idx] != lRGBprecision) { if (lRGBprecision == 16) { c = (int) ((c * scaleFactors[idx] * 257.0f) + 0.5f); } else { c = (int) ((c * scaleFactors[idx]) + 0.5f); } } // now range of c is 0-255 or 0-65535, depending on lRGBprecision return tosRGB8LUT[c] & 0xff; } /** * Returns the red color component for the specified pixel, scaled * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A * color conversion is done if necessary. The pixel value is specified * as an {@code int}. * The returned value is a non pre-multiplied value. Thus, if the * alpha is premultiplied, this method divides it out before returning * the value. If the alpha value is 0, for example, the red value * is 0. * @param pixel the specified pixel * @return the red color component for the specified pixel, from * 0 to 255 in the sRGB {@code ColorSpace}. */ public final int getRed(int pixel) { if (is_sRGB) { return getsRGBComponentFromsRGB(pixel, 0); } else if (is_LinearRGB) { return getsRGBComponentFromLinearRGB(pixel, 0); } float[] rgb = getDefaultRGBComponents(pixel); return (int) (rgb[0] * 255.0f + 0.5f); } /** * Returns the green color component for the specified pixel, scaled * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A * color conversion is done if necessary. The pixel value is specified * as an {@code int}. * The returned value is a non pre-multiplied value. Thus, if the * alpha is premultiplied, this method divides it out before returning * the value. If the alpha value is 0, for example, the green value * is 0. * @param pixel the specified pixel * @return the green color component for the specified pixel, from * 0 to 255 in the sRGB {@code ColorSpace}. */ public final int getGreen(int pixel) { if (is_sRGB) { return getsRGBComponentFromsRGB(pixel, 1); } else if (is_LinearRGB) { return getsRGBComponentFromLinearRGB(pixel, 1); } float[] rgb = getDefaultRGBComponents(pixel); return (int) (rgb[1] * 255.0f + 0.5f); } /** * Returns the blue color component for the specified pixel, scaled * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A * color conversion is done if necessary. The pixel value is specified * as an {@code int}. * The returned value is a non pre-multiplied value. Thus, if the * alpha is premultiplied, this method divides it out before returning * the value. If the alpha value is 0, for example, the blue value * is 0. * @param pixel the specified pixel * @return the blue color component for the specified pixel, from * 0 to 255 in the sRGB {@code ColorSpace}. */ public final int getBlue(int pixel) { if (is_sRGB) { return getsRGBComponentFromsRGB(pixel, 2); } else if (is_LinearRGB) { return getsRGBComponentFromLinearRGB(pixel, 2); } float[] rgb = getDefaultRGBComponents(pixel); return (int) (rgb[2] * 255.0f + 0.5f); } /** * Returns the alpha component for the specified pixel, scaled * from 0 to 255. The pixel value is specified as an {@code int}. * @param pixel the specified pixel * @return the value of the alpha component of {@code pixel} * from 0 to 255. */ public final int getAlpha(int pixel) { if (!supportsAlpha) return 255; int a = ((pixel & maskArray[3]) >>> maskOffsets[3]); if (scaleFactors[3] != 1.0f) { a = (int)(a * scaleFactors[3] + 0.5f); } 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 {@code int}. * The returned value is in a non pre-multiplied format. Thus, if * the alpha is premultiplied, this method divides it out of the * color components. If the alpha value is 0, for example, the color * values are each 0. * @param pixel the specified pixel * @return the RGB value of the color/alpha components of the specified * pixel. * @see ColorModel#getRGBdefault */ public final int getRGB(int pixel) { if (is_sRGB || is_LinearRGB) { return (getAlpha(pixel) << 24) | (getRed(pixel) << 16) | (getGreen(pixel) << 8) | (getBlue(pixel) << 0); } float[] rgb = getDefaultRGBComponents(pixel); return (getAlpha(pixel) << 24) | (((int) (rgb[0] * 255.0f + 0.5f)) << 16) | (((int) (rgb[1] * 255.0f + 0.5f)) << 8) | (((int) (rgb[2] * 255.0f + 0.5f)) << 0); } /** * Returns the red color component for the specified pixel, scaled * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A * color conversion is done if necessary. The pixel value is specified * by an array of data elements of type {@code transferType} passed * in as an object reference. * The returned value is a non pre-multiplied value. Thus, if the * alpha is premultiplied, this method divides it out before returning * the value. If the alpha value is 0, for example, the red value * is 0. * If {@code inData} is not a primitive array of type * {@code transferType}, a {@code ClassCastException} is * thrown. An {@code ArrayIndexOutOfBoundsException} is * thrown if {@code inData} is not large enough to hold a * pixel value for this {@code ColorModel}. Since * {@code DirectColorModel} can be subclassed, subclasses inherit * the implementation of this method and if they don't override it * then they throw an exception if they use an unsupported * {@code transferType}. * An {@code UnsupportedOperationException} is thrown if this * {@code transferType} is not supported by this * {@code ColorModel}. * @param inData the array containing the pixel value * @return the value of the red component of the specified pixel. * @throws ArrayIndexOutOfBoundsException if {@code inData} is not * large enough to hold a pixel value for this color model * @throws ClassCastException if {@code inData} is not a * primitive array of type {@code transferType} * @throws UnsupportedOperationException if this {@code transferType} * is not supported by this color model */ 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 {@code ColorSpace}, sRGB. A * color conversion is done if necessary. The pixel value is specified * by an array of data elements of type {@code transferType} passed * in as an object reference. * The returned value is a non pre-multiplied value. Thus, if the * alpha is premultiplied, this method divides it out before returning * the value. If the alpha value is 0, for example, the green value * is 0. If {@code inData} is not a primitive array of type * {@code transferType}, a {@code ClassCastException} is thrown. * An {@code ArrayIndexOutOfBoundsException} is * thrown if {@code inData} is not large enough to hold a pixel * value for this {@code ColorModel}. Since * {@code DirectColorModel} can be subclassed, subclasses inherit * the implementation of this method and if they don't override it * then they throw an exception if they use an unsupported * {@code transferType}. * An {@code UnsupportedOperationException} is * thrown if this {@code transferType} is not supported by this * {@code ColorModel}. * @param inData the array containing the pixel value * @return the value of the green component of the specified pixel. * @throws ArrayIndexOutOfBoundsException if {@code inData} is not * large enough to hold a pixel value for this color model * @throws ClassCastException if {@code inData} is not a * primitive array of type {@code transferType} * @throws UnsupportedOperationException if this {@code transferType} * is not supported by this color model */ 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 {@code ColorSpace}, sRGB. A * color conversion is done if necessary. The pixel value is specified * by an array of data elements of type {@code transferType} passed * in as an object reference. * The returned value is a non pre-multiplied value. Thus, if the * alpha is premultiplied, this method divides it out before returning * the value. If the alpha value is 0, for example, the blue value * is 0. If {@code inData} is not a primitive array of type * {@code transferType}, a {@code ClassCastException} is thrown. * An {@code ArrayIndexOutOfBoundsException} is * thrown if {@code inData} is not large enough to hold a pixel * value for this {@code ColorModel}. Since * {@code DirectColorModel} can be subclassed, subclasses inherit * the implementation of this method and if they don't override it * then they throw an exception if they use an unsupported * {@code transferType}. * An {@code UnsupportedOperationException} is * thrown if this {@code transferType} is not supported by this * {@code ColorModel}. * @param inData the array containing the pixel value * @return the value of the blue component of the specified pixel. * @throws ArrayIndexOutOfBoundsException if {@code inData} is not * large enough to hold a pixel value for this color model * @throws ClassCastException if {@code inData} is not a * primitive array of type {@code transferType} * @throws UnsupportedOperationException if this {@code transferType} * is not supported by this color model */ 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 {@code transferType} passed in as an object * reference. * If {@code inData} is not a primitive array of type * {@code transferType}, a {@code ClassCastException} is * thrown. An {@code ArrayIndexOutOfBoundsException} is * thrown if {@code inData} is not large enough to hold a pixel * value for this {@code ColorModel}. Since * {@code DirectColorModel} can be subclassed, subclasses inherit * the implementation of this method and if they don't override it * then they throw an exception if they use an unsupported * {@code transferType}. * If this {@code transferType} is not supported, an * {@code UnsupportedOperationException} is thrown. * @param inData the specified pixel * @return the alpha component of the specified pixel, scaled from * 0 to 255. * @exception ClassCastException if {@code inData} * is not a primitive array of type {@code transferType} * @exception ArrayIndexOutOfBoundsException if * {@code inData} is not large enough to hold a pixel value * for this {@code ColorModel} * @exception UnsupportedOperationException if this * {@code tranferType} is not supported by this * {@code 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 {@code transferType} passed in as an object * reference. If {@code inData} is not a primitive array of type * {@code transferType}, a {@code ClassCastException} is * thrown. An {@code ArrayIndexOutOfBoundsException} is * thrown if {@code inData} is not large enough to hold a pixel * value for this {@code ColorModel}. * The returned value is in a non pre-multiplied format. Thus, if * the alpha is premultiplied, this method divides it out of the * color components. If the alpha value is 0, for example, the color * values is 0. Since {@code DirectColorModel} can be * subclassed, subclasses inherit the implementation of this method * and if they don't override it then * they throw an exception if they use an unsupported * {@code transferType}. * * @param inData the specified pixel * @return the color and alpha components of the specified pixel. * @exception UnsupportedOperationException if this * {@code transferType} is not supported by this * {@code ColorModel} * @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 * {@code ColorModel}, given an integer pixel representation in the * default RGB color model. * This array can then be passed to the {@code setDataElements} * method of a {@code WritableRaster} object. If the pixel variable * is {@code null}, a new array is allocated. If {@code pixel} * is not {@code null}, it must be a primitive array of type * {@code transferType}; otherwise, a * {@code ClassCastException} is thrown. An * {@code ArrayIndexOutOfBoundsException} is * thrown if {@code pixel} is not large enough to hold a pixel * value for this {@code ColorModel}. The pixel array is returned. * Since {@code DirectColorModel} can be subclassed, subclasses * inherit the implementation of this method and if they don't * override it then they throw an exception if they use an unsupported * {@code transferType}. * * @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 * {@code ColorModel} * @exception ClassCastException if {@code pixel} * is not a primitive array of type {@code transferType} * @exception ArrayIndexOutOfBoundsException if * {@code pixel} is not large enough to hold a pixel value * for this {@code ColorModel} * @exception UnsupportedOperationException if this * {@code transferType} is not supported by this * {@code ColorModel} * @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[] intpixel = null; if (transferType == DataBuffer.TYPE_INT && pixel != null) { intpixel = (int[])pixel; intpixel[0] = 0; } else { intpixel = new int[1]; } ColorModel defaultCM = ColorModel.getRGBdefault(); if (this == defaultCM || equals(defaultCM)) { intpixel[0] = rgb; return intpixel; } int red, grn, blu, alp; red = (rgb>>16) & 0xff; grn = (rgb>>8) & 0xff; blu = rgb & 0xff; if (is_sRGB || is_LinearRGB) { int precision; float factor; if (is_LinearRGB) { if (lRGBprecision == 8) { red = fromsRGB8LUT8[red] & 0xff; grn = fromsRGB8LUT8[grn] & 0xff; blu = fromsRGB8LUT8[blu] & 0xff; precision = 8; factor = 1.0f / 255.0f; } else { red = fromsRGB8LUT16[red] & 0xffff; grn = fromsRGB8LUT16[grn] & 0xffff; blu = fromsRGB8LUT16[blu] & 0xffff; precision = 16; factor = 1.0f / 65535.0f; } } else { precision = 8; factor = 1.0f / 255.0f; } if (supportsAlpha) { alp = (rgb>>24) & 0xff; if (isAlphaPremultiplied) { factor *= (alp * (1.0f / 255.0f)); precision = -1; // force component calculations below } if (nBits[3] != 8) { alp = (int) ((alp * (1.0f / 255.0f) * ((1< ((1<>24) & 0xff; if (isAlphaPremultiplied) { factor *= alp; for (int i = 0; i < 3; i++) { norm[i] *= factor; } } if (nBits[3] != 8) { alp = (int) ((alp * (1.0f / 255.0f) * ((1< ((1< 23) { // fix 4412670 - for components of 24 or more bits // some calculations done above with float precision // may lose enough precision that the integer result // overflows nBits, so we need to clamp. if (red > ((1< ((1< ((1<>> maskOffsets[i]; } return components; } /** * Returns an array of unnormalized color/alpha components given a pixel * in this {@code ColorModel}. The pixel value is specified by an * array of data elements of type {@code transferType} passed in as * an object reference. If {@code pixel} is not a primitive array * of type {@code transferType}, a {@code ClassCastException} * is thrown. An {@code ArrayIndexOutOfBoundsException} is * thrown if {@code pixel} is not large enough to hold a * pixel value for this {@code ColorModel}. If the * {@code components} array is {@code null}, a new * array is allocated. The {@code components} array is returned. * Color/alpha components are stored in the {@code components} array * starting at {@code offset}, even if the array is allocated by * this method. An {@code ArrayIndexOutOfBoundsException} * is thrown if the {@code components} array is not * {@code null} and is not large enough to hold all the color and * alpha components, starting at {@code offset}. * Since {@code DirectColorModel} can be subclassed, subclasses * inherit the implementation of this method and if they don't * override it then they throw an exception if they use an unsupported * {@code transferType}. * @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 {@code components} 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. * @exception ClassCastException if {@code pixel} * is not a primitive array of type {@code transferType} * @exception ArrayIndexOutOfBoundsException if * {@code pixel} is not large enough to hold a pixel value * for this {@code ColorModel}, or if {@code components} * is not {@code null} and is not large enough to hold all the * color and alpha components, starting at {@code offset} * @exception UnsupportedOperationException if this * {@code transferType} is not supported by this * color model */ public final 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 {@code WritableRaster} with the specified width and * height that has a data layout ({@code SampleModel}) compatible * with this {@code ColorModel}. * @param w the width to apply to the new {@code WritableRaster} * @param h the height to apply to the new {@code WritableRaster} * @return a {@code WritableRaster} object with the specified * width and height. * @throws IllegalArgumentException if {@code w} or {@code h} * is less than or equal to zero * @see WritableRaster * @see SampleModel */ public final WritableRaster createCompatibleWritableRaster (int w, int h) { if ((w <= 0) || (h <= 0)) { throw new IllegalArgumentException("Width (" + w + ") and height (" + h + ") cannot be <= 0"); } 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 {@code int} in this * {@code ColorModel}, given an array of unnormalized color/alpha * components. An {@code ArrayIndexOutOfBoundsException} is * thrown if the {@code components} array is * not large enough to hold all the color and alpha components, starting * at {@code offset}. * @param components an array of unnormalized color and alpha * components * @param offset the index into {@code components} at which to * begin retrieving the color and alpha components * @return an {@code int} pixel value in this * {@code ColorModel} corresponding to the specified components. * @exception ArrayIndexOutOfBoundsException if * the {@code components} array is not large enough to * hold all of the color and alpha components starting at * {@code offset} */ public int getDataElement(int[] components, int offset) { int pixel = 0; for (int i=0; i < numComponents; i++) { pixel |= ((components[offset+i]<