/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt.image;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
A ColorModel
class that works with pixel values that
represent color and alpha information as separate samples and that
store each sample in a separate data element. This class can be
used with an arbitrary ColorSpace
. The number of
color samples in the pixel values must be same as the number of
color components in the ColorSpace
. There may be a
single alpha sample.
For those methods that use
a primitive array pixel representation of type transferType
,
the array length is the same as the number of color and alpha samples.
Color samples are stored first in the array followed by the alpha
sample, if present. The order of the color samples is specified
by the ColorSpace
. 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.
The translation from pixel sample values to color/alpha components for
display or processing purposes is based on a one-to-one correspondence of
samples to components.
Depending on the transfer type used to create an instance of
ComponentColorModel
, the pixel sample values
represented by that instance may be signed or unsigned and may
be of integral type or float or double (see below for details).
The translation from sample values to normalized color/alpha components
must follow certain rules. For float and double samples, the translation
is an identity, i.e. normalized component values are equal to the
corresponding sample values. For integral samples, the translation
should be only a simple scale and offset, where the scale and offset
constants may be different for each component. The result of
applying the scale and offset constants is a set of color/alpha
component values, which are guaranteed to fall within a certain
range. Typically, the range for a color component will be the range
defined by the getMinValue
and getMaxValue
methods of the ColorSpace
class. The range for an
alpha component should be 0.0 to 1.0.
Instances of ComponentColorModel
created with transfer types
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
and DataBuffer.TYPE_INT
have pixel sample values which
are treated as unsigned integral values.
The number of bits in a color or alpha sample of a pixel value might not
be the same as the number of bits for the corresponding color or alpha
sample passed to the
ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)
constructor. In
that case, this class assumes that the least significant n bits of a sample
value hold the component value, where n is the number of significant bits
for the component passed to the constructor. It also assumes that
any higher-order bits in a sample value are zero. Thus, sample values
range from 0 to 2n - 1. This class maps these sample values
to normalized color component values such that 0 maps to the value
obtained from the ColorSpace's
getMinValue
method for each component and 2n - 1 maps to the value
obtained from getMaxValue
. To create a
ComponentColorModel
with a different color sample mapping
requires subclassing this class and overriding the
getNormalizedComponents(Object, float[], int)
method.
The mapping for an alpha sample always maps 0 to 0.0 and
2n - 1 to 1.0.
For instances with unsigned sample values,
the unnormalized color/alpha component representation is only
supported if two conditions hold. First, sample value value 0 must
map to normalized component value 0.0 and sample value 2n - 1
to 1.0. Second the min/max range of all color components of the
ColorSpace
must be 0.0 to 1.0. In this case, the
component representation is the n least
significant bits of the corresponding sample. Thus each component is
an unsigned integral value between 0 and 2n - 1, where
n is the number of significant bits for a particular component.
If these conditions are not met, any method taking an unnormalized
component argument will throw an IllegalArgumentException
.
Instances of ComponentColorModel
created with transfer types
DataBuffer.TYPE_SHORT
, DataBuffer.TYPE_FLOAT
, and
DataBuffer.TYPE_DOUBLE
have pixel sample values which
are treated as signed short, float, or double values.
Such instances do not support the unnormalized color/alpha component
representation, so any methods taking such a representation as an argument
will throw an IllegalArgumentException
when called on one
of these instances. The normalized component values of instances
of this class have a range which depends on the transfer
type as follows: for float samples, the full range of the float data
type; for double samples, the full range of the float data type
(resulting from casting double to float); for short samples,
from approximately -maxVal to +maxVal, where maxVal is the per
component maximum value for the ColorSpace
(-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps
to +maxVal). A subclass may override the scaling for short sample
values to normalized component values by overriding the
getNormalizedComponents(Object, float[], int)
method.
For float and double samples, the normalized component values are
taken to be equal to the corresponding sample values, and subclasses
should not attempt to add any non-identity scaling for these transfer
types.
Instances of ComponentColorModel
created with transfer types
DataBuffer.TYPE_SHORT
, DataBuffer.TYPE_FLOAT
, and
DataBuffer.TYPE_DOUBLE
use all the bits of all sample values. Thus all color/alpha components
have 16 bits when using DataBuffer.TYPE_SHORT
, 32 bits when
using DataBuffer.TYPE_FLOAT
, and 64 bits when using
DataBuffer.TYPE_DOUBLE
. When the
ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)
form of constructor is used with one of these transfer types, the
bits array argument is ignored.
It is possible to have color/alpha sample values
which cannot be reasonably interpreted as component values for rendering.
This can happen when ComponentColorModel
is subclassed to
override the mapping of unsigned sample values to normalized color
component values or when signed sample values outside a certain range
are used. (As an example, specifying an alpha component as a signed
short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can
lead to unexpected results.) It is the
responsibility of applications to appropriately scale pixel data before
rendering such that color components fall within the normalized range
of the ColorSpace
(obtained using the getMinValue
and getMaxValue
methods of the ColorSpace
class)
and the alpha component is between 0.0 and 1.0. If color or alpha
component values fall outside these ranges, rendering results are
indeterminate.
Methods that use a single int pixel representation throw
an IllegalArgumentException
, unless the number of components
for the ComponentColorModel
is one and the component
value is unsigned -- in other words, a single color component using
a transfer type of DataBuffer.TYPE_BYTE
,
DataBuffer.TYPE_USHORT
, or DataBuffer.TYPE_INT
and no alpha.
A ComponentColorModel
can be used in conjunction with a
ComponentSampleModel
, a BandedSampleModel
,
or a PixelInterleavedSampleModel
to construct a
BufferedImage
.
See Also:
/**
* A <CODE>ColorModel</CODE> class that works with pixel values that
* represent color and alpha information as separate samples and that
* store each sample in a separate data element. This class can be
* used with an arbitrary <CODE>ColorSpace</CODE>. The number of
* color samples in the pixel values must be same as the number of
* color components in the <CODE>ColorSpace</CODE>. There may be a
* single alpha sample.
* <p>
* For those methods that use
* a primitive array pixel representation of type <CODE>transferType</CODE>,
* the array length is the same as the number of color and alpha samples.
* Color samples are stored first in the array followed by the alpha
* sample, if present. The order of the color samples is specified
* by the <CODE>ColorSpace</CODE>. Typically, this order reflects the
* name of the color space type. For example, for <CODE>TYPE_RGB</CODE>,
* index 0 corresponds to red, index 1 to green, and index 2 to blue.
* <p>
* The translation from pixel sample values to color/alpha components for
* display or processing purposes is based on a one-to-one correspondence of
* samples to components.
* Depending on the transfer type used to create an instance of
* <code>ComponentColorModel</code>, the pixel sample values
* represented by that instance may be signed or unsigned and may
* be of integral type or float or double (see below for details).
* The translation from sample values to normalized color/alpha components
* must follow certain rules. For float and double samples, the translation
* is an identity, i.e. normalized component values are equal to the
* corresponding sample values. For integral samples, the translation
* should be only a simple scale and offset, where the scale and offset
* constants may be different for each component. The result of
* applying the scale and offset constants is a set of color/alpha
* component values, which are guaranteed to fall within a certain
* range. Typically, the range for a color component will be the range
* defined by the <code>getMinValue</code> and <code>getMaxValue</code>
* methods of the <code>ColorSpace</code> class. The range for an
* alpha component should be 0.0 to 1.0.
* <p>
* Instances of <code>ComponentColorModel</code> created with transfer types
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* and <CODE>DataBuffer.TYPE_INT</CODE> have pixel sample values which
* are treated as unsigned integral values.
* The number of bits in a color or alpha sample of a pixel value might not
* be the same as the number of bits for the corresponding color or alpha
* sample passed to the
* <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
* constructor. In
* that case, this class assumes that the least significant n bits of a sample
* value hold the component value, where n is the number of significant bits
* for the component passed to the constructor. It also assumes that
* any higher-order bits in a sample value are zero. Thus, sample values
* range from 0 to 2<sup>n</sup> - 1. This class maps these sample values
* to normalized color component values such that 0 maps to the value
* obtained from the <code>ColorSpace's</code> <code>getMinValue</code>
* method for each component and 2<sup>n</sup> - 1 maps to the value
* obtained from <code>getMaxValue</code>. To create a
* <code>ComponentColorModel</code> with a different color sample mapping
* requires subclassing this class and overriding the
* <code>getNormalizedComponents(Object, float[], int)</code> method.
* The mapping for an alpha sample always maps 0 to 0.0 and
* 2<sup>n</sup> - 1 to 1.0.
* <p>
* For instances with unsigned sample values,
* the unnormalized color/alpha component representation is only
* supported if two conditions hold. First, sample value value 0 must
* map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1
* to 1.0. Second the min/max range of all color components of the
* <code>ColorSpace</code> must be 0.0 to 1.0. In this case, the
* component representation is the n least
* significant bits of the corresponding sample. Thus each component is
* an unsigned integral value between 0 and 2<sup>n</sup> - 1, where
* n is the number of significant bits for a particular component.
* If these conditions are not met, any method taking an unnormalized
* component argument will throw an <code>IllegalArgumentException</code>.
* <p>
* Instances of <code>ComponentColorModel</code> created with transfer types
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
* <CODE>DataBuffer.TYPE_DOUBLE</CODE> have pixel sample values which
* are treated as signed short, float, or double values.
* Such instances do not support the unnormalized color/alpha component
* representation, so any methods taking such a representation as an argument
* will throw an <code>IllegalArgumentException</code> when called on one
* of these instances. The normalized component values of instances
* of this class have a range which depends on the transfer
* type as follows: for float samples, the full range of the float data
* type; for double samples, the full range of the float data type
* (resulting from casting double to float); for short samples,
* from approximately -maxVal to +maxVal, where maxVal is the per
* component maximum value for the <code>ColorSpace</code>
* (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps
* to +maxVal). A subclass may override the scaling for short sample
* values to normalized component values by overriding the
* <code>getNormalizedComponents(Object, float[], int)</code> method.
* For float and double samples, the normalized component values are
* taken to be equal to the corresponding sample values, and subclasses
* should not attempt to add any non-identity scaling for these transfer
* types.
* <p>
* Instances of <code>ComponentColorModel</code> created with transfer types
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
* <CODE>DataBuffer.TYPE_DOUBLE</CODE>
* use all the bits of all sample values. Thus all color/alpha components
* have 16 bits when using <CODE>DataBuffer.TYPE_SHORT</CODE>, 32 bits when
* using <CODE>DataBuffer.TYPE_FLOAT</CODE>, and 64 bits when using
* <CODE>DataBuffer.TYPE_DOUBLE</CODE>. When the
* <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
* form of constructor is used with one of these transfer types, the
* bits array argument is ignored.
* <p>
* It is possible to have color/alpha sample values
* which cannot be reasonably interpreted as component values for rendering.
* This can happen when <code>ComponentColorModel</code> is subclassed to
* override the mapping of unsigned sample values to normalized color
* component values or when signed sample values outside a certain range
* are used. (As an example, specifying an alpha component as a signed
* short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can
* lead to unexpected results.) It is the
* responsibility of applications to appropriately scale pixel data before
* rendering such that color components fall within the normalized range
* of the <code>ColorSpace</code> (obtained using the <code>getMinValue</code>
* and <code>getMaxValue</code> methods of the <code>ColorSpace</code> class)
* and the alpha component is between 0.0 and 1.0. If color or alpha
* component values fall outside these ranges, rendering results are
* indeterminate.
* <p>
* Methods that use a single int pixel representation throw
* an <CODE>IllegalArgumentException</CODE>, unless the number of components
* for the <CODE>ComponentColorModel</CODE> is one and the component
* value is unsigned -- in other words, a single color component using
* a transfer type of <CODE>DataBuffer.TYPE_BYTE</CODE>,
* <CODE>DataBuffer.TYPE_USHORT</CODE>, or <CODE>DataBuffer.TYPE_INT</CODE>
* and no alpha.
* <p>
* A <CODE>ComponentColorModel</CODE> can be used in conjunction with a
* <CODE>ComponentSampleModel</CODE>, a <CODE>BandedSampleModel</CODE>,
* or a <CODE>PixelInterleavedSampleModel</CODE> to construct a
* <CODE>BufferedImage</CODE>.
*
* @see ColorModel
* @see ColorSpace
* @see ComponentSampleModel
* @see BandedSampleModel
* @see PixelInterleavedSampleModel
* @see BufferedImage
*
*/
public class ComponentColorModel extends ColorModel {
signed
is true
for short
,
float
, and double
transfer types; it
is false
for byte
, ushort
,
and int
transfer types.
/**
* <code>signed</code> is <code>true</code> for <code>short</code>,
* <code>float</code>, and <code>double</code> transfer types; it
* is <code>false</code> for <code>byte</code>, <code>ushort</code>,
* and <code>int</code> transfer types.
*/
private boolean signed; // true for transfer types short, float, double
// false for byte, ushort, int
private boolean is_sRGB_stdScale;
private boolean is_LinearRGB_stdScale;
private boolean is_LinearGray_stdScale;
private boolean is_ICCGray_stdScale;
private byte[] tosRGB8LUT;
private byte[] fromsRGB8LUT8;
private short[] fromsRGB8LUT16;
private byte[] fromLinearGray16ToOtherGray8LUT;
private short[] fromLinearGray16ToOtherGray16LUT;
private boolean needScaleInit;
private boolean noUnnorm;
private boolean nonStdScale;
private float[] min;
private float[] diffMinMax;
private float[] compOffset;
private float[] compScale;
Constructs a ComponentColorModel
from the specified
parameters. Color components will be in the specified
ColorSpace
. The supported transfer types are
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
,
DataBuffer.TYPE_SHORT
, DataBuffer.TYPE_FLOAT
,
and DataBuffer.TYPE_DOUBLE
.
If not null, the bits
array specifies the
number of significant bits per color and alpha component and its
length should be at least the number of components in the
ColorSpace
if there is no alpha
information in the pixel values, or one more than this number if
there is alpha information. When the transferType
is
DataBuffer.TYPE_SHORT
, DataBuffer.TYPE_FLOAT
,
or DataBuffer.TYPE_DOUBLE
the bits
array
argument is ignored. hasAlpha
indicates whether alpha
information is present. If hasAlpha
is true, then
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
specifies what alpha values can be represented by this color model.
The acceptable transparency
values are
OPAQUE
, BITMASK
or TRANSLUCENT
.
The transferType
is the type of primitive array used
to represent pixel values.
Params: - colorSpace – The
ColorSpace
associated
with this color model. - bits – The number of significant bits per component.
May be null, in which case all bits of all
component samples will be significant.
Ignored if transferType is one of
DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or
DataBuffer.TYPE_DOUBLE
,
in which case all bits of all component
samples will be significant. - hasAlpha – If true, this color model supports alpha.
- isAlphaPremultiplied – If true, alpha is premultiplied.
- transparency – Specifies what alpha values can be represented
by this color model.
- transferType – Specifies the type of primitive array used to
represent pixel values.
Throws: - IllegalArgumentException – If the
bits
array
argument is not null, its length is less than the number of
color and alpha components, and transferType is one of
DataBuffer.TYPE_BYTE
,
DataBuffer.TYPE_USHORT
, or
DataBuffer.TYPE_INT
. - IllegalArgumentException – If transferType is not one of
DataBuffer.TYPE_BYTE
,
DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
,
DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or
DataBuffer.TYPE_DOUBLE
.
See Also:
/**
* Constructs a <CODE>ComponentColorModel</CODE> from the specified
* parameters. Color components will be in the specified
* <CODE>ColorSpace</CODE>. The supported transfer types are
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>,
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
* and <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
* If not null, the <CODE>bits</CODE> array specifies the
* number of significant bits per color and alpha component and its
* length should be at least the number of components in the
* <CODE>ColorSpace</CODE> if there is no alpha
* information in the pixel values, or one more than this number if
* there is alpha information. When the <CODE>transferType</CODE> is
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
* or <CODE>DataBuffer.TYPE_DOUBLE</CODE> the <CODE>bits</CODE> array
* argument is ignored. <CODE>hasAlpha</CODE> indicates whether alpha
* information is present. If <CODE>hasAlpha</CODE> is true, then
* the boolean <CODE>isAlphaPremultiplied</CODE>
* 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 <CODE>transparency</CODE>
* specifies what alpha values can be represented by this color model.
* The acceptable <code>transparency</code> values are
* <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
* The <CODE>transferType</CODE> is the type of primitive array used
* to represent pixel values.
*
* @param colorSpace The <CODE>ColorSpace</CODE> associated
* with this color model.
* @param bits The number of significant bits per component.
* May be null, in which case all bits of all
* component samples will be significant.
* Ignored if transferType is one of
* <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
* <CODE>DataBuffer.TYPE_DOUBLE</CODE>,
* in which case all bits of all component
* samples will be significant.
* @param hasAlpha If true, this color model supports alpha.
* @param isAlphaPremultiplied If true, alpha is premultiplied.
* @param transparency Specifies what alpha values can be represented
* by this color model.
* @param transferType Specifies the type of primitive array used to
* represent pixel values.
*
* @throws IllegalArgumentException If the <CODE>bits</CODE> array
* argument is not null, its length is less than the number of
* color and alpha components, and transferType is one of
* <CODE>DataBuffer.TYPE_BYTE</CODE>,
* <CODE>DataBuffer.TYPE_USHORT</CODE>, or
* <CODE>DataBuffer.TYPE_INT</CODE>.
* @throws IllegalArgumentException If transferType is not one of
* <CODE>DataBuffer.TYPE_BYTE</CODE>,
* <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>,
* <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
* <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
*
* @see ColorSpace
* @see java.awt.Transparency
*/
public ComponentColorModel (ColorSpace colorSpace,
int[] bits,
boolean hasAlpha,
boolean isAlphaPremultiplied,
int transparency,
int transferType) {
super (bitsHelper(transferType, colorSpace, hasAlpha),
bitsArrayHelper(bits, transferType, colorSpace, hasAlpha),
colorSpace, hasAlpha, isAlphaPremultiplied, transparency,
transferType);
switch(transferType) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_INT:
signed = false;
needScaleInit = true;
break;
case DataBuffer.TYPE_SHORT:
signed = true;
needScaleInit = true;
break;
case DataBuffer.TYPE_FLOAT:
case DataBuffer.TYPE_DOUBLE:
signed = true;
needScaleInit = false;
noUnnorm = true;
nonStdScale = false;
break;
default:
throw new IllegalArgumentException("This constructor is not "+
"compatible with transferType " + transferType);
}
setupLUTs();
}
Constructs a ComponentColorModel
from the specified
parameters. Color components will be in the specified
ColorSpace
. The supported transfer types are
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
,
DataBuffer.TYPE_SHORT
, DataBuffer.TYPE_FLOAT
,
and DataBuffer.TYPE_DOUBLE
. The number of significant
bits per color and alpha component will be 8, 16, 32, 16, 32, or 64,
respectively. The number of color components will be the
number of components in the ColorSpace
. There will be
an alpha component if hasAlpha
is true
.
If hasAlpha
is true, then
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
specifies what alpha values can be represented by this color model.
The acceptable transparency
values are
OPAQUE
, BITMASK
or TRANSLUCENT
.
The transferType
is the type of primitive array used
to represent pixel values.
Params: - colorSpace – The
ColorSpace
associated
with this color model. - hasAlpha – If true, this color model supports alpha.
- isAlphaPremultiplied – If true, alpha is premultiplied.
- transparency – Specifies what alpha values can be represented
by this color model.
- transferType – Specifies the type of primitive array used to
represent pixel values.
Throws: - IllegalArgumentException – If transferType is not one of
DataBuffer.TYPE_BYTE
,
DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
,
DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or
DataBuffer.TYPE_DOUBLE
.
See Also: Since: 1.4
/**
* Constructs a <CODE>ComponentColorModel</CODE> from the specified
* parameters. Color components will be in the specified
* <CODE>ColorSpace</CODE>. The supported transfer types are
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>,
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
* and <CODE>DataBuffer.TYPE_DOUBLE</CODE>. The number of significant
* bits per color and alpha component will be 8, 16, 32, 16, 32, or 64,
* respectively. The number of color components will be the
* number of components in the <CODE>ColorSpace</CODE>. There will be
* an alpha component if <CODE>hasAlpha</CODE> is <CODE>true</CODE>.
* If <CODE>hasAlpha</CODE> is true, then
* the boolean <CODE>isAlphaPremultiplied</CODE>
* 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 <CODE>transparency</CODE>
* specifies what alpha values can be represented by this color model.
* The acceptable <code>transparency</code> values are
* <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
* The <CODE>transferType</CODE> is the type of primitive array used
* to represent pixel values.
*
* @param colorSpace The <CODE>ColorSpace</CODE> associated
* with this color model.
* @param hasAlpha If true, this color model supports alpha.
* @param isAlphaPremultiplied If true, alpha is premultiplied.
* @param transparency Specifies what alpha values can be represented
* by this color model.
* @param transferType Specifies the type of primitive array used to
* represent pixel values.
*
* @throws IllegalArgumentException If transferType is not one of
* <CODE>DataBuffer.TYPE_BYTE</CODE>,
* <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>,
* <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
* <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
*
* @see ColorSpace
* @see java.awt.Transparency
* @since 1.4
*/
public ComponentColorModel (ColorSpace colorSpace,
boolean hasAlpha,
boolean isAlphaPremultiplied,
int transparency,
int transferType) {
this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
transparency, transferType);
}
private static int bitsHelper(int transferType,
ColorSpace colorSpace,
boolean hasAlpha) {
int numBits = DataBuffer.getDataTypeSize(transferType);
int numComponents = colorSpace.getNumComponents();
if (hasAlpha) {
++numComponents;
}
return numBits * numComponents;
}
private static int[] bitsArrayHelper(int[] origBits,
int transferType,
ColorSpace colorSpace,
boolean hasAlpha) {
switch(transferType) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_INT:
if (origBits != null) {
return origBits;
}
break;
default:
break;
}
int numBits = DataBuffer.getDataTypeSize(transferType);
int numComponents = colorSpace.getNumComponents();
if (hasAlpha) {
++numComponents;
}
int[] bits = new int[numComponents];
for (int i = 0; i < numComponents; i++) {
bits[i] = numBits;
}
return bits;
}
private void setupLUTs() {
// REMIND: there is potential to accelerate sRGB, LinearRGB,
// LinearGray, ICCGray, and non-ICC Gray spaces with non-standard
// scaling, if that becomes important
//
// NOTE: The is_xxx_stdScale and nonStdScale booleans are provisionally
// set here when this method is called at construction time. These
// variables may be set again when initScale is called later.
// When setupLUTs returns, nonStdScale is true if (the transferType
// is not float or double) AND (some minimum ColorSpace component
// value is not 0.0 OR some maximum ColorSpace component value
// is not 1.0). This is correct for the calls to
// getNormalizedComponents(Object, float[], int) from initScale().
// initScale() may change the value nonStdScale based on the
// return value of getNormalizedComponents() - this will only
// happen if getNormalizedComponents() has been overridden by a
// subclass to make the mapping of min/max pixel sample values
// something different from min/max color component values.
if (is_sRGB) {
is_sRGB_stdScale = true;
nonStdScale = false;
} else if (ColorModel.isLinearRGBspace(colorSpace)) {
// Note that the built-in Linear RGB space has a normalized
// range of 0.0 - 1.0 for each coordinate. Usage of these
// LUTs makes that assumption.
is_LinearRGB_stdScale = true;
nonStdScale = false;
if (transferType == DataBuffer.TYPE_BYTE) {
tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
} else {
tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
}
} else if ((colorSpaceType == ColorSpace.TYPE_GRAY) &&
(colorSpace instanceof ICC_ColorSpace) &&
(colorSpace.getMinValue(0) == 0.0f) &&
(colorSpace.getMaxValue(0) == 1.0f)) {
// Note that a normalized range of 0.0 - 1.0 for the gray
// component is required, because usage of these LUTs makes
// that assumption.
ICC_ColorSpace ics = (ICC_ColorSpace) colorSpace;
is_ICCGray_stdScale = true;
nonStdScale = false;
fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
if (ColorModel.isLinearGRAYspace(ics)) {
is_LinearGray_stdScale = true;
if (transferType == DataBuffer.TYPE_BYTE) {
tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
} else {
tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
}
} else {
if (transferType == DataBuffer.TYPE_BYTE) {
tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
fromLinearGray16ToOtherGray8LUT =
ColorModel.getLinearGray16ToOtherGray8LUT(ics);
} else {
tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
fromLinearGray16ToOtherGray16LUT =
ColorModel.getLinearGray16ToOtherGray16LUT(ics);
}
}
} else if (needScaleInit) {
// if transferType is byte, ushort, int, or short and we
// don't already know the ColorSpace has minVlaue == 0.0f and
// maxValue == 1.0f for all components, we need to check that
// now and setup the min[] and diffMinMax[] arrays if necessary.
nonStdScale = false;
for (int i = 0; i < numColorComponents; i++) {
if ((colorSpace.getMinValue(i) != 0.0f) ||
(colorSpace.getMaxValue(i) != 1.0f)) {
nonStdScale = true;
break;
}
}
if (nonStdScale) {
min = new float[numColorComponents];
diffMinMax = new float[numColorComponents];
for (int i = 0; i < numColorComponents; i++) {
min[i] = colorSpace.getMinValue(i);
diffMinMax[i] = colorSpace.getMaxValue(i) - min[i];
}
}
}
}
private void initScale() {
// This method is called the first time any method which uses
// pixel sample value to color component value scaling information
// is called if the transferType supports non-standard scaling
// as defined above (byte, ushort, int, and short), unless the
// method is getNormalizedComponents(Object, float[], int) (that
// method must be overridden to use non-standard scaling). This
// method also sets up the noUnnorm boolean variable for these
// transferTypes. After this method is called, the nonStdScale
// variable will be true if getNormalizedComponents() maps a
// sample value of 0 to anything other than 0.0f OR maps a
// sample value of 2^^n - 1 (2^^15 - 1 for short transferType)
// to anything other than 1.0f. Note that this can be independent
// of the colorSpace min/max component values, if the
// getNormalizedComponents() method has been overridden for some
// reason, e.g. to provide greater dynamic range in the sample
// values than in the color component values. Unfortunately,
// this method can't be called at construction time, since a
// subclass may still have uninitialized state that would cause
// getNormalizedComponents() to return an incorrect result.
needScaleInit = false; // only needs to called once
if (nonStdScale || signed) {
// The unnormalized form is only supported for unsigned
// transferTypes and when the ColorSpace min/max values
// are 0.0/1.0. When this method is called nonStdScale is
// true if the latter condition does not hold. In addition,
// the unnormalized form requires that the full range of
// the pixel sample values map to the full 0.0 - 1.0 range
// of color component values. That condition is checked
// later in this method.
noUnnorm = true;
} else {
noUnnorm = false;
}
float[] lowVal, highVal;
switch (transferType) {
case DataBuffer.TYPE_BYTE:
{
byte[] bpixel = new byte[numComponents];
for (int i = 0; i < numColorComponents; i++) {
bpixel[i] = 0;
}
if (supportsAlpha) {
bpixel[numColorComponents] =
(byte) ((1 << nBits[numColorComponents]) - 1);
}
lowVal = getNormalizedComponents(bpixel, null, 0);
for (int i = 0; i < numColorComponents; i++) {
bpixel[i] = (byte) ((1 << nBits[i]) - 1);
}
highVal = getNormalizedComponents(bpixel, null, 0);
}
break;
case DataBuffer.TYPE_USHORT:
{
short[] uspixel = new short[numComponents];
for (int i = 0; i < numColorComponents; i++) {
uspixel[i] = 0;
}
if (supportsAlpha) {
uspixel[numColorComponents] =
(short) ((1 << nBits[numColorComponents]) - 1);
}
lowVal = getNormalizedComponents(uspixel, null, 0);
for (int i = 0; i < numColorComponents; i++) {
uspixel[i] = (short) ((1 << nBits[i]) - 1);
}
highVal = getNormalizedComponents(uspixel, null, 0);
}
break;
case DataBuffer.TYPE_INT:
{
int[] ipixel = new int[numComponents];
for (int i = 0; i < numColorComponents; i++) {
ipixel[i] = 0;
}
if (supportsAlpha) {
ipixel[numColorComponents] =
((1 << nBits[numColorComponents]) - 1);
}
lowVal = getNormalizedComponents(ipixel, null, 0);
for (int i = 0; i < numColorComponents; i++) {
ipixel[i] = ((1 << nBits[i]) - 1);
}
highVal = getNormalizedComponents(ipixel, null, 0);
}
break;
case DataBuffer.TYPE_SHORT:
{
short[] spixel = new short[numComponents];
for (int i = 0; i < numColorComponents; i++) {
spixel[i] = 0;
}
if (supportsAlpha) {
spixel[numColorComponents] = 32767;
}
lowVal = getNormalizedComponents(spixel, null, 0);
for (int i = 0; i < numColorComponents; i++) {
spixel[i] = 32767;
}
highVal = getNormalizedComponents(spixel, null, 0);
}
break;
default:
lowVal = highVal = null; // to keep the compiler from complaining
break;
}
nonStdScale = false;
for (int i = 0; i < numColorComponents; i++) {
if ((lowVal[i] != 0.0f) || (highVal[i] != 1.0f)) {
nonStdScale = true;
break;
}
}
if (nonStdScale) {
noUnnorm = true;
is_sRGB_stdScale = false;
is_LinearRGB_stdScale = false;
is_LinearGray_stdScale = false;
is_ICCGray_stdScale = false;
compOffset = new float[numColorComponents];
compScale = new float[numColorComponents];
for (int i = 0; i < numColorComponents; i++) {
compOffset[i] = lowVal[i];
compScale[i] = 1.0f / (highVal[i] - lowVal[i]);
}
}
}
private int getRGBComponent(int pixel, int idx) {
if (numComponents > 1) {
throw new
IllegalArgumentException("More than one component per pixel");
}
if (signed) {
throw new
IllegalArgumentException("Component value is signed");
}
if (needScaleInit) {
initScale();
}
// Since there is only 1 component, there is no alpha
// Normalize the pixel in order to convert it
Object opixel = null;
switch (transferType) {
case DataBuffer.TYPE_BYTE:
{
byte[] bpixel = { (byte) pixel };
opixel = bpixel;
}
break;
case DataBuffer.TYPE_USHORT:
{
short[] spixel = { (short) pixel };
opixel = spixel;
}
break;
case DataBuffer.TYPE_INT:
{
int[] ipixel = { pixel };
opixel = ipixel;
}
break;
}
float[] norm = getNormalizedComponents(opixel, null, 0);
float[] rgb = colorSpace.toRGB(norm);
return (int) (rgb[idx] * 255.0f + 0.5f);
}
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.
If the alpha is premultiplied, this method divides
it out before returning the value (if the alpha value is 0,
the red value will be 0).
Params: - pixel – The pixel from which you want to get the red color component.
Throws: - IllegalArgumentException – If there is more than
one component in this
ColorModel
. - IllegalArgumentException – If the component value for this
ColorModel
is signed
Returns: The red color component for the specified pixel, as an int.
/**
* 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.
* If the alpha is premultiplied, this method divides
* it out before returning the value (if the alpha value is 0,
* the red value will be 0).
*
* @param pixel The pixel from which you want to get the red color component.
*
* @return The red color component for the specified pixel, as an int.
*
* @throws IllegalArgumentException If there is more than
* one component in this <CODE>ColorModel</CODE>.
* @throws IllegalArgumentException If the component value for this
* <CODE>ColorModel</CODE> is signed
*/
public int getRed(int pixel) {
return getRGBComponent(pixel, 0);
}
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. If the alpha is premultiplied, this method
divides it out before returning the value (if the alpha value is 0,
the green value will be 0).
Params: - pixel – The pixel from which you want to get the green color component.
Throws: - IllegalArgumentException – If there is more than
one component in this
ColorModel
. - IllegalArgumentException – If the component value for this
ColorModel
is signed
Returns: The green color component for the specified pixel, as an int.
/**
* 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. If the alpha is premultiplied, this method
* divides it out before returning the value (if the alpha value is 0,
* the green value will be 0).
*
* @param pixel The pixel from which you want to get the green color component.
*
* @return The green color component for the specified pixel, as an int.
*
* @throws IllegalArgumentException If there is more than
* one component in this <CODE>ColorModel</CODE>.
* @throws IllegalArgumentException If the component value for this
* <CODE>ColorModel</CODE> is signed
*/
public int getGreen(int pixel) {
return getRGBComponent(pixel, 1);
}
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. 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).
Params: - pixel – The pixel from which you want to get the blue color component.
Throws: - IllegalArgumentException – If there is more than
one component in this
ColorModel
. - IllegalArgumentException – If the component value for this
ColorModel
is signed
Returns: The blue color component for the specified pixel, as an int.
/**
* 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. 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).
*
* @param pixel The pixel from which you want to get the blue color component.
*
* @return The blue color component for the specified pixel, as an int.
*
* @throws IllegalArgumentException If there is more than
* one component in this <CODE>ColorModel</CODE>.
* @throws IllegalArgumentException If the component value for this
* <CODE>ColorModel</CODE> is signed
*/
public int getBlue(int pixel) {
return getRGBComponent(pixel, 2);
}
Returns the alpha component for the specified pixel, scaled
from 0 to 255. The pixel value is specified as an int.
Params: - pixel – The pixel from which you want to get the alpha component.
Throws: - IllegalArgumentException – If there is more than
one component in this
ColorModel
. - IllegalArgumentException – If the component value for this
ColorModel
is signed
Returns: The alpha component for the specified pixel, as an int.
/**
* Returns the alpha component for the specified pixel, scaled
* from 0 to 255. The pixel value is specified as an int.
*
* @param pixel The pixel from which you want to get the alpha component.
*
* @return The alpha component for the specified pixel, as an int.
*
* @throws IllegalArgumentException If there is more than
* one component in this <CODE>ColorModel</CODE>.
* @throws IllegalArgumentException If the component value for this
* <CODE>ColorModel</CODE> is signed
*/
public int getAlpha(int pixel) {
if (supportsAlpha == false) {
return 255;
}
if (numComponents > 1) {
throw new
IllegalArgumentException("More than one component per pixel");
}
if (signed) {
throw new
IllegalArgumentException("Component value is signed");
}
return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f);
}
Returns the color/alpha components of the pixel in the default
RGB color model format. A color conversion is done if necessary.
The returned value will be in a non pre-multiplied format. If
the alpha is premultiplied, this method divides it out of the
color components (if the alpha value is 0, the color values will be 0).
Params: - pixel – The pixel from which you want to get the color/alpha components.
Throws: - IllegalArgumentException – If there is more than
one component in this
ColorModel
. - IllegalArgumentException – If the component value for this
ColorModel
is signed
Returns: The color/alpha components for the specified pixel, as an int.
/**
* Returns the color/alpha components of the pixel in the default
* RGB color model format. A color conversion is done if necessary.
* The returned value will be in a non pre-multiplied format. If
* the alpha is premultiplied, this method divides it out of the
* color components (if the alpha value is 0, the color values will be 0).
*
* @param pixel The pixel from which you want to get the color/alpha components.
*
* @return The color/alpha components for the specified pixel, as an int.
*
* @throws IllegalArgumentException If there is more than
* one component in this <CODE>ColorModel</CODE>.
* @throws IllegalArgumentException If the component value for this
* <CODE>ColorModel</CODE> is signed
*/
public int getRGB(int pixel) {
if (numComponents > 1) {
throw new
IllegalArgumentException("More than one component per pixel");
}
if (signed) {
throw new
IllegalArgumentException("Component value is signed");
}
return (getAlpha(pixel) << 24)
| (getRed(pixel) << 16)
| (getGreen(pixel) << 8)
| (getBlue(pixel) << 0);
}
private int extractComponent(Object inData, int idx, int precision) {
// Extract component idx from inData. The precision argument
// should be either 8 or 16. If it's 8, this method will return
// an 8-bit value. If it's 16, this method will return a 16-bit
// value for transferTypes other than TYPE_BYTE. For TYPE_BYTE,
// an 8-bit value will be returned.
// This method maps the input value corresponding to a
// normalized ColorSpace component value of 0.0 to 0, and the
// input value corresponding to a normalized ColorSpace
// component value of 1.0 to 2^n - 1 (where n is 8 or 16), so
// it is appropriate only for ColorSpaces with min/max component
// values of 0.0/1.0. This will be true for sRGB, the built-in
// Linear RGB and Linear Gray spaces, and any other ICC grayscale
// spaces for which we have precomputed LUTs.
boolean needAlpha = (supportsAlpha && isAlphaPremultiplied);
int alp = 0;
int comp;
int mask = (1 << nBits[idx]) - 1;
switch (transferType) {
// Note: we do no clamping of the pixel data here - we
// assume that the data is scaled properly
case DataBuffer.TYPE_SHORT: {
short sdata[] = (short[]) inData;
float scalefactor = (float) ((1 << precision) - 1);
if (needAlpha) {
short s = sdata[numColorComponents];
if (s != (short) 0) {
return (int) ((((float) sdata[idx]) /
((float) s)) * scalefactor + 0.5f);
} else {
return 0;
}
} else {
return (int) ((sdata[idx] / 32767.0f) * scalefactor + 0.5f);
}
}
case DataBuffer.TYPE_FLOAT: {
float fdata[] = (float[]) inData;
float scalefactor = (float) ((1 << precision) - 1);
if (needAlpha) {
float f = fdata[numColorComponents];
if (f != 0.0f) {
return (int) (((fdata[idx] / f) * scalefactor) + 0.5f);
} else {
return 0;
}
} else {
return (int) (fdata[idx] * scalefactor + 0.5f);
}
}
case DataBuffer.TYPE_DOUBLE: {
double ddata[] = (double[]) inData;
double scalefactor = (double) ((1 << precision) - 1);
if (needAlpha) {
double d = ddata[numColorComponents];
if (d != 0.0) {
return (int) (((ddata[idx] / d) * scalefactor) + 0.5);
} else {
return 0;
}
} else {
return (int) (ddata[idx] * scalefactor + 0.5);
}
}
case DataBuffer.TYPE_BYTE:
byte bdata[] = (byte[])inData;
comp = bdata[idx] & mask;
precision = 8;
if (needAlpha) {
alp = bdata[numColorComponents] & mask;
}
break;
case DataBuffer.TYPE_USHORT:
short usdata[] = (short[])inData;
comp = usdata[idx] & mask;
if (needAlpha) {
alp = usdata[numColorComponents] & mask;
}
break;
case DataBuffer.TYPE_INT:
int idata[] = (int[])inData;
comp = idata[idx];
if (needAlpha) {
alp = idata[numColorComponents];
}
break;
default:
throw new
UnsupportedOperationException("This method has not "+
"been implemented for transferType " + transferType);
}
if (needAlpha) {
if (alp != 0) {
float scalefactor = (float) ((1 << precision) - 1);
float fcomp = ((float) comp) / ((float)mask);
float invalp = ((float) ((1<<nBits[numColorComponents]) - 1)) /
((float) alp);
return (int) (fcomp * invalp * scalefactor + 0.5f);
} else {
return 0;
}
} else {
if (nBits[idx] != precision) {
float scalefactor = (float) ((1 << precision) - 1);
float fcomp = ((float) comp) / ((float)mask);
return (int) (fcomp * scalefactor + 0.5f);
}
return comp;
}
}
private int getRGBComponent(Object inData, int idx) {
if (needScaleInit) {
initScale();
}
if (is_sRGB_stdScale) {
return extractComponent(inData, idx, 8);
} else if (is_LinearRGB_stdScale) {
int lutidx = extractComponent(inData, idx, 16);
return tosRGB8LUT[lutidx] & 0xff;
} else if (is_ICCGray_stdScale) {
int lutidx = extractComponent(inData, 0, 16);
return tosRGB8LUT[lutidx] & 0xff;
}
// Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace
float[] norm = getNormalizedComponents(inData, null, 0);
// Note that getNormalizedComponents returns non-premultiplied values
float[] rgb = colorSpace.toRGB(norm);
return (int) (rgb[idx] * 255.0f + 0.5f);
}
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. If the
alpha is premultiplied, this method divides it out before returning
the value (if the alpha value is 0, the red value will be 0). Since
ComponentColorModel
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
transferType
.
Params: - inData – The pixel from which you want to get the red color component,
specified by an array of data elements of type
transferType
.
Throws: - ClassCastException – If
inData
is not a primitive array
of type transferType
. - ArrayIndexOutOfBoundsException – if
inData
is not
large enough to hold a pixel value for this
ColorModel
. - UnsupportedOperationException – If the transfer type of
this
ComponentColorModel
is not one of the supported transfer types:
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
, DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or DataBuffer.TYPE_DOUBLE
.
Returns: The red color component for the specified pixel, as an int.
/**
* 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 <CODE>pixel</CODE> value is specified by an array
* of data elements of type <CODE>transferType</CODE> passed in as an object
* reference. The returned value will be a non pre-multiplied value. If the
* alpha is premultiplied, this method divides it out before returning
* the value (if the alpha value is 0, the red value will be 0). Since
* <code>ComponentColorModel</code> 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</code>.
*
* @param inData The pixel from which you want to get the red color component,
* specified by an array of data elements of type <CODE>transferType</CODE>.
*
* @return The red color component for the specified pixel, as an int.
*
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
* of type <CODE>transferType</CODE>.
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
* large enough to hold a pixel value for this
* <CODE>ColorModel</CODE>.
* @throws UnsupportedOperationException If the transfer type of
* this <CODE>ComponentColorModel</CODE>
* is not one of the supported transfer types:
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
*/
public int getRed(Object inData) {
return getRGBComponent(inData, 0);
}
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 is a non pre-multiplied
value. If the alpha is premultiplied, this method divides it out before
returning the value (if the alpha value is 0, the green value will be 0).
Since ComponentColorModel
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 transferType
.
Params: - inData – The pixel from which you want to get the green color component,
specified by an array of data elements of type
transferType
.
Throws: - ClassCastException – If
inData
is not a primitive array
of type transferType
. - ArrayIndexOutOfBoundsException – if
inData
is not
large enough to hold a pixel value for this
ColorModel
. - UnsupportedOperationException – If the transfer type of
this
ComponentColorModel
is not one of the supported transfer types:
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
, DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or DataBuffer.TYPE_DOUBLE
.
Returns: The green color component for the specified pixel, as an int.
/**
* Returns the green color component for the specified pixel, scaled
* from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
* A color conversion is done if necessary. The <CODE>pixel</CODE> value
* is specified by an array of data elements of type <CODE>transferType</CODE>
* passed in as an object reference. The returned value is a non pre-multiplied
* value. If the alpha is premultiplied, this method divides it out before
* returning the value (if the alpha value is 0, the green value will be 0).
* Since <code>ComponentColorModel</code> 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</code>.
*
* @param inData The pixel from which you want to get the green color component,
* specified by an array of data elements of type <CODE>transferType</CODE>.
*
* @return The green color component for the specified pixel, as an int.
*
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
* of type <CODE>transferType</CODE>.
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
* large enough to hold a pixel value for this
* <CODE>ColorModel</CODE>.
* @throws UnsupportedOperationException If the transfer type of
* this <CODE>ComponentColorModel</CODE>
* is not one of the supported transfer types:
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
*/
public int getGreen(Object inData) {
return getRGBComponent(inData, 1);
}
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 is a non pre-multiplied
value. 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).
Since ComponentColorModel
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 transferType
.
Params: - inData – The pixel from which you want to get the blue color component,
specified by an array of data elements of type
transferType
.
Throws: - ClassCastException – If
inData
is not a primitive array
of type transferType
. - ArrayIndexOutOfBoundsException – if
inData
is not
large enough to hold a pixel value for this
ColorModel
. - UnsupportedOperationException – If the transfer type of
this
ComponentColorModel
is not one of the supported transfer types:
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
, DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or DataBuffer.TYPE_DOUBLE
.
Returns: The blue color component for the specified pixel, as an int.
/**
* Returns the blue color component for the specified pixel, scaled
* from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
* A color conversion is done if necessary. The <CODE>pixel</CODE> value is
* specified by an array of data elements of type <CODE>transferType</CODE>
* passed in as an object reference. The returned value is a non pre-multiplied
* value. 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).
* Since <code>ComponentColorModel</code> 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</code>.
*
* @param inData The pixel from which you want to get the blue color component,
* specified by an array of data elements of type <CODE>transferType</CODE>.
*
* @return The blue color component for the specified pixel, as an int.
*
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
* of type <CODE>transferType</CODE>.
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
* large enough to hold a pixel value for this
* <CODE>ColorModel</CODE>.
* @throws UnsupportedOperationException If the transfer type of
* this <CODE>ComponentColorModel</CODE>
* is not one of the supported transfer types:
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
*/
public int getBlue(Object inData) {
return getRGBComponent(inData, 2);
}
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. Since ComponentColorModel
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
transferType
.
Params: - inData – The pixel from which you want to get the alpha component,
specified by an array of data elements of type
transferType
.
Throws: - ClassCastException – If
inData
is not a primitive array
of type transferType
. - ArrayIndexOutOfBoundsException – if
inData
is not
large enough to hold a pixel value for this
ColorModel
. - UnsupportedOperationException – If the transfer type of
this
ComponentColorModel
is not one of the supported transfer types:
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
, DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or DataBuffer.TYPE_DOUBLE
.
Returns: The alpha component for the specified pixel, as an int.
/**
* 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</CODE> passed in as an
* object reference. Since <code>ComponentColorModel</code> 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</code>.
*
* @param inData The pixel from which you want to get the alpha component,
* specified by an array of data elements of type <CODE>transferType</CODE>.
*
* @return The alpha component for the specified pixel, as an int.
*
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
* of type <CODE>transferType</CODE>.
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
* large enough to hold a pixel value for this
* <CODE>ColorModel</CODE>.
* @throws UnsupportedOperationException If the transfer type of
* this <CODE>ComponentColorModel</CODE>
* is not one of the supported transfer types:
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
*/
public int getAlpha(Object inData) {
if (supportsAlpha == false) {
return 255;
}
int alpha = 0;
int aIdx = numColorComponents;
int mask = (1 << nBits[aIdx]) - 1;
switch (transferType) {
case DataBuffer.TYPE_SHORT:
short sdata[] = (short[])inData;
alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f);
return alpha;
case DataBuffer.TYPE_FLOAT:
float fdata[] = (float[])inData;
alpha = (int) (fdata[aIdx] * 255.0f + 0.5f);
return alpha;
case DataBuffer.TYPE_DOUBLE:
double ddata[] = (double[])inData;
alpha = (int) (ddata[aIdx] * 255.0 + 0.5);
return alpha;
case DataBuffer.TYPE_BYTE:
byte bdata[] = (byte[])inData;
alpha = bdata[aIdx] & mask;
break;
case DataBuffer.TYPE_USHORT:
short usdata[] = (short[])inData;
alpha = usdata[aIdx] & mask;
break;
case DataBuffer.TYPE_INT:
int idata[] = (int[])inData;
alpha = idata[aIdx];
break;
default:
throw new
UnsupportedOperationException("This method has not "+
"been implemented for transferType " + transferType);
}
if (nBits[aIdx] == 8) {
return alpha;
} else {
return (int)
((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) *
255.0f + 0.5f);
}
}
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.
The returned value is in a non pre-multiplied format. If
the alpha is premultiplied, this method divides it out of the
color components (if the alpha value is 0, the color values will be 0).
Since ComponentColorModel
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 transferType
.
Params: - inData – The pixel from which you want to get the color/alpha components,
specified by an array of data elements of type
transferType
.
Throws: - ClassCastException – If
inData
is not a primitive array
of type transferType
. - ArrayIndexOutOfBoundsException – if
inData
is not
large enough to hold a pixel value for this
ColorModel
. - UnsupportedOperationException – If the transfer type of
this
ComponentColorModel
is not one of the supported transfer types:
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
, DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or DataBuffer.TYPE_DOUBLE
.
See Also: Returns: The color/alpha components for the specified pixel, as an int.
/**
* 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</CODE> passed
* in as an object reference.
* The returned value is in a non pre-multiplied format. If
* the alpha is premultiplied, this method divides it out of the
* color components (if the alpha value is 0, the color values will be 0).
* Since <code>ComponentColorModel</code> 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</code>.
*
* @param inData The pixel from which you want to get the color/alpha components,
* specified by an array of data elements of type <CODE>transferType</CODE>.
*
* @return The color/alpha components for the specified pixel, as an int.
*
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
* of type <CODE>transferType</CODE>.
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
* large enough to hold a pixel value for this
* <CODE>ColorModel</CODE>.
* @throws UnsupportedOperationException If the transfer type of
* this <CODE>ComponentColorModel</CODE>
* is not one of the supported transfer types:
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
* @see ColorModel#getRGBdefault
*/
public int getRGB(Object inData) {
if (needScaleInit) {
initScale();
}
if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
return (getAlpha(inData) << 24)
| (getRed(inData) << 16)
| (getGreen(inData) << 8)
| (getBlue(inData));
} else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
int gray = getRed(inData); // Red sRGB component should equal
// green and blue components
return (getAlpha(inData) << 24)
| (gray << 16)
| (gray << 8)
| gray;
}
float[] norm = getNormalizedComponents(inData, null, 0);
// Note that getNormalizedComponents returns non-premult values
float[] rgb = colorSpace.toRGB(norm);
return (getAlpha(inData) << 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 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
parameter is null, a new array is allocated. Since
ComponentColorModel
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
transferType
.
Params: - rgb – the integer representation of the pixel in the RGB
color model
- pixel – the specified pixel
Throws: - ClassCastException – If
pixel
is not null and
is not a primitive array of type transferType
. - ArrayIndexOutOfBoundsException – If
pixel
is
not large enough to hold a pixel value for this
ColorModel
. - UnsupportedOperationException – If the transfer type of
this
ComponentColorModel
is not one of the supported transfer types:
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
, DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or DataBuffer.TYPE_DOUBLE
.
See Also: Returns: The data element array representation of a pixel
in this ColorModel
.
/**
* Returns a data element array representation of a pixel in this
* <CODE>ColorModel</CODE>, given an integer pixel representation
* in the default RGB color model.
* This array can then be passed to the <CODE>setDataElements</CODE>
* method of a <CODE>WritableRaster</CODE> object. If the
* <CODE>pixel</CODE>
* parameter is null, a new array is allocated. Since
* <code>ComponentColorModel</code> 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</code>.
*
* @param rgb the integer representation of the pixel in the RGB
* color model
* @param pixel the specified pixel
* @return The data element array representation of a pixel
* in this <CODE>ColorModel</CODE>.
* @throws ClassCastException If <CODE>pixel</CODE> is not null and
* is not a primitive array of type <CODE>transferType</CODE>.
* @throws ArrayIndexOutOfBoundsException If <CODE>pixel</CODE> is
* not large enough to hold a pixel value for this
* <CODE>ColorModel</CODE>.
* @throws UnsupportedOperationException If the transfer type of
* this <CODE>ComponentColorModel</CODE>
* is not one of the supported transfer types:
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
*
* @see WritableRaster#setDataElements
* @see SampleModel#setDataElements
*/
public Object getDataElements(int rgb, Object pixel) {
// REMIND: Use rendering hints?
int red, grn, blu, alp;
red = (rgb>>16) & 0xff;
grn = (rgb>>8) & 0xff;
blu = rgb & 0xff;
if (needScaleInit) {
initScale();
}
if (signed) {
// Handle SHORT, FLOAT, & DOUBLE here
switch(transferType) {
case DataBuffer.TYPE_SHORT:
{
short sdata[];
if (pixel == null) {
sdata = new short[numComponents];
} else {
sdata = (short[])pixel;
}
float factor;
if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
factor = 32767.0f / 255.0f;
if (is_LinearRGB_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
factor = 32767.0f / 65535.0f;
}
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
sdata[3] =
(short) (alp * (32767.0f / 255.0f) + 0.5f);
if (isAlphaPremultiplied) {
factor = alp * factor * (1.0f / 255.0f);
}
}
sdata[0] = (short) (red * factor + 0.5f);
sdata[1] = (short) (grn * factor + 0.5f);
sdata[2] = (short) (blu * factor + 0.5f);
} else if (is_LinearGray_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
float gray = ((0.2125f * red) +
(0.7154f * grn) +
(0.0721f * blu)) / 65535.0f;
factor = 32767.0f;
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
sdata[1] =
(short) (alp * (32767.0f / 255.0f) + 0.5f);
if (isAlphaPremultiplied) {
factor = alp * factor * (1.0f / 255.0f);
}
}
sdata[0] = (short) (gray * factor + 0.5f);
} else if (is_ICCGray_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
int gray = (int) ((0.2125f * red) +
(0.7154f * grn) +
(0.0721f * blu) + 0.5f);
gray = fromLinearGray16ToOtherGray16LUT[gray] & 0xffff;
factor = 32767.0f / 65535.0f;
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
sdata[1] =
(short) (alp * (32767.0f / 255.0f) + 0.5f);
if (isAlphaPremultiplied) {
factor = alp * factor * (1.0f / 255.0f);
}
}
sdata[0] = (short) (gray * factor + 0.5f);
} else {
factor = 1.0f / 255.0f;
float norm[] = new float[3];
norm[0] = red * factor;
norm[1] = grn * factor;
norm[2] = blu * factor;
norm = colorSpace.fromRGB(norm);
if (nonStdScale) {
for (int i = 0; i < numColorComponents; i++) {
norm[i] = (norm[i] - compOffset[i]) *
compScale[i];
// REMIND: need to analyze whether this
// clamping is necessary
if (norm[i] < 0.0f) {
norm[i] = 0.0f;
}
if (norm[i] > 1.0f) {
norm[i] = 1.0f;
}
}
}
factor = 32767.0f;
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
sdata[numColorComponents] =
(short) (alp * (32767.0f / 255.0f) + 0.5f);
if (isAlphaPremultiplied) {
factor *= alp * (1.0f / 255.0f);
}
}
for (int i = 0; i < numColorComponents; i++) {
sdata[i] = (short) (norm[i] * factor + 0.5f);
}
}
return sdata;
}
case DataBuffer.TYPE_FLOAT:
{
float fdata[];
if (pixel == null) {
fdata = new float[numComponents];
} else {
fdata = (float[])pixel;
}
float factor;
if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
if (is_LinearRGB_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
factor = 1.0f / 65535.0f;
} else {
factor = 1.0f / 255.0f;
}
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
fdata[3] = alp * (1.0f / 255.0f);
if (isAlphaPremultiplied) {
factor *= fdata[3];
}
}
fdata[0] = red * factor;
fdata[1] = grn * factor;
fdata[2] = blu * factor;
} else if (is_LinearGray_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
fdata[0] = ((0.2125f * red) +
(0.7154f * grn) +
(0.0721f * blu)) / 65535.0f;
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
fdata[1] = alp * (1.0f / 255.0f);
if (isAlphaPremultiplied) {
fdata[0] *= fdata[1];
}
}
} else if (is_ICCGray_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
int gray = (int) ((0.2125f * red) +
(0.7154f * grn) +
(0.0721f * blu) + 0.5f);
fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
0xffff) / 65535.0f;
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
fdata[1] = alp * (1.0f / 255.0f);
if (isAlphaPremultiplied) {
fdata[0] *= fdata[1];
}
}
} else {
float norm[] = new float[3];
factor = 1.0f / 255.0f;
norm[0] = red * factor;
norm[1] = grn * factor;
norm[2] = blu * factor;
norm = colorSpace.fromRGB(norm);
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
fdata[numColorComponents] = alp * factor;
if (isAlphaPremultiplied) {
factor *= alp;
for (int i = 0; i < numColorComponents; i++) {
norm[i] *= factor;
}
}
}
for (int i = 0; i < numColorComponents; i++) {
fdata[i] = norm[i];
}
}
return fdata;
}
case DataBuffer.TYPE_DOUBLE:
{
double ddata[];
if (pixel == null) {
ddata = new double[numComponents];
} else {
ddata = (double[])pixel;
}
if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
double factor;
if (is_LinearRGB_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
factor = 1.0 / 65535.0;
} else {
factor = 1.0 / 255.0;
}
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
ddata[3] = alp * (1.0 / 255.0);
if (isAlphaPremultiplied) {
factor *= ddata[3];
}
}
ddata[0] = red * factor;
ddata[1] = grn * factor;
ddata[2] = blu * factor;
} else if (is_LinearGray_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
ddata[0] = ((0.2125 * red) +
(0.7154 * grn) +
(0.0721 * blu)) / 65535.0;
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
ddata[1] = alp * (1.0 / 255.0);
if (isAlphaPremultiplied) {
ddata[0] *= ddata[1];
}
}
} else if (is_ICCGray_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
int gray = (int) ((0.2125f * red) +
(0.7154f * grn) +
(0.0721f * blu) + 0.5f);
ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
0xffff) / 65535.0;
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
ddata[1] = alp * (1.0 / 255.0);
if (isAlphaPremultiplied) {
ddata[0] *= ddata[1];
}
}
} else {
float factor = 1.0f / 255.0f;
float norm[] = new float[3];
norm[0] = red * factor;
norm[1] = grn * factor;
norm[2] = blu * factor;
norm = colorSpace.fromRGB(norm);
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
ddata[numColorComponents] = alp * (1.0 / 255.0);
if (isAlphaPremultiplied) {
factor *= alp;
for (int i = 0; i < numColorComponents; i++) {
norm[i] *= factor;
}
}
}
for (int i = 0; i < numColorComponents; i++) {
ddata[i] = norm[i];
}
}
return ddata;
}
}
}
// Handle BYTE, USHORT, & INT here
//REMIND: maybe more efficient not to use int array for
//DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
int intpixel[];
if (transferType == DataBuffer.TYPE_INT &&
pixel != null) {
intpixel = (int[])pixel;
} else {
intpixel = new int[numComponents];
}
if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
int precision;
float factor;
if (is_LinearRGB_stdScale) {
if (transferType == DataBuffer.TYPE_BYTE) {
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 (nBits[3] == 8) {
intpixel[3] = alp;
}
else {
intpixel[3] = (int)
(alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1) + 0.5f);
}
if (isAlphaPremultiplied) {
factor *= (alp * (1.0f / 255.0f));
precision = -1; // force component calculations below
}
}
if (nBits[0] == precision) {
intpixel[0] = red;
}
else {
intpixel[0] = (int) (red * factor * ((1<<nBits[0]) - 1) + 0.5f);
}
if (nBits[1] == precision) {
intpixel[1] = (int)(grn);
}
else {
intpixel[1] = (int) (grn * factor * ((1<<nBits[1]) - 1) + 0.5f);
}
if (nBits[2] == precision) {
intpixel[2] = (int)(blu);
}
else {
intpixel[2] = (int) (blu * factor * ((1<<nBits[2]) - 1) + 0.5f);
}
} else if (is_LinearGray_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
float gray = ((0.2125f * red) +
(0.7154f * grn) +
(0.0721f * blu)) / 65535.0f;
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
if (nBits[1] == 8) {
intpixel[1] = alp;
} else {
intpixel[1] = (int) (alp * (1.0f / 255.0f) *
((1 << nBits[1]) - 1) + 0.5f);
}
if (isAlphaPremultiplied) {
gray *= (alp * (1.0f / 255.0f));
}
}
intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
} else if (is_ICCGray_stdScale) {
red = fromsRGB8LUT16[red] & 0xffff;
grn = fromsRGB8LUT16[grn] & 0xffff;
blu = fromsRGB8LUT16[blu] & 0xffff;
int gray16 = (int) ((0.2125f * red) +
(0.7154f * grn) +
(0.0721f * blu) + 0.5f);
float gray = (fromLinearGray16ToOtherGray16LUT[gray16] &
0xffff) / 65535.0f;
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
if (nBits[1] == 8) {
intpixel[1] = alp;
} else {
intpixel[1] = (int) (alp * (1.0f / 255.0f) *
((1 << nBits[1]) - 1) + 0.5f);
}
if (isAlphaPremultiplied) {
gray *= (alp * (1.0f / 255.0f));
}
}
intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
} else {
// Need to convert the color
float[] norm = new float[3];
float factor = 1.0f / 255.0f;
norm[0] = red * factor;
norm[1] = grn * factor;
norm[2] = blu * factor;
norm = colorSpace.fromRGB(norm);
if (nonStdScale) {
for (int i = 0; i < numColorComponents; i++) {
norm[i] = (norm[i] - compOffset[i]) *
compScale[i];
// REMIND: need to analyze whether this
// clamping is necessary
if (norm[i] < 0.0f) {
norm[i] = 0.0f;
}
if (norm[i] > 1.0f) {
norm[i] = 1.0f;
}
}
}
if (supportsAlpha) {
alp = (rgb>>24) & 0xff;
if (nBits[numColorComponents] == 8) {
intpixel[numColorComponents] = alp;
}
else {
intpixel[numColorComponents] =
(int) (alp * factor *
((1<<nBits[numColorComponents]) - 1) + 0.5f);
}
if (isAlphaPremultiplied) {
factor *= alp;
for (int i = 0; i < numColorComponents; i++) {
norm[i] *= factor;
}
}
}
for (int i = 0; i < numColorComponents; i++) {
intpixel[i] = (int) (norm[i] * ((1<<nBits[i]) - 1) + 0.5f);
}
}
switch (transferType) {
case DataBuffer.TYPE_BYTE: {
byte bdata[];
if (pixel == null) {
bdata = new byte[numComponents];
} else {
bdata = (byte[])pixel;
}
for (int i = 0; i < numComponents; i++) {
bdata[i] = (byte)(0xff&intpixel[i]);
}
return bdata;
}
case DataBuffer.TYPE_USHORT:{
short sdata[];
if (pixel == null) {
sdata = new short[numComponents];
} else {
sdata = (short[])pixel;
}
for (int i = 0; i < numComponents; i++) {
sdata[i] = (short)(intpixel[i]&0xffff);
}
return sdata;
}
case DataBuffer.TYPE_INT:
if (maxBits > 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.
for (int i = 0; i < numComponents; i++) {
if (intpixel[i] > ((1<<nBits[i]) - 1)) {
intpixel[i] = (1<<nBits[i]) - 1;
}
}
}
return intpixel;
}
throw new IllegalArgumentException("This method has not been "+
"implemented for transferType " + transferType);
}
Returns an array of unnormalized color/alpha components given a pixel
in this ColorModel
.
An IllegalArgumentException is thrown if the component value for this
ColorModel
is not conveniently representable in the
unnormalized form. Color/alpha components are stored
in the components
array starting at offset
(even if the array is allocated by this method).
Params: - pixel – The pixel value specified as an integer.
- components – An integer array in which to store the unnormalized
color/alpha components. If the
components
array is null,
a new array is allocated. - offset – An offset into the
components
array.
Throws: - IllegalArgumentException – If there is more than one
component in this
ColorModel
. - IllegalArgumentException – If this
ColorModel
does not support the unnormalized form - ArrayIndexOutOfBoundsException – If the
components
array is not null and is not large enough to hold all the color and
alpha components (starting at offset).
Returns: The components array.
/** Returns an array of unnormalized color/alpha components given a pixel
* in this <CODE>ColorModel</CODE>.
* An IllegalArgumentException is thrown if the component value for this
* <CODE>ColorModel</CODE> is not conveniently representable in the
* unnormalized form. Color/alpha components are stored
* in the <CODE>components</CODE> array starting at <CODE>offset</CODE>
* (even if the array is allocated by this method).
*
* @param pixel The pixel value specified as an integer.
* @param components An integer array in which to store the unnormalized
* color/alpha components. If the <CODE>components</CODE> array is null,
* a new array is allocated.
* @param offset An offset into the <CODE>components</CODE> array.
*
* @return The components array.
*
* @throws IllegalArgumentException If there is more than one
* component in this <CODE>ColorModel</CODE>.
* @throws IllegalArgumentException If this
* <CODE>ColorModel</CODE> does not support the unnormalized form
* @throws ArrayIndexOutOfBoundsException If the <CODE>components</CODE>
* array is not null and is not large enough to hold all the color and
* alpha components (starting at offset).
*/
public int[] getComponents(int pixel, int[] components, int offset) {
if (numComponents > 1) {
throw new
IllegalArgumentException("More than one component per pixel");
}
if (needScaleInit) {
initScale();
}
if (noUnnorm) {
throw new
IllegalArgumentException(
"This ColorModel does not support the unnormalized form");
}
if (components == null) {
components = new int[offset+1];
}
components[offset+0] = (pixel & ((1<<nBits[0]) - 1));
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.
An IllegalArgumentException is thrown if the component values for this
ColorModel
are not conveniently representable in the
unnormalized form.
Color/alpha components are stored in the components
array
starting at offset
(even if the array is allocated by
this method). Since ComponentColorModel
can be
subclassed, subclasses inherit the
implementation of this method and if they don't override it then
this method might throw an exception if they use an unsupported
transferType
.
Params: - pixel – A pixel value specified by an array of data elements of
type
transferType
. - components – An integer array in which to store the unnormalized
color/alpha components. If the
components
array is null,
a new array is allocated. - offset – An offset into the
components
array.
Throws: - IllegalArgumentException – If this
ComponentColorModel
does not support the unnormalized form - UnsupportedOperationException – in some cases iff the
transfer type of this
ComponentColorModel
is not one of the following transfer types:
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
or DataBuffer.TYPE_INT
. - ClassCastException – If
pixel
is not a primitive
array of type transferType
. - IllegalArgumentException – If the
components
array is
not null and is not large enough to hold all the color and alpha
components (starting at offset), or if pixel
is not large
enough to hold a pixel value for this ColorModel.
Returns: The components
array.
/**
* Returns an array of unnormalized color/alpha components given a pixel
* in this <CODE>ColorModel</CODE>. The pixel value is specified by an
* array of data elements of type <CODE>transferType</CODE> passed in as
* an object reference.
* An IllegalArgumentException is thrown if the component values for this
* <CODE>ColorModel</CODE> are not conveniently representable in the
* unnormalized form.
* Color/alpha components are stored in the <CODE>components</CODE> array
* starting at <CODE>offset</CODE> (even if the array is allocated by
* this method). Since <code>ComponentColorModel</code> can be
* subclassed, subclasses inherit the
* implementation of this method and if they don't override it then
* this method might throw an exception if they use an unsupported
* <code>transferType</code>.
*
* @param pixel A pixel value specified by an array of data elements of
* type <CODE>transferType</CODE>.
* @param components An integer array in which to store the unnormalized
* color/alpha components. If the <CODE>components</CODE> array is null,
* a new array is allocated.
* @param offset An offset into the <CODE>components</CODE> array.
*
* @return The <CODE>components</CODE> array.
*
* @throws IllegalArgumentException If this
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form
* @throws UnsupportedOperationException in some cases iff the
* transfer type of this <CODE>ComponentColorModel</CODE>
* is not one of the following transfer types:
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* or <CODE>DataBuffer.TYPE_INT</CODE>.
* @throws ClassCastException If <CODE>pixel</CODE> is not a primitive
* array of type <CODE>transferType</CODE>.
* @throws IllegalArgumentException If the <CODE>components</CODE> array is
* not null and is not large enough to hold all the color and alpha
* components (starting at offset), or if <CODE>pixel</CODE> is not large
* enough to hold a pixel value for this ColorModel.
*/
public int[] getComponents(Object pixel, int[] components, int offset) {
int intpixel[];
if (needScaleInit) {
initScale();
}
if (noUnnorm) {
throw new
IllegalArgumentException(
"This ColorModel does not support the unnormalized form");
}
if (pixel instanceof int[]) {
intpixel = (int[])pixel;
} else {
intpixel = DataBuffer.toIntArray(pixel);
if (intpixel == null) {
throw new UnsupportedOperationException("This method has not been "+
"implemented for transferType " + transferType);
}
}
if (intpixel.length < numComponents) {
throw new IllegalArgumentException
("Length of pixel array < number of components in model");
}
if (components == null) {
components = new int[offset+numComponents];
}
else if ((components.length-offset) < numComponents) {
throw new IllegalArgumentException
("Length of components array < number of components in model");
}
System.arraycopy(intpixel, 0, components, offset, numComponents);
return components;
}
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 2n - 1, where
n is the number of bits for a particular component. Normalized
components are float values between a per component minimum and
maximum specified by the ColorSpace
object for this
ColorModel
. An IllegalArgumentException
will be thrown if color component values for this
ColorModel
are not conveniently representable in the
unnormalized form. 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
). An
IllegalArgumentException
is thrown if the
normComponents
array is not large enough to hold
all the color and alpha components starting at
normOffset
.
Params: - normComponents – an array containing normalized components
- normOffset – the offset into the
normComponents
array at which to start retrieving normalized components - components – an array that receives the components from
normComponents
- offset – the index into
components
at which to
begin storing normalized components from
normComponents
Throws: - IllegalArgumentException – If this
ComponentColorModel
does not support the unnormalized form - IllegalArgumentException – if the length of
normComponents
minus normOffset
is less than numComponents
Returns: an array containing unnormalized color and alpha
components.
/**
* 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<sup>n</sup> - 1, where
* n is the number of bits for a particular component. Normalized
* components are float values between a per component minimum and
* maximum specified by the <code>ColorSpace</code> object for this
* <code>ColorModel</code>. An <code>IllegalArgumentException</code>
* will be thrown if color component values for this
* <code>ColorModel</code> are not conveniently representable in the
* unnormalized form. If the
* <code>components</code> array is <code>null</code>, a new array
* will be allocated. The <code>components</code> array will
* be returned. Color/alpha components are stored in the
* <code>components</code> array starting at <code>offset</code> (even
* if the array is allocated by this method). An
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* <code>components</code> array is not <code>null</code> and is not
* large enough to hold all the color and alpha
* components (starting at <code>offset</code>). An
* <code>IllegalArgumentException</code> is thrown if the
* <code>normComponents</code> array is not large enough to hold
* all the color and alpha components starting at
* <code>normOffset</code>.
* @param normComponents an array containing normalized components
* @param normOffset the offset into the <code>normComponents</code>
* array at which to start retrieving normalized components
* @param components an array that receives the components from
* <code>normComponents</code>
* @param offset the index into <code>components</code> at which to
* begin storing normalized components from
* <code>normComponents</code>
* @return an array containing unnormalized color and alpha
* components.
* @throws IllegalArgumentException If this
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form
* @throws IllegalArgumentException if the length of
* <code>normComponents</code> minus <code>normOffset</code>
* is less than <code>numComponents</code>
*/
public int[] getUnnormalizedComponents(float[] normComponents,
int normOffset,
int[] components, int offset) {
if (needScaleInit) {
initScale();
}
if (noUnnorm) {
throw new
IllegalArgumentException(
"This ColorModel does not support the unnormalized form");
}
return super.getUnnormalizedComponents(normComponents, normOffset,
components, offset);
}
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 2n - 1, where
n is the number of bits for a particular component. Normalized
components are float values between a per component minimum and
maximum specified by the ColorSpace
object for this
ColorModel
. An IllegalArgumentException
will be thrown if color component values for this
ColorModel
are not conveniently representable in the
unnormalized form. If the
normComponents
array is null
, a new array
will be allocated. The normComponents
array
will be returned. Color/alpha components are stored in the
normComponents
array starting at
normOffset
(even if the array is allocated by this
method). An ArrayIndexOutOfBoundsException
is thrown
if the normComponents
array is not null
and is not large enough to hold all the color and alpha components
(starting at normOffset
). An
IllegalArgumentException
is thrown if the
components
array is not large enough to hold all the
color and alpha components starting at offset
.
Params: - components – an array containing unnormalized components
- offset – the offset into the
components
array at
which to start retrieving unnormalized components - normComponents – an array that receives the normalized components
- normOffset – the index into
normComponents
at
which to begin storing normalized components
Throws: - IllegalArgumentException – If this
ComponentColorModel
does not support the unnormalized form
Returns: an array containing normalized color and alpha
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<sup>n</sup> - 1, where
* n is the number of bits for a particular component. Normalized
* components are float values between a per component minimum and
* maximum specified by the <code>ColorSpace</code> object for this
* <code>ColorModel</code>. An <code>IllegalArgumentException</code>
* will be thrown if color component values for this
* <code>ColorModel</code> are not conveniently representable in the
* unnormalized form. If the
* <code>normComponents</code> array is <code>null</code>, a new array
* will be allocated. The <code>normComponents</code> array
* will be returned. Color/alpha components are stored in the
* <code>normComponents</code> array starting at
* <code>normOffset</code> (even if the array is allocated by this
* method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
* if the <code>normComponents</code> array is not <code>null</code>
* and is not large enough to hold all the color and alpha components
* (starting at <code>normOffset</code>). An
* <code>IllegalArgumentException</code> is thrown if the
* <code>components</code> array is not large enough to hold all the
* color and alpha components starting at <code>offset</code>.
* @param components an array containing unnormalized components
* @param offset the offset into the <code>components</code> array at
* which to start retrieving unnormalized components
* @param normComponents an array that receives the normalized components
* @param normOffset the index into <code>normComponents</code> at
* which to begin storing normalized components
* @return an array containing normalized color and alpha
* components.
* @throws IllegalArgumentException If this
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form
*/
public float[] getNormalizedComponents(int[] components, int offset,
float[] normComponents,
int normOffset) {
if (needScaleInit) {
initScale();
}
if (noUnnorm) {
throw new
IllegalArgumentException(
"This ColorModel does not support the unnormalized form");
}
return super.getNormalizedComponents(components, offset,
normComponents, normOffset);
}
Returns a pixel value represented as an int in this ColorModel
,
given an array of unnormalized color/alpha components.
Params: - components – An array of unnormalized color/alpha components.
- offset – An offset into the
components
array.
Throws: - IllegalArgumentException – If there is more than one component
in this
ColorModel
. - IllegalArgumentException – If this
ComponentColorModel
does not support the unnormalized form
Returns: A pixel value represented as an int.
/**
* Returns a pixel value represented as an int in this <CODE>ColorModel</CODE>,
* given an array of unnormalized color/alpha components.
*
* @param components An array of unnormalized color/alpha components.
* @param offset An offset into the <CODE>components</CODE> array.
*
* @return A pixel value represented as an int.
*
* @throws IllegalArgumentException If there is more than one component
* in this <CODE>ColorModel</CODE>.
* @throws IllegalArgumentException If this
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form
*/
public int getDataElement(int[] components, int offset) {
if (needScaleInit) {
initScale();
}
if (numComponents == 1) {
if (noUnnorm) {
throw new
IllegalArgumentException(
"This ColorModel does not support the unnormalized form");
}
return components[offset+0];
}
throw new IllegalArgumentException("This model returns "+
numComponents+
" elements in the pixel array.");
}
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.
Params: - components – An array of unnormalized color/alpha components.
- offset – The integer offset into the
components
array. - obj – The object in which to store the data element array
representation of the pixel. If
obj
variable is null,
a new array is allocated. If obj
is not null, it must
be a primitive array of type transferType
. An
ArrayIndexOutOfBoundsException
is thrown if
obj
is not large enough to hold a pixel value
for this ColorModel
. Since
ComponentColorModel
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 transferType
.
Throws: - IllegalArgumentException – If the components array
is not large enough to hold all the color and alpha components
(starting at offset).
- ClassCastException – If
obj
is not null and is not a
primitive array of type transferType
. - ArrayIndexOutOfBoundsException – If
obj
is not large
enough to hold a pixel value for this ColorModel
. - IllegalArgumentException – If this
ComponentColorModel
does not support the unnormalized form - UnsupportedOperationException – If the transfer type of
this
ComponentColorModel
is not one of the following transfer types:
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
or DataBuffer.TYPE_INT
.
See Also: Returns: The data element array representation of a pixel
in this ColorModel
.
/**
* Returns a data element array representation of a pixel in this
* <CODE>ColorModel</CODE>, given an array of unnormalized color/alpha
* components. This array can then be passed to the <CODE>setDataElements</CODE>
* method of a <CODE>WritableRaster</CODE> object.
*
* @param components An array of unnormalized color/alpha components.
* @param offset The integer offset into the <CODE>components</CODE> array.
* @param obj The object in which to store the data element array
* representation of the pixel. If <CODE>obj</CODE> variable is null,
* a new array is allocated. If <CODE>obj</CODE> is not null, it must
* be a primitive array of type <CODE>transferType</CODE>. An
* <CODE>ArrayIndexOutOfBoundsException</CODE> is thrown if
* <CODE>obj</CODE> is not large enough to hold a pixel value
* for this <CODE>ColorModel</CODE>. Since
* <code>ComponentColorModel</code> 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</code>.
*
* @return The data element array representation of a pixel
* in this <CODE>ColorModel</CODE>.
*
* @throws IllegalArgumentException If the components array
* is not large enough to hold all the color and alpha components
* (starting at offset).
* @throws ClassCastException If <CODE>obj</CODE> is not null and is not a
* primitive array of type <CODE>transferType</CODE>.
* @throws ArrayIndexOutOfBoundsException If <CODE>obj</CODE> is not large
* enough to hold a pixel value for this <CODE>ColorModel</CODE>.
* @throws IllegalArgumentException If this
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form
* @throws UnsupportedOperationException If the transfer type of
* this <CODE>ComponentColorModel</CODE>
* is not one of the following transfer types:
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* or <CODE>DataBuffer.TYPE_INT</CODE>.
*
* @see WritableRaster#setDataElements
* @see SampleModel#setDataElements
*/
public Object getDataElements(int[] components, int offset, Object obj) {
if (needScaleInit) {
initScale();
}
if (noUnnorm) {
throw new
IllegalArgumentException(
"This ColorModel does not support the unnormalized form");
}
if ((components.length-offset) < numComponents) {
throw new IllegalArgumentException("Component array too small"+
" (should be "+numComponents);
}
switch(transferType) {
case DataBuffer.TYPE_INT:
{
int[] pixel;
if (obj == null) {
pixel = new int[numComponents];
}
else {
pixel = (int[]) obj;
}
System.arraycopy(components, offset, pixel, 0,
numComponents);
return pixel;
}
case DataBuffer.TYPE_BYTE:
{
byte[] pixel;
if (obj == null) {
pixel = new byte[numComponents];
}
else {
pixel = (byte[]) obj;
}
for (int i=0; i < numComponents; i++) {
pixel[i] = (byte) (components[offset+i]&0xff);
}
return pixel;
}
case DataBuffer.TYPE_USHORT:
{
short[] pixel;
if (obj == null) {
pixel = new short[numComponents];
}
else {
pixel = (short[]) obj;
}
for (int i=0; i < numComponents; i++) {
pixel[i] = (short) (components[offset+i]&0xffff);
}
return pixel;
}
default:
throw new UnsupportedOperationException("This method has not been "+
"implemented for transferType " +
transferType);
}
}
Returns a pixel value represented as an int
in this
ColorModel
, given an array of normalized color/alpha
components. This method will throw an
IllegalArgumentException
if pixel values for this
ColorModel
are not conveniently representable as a
single int
. An
ArrayIndexOutOfBoundsException
is thrown if the
normComponents
array is not large enough to hold all the
color and alpha components (starting at normOffset
).
Params: - normComponents – an array of normalized color and alpha
components
- normOffset – the index into
normComponents
at which to
begin retrieving the color and alpha components
Throws: - IllegalArgumentException – if
pixel values for this
ColorModel
are not
conveniently representable as a single int
- ArrayIndexOutOfBoundsException – if
the
normComponents
array is not large enough to
hold all of the color and alpha components starting at
normOffset
Returns: an int
pixel value in this
ColorModel
corresponding to the specified components. Since: 1.4
/**
* Returns a pixel value represented as an <code>int</code> in this
* <code>ColorModel</code>, given an array of normalized color/alpha
* components. This method will throw an
* <code>IllegalArgumentException</code> if pixel values for this
* <code>ColorModel</code> are not conveniently representable as a
* single <code>int</code>. An
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* <code>normComponents</code> array is not large enough to hold all the
* color and alpha components (starting at <code>normOffset</code>).
* @param normComponents an array of normalized color and alpha
* components
* @param normOffset the index into <code>normComponents</code> at which to
* begin retrieving the color and alpha components
* @return an <code>int</code> pixel value in this
* <code>ColorModel</code> corresponding to the specified components.
* @throws IllegalArgumentException if
* pixel values for this <code>ColorModel</code> are not
* conveniently representable as a single <code>int</code>
* @throws ArrayIndexOutOfBoundsException if
* the <code>normComponents</code> array is not large enough to
* hold all of the color and alpha components starting at
* <code>normOffset</code>
* @since 1.4
*/
public int getDataElement(float[] normComponents, int normOffset) {
if (numComponents > 1) {
throw new
IllegalArgumentException("More than one component per pixel");
}
if (signed) {
throw new
IllegalArgumentException("Component value is signed");
}
if (needScaleInit) {
initScale();
}
Object pixel = getDataElements(normComponents, normOffset, null);
switch (transferType) {
case DataBuffer.TYPE_BYTE:
{
byte bpixel[] = (byte[]) pixel;
return bpixel[0] & 0xff;
}
case DataBuffer.TYPE_USHORT:
{
short[] uspixel = (short[]) pixel;
return uspixel[0] & 0xffff;
}
case DataBuffer.TYPE_INT:
{
int[] ipixel = (int[]) pixel;
return ipixel[0];
}
default:
throw new UnsupportedOperationException("This method has not been "
+ "implemented for transferType " + transferType);
}
}
Returns a data element array representation of a pixel in this
ColorModel
, given an array of normalized color/alpha
components. This array can then be passed to the
setDataElements
method of a WritableRaster
object. An ArrayIndexOutOfBoundsException
is thrown
if the normComponents
array is not large enough to hold
all the color and alpha components (starting at
normOffset
). 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
.
Params: - normComponents – an array of normalized color and alpha
components
- normOffset – the index into
normComponents
at which to
begin retrieving color and alpha components - obj – a primitive data array to hold the returned pixel
Throws: - ClassCastException – if
obj
is not a primitive array of type transferType
- ArrayIndexOutOfBoundsException – if
obj
is not large enough to hold a pixel value
for this ColorModel
or the normComponents
array is not large enough to hold all of the color and alpha
components starting at normOffset
See Also: Returns: an Object
which is a primitive data array
representation of a pixel Since: 1.4
/**
* Returns a data element array representation of a pixel in this
* <code>ColorModel</code>, given an array of normalized color/alpha
* components. This array can then be passed to the
* <code>setDataElements</code> method of a <code>WritableRaster</code>
* object. An <code>ArrayIndexOutOfBoundsException</code> is thrown
* if the <code>normComponents</code> array is not large enough to hold
* all the color and alpha components (starting at
* <code>normOffset</code>). If the <code>obj</code> variable is
* <code>null</code>, a new array will be allocated. If
* <code>obj</code> is not <code>null</code>, it must be a primitive
* array of type transferType; otherwise, a
* <code>ClassCastException</code> is thrown. An
* <code>ArrayIndexOutOfBoundsException</code> is thrown if
* <code>obj</code> is not large enough to hold a pixel value for this
* <code>ColorModel</code>.
* @param normComponents an array of normalized color and alpha
* components
* @param normOffset the index into <code>normComponents</code> at which to
* begin retrieving color and alpha components
* @param obj a primitive data array to hold the returned pixel
* @return an <code>Object</code> which is a primitive data array
* representation of a pixel
* @throws ClassCastException if <code>obj</code>
* is not a primitive array of type <code>transferType</code>
* @throws ArrayIndexOutOfBoundsException if
* <code>obj</code> is not large enough to hold a pixel value
* for this <code>ColorModel</code> or the <code>normComponents</code>
* array is not large enough to hold all of the color and alpha
* components starting at <code>normOffset</code>
* @see WritableRaster#setDataElements
* @see SampleModel#setDataElements
* @since 1.4
*/
public Object getDataElements(float[] normComponents, int normOffset,
Object obj) {
boolean needAlpha = supportsAlpha && isAlphaPremultiplied;
float[] stdNormComponents;
if (needScaleInit) {
initScale();
}
if (nonStdScale) {
stdNormComponents = new float[numComponents];
for (int c = 0, nc = normOffset; c < numColorComponents;
c++, nc++) {
stdNormComponents[c] = (normComponents[nc] - compOffset[c]) *
compScale[c];
// REMIND: need to analyze whether this
// clamping is necessary
if (stdNormComponents[c] < 0.0f) {
stdNormComponents[c] = 0.0f;
}
if (stdNormComponents[c] > 1.0f) {
stdNormComponents[c] = 1.0f;
}
}
if (supportsAlpha) {
stdNormComponents[numColorComponents] =
normComponents[numColorComponents + normOffset];
}
normOffset = 0;
} else {
stdNormComponents = normComponents;
}
switch (transferType) {
case DataBuffer.TYPE_BYTE:
byte[] bpixel;
if (obj == null) {
bpixel = new byte[numComponents];
} else {
bpixel = (byte[]) obj;
}
if (needAlpha) {
float alpha =
stdNormComponents[numColorComponents + normOffset];
for (int c = 0, nc = normOffset; c < numColorComponents;
c++, nc++) {
bpixel[c] = (byte) ((stdNormComponents[nc] * alpha) *
((float) ((1 << nBits[c]) - 1)) + 0.5f);
}
bpixel[numColorComponents] =
(byte) (alpha *
((float) ((1 << nBits[numColorComponents]) - 1)) +
0.5f);
} else {
for (int c = 0, nc = normOffset; c < numComponents;
c++, nc++) {
bpixel[c] = (byte) (stdNormComponents[nc] *
((float) ((1 << nBits[c]) - 1)) + 0.5f);
}
}
return bpixel;
case DataBuffer.TYPE_USHORT:
short[] uspixel;
if (obj == null) {
uspixel = new short[numComponents];
} else {
uspixel = (short[]) obj;
}
if (needAlpha) {
float alpha =
stdNormComponents[numColorComponents + normOffset];
for (int c = 0, nc = normOffset; c < numColorComponents;
c++, nc++) {
uspixel[c] = (short) ((stdNormComponents[nc] * alpha) *
((float) ((1 << nBits[c]) - 1)) +
0.5f);
}
uspixel[numColorComponents] =
(short) (alpha *
((float) ((1 << nBits[numColorComponents]) - 1)) +
0.5f);
} else {
for (int c = 0, nc = normOffset; c < numComponents;
c++, nc++) {
uspixel[c] = (short) (stdNormComponents[nc] *
((float) ((1 << nBits[c]) - 1)) +
0.5f);
}
}
return uspixel;
case DataBuffer.TYPE_INT:
int[] ipixel;
if (obj == null) {
ipixel = new int[numComponents];
} else {
ipixel = (int[]) obj;
}
if (needAlpha) {
float alpha =
stdNormComponents[numColorComponents + normOffset];
for (int c = 0, nc = normOffset; c < numColorComponents;
c++, nc++) {
ipixel[c] = (int) ((stdNormComponents[nc] * alpha) *
((float) ((1 << nBits[c]) - 1)) + 0.5f);
}
ipixel[numColorComponents] =
(int) (alpha *
((float) ((1 << nBits[numColorComponents]) - 1)) +
0.5f);
} else {
for (int c = 0, nc = normOffset; c < numComponents;
c++, nc++) {
ipixel[c] = (int) (stdNormComponents[nc] *
((float) ((1 << nBits[c]) - 1)) + 0.5f);
}
}
return ipixel;
case DataBuffer.TYPE_SHORT:
short[] spixel;
if (obj == null) {
spixel = new short[numComponents];
} else {
spixel = (short[]) obj;
}
if (needAlpha) {
float alpha =
stdNormComponents[numColorComponents + normOffset];
for (int c = 0, nc = normOffset; c < numColorComponents;
c++, nc++) {
spixel[c] = (short)
(stdNormComponents[nc] * alpha * 32767.0f + 0.5f);
}
spixel[numColorComponents] = (short) (alpha * 32767.0f + 0.5f);
} else {
for (int c = 0, nc = normOffset; c < numComponents;
c++, nc++) {
spixel[c] = (short)
(stdNormComponents[nc] * 32767.0f + 0.5f);
}
}
return spixel;
case DataBuffer.TYPE_FLOAT:
float[] fpixel;
if (obj == null) {
fpixel = new float[numComponents];
} else {
fpixel = (float[]) obj;
}
if (needAlpha) {
float alpha = normComponents[numColorComponents + normOffset];
for (int c = 0, nc = normOffset; c < numColorComponents;
c++, nc++) {
fpixel[c] = normComponents[nc] * alpha;
}
fpixel[numColorComponents] = alpha;
} else {
for (int c = 0, nc = normOffset; c < numComponents;
c++, nc++) {
fpixel[c] = normComponents[nc];
}
}
return fpixel;
case DataBuffer.TYPE_DOUBLE:
double[] dpixel;
if (obj == null) {
dpixel = new double[numComponents];
} else {
dpixel = (double[]) obj;
}
if (needAlpha) {
double alpha =
(double) (normComponents[numColorComponents + normOffset]);
for (int c = 0, nc = normOffset; c < numColorComponents;
c++, nc++) {
dpixel[c] = normComponents[nc] * alpha;
}
dpixel[numColorComponents] = alpha;
} else {
for (int c = 0, nc = normOffset; c < numComponents;
c++, nc++) {
dpixel[c] = (double) normComponents[nc];
}
}
return dpixel;
default:
throw new UnsupportedOperationException("This method has not been "+
"implemented for transferType " +
transferType);
}
}
Returns an array of all of the color/alpha components in normalized
form, 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
.
Normalized components are float values between a per component minimum
and maximum specified by the ColorSpace
object for this
ColorModel
. If the
normComponents
array is null
, a new array
will be allocated. The normComponents
array
will be returned. Color/alpha components are stored in the
normComponents
array starting at
normOffset
(even if the array is allocated by this
method). An ArrayIndexOutOfBoundsException
is thrown
if the normComponents
array is not null
and is not large enough to hold all the color and alpha components
(starting at normOffset
).
This method must be overridden by a subclass if that subclass
is designed to translate pixel sample values to color component values
in a non-default way. The default translations implemented by this
class is described in the class comments. Any subclass implementing
a non-default translation must follow the constraints on allowable
translations defined there.
Params: - pixel – the specified pixel
- normComponents – an array to receive the normalized components
- normOffset – the offset into the
normComponents
array at which to start storing normalized components
Throws: - ClassCastException – if
pixel
is not a primitive
array of type transferType - ArrayIndexOutOfBoundsException – if
normComponents
is not large enough to hold all
color and alpha components starting at normOffset
- ArrayIndexOutOfBoundsException – if
pixel
is not large enough to hold a pixel
value for this ColorModel
.
Returns: an array containing normalized color and alpha
components. Since: 1.4
/**
* Returns an array of all of the color/alpha components in normalized
* form, given a pixel in this <code>ColorModel</code>. 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 <code>ClassCastException</code> is thrown.
* An <code>ArrayIndexOutOfBoundsException</code> is thrown if
* <code>pixel</code> is not large enough to hold a pixel value for this
* <code>ColorModel</code>.
* Normalized components are float values between a per component minimum
* and maximum specified by the <code>ColorSpace</code> object for this
* <code>ColorModel</code>. If the
* <code>normComponents</code> array is <code>null</code>, a new array
* will be allocated. The <code>normComponents</code> array
* will be returned. Color/alpha components are stored in the
* <code>normComponents</code> array starting at
* <code>normOffset</code> (even if the array is allocated by this
* method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
* if the <code>normComponents</code> array is not <code>null</code>
* and is not large enough to hold all the color and alpha components
* (starting at <code>normOffset</code>).
* <p>
* This method must be overridden by a subclass if that subclass
* is designed to translate pixel sample values to color component values
* in a non-default way. The default translations implemented by this
* class is described in the class comments. Any subclass implementing
* a non-default translation must follow the constraints on allowable
* translations defined there.
* @param pixel the specified pixel
* @param normComponents an array to receive the normalized components
* @param normOffset the offset into the <code>normComponents</code>
* array at which to start storing normalized components
* @return an array containing normalized color and alpha
* components.
* @throws ClassCastException if <code>pixel</code> is not a primitive
* array of type transferType
* @throws ArrayIndexOutOfBoundsException if
* <code>normComponents</code> is not large enough to hold all
* color and alpha components starting at <code>normOffset</code>
* @throws ArrayIndexOutOfBoundsException if
* <code>pixel</code> is not large enough to hold a pixel
* value for this <code>ColorModel</code>.
* @since 1.4
*/
public float[] getNormalizedComponents(Object pixel,
float[] normComponents,
int normOffset) {
if (normComponents == null) {
normComponents = new float[numComponents+normOffset];
}
switch (transferType) {
case DataBuffer.TYPE_BYTE:
byte[] bpixel = (byte[]) pixel;
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
normComponents[nc] = ((float) (bpixel[c] & 0xff)) /
((float) ((1 << nBits[c]) - 1));
}
break;
case DataBuffer.TYPE_USHORT:
short[] uspixel = (short[]) pixel;
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
normComponents[nc] = ((float) (uspixel[c] & 0xffff)) /
((float) ((1 << nBits[c]) - 1));
}
break;
case DataBuffer.TYPE_INT:
int[] ipixel = (int[]) pixel;
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
normComponents[nc] = ((float) ipixel[c]) /
((float) ((1 << nBits[c]) - 1));
}
break;
case DataBuffer.TYPE_SHORT:
short[] spixel = (short[]) pixel;
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
normComponents[nc] = ((float) spixel[c]) / 32767.0f;
}
break;
case DataBuffer.TYPE_FLOAT:
float[] fpixel = (float[]) pixel;
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
normComponents[nc] = fpixel[c];
}
break;
case DataBuffer.TYPE_DOUBLE:
double[] dpixel = (double[]) pixel;
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
normComponents[nc] = (float) dpixel[c];
}
break;
default:
throw new UnsupportedOperationException("This method has not been "+
"implemented for transferType " +
transferType);
}
if (supportsAlpha && isAlphaPremultiplied) {
float alpha = normComponents[numColorComponents + normOffset];
if (alpha != 0.0f) {
float invAlpha = 1.0f / alpha;
for (int c = normOffset; c < numColorComponents + normOffset;
c++) {
normComponents[c] *= invAlpha;
}
}
}
if (min != null) {
// Normally (i.e. when this class is not subclassed to override
// this method), the test (min != null) will be equivalent to
// the test (nonStdScale). However, there is an unlikely, but
// possible case, in which this method is overridden, nonStdScale
// is set true by initScale(), the subclass method for some
// reason calls this superclass method, but the min and
// diffMinMax arrays were never initialized by setupLUTs(). In
// that case, the right thing to do is follow the intended
// semantics of this method, and rescale the color components
// only if the ColorSpace min/max were detected to be other
// than 0.0/1.0 by setupLUTs(). Note that this implies the
// transferType is byte, ushort, int, or short - i.e. components
// derived from float and double pixel data are never rescaled.
for (int c = 0; c < numColorComponents; c++) {
normComponents[c + normOffset] = min[c] +
diffMinMax[c] * normComponents[c + normOffset];
}
}
return normComponents;
}
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 also returns an instance of
this ColorModel
with
the isAlphaPremultiplied
flag set appropriately.
Since ColorModel
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
transferType
.
Throws: - NullPointerException – if
raster
is
null
and data coercion is required. - UnsupportedOperationException – if the transfer type of
this
ComponentColorModel
is not one of the supported transfer types:
DataBuffer.TYPE_BYTE
, DataBuffer.TYPE_USHORT
,
DataBuffer.TYPE_INT
, DataBuffer.TYPE_SHORT
,
DataBuffer.TYPE_FLOAT
, or DataBuffer.TYPE_DOUBLE
.
/**
* Forces the raster data to match the state specified in the
* <CODE>isAlphaPremultiplied</CODE> variable, assuming the data
* is currently correctly described by this <CODE>ColorModel</CODE>.
* 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 also returns an instance of
* this <CODE>ColorModel</CODE> with
* the <CODE>isAlphaPremultiplied</CODE> flag set appropriately.
* Since <code>ColorModel</code> 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</code>.
*
* @throws NullPointerException if <code>raster</code> is
* <code>null</code> and data coercion is required.
* @throws UnsupportedOperationException if the transfer type of
* this <CODE>ComponentColorModel</CODE>
* is not one of the supported transfer types:
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
*/
public ColorModel coerceData (WritableRaster raster,
boolean isAlphaPremultiplied) {
if ((supportsAlpha == false) ||
(this.isAlphaPremultiplied == isAlphaPremultiplied))
{
// Nothing to do
return this;
}
int w = raster.getWidth();
int h = raster.getHeight();
int aIdx = raster.getNumBands() - 1;
float normAlpha;
int rminX = raster.getMinX();
int rY = raster.getMinY();
int rX;
if (isAlphaPremultiplied) {
switch (transferType) {
case DataBuffer.TYPE_BYTE: {
byte pixel[] = null;
byte zpixel[] = null;
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (byte[])raster.getDataElements(rX, rY,
pixel);
normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
if (normAlpha != 0.0f) {
for (int c=0; c < aIdx; c++) {
pixel[c] = (byte)((pixel[c] & 0xff) *
normAlpha + 0.5f);
}
raster.setDataElements(rX, rY, pixel);
} else {
if (zpixel == null) {
zpixel = new byte[numComponents];
java.util.Arrays.fill(zpixel, (byte) 0);
}
raster.setDataElements(rX, rY, zpixel);
}
}
}
}
break;
case DataBuffer.TYPE_USHORT: {
short pixel[] = null;
short zpixel[] = null;
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (short[])raster.getDataElements(rX, rY,
pixel);
normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
if (normAlpha != 0.0f) {
for (int c=0; c < aIdx; c++) {
pixel[c] = (short)
((pixel[c] & 0xffff) * normAlpha +
0.5f);
}
raster.setDataElements(rX, rY, pixel);
} else {
if (zpixel == null) {
zpixel = new short[numComponents];
java.util.Arrays.fill(zpixel, (short) 0);
}
raster.setDataElements(rX, rY, zpixel);
}
}
}
}
break;
case DataBuffer.TYPE_INT: {
int pixel[] = null;
int zpixel[] = null;
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (int[])raster.getDataElements(rX, rY,
pixel);
normAlpha = pixel[aIdx] * alphaScale;
if (normAlpha != 0.0f) {
for (int c=0; c < aIdx; c++) {
pixel[c] = (int) (pixel[c] * normAlpha +
0.5f);
}
raster.setDataElements(rX, rY, pixel);
} else {
if (zpixel == null) {
zpixel = new int[numComponents];
java.util.Arrays.fill(zpixel, 0);
}
raster.setDataElements(rX, rY, zpixel);
}
}
}
}
break;
case DataBuffer.TYPE_SHORT: {
short pixel[] = null;
short zpixel[] = null;
float alphaScale = 1.0f / 32767.0f;
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (short[]) raster.getDataElements(rX, rY,
pixel);
normAlpha = pixel[aIdx] * alphaScale;
if (normAlpha != 0.0f) {
for (int c=0; c < aIdx; c++) {
pixel[c] = (short) (pixel[c] * normAlpha +
0.5f);
}
raster.setDataElements(rX, rY, pixel);
} else {
if (zpixel == null) {
zpixel = new short[numComponents];
java.util.Arrays.fill(zpixel, (short) 0);
}
raster.setDataElements(rX, rY, zpixel);
}
}
}
}
break;
case DataBuffer.TYPE_FLOAT: {
float pixel[] = null;
float zpixel[] = null;
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (float[]) raster.getDataElements(rX, rY,
pixel);
normAlpha = pixel[aIdx];
if (normAlpha != 0.0f) {
for (int c=0; c < aIdx; c++) {
pixel[c] *= normAlpha;
}
raster.setDataElements(rX, rY, pixel);
} else {
if (zpixel == null) {
zpixel = new float[numComponents];
java.util.Arrays.fill(zpixel, 0.0f);
}
raster.setDataElements(rX, rY, zpixel);
}
}
}
}
break;
case DataBuffer.TYPE_DOUBLE: {
double pixel[] = null;
double zpixel[] = null;
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (double[]) raster.getDataElements(rX, rY,
pixel);
double dnormAlpha = pixel[aIdx];
if (dnormAlpha != 0.0) {
for (int c=0; c < aIdx; c++) {
pixel[c] *= dnormAlpha;
}
raster.setDataElements(rX, rY, pixel);
} else {
if (zpixel == null) {
zpixel = new double[numComponents];
java.util.Arrays.fill(zpixel, 0.0);
}
raster.setDataElements(rX, rY, zpixel);
}
}
}
}
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: {
byte pixel[] = null;
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (byte[])raster.getDataElements(rX, rY,
pixel);
normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
if (normAlpha != 0.0f) {
float invAlpha = 1.0f / normAlpha;
for (int c=0; c < aIdx; c++) {
pixel[c] = (byte)
((pixel[c] & 0xff) * invAlpha + 0.5f);
}
raster.setDataElements(rX, rY, pixel);
}
}
}
}
break;
case DataBuffer.TYPE_USHORT: {
short pixel[] = null;
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (short[])raster.getDataElements(rX, rY,
pixel);
normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
if (normAlpha != 0.0f) {
float invAlpha = 1.0f / normAlpha;
for (int c=0; c < aIdx; c++) {
pixel[c] = (short)
((pixel[c] & 0xffff) * invAlpha + 0.5f);
}
raster.setDataElements(rX, rY, pixel);
}
}
}
}
break;
case DataBuffer.TYPE_INT: {
int pixel[] = null;
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (int[])raster.getDataElements(rX, rY,
pixel);
normAlpha = pixel[aIdx] * alphaScale;
if (normAlpha != 0.0f) {
float invAlpha = 1.0f / normAlpha;
for (int c=0; c < aIdx; c++) {
pixel[c] = (int)
(pixel[c] * invAlpha + 0.5f);
}
raster.setDataElements(rX, rY, pixel);
}
}
}
}
break;
case DataBuffer.TYPE_SHORT: {
short pixel[] = null;
float alphaScale = 1.0f / 32767.0f;
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (short[])raster.getDataElements(rX, rY,
pixel);
normAlpha = pixel[aIdx] * alphaScale;
if (normAlpha != 0.0f) {
float invAlpha = 1.0f / normAlpha;
for (int c=0; c < aIdx; c++) {
pixel[c] = (short)
(pixel[c] * invAlpha + 0.5f);
}
raster.setDataElements(rX, rY, pixel);
}
}
}
}
break;
case DataBuffer.TYPE_FLOAT: {
float pixel[] = null;
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (float[])raster.getDataElements(rX, rY,
pixel);
normAlpha = pixel[aIdx];
if (normAlpha != 0.0f) {
float invAlpha = 1.0f / normAlpha;
for (int c=0; c < aIdx; c++) {
pixel[c] *= invAlpha;
}
raster.setDataElements(rX, rY, pixel);
}
}
}
}
break;
case DataBuffer.TYPE_DOUBLE: {
double pixel[] = null;
for (int y = 0; y < h; y++, rY++) {
rX = rminX;
for (int x = 0; x < w; x++, rX++) {
pixel = (double[])raster.getDataElements(rX, rY,
pixel);
double dnormAlpha = pixel[aIdx];
if (dnormAlpha != 0.0) {
double invAlpha = 1.0 / dnormAlpha;
for (int c=0; c < aIdx; c++) {
pixel[c] *= invAlpha;
}
raster.setDataElements(rX, rY, pixel);
}
}
}
}
break;
default:
throw new UnsupportedOperationException("This method has not been "+
"implemented for transferType " + transferType);
}
}
// Return a new color model
if (!signed) {
return new ComponentColorModel(colorSpace, nBits, supportsAlpha,
isAlphaPremultiplied, transparency,
transferType);
} else {
return new ComponentColorModel(colorSpace, supportsAlpha,
isAlphaPremultiplied, transparency,
transferType);
}
}
Returns true if raster
is compatible with this
ColorModel
; false if it is not.
Params: - raster – The
Raster
object to test for compatibility.
Returns: true
if raster
is compatible with this
ColorModel
, false
if it is not.
/**
* Returns true if <CODE>raster</CODE> is compatible with this
* <CODE>ColorModel</CODE>; false if it is not.
*
* @param raster The <CODE>Raster</CODE> object to test for compatibility.
*
* @return <CODE>true</CODE> if <CODE>raster</CODE> is compatible with this
* <CODE>ColorModel</CODE>, <CODE>false</CODE> if it is not.
*/
public boolean isCompatibleRaster(Raster raster) {
SampleModel sm = raster.getSampleModel();
if (sm instanceof ComponentSampleModel) {
if (sm.getNumBands() != getNumComponents()) {
return false;
}
for (int i=0; i<nBits.length; i++) {
if (sm.getSampleSize(i) < nBits[i]) {
return false;
}
}
return (raster.getTransferType() == transferType);
}
else {
return false;
}
}
Creates a WritableRaster
with the specified width and height,
that has a data layout (SampleModel
) compatible with
this ColorModel
.
Params: - w – The width of the
WritableRaster
you want to create. - h – The height of the
WritableRaster
you want to create.
See Also: Returns: A WritableRaster
that is compatible with
this ColorModel
.
/**
* Creates a <CODE>WritableRaster</CODE> with the specified width and height,
* that has a data layout (<CODE>SampleModel</CODE>) compatible with
* this <CODE>ColorModel</CODE>.
*
* @param w The width of the <CODE>WritableRaster</CODE> you want to create.
* @param h The height of the <CODE>WritableRaster</CODE> you want to create.
*
* @return A <CODE>WritableRaster</CODE> that is compatible with
* this <CODE>ColorModel</CODE>.
* @see WritableRaster
* @see SampleModel
*/
public WritableRaster createCompatibleWritableRaster (int w, int h) {
int dataSize = w*h*numComponents;
WritableRaster raster = null;
switch (transferType) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_USHORT:
raster = Raster.createInterleavedRaster(transferType,
w, h,
numComponents, null);
break;
default:
SampleModel sm = createCompatibleSampleModel(w, h);
DataBuffer db = sm.createDataBuffer();
raster = Raster.createWritableRaster(sm, db, null);
}
return raster;
}
Creates a SampleModel
with the specified width and height,
that has a data layout compatible with this ColorModel
.
Params: - w – The width of the
SampleModel
you want to create. - h – The height of the
SampleModel
you want to create.
See Also: Returns: A SampleModel
that is compatible with this
ColorModel
.
/**
* Creates a <CODE>SampleModel</CODE> with the specified width and height,
* that has a data layout compatible with this <CODE>ColorModel</CODE>.
*
* @param w The width of the <CODE>SampleModel</CODE> you want to create.
* @param h The height of the <CODE>SampleModel</CODE> you want to create.
*
* @return A <CODE>SampleModel</CODE> that is compatible with this
* <CODE>ColorModel</CODE>.
*
* @see SampleModel
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
int[] bandOffsets = new int[numComponents];
for (int i=0; i < numComponents; i++) {
bandOffsets[i] = i;
}
switch (transferType) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_USHORT:
return new PixelInterleavedSampleModel(transferType, w, h,
numComponents,
w*numComponents,
bandOffsets);
default:
return new ComponentSampleModel(transferType, w, h,
numComponents,
w*numComponents,
bandOffsets);
}
}
Checks whether or not the specified SampleModel
is compatible with this ColorModel
.
Params: - sm – The
SampleModel
to test for compatibility.
See Also: Returns: true
if the SampleModel
is
compatible with this ColorModel
, false
if it is not.
/**
* Checks whether or not the specified <CODE>SampleModel</CODE>
* is compatible with this <CODE>ColorModel</CODE>.
*
* @param sm The <CODE>SampleModel</CODE> to test for compatibility.
*
* @return <CODE>true</CODE> if the <CODE>SampleModel</CODE> is
* compatible with this <CODE>ColorModel</CODE>, <CODE>false</CODE>
* if it is not.
*
* @see SampleModel
*/
public boolean isCompatibleSampleModel(SampleModel sm) {
if (!(sm instanceof ComponentSampleModel)) {
return false;
}
// Must have the same number of components
if (numComponents != sm.getNumBands()) {
return false;
}
if (sm.getTransferType() != transferType) {
return false;
}
return true;
}
Returns a Raster
representing the alpha channel of an image,
extracted from the input Raster
.
This method assumes that Raster
objects associated with
this ColorModel
store the alpha band, if present, as
the last band of image data. Returns null if there is no separate spatial
alpha channel associated with this ColorModel
.
This method creates a new Raster
, but will share the data
array.
Params: - raster – The
WritableRaster
from which to extract the
alpha channel.
Returns: A WritableRaster
containing the image's alpha channel.
/**
* Returns a <CODE>Raster</CODE> representing the alpha channel of an image,
* extracted from the input <CODE>Raster</CODE>.
* This method assumes that <CODE>Raster</CODE> objects associated with
* this <CODE>ColorModel</CODE> store the alpha band, if present, as
* the last band of image data. Returns null if there is no separate spatial
* alpha channel associated with this <CODE>ColorModel</CODE>.
* This method creates a new <CODE>Raster</CODE>, but will share the data
* array.
*
* @param raster The <CODE>WritableRaster</CODE> from which to extract the
* alpha channel.
*
* @return A <CODE>WritableRaster</CODE> containing the image's alpha channel.
*
*/
public WritableRaster getAlphaRaster(WritableRaster raster) {
if (hasAlpha() == false) {
return null;
}
int x = raster.getMinX();
int y = raster.getMinY();
int[] band = new int[1];
band[0] = raster.getNumBands() - 1;
return raster.createWritableChild(x, y, raster.getWidth(),
raster.getHeight(), x, y,
band);
}
Compares this color model with another for equality.
Params: - obj – The object to compare with this color model.
Returns: true
if the color model objects are equal,
false
if they are not.
/**
* Compares this color model with another for equality.
*
* @param obj The object to compare with this color model.
* @return <CODE>true</CODE> if the color model objects are equal,
* <CODE>false</CODE> if they are not.
*/
public boolean equals(Object obj) {
if (!super.equals(obj)) {
return false;
}
if (obj.getClass() != getClass()) {
return false;
}
return true;
}
}