0001 /*
0002 * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.awt.image;
0027
0028 import java.awt.color.ColorSpace;
0029 import java.awt.color.ICC_ColorSpace;
0030
0031 /**
0032 * A <CODE>ColorModel</CODE> class that works with pixel values that
0033 * represent color and alpha information as separate samples and that
0034 * store each sample in a separate data element. This class can be
0035 * used with an arbitrary <CODE>ColorSpace</CODE>. The number of
0036 * color samples in the pixel values must be same as the number of
0037 * color components in the <CODE>ColorSpace</CODE>. There may be a
0038 * single alpha sample.
0039 * <p>
0040 * For those methods that use
0041 * a primitive array pixel representation of type <CODE>transferType</CODE>,
0042 * the array length is the same as the number of color and alpha samples.
0043 * Color samples are stored first in the array followed by the alpha
0044 * sample, if present. The order of the color samples is specified
0045 * by the <CODE>ColorSpace</CODE>. Typically, this order reflects the
0046 * name of the color space type. For example, for <CODE>TYPE_RGB</CODE>,
0047 * index 0 corresponds to red, index 1 to green, and index 2 to blue.
0048 * <p>
0049 * The translation from pixel sample values to color/alpha components for
0050 * display or processing purposes is based on a one-to-one correspondence of
0051 * samples to components.
0052 * Depending on the transfer type used to create an instance of
0053 * <code>ComponentColorModel</code>, the pixel sample values
0054 * represented by that instance may be signed or unsigned and may
0055 * be of integral type or float or double (see below for details).
0056 * The translation from sample values to normalized color/alpha components
0057 * must follow certain rules. For float and double samples, the translation
0058 * is an identity, i.e. normalized component values are equal to the
0059 * corresponding sample values. For integral samples, the translation
0060 * should be only a simple scale and offset, where the scale and offset
0061 * constants may be different for each component. The result of
0062 * applying the scale and offset constants is a set of color/alpha
0063 * component values, which are guaranteed to fall within a certain
0064 * range. Typically, the range for a color component will be the range
0065 * defined by the <code>getMinValue</code> and <code>getMaxValue</code>
0066 * methods of the <code>ColorSpace</code> class. The range for an
0067 * alpha component should be 0.0 to 1.0.
0068 * <p>
0069 * Instances of <code>ComponentColorModel</code> created with transfer types
0070 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
0071 * and <CODE>DataBuffer.TYPE_INT</CODE> have pixel sample values which
0072 * are treated as unsigned integral values.
0073 * The number of bits in a color or alpha sample of a pixel value might not
0074 * be the same as the number of bits for the corresponding color or alpha
0075 * sample passed to the
0076 * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
0077 * constructor. In
0078 * that case, this class assumes that the least significant n bits of a sample
0079 * value hold the component value, where n is the number of significant bits
0080 * for the component passed to the constructor. It also assumes that
0081 * any higher-order bits in a sample value are zero. Thus, sample values
0082 * range from 0 to 2<sup>n</sup> - 1. This class maps these sample values
0083 * to normalized color component values such that 0 maps to the value
0084 * obtained from the <code>ColorSpace's</code> <code>getMinValue</code>
0085 * method for each component and 2<sup>n</sup> - 1 maps to the value
0086 * obtained from <code>getMaxValue</code>. To create a
0087 * <code>ComponentColorModel</code> with a different color sample mapping
0088 * requires subclassing this class and overriding the
0089 * <code>getNormalizedComponents(Object, float[], int)</code> method.
0090 * The mapping for an alpha sample always maps 0 to 0.0 and
0091 * 2<sup>n</sup> - 1 to 1.0.
0092 * <p>
0093 * For instances with unsigned sample values,
0094 * the unnormalized color/alpha component representation is only
0095 * supported if two conditions hold. First, sample value value 0 must
0096 * map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1
0097 * to 1.0. Second the min/max range of all color components of the
0098 * <code>ColorSpace</code> must be 0.0 to 1.0. In this case, the
0099 * component representation is the n least
0100 * significant bits of the corresponding sample. Thus each component is
0101 * an unsigned integral value between 0 and 2<sup>n</sup> - 1, where
0102 * n is the number of significant bits for a particular component.
0103 * If these conditions are not met, any method taking an unnormalized
0104 * component argument will throw an <code>IllegalArgumentException</code>.
0105 * <p>
0106 * Instances of <code>ComponentColorModel</code> created with transfer types
0107 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
0108 * <CODE>DataBuffer.TYPE_DOUBLE</CODE> have pixel sample values which
0109 * are treated as signed short, float, or double values.
0110 * Such instances do not support the unnormalized color/alpha component
0111 * representation, so any methods taking such a representation as an argument
0112 * will throw an <code>IllegalArgumentException</code> when called on one
0113 * of these instances. The normalized component values of instances
0114 * of this class have a range which depends on the transfer
0115 * type as follows: for float samples, the full range of the float data
0116 * type; for double samples, the full range of the float data type
0117 * (resulting from casting double to float); for short samples,
0118 * from approximately -maxVal to +maxVal, where maxVal is the per
0119 * component maximum value for the <code>ColorSpace</code>
0120 * (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps
0121 * to +maxVal). A subclass may override the scaling for short sample
0122 * values to normalized component values by overriding the
0123 * <code>getNormalizedComponents(Object, float[], int)</code> method.
0124 * For float and double samples, the normalized component values are
0125 * taken to be equal to the corresponding sample values, and subclasses
0126 * should not attempt to add any non-identity scaling for these transfer
0127 * types.
0128 * <p>
0129 * Instances of <code>ComponentColorModel</code> created with transfer types
0130 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
0131 * <CODE>DataBuffer.TYPE_DOUBLE</CODE>
0132 * use all the bits of all sample values. Thus all color/alpha components
0133 * have 16 bits when using <CODE>DataBuffer.TYPE_SHORT</CODE>, 32 bits when
0134 * using <CODE>DataBuffer.TYPE_FLOAT</CODE>, and 64 bits when using
0135 * <CODE>DataBuffer.TYPE_DOUBLE</CODE>. When the
0136 * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
0137 * form of constructor is used with one of these transfer types, the
0138 * bits array argument is ignored.
0139 * <p>
0140 * It is possible to have color/alpha sample values
0141 * which cannot be reasonably interpreted as component values for rendering.
0142 * This can happen when <code>ComponentColorModel</code> is subclassed to
0143 * override the mapping of unsigned sample values to normalized color
0144 * component values or when signed sample values outside a certain range
0145 * are used. (As an example, specifying an alpha component as a signed
0146 * short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can
0147 * lead to unexpected results.) It is the
0148 * responsibility of applications to appropriately scale pixel data before
0149 * rendering such that color components fall within the normalized range
0150 * of the <code>ColorSpace</code> (obtained using the <code>getMinValue</code>
0151 * and <code>getMaxValue</code> methods of the <code>ColorSpace</code> class)
0152 * and the alpha component is between 0.0 and 1.0. If color or alpha
0153 * component values fall outside these ranges, rendering results are
0154 * indeterminate.
0155 * <p>
0156 * Methods that use a single int pixel representation throw
0157 * an <CODE>IllegalArgumentException</CODE>, unless the number of components
0158 * for the <CODE>ComponentColorModel</CODE> is one and the component
0159 * value is unsigned -- in other words, a single color component using
0160 * a transfer type of <CODE>DataBuffer.TYPE_BYTE</CODE>,
0161 * <CODE>DataBuffer.TYPE_USHORT</CODE>, or <CODE>DataBuffer.TYPE_INT</CODE>
0162 * and no alpha.
0163 * <p>
0164 * A <CODE>ComponentColorModel</CODE> can be used in conjunction with a
0165 * <CODE>ComponentSampleModel</CODE>, a <CODE>BandedSampleModel</CODE>,
0166 * or a <CODE>PixelInterleavedSampleModel</CODE> to construct a
0167 * <CODE>BufferedImage</CODE>.
0168 *
0169 * @see ColorModel
0170 * @see ColorSpace
0171 * @see ComponentSampleModel
0172 * @see BandedSampleModel
0173 * @see PixelInterleavedSampleModel
0174 * @see BufferedImage
0175 *
0176 * @version 10 Feb 1997
0177 */
0178 public class ComponentColorModel extends ColorModel {
0179
0180 /**
0181 * <code>signed</code> is <code>true</code> for <code>short</code>,
0182 * <code>float</code>, and <code>double</code> transfer types; it
0183 * is <code>false</code> for <code>byte</code>, <code>ushort</code>,
0184 * and <code>int</code> transfer types.
0185 */
0186 private boolean signed; // true for transfer types short, float, double
0187 // false for byte, ushort, int
0188 private boolean is_sRGB_stdScale;
0189 private boolean is_LinearRGB_stdScale;
0190 private boolean is_LinearGray_stdScale;
0191 private boolean is_ICCGray_stdScale;
0192 private byte[] tosRGB8LUT;
0193 private byte[] fromsRGB8LUT8;
0194 private short[] fromsRGB8LUT16;
0195 private byte[] fromLinearGray16ToOtherGray8LUT;
0196 private short[] fromLinearGray16ToOtherGray16LUT;
0197 private boolean needScaleInit;
0198 private boolean noUnnorm;
0199 private boolean nonStdScale;
0200 private float[] min;
0201 private float[] diffMinMax;
0202 private float[] compOffset;
0203 private float[] compScale;
0204
0205 /**
0206 * Constructs a <CODE>ComponentColorModel</CODE> from the specified
0207 * parameters. Color components will be in the specified
0208 * <CODE>ColorSpace</CODE>. The supported transfer types are
0209 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
0210 * <CODE>DataBuffer.TYPE_INT</CODE>,
0211 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
0212 * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
0213 * If not null, the <CODE>bits</CODE> array specifies the
0214 * number of significant bits per color and alpha component and its
0215 * length should be at least the number of components in the
0216 * <CODE>ColorSpace</CODE> if there is no alpha
0217 * information in the pixel values, or one more than this number if
0218 * there is alpha information. When the <CODE>transferType</CODE> is
0219 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
0220 * or <CODE>DataBuffer.TYPE_DOUBLE</CODE> the <CODE>bits</CODE> array
0221 * argument is ignored. <CODE>hasAlpha</CODE> indicates whether alpha
0222 * information is present. If <CODE>hasAlpha</CODE> is true, then
0223 * the boolean <CODE>isAlphaPremultiplied</CODE>
0224 * specifies how to interpret color and alpha samples in pixel values.
0225 * If the boolean is true, color samples are assumed to have been
0226 * multiplied by the alpha sample. The <CODE>transparency</CODE>
0227 * specifies what alpha values can be represented by this color model.
0228 * The acceptable <code>transparency</code> values are
0229 * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
0230 * The <CODE>transferType</CODE> is the type of primitive array used
0231 * to represent pixel values.
0232 *
0233 * @param colorSpace The <CODE>ColorSpace</CODE> associated
0234 * with this color model.
0235 * @param bits The number of significant bits per component.
0236 * May be null, in which case all bits of all
0237 * component samples will be significant.
0238 * Ignored if transferType is one of
0239 * <CODE>DataBuffer.TYPE_SHORT</CODE>,
0240 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
0241 * <CODE>DataBuffer.TYPE_DOUBLE</CODE>,
0242 * in which case all bits of all component
0243 * samples will be significant.
0244 * @param hasAlpha If true, this color model supports alpha.
0245 * @param isAlphaPremultiplied If true, alpha is premultiplied.
0246 * @param transparency Specifies what alpha values can be represented
0247 * by this color model.
0248 * @param transferType Specifies the type of primitive array used to
0249 * represent pixel values.
0250 *
0251 * @throws IllegalArgumentException If the <CODE>bits</CODE> array
0252 * argument is not null, its length is less than the number of
0253 * color and alpha components, and transferType is one of
0254 * <CODE>DataBuffer.TYPE_BYTE</CODE>,
0255 * <CODE>DataBuffer.TYPE_USHORT</CODE>, or
0256 * <CODE>DataBuffer.TYPE_INT</CODE>.
0257 * @throws IllegalArgumentException If transferType is not one of
0258 * <CODE>DataBuffer.TYPE_BYTE</CODE>,
0259 * <CODE>DataBuffer.TYPE_USHORT</CODE>,
0260 * <CODE>DataBuffer.TYPE_INT</CODE>,
0261 * <CODE>DataBuffer.TYPE_SHORT</CODE>,
0262 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
0263 * <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
0264 *
0265 * @see ColorSpace
0266 * @see java.awt.Transparency
0267 */
0268 public ComponentColorModel(ColorSpace colorSpace, int[] bits,
0269 boolean hasAlpha, boolean isAlphaPremultiplied,
0270 int transparency, int transferType) {
0271 super (bitsHelper(transferType, colorSpace, hasAlpha),
0272 bitsArrayHelper(bits, transferType, colorSpace,
0273 hasAlpha), colorSpace, hasAlpha,
0274 isAlphaPremultiplied, transparency, transferType);
0275 switch (transferType) {
0276 case DataBuffer.TYPE_BYTE:
0277 case DataBuffer.TYPE_USHORT:
0278 case DataBuffer.TYPE_INT:
0279 signed = false;
0280 needScaleInit = true;
0281 break;
0282 case DataBuffer.TYPE_SHORT:
0283 signed = true;
0284 needScaleInit = true;
0285 break;
0286 case DataBuffer.TYPE_FLOAT:
0287 case DataBuffer.TYPE_DOUBLE:
0288 signed = true;
0289 needScaleInit = false;
0290 noUnnorm = true;
0291 nonStdScale = false;
0292 break;
0293 default:
0294 throw new IllegalArgumentException(
0295 "This constructor is not "
0296 + "compatible with transferType "
0297 + transferType);
0298 }
0299 setupLUTs();
0300 }
0301
0302 /**
0303 * Constructs a <CODE>ComponentColorModel</CODE> from the specified
0304 * parameters. Color components will be in the specified
0305 * <CODE>ColorSpace</CODE>. The supported transfer types are
0306 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
0307 * <CODE>DataBuffer.TYPE_INT</CODE>,
0308 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
0309 * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>. The number of significant
0310 * bits per color and alpha component will be 8, 16, 32, 16, 32, or 64,
0311 * respectively. The number of color components will be the
0312 * number of components in the <CODE>ColorSpace</CODE>. There will be
0313 * an alpha component if <CODE>hasAlpha</CODE> is <CODE>true</CODE>.
0314 * If <CODE>hasAlpha</CODE> is true, then
0315 * the boolean <CODE>isAlphaPremultiplied</CODE>
0316 * specifies how to interpret color and alpha samples in pixel values.
0317 * If the boolean is true, color samples are assumed to have been
0318 * multiplied by the alpha sample. The <CODE>transparency</CODE>
0319 * specifies what alpha values can be represented by this color model.
0320 * The acceptable <code>transparency</code> values are
0321 * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
0322 * The <CODE>transferType</CODE> is the type of primitive array used
0323 * to represent pixel values.
0324 *
0325 * @param colorSpace The <CODE>ColorSpace</CODE> associated
0326 * with this color model.
0327 * @param hasAlpha If true, this color model supports alpha.
0328 * @param isAlphaPremultiplied If true, alpha is premultiplied.
0329 * @param transparency Specifies what alpha values can be represented
0330 * by this color model.
0331 * @param transferType Specifies the type of primitive array used to
0332 * represent pixel values.
0333 *
0334 * @throws IllegalArgumentException If transferType is not one of
0335 * <CODE>DataBuffer.TYPE_BYTE</CODE>,
0336 * <CODE>DataBuffer.TYPE_USHORT</CODE>,
0337 * <CODE>DataBuffer.TYPE_INT</CODE>,
0338 * <CODE>DataBuffer.TYPE_SHORT</CODE>,
0339 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
0340 * <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
0341 *
0342 * @see ColorSpace
0343 * @see java.awt.Transparency
0344 * @since 1.4
0345 */
0346 public ComponentColorModel(ColorSpace colorSpace, boolean hasAlpha,
0347 boolean isAlphaPremultiplied, int transparency,
0348 int transferType) {
0349 this (colorSpace, null, hasAlpha, isAlphaPremultiplied,
0350 transparency, transferType);
0351 }
0352
0353 private static int bitsHelper(int transferType,
0354 ColorSpace colorSpace, boolean hasAlpha) {
0355 int numBits = DataBuffer.getDataTypeSize(transferType);
0356 int numComponents = colorSpace.getNumComponents();
0357 if (hasAlpha) {
0358 ++numComponents;
0359 }
0360 return numBits * numComponents;
0361 }
0362
0363 private static int[] bitsArrayHelper(int[] origBits,
0364 int transferType, ColorSpace colorSpace, boolean hasAlpha) {
0365 switch (transferType) {
0366 case DataBuffer.TYPE_BYTE:
0367 case DataBuffer.TYPE_USHORT:
0368 case DataBuffer.TYPE_INT:
0369 if (origBits != null) {
0370 return origBits;
0371 }
0372 break;
0373 default:
0374 break;
0375 }
0376 int numBits = DataBuffer.getDataTypeSize(transferType);
0377 int numComponents = colorSpace.getNumComponents();
0378 if (hasAlpha) {
0379 ++numComponents;
0380 }
0381 int[] bits = new int[numComponents];
0382 for (int i = 0; i < numComponents; i++) {
0383 bits[i] = numBits;
0384 }
0385 return bits;
0386 }
0387
0388 private void setupLUTs() {
0389 // REMIND: there is potential to accelerate sRGB, LinearRGB,
0390 // LinearGray, ICCGray, and non-ICC Gray spaces with non-standard
0391 // scaling, if that becomes important
0392 //
0393 // NOTE: The is_xxx_stdScale and nonStdScale booleans are provisionally
0394 // set here when this method is called at construction time. These
0395 // variables may be set again when initScale is called later.
0396 // When setupLUTs returns, nonStdScale is true if (the transferType
0397 // is not float or double) AND (some minimum ColorSpace component
0398 // value is not 0.0 OR some maximum ColorSpace component value
0399 // is not 1.0). This is correct for the calls to
0400 // getNormalizedComponents(Object, float[], int) from initScale().
0401 // initScale() may change the value nonStdScale based on the
0402 // return value of getNormalizedComponents() - this will only
0403 // happen if getNormalizedComponents() has been overridden by a
0404 // subclass to make the mapping of min/max pixel sample values
0405 // something different from min/max color component values.
0406 if (is_sRGB) {
0407 is_sRGB_stdScale = true;
0408 nonStdScale = false;
0409 } else if (ColorModel.isLinearRGBspace(colorSpace)) {
0410 // Note that the built-in Linear RGB space has a normalized
0411 // range of 0.0 - 1.0 for each coordinate. Usage of these
0412 // LUTs makes that assumption.
0413 is_LinearRGB_stdScale = true;
0414 nonStdScale = false;
0415 if (transferType == DataBuffer.TYPE_BYTE) {
0416 tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
0417 fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
0418 } else {
0419 tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
0420 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
0421 }
0422 } else if ((colorSpaceType == ColorSpace.TYPE_GRAY)
0423 && (colorSpace instanceof ICC_ColorSpace)
0424 && (colorSpace.getMinValue(0) == 0.0f)
0425 && (colorSpace.getMaxValue(0) == 1.0f)) {
0426 // Note that a normalized range of 0.0 - 1.0 for the gray
0427 // component is required, because usage of these LUTs makes
0428 // that assumption.
0429 ICC_ColorSpace ics = (ICC_ColorSpace) colorSpace;
0430 is_ICCGray_stdScale = true;
0431 nonStdScale = false;
0432 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
0433 if (ColorModel.isLinearGRAYspace(ics)) {
0434 is_LinearGray_stdScale = true;
0435 if (transferType == DataBuffer.TYPE_BYTE) {
0436 tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
0437 } else {
0438 tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
0439 }
0440 } else {
0441 if (transferType == DataBuffer.TYPE_BYTE) {
0442 tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
0443 fromLinearGray16ToOtherGray8LUT = ColorModel
0444 .getLinearGray16ToOtherGray8LUT(ics);
0445 } else {
0446 tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
0447 fromLinearGray16ToOtherGray16LUT = ColorModel
0448 .getLinearGray16ToOtherGray16LUT(ics);
0449 }
0450 }
0451 } else if (needScaleInit) {
0452 // if transferType is byte, ushort, int, or short and we
0453 // don't already know the ColorSpace has minVlaue == 0.0f and
0454 // maxValue == 1.0f for all components, we need to check that
0455 // now and setup the min[] and diffMinMax[] arrays if necessary.
0456 nonStdScale = false;
0457 for (int i = 0; i < numColorComponents; i++) {
0458 if ((colorSpace.getMinValue(i) != 0.0f)
0459 || (colorSpace.getMaxValue(i) != 1.0f)) {
0460 nonStdScale = true;
0461 break;
0462 }
0463 }
0464 if (nonStdScale) {
0465 min = new float[numColorComponents];
0466 diffMinMax = new float[numColorComponents];
0467 for (int i = 0; i < numColorComponents; i++) {
0468 min[i] = colorSpace.getMinValue(i);
0469 diffMinMax[i] = colorSpace.getMaxValue(i) - min[i];
0470 }
0471 }
0472 }
0473 }
0474
0475 private void initScale() {
0476 // This method is called the first time any method which uses
0477 // pixel sample value to color component value scaling information
0478 // is called if the transferType supports non-standard scaling
0479 // as defined above (byte, ushort, int, and short), unless the
0480 // method is getNormalizedComponents(Object, float[], int) (that
0481 // method must be overridden to use non-standard scaling). This
0482 // method also sets up the noUnnorm boolean variable for these
0483 // transferTypes. After this method is called, the nonStdScale
0484 // variable will be true if getNormalizedComponents() maps a
0485 // sample value of 0 to anything other than 0.0f OR maps a
0486 // sample value of 2^^n - 1 (2^^15 - 1 for short transferType)
0487 // to anything other than 1.0f. Note that this can be independent
0488 // of the colorSpace min/max component values, if the
0489 // getNormalizedComponents() method has been overridden for some
0490 // reason, e.g. to provide greater dynamic range in the sample
0491 // values than in the color component values. Unfortunately,
0492 // this method can't be called at construction time, since a
0493 // subclass may still have uninitialized state that would cause
0494 // getNormalizedComponents() to return an incorrect result.
0495 needScaleInit = false; // only needs to called once
0496 if (nonStdScale || signed) {
0497 // The unnormalized form is only supported for unsigned
0498 // transferTypes and when the ColorSpace min/max values
0499 // are 0.0/1.0. When this method is called nonStdScale is
0500 // true if the latter condition does not hold. In addition,
0501 // the unnormalized form requires that the full range of
0502 // the pixel sample values map to the full 0.0 - 1.0 range
0503 // of color component values. That condition is checked
0504 // later in this method.
0505 noUnnorm = true;
0506 } else {
0507 noUnnorm = false;
0508 }
0509 float[] lowVal, highVal;
0510 switch (transferType) {
0511 case DataBuffer.TYPE_BYTE: {
0512 byte[] bpixel = new byte[numComponents];
0513 for (int i = 0; i < numColorComponents; i++) {
0514 bpixel[i] = 0;
0515 }
0516 if (supportsAlpha) {
0517 bpixel[numColorComponents] = (byte) ((1 << nBits[numColorComponents]) - 1);
0518 }
0519 lowVal = getNormalizedComponents(bpixel, null, 0);
0520 for (int i = 0; i < numColorComponents; i++) {
0521 bpixel[i] = (byte) ((1 << nBits[i]) - 1);
0522 }
0523 highVal = getNormalizedComponents(bpixel, null, 0);
0524 }
0525 break;
0526 case DataBuffer.TYPE_USHORT: {
0527 short[] uspixel = new short[numComponents];
0528 for (int i = 0; i < numColorComponents; i++) {
0529 uspixel[i] = 0;
0530 }
0531 if (supportsAlpha) {
0532 uspixel[numColorComponents] = (short) ((1 << nBits[numColorComponents]) - 1);
0533 }
0534 lowVal = getNormalizedComponents(uspixel, null, 0);
0535 for (int i = 0; i < numColorComponents; i++) {
0536 uspixel[i] = (short) ((1 << nBits[i]) - 1);
0537 }
0538 highVal = getNormalizedComponents(uspixel, null, 0);
0539 }
0540 break;
0541 case DataBuffer.TYPE_INT: {
0542 int[] ipixel = new int[numComponents];
0543 for (int i = 0; i < numColorComponents; i++) {
0544 ipixel[i] = 0;
0545 }
0546 if (supportsAlpha) {
0547 ipixel[numColorComponents] = ((1 << nBits[numColorComponents]) - 1);
0548 }
0549 lowVal = getNormalizedComponents(ipixel, null, 0);
0550 for (int i = 0; i < numColorComponents; i++) {
0551 ipixel[i] = ((1 << nBits[i]) - 1);
0552 }
0553 highVal = getNormalizedComponents(ipixel, null, 0);
0554 }
0555 break;
0556 case DataBuffer.TYPE_SHORT: {
0557 short[] spixel = new short[numComponents];
0558 for (int i = 0; i < numColorComponents; i++) {
0559 spixel[i] = 0;
0560 }
0561 if (supportsAlpha) {
0562 spixel[numColorComponents] = 32767;
0563 }
0564 lowVal = getNormalizedComponents(spixel, null, 0);
0565 for (int i = 0; i < numColorComponents; i++) {
0566 spixel[i] = 32767;
0567 }
0568 highVal = getNormalizedComponents(spixel, null, 0);
0569 }
0570 break;
0571 default:
0572 lowVal = highVal = null; // to keep the compiler from complaining
0573 break;
0574 }
0575 nonStdScale = false;
0576 for (int i = 0; i < numColorComponents; i++) {
0577 if ((lowVal[i] != 0.0f) || (highVal[i] != 1.0f)) {
0578 nonStdScale = true;
0579 break;
0580 }
0581 }
0582 if (nonStdScale) {
0583 noUnnorm = true;
0584 is_sRGB_stdScale = false;
0585 is_LinearRGB_stdScale = false;
0586 is_LinearGray_stdScale = false;
0587 is_ICCGray_stdScale = false;
0588 compOffset = new float[numColorComponents];
0589 compScale = new float[numColorComponents];
0590 for (int i = 0; i < numColorComponents; i++) {
0591 compOffset[i] = lowVal[i];
0592 compScale[i] = 1.0f / (highVal[i] - lowVal[i]);
0593 }
0594 }
0595 }
0596
0597 private int getRGBComponent(int pixel, int idx) {
0598 if (numComponents > 1) {
0599 throw new IllegalArgumentException(
0600 "More than one component per pixel");
0601 }
0602 if (signed) {
0603 throw new IllegalArgumentException(
0604 "Component value is signed");
0605 }
0606 if (needScaleInit) {
0607 initScale();
0608 }
0609 // Since there is only 1 component, there is no alpha
0610
0611 // Normalize the pixel in order to convert it
0612 Object opixel = null;
0613 switch (transferType) {
0614 case DataBuffer.TYPE_BYTE: {
0615 byte[] bpixel = { (byte) pixel };
0616 opixel = bpixel;
0617 }
0618 break;
0619 case DataBuffer.TYPE_USHORT: {
0620 short[] spixel = { (short) pixel };
0621 opixel = spixel;
0622 }
0623 break;
0624 case DataBuffer.TYPE_INT: {
0625 int[] ipixel = { pixel };
0626 opixel = ipixel;
0627 }
0628 break;
0629 }
0630 float[] norm = getNormalizedComponents(opixel, null, 0);
0631 float[] rgb = colorSpace.toRGB(norm);
0632
0633 return (int) (rgb[idx] * 255.0f + 0.5f);
0634 }
0635
0636 /**
0637 * Returns the red color component for the specified pixel, scaled
0638 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
0639 * is done if necessary. The pixel value is specified as an int.
0640 * The returned value will be a non pre-multiplied value.
0641 * If the alpha is premultiplied, this method divides
0642 * it out before returning the value (if the alpha value is 0,
0643 * the red value will be 0).
0644 *
0645 * @param pixel The pixel from which you want to get the red color component.
0646 *
0647 * @return The red color component for the specified pixel, as an int.
0648 *
0649 * @throws IllegalArgumentException If there is more than
0650 * one component in this <CODE>ColorModel</CODE>.
0651 * @throws IllegalArgumentException If the component value for this
0652 * <CODE>ColorModel</CODE> is signed
0653 */
0654 public int getRed(int pixel) {
0655 return getRGBComponent(pixel, 0);
0656 }
0657
0658 /**
0659 * Returns the green color component for the specified pixel, scaled
0660 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
0661 * is done if necessary. The pixel value is specified as an int.
0662 * The returned value will be a non
0663 * pre-multiplied value. If the alpha is premultiplied, this method
0664 * divides it out before returning the value (if the alpha value is 0,
0665 * the green value will be 0).
0666 *
0667 * @param pixel The pixel from which you want to get the green color component.
0668 *
0669 * @return The green color component for the specified pixel, as an int.
0670 *
0671 * @throws IllegalArgumentException If there is more than
0672 * one component in this <CODE>ColorModel</CODE>.
0673 * @throws IllegalArgumentException If the component value for this
0674 * <CODE>ColorModel</CODE> is signed
0675 */
0676 public int getGreen(int pixel) {
0677 return getRGBComponent(pixel, 1);
0678 }
0679
0680 /**
0681 * Returns the blue color component for the specified pixel, scaled
0682 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
0683 * is done if necessary. The pixel value is specified as an int.
0684 * The returned value will be a non
0685 * pre-multiplied value. If the alpha is premultiplied, this method
0686 * divides it out before returning the value (if the alpha value is 0,
0687 * the blue value will be 0).
0688 *
0689 * @param pixel The pixel from which you want to get the blue color component.
0690 *
0691 * @return The blue color component for the specified pixel, as an int.
0692 *
0693 * @throws IllegalArgumentException If there is more than
0694 * one component in this <CODE>ColorModel</CODE>.
0695 * @throws IllegalArgumentException If the component value for this
0696 * <CODE>ColorModel</CODE> is signed
0697 */
0698 public int getBlue(int pixel) {
0699 return getRGBComponent(pixel, 2);
0700 }
0701
0702 /**
0703 * Returns the alpha component for the specified pixel, scaled
0704 * from 0 to 255. The pixel value is specified as an int.
0705 *
0706 * @param pixel The pixel from which you want to get the alpha component.
0707 *
0708 * @return The alpha component for the specified pixel, as an int.
0709 *
0710 * @throws IllegalArgumentException If there is more than
0711 * one component in this <CODE>ColorModel</CODE>.
0712 * @throws IllegalArgumentException If the component value for this
0713 * <CODE>ColorModel</CODE> is signed
0714 */
0715 public int getAlpha(int pixel) {
0716 if (supportsAlpha == false) {
0717 return 255;
0718 }
0719 if (numComponents > 1) {
0720 throw new IllegalArgumentException(
0721 "More than one component per pixel");
0722 }
0723 if (signed) {
0724 throw new IllegalArgumentException(
0725 "Component value is signed");
0726 }
0727
0728 return (int) ((((float) pixel) / ((1 << nBits[0]) - 1)) * 255.0f + 0.5f);
0729 }
0730
0731 /**
0732 * Returns the color/alpha components of the pixel in the default
0733 * RGB color model format. A color conversion is done if necessary.
0734 * The returned value will be in a non pre-multiplied format. If
0735 * the alpha is premultiplied, this method divides it out of the
0736 * color components (if the alpha value is 0, the color values will be 0).
0737 *
0738 * @param pixel The pixel from which you want to get the color/alpha components.
0739 *
0740 * @return The color/alpha components for the specified pixel, as an int.
0741 *
0742 * @throws IllegalArgumentException If there is more than
0743 * one component in this <CODE>ColorModel</CODE>.
0744 * @throws IllegalArgumentException If the component value for this
0745 * <CODE>ColorModel</CODE> is signed
0746 */
0747 public int getRGB(int pixel) {
0748 if (numComponents > 1) {
0749 throw new IllegalArgumentException(
0750 "More than one component per pixel");
0751 }
0752 if (signed) {
0753 throw new IllegalArgumentException(
0754 "Component value is signed");
0755 }
0756
0757 return (getAlpha(pixel) << 24) | (getRed(pixel) << 16)
0758 | (getGreen(pixel) << 8) | (getBlue(pixel) << 0);
0759 }
0760
0761 private int extractComponent(Object inData, int idx, int precision) {
0762 // Extract component idx from inData. The precision argument
0763 // should be either 8 or 16. If it's 8, this method will return
0764 // an 8-bit value. If it's 16, this method will return a 16-bit
0765 // value for transferTypes other than TYPE_BYTE. For TYPE_BYTE,
0766 // an 8-bit value will be returned.
0767
0768 // This method maps the input value corresponding to a
0769 // normalized ColorSpace component value of 0.0 to 0, and the
0770 // input value corresponding to a normalized ColorSpace
0771 // component value of 1.0 to 2^n - 1 (where n is 8 or 16), so
0772 // it is appropriate only for ColorSpaces with min/max component
0773 // values of 0.0/1.0. This will be true for sRGB, the built-in
0774 // Linear RGB and Linear Gray spaces, and any other ICC grayscale
0775 // spaces for which we have precomputed LUTs.
0776
0777 boolean needAlpha = (supportsAlpha && isAlphaPremultiplied);
0778 int alp = 0;
0779 int comp;
0780 int mask = (1 << nBits[idx]) - 1;
0781
0782 switch (transferType) {
0783 // Note: we do no clamping of the pixel data here - we
0784 // assume that the data is scaled properly
0785 case DataBuffer.TYPE_SHORT: {
0786 short sdata[] = (short[]) inData;
0787 float scalefactor = (float) ((1 << precision) - 1);
0788 if (needAlpha) {
0789 short s = sdata[numColorComponents];
0790 if (s != (short) 0) {
0791 return (int) ((((float) sdata[idx]) / ((float) s))
0792 * scalefactor + 0.5f);
0793 } else {
0794 return 0;
0795 }
0796 } else {
0797 return (int) ((sdata[idx] / 32767.0f) * scalefactor + 0.5f);
0798 }
0799 }
0800 case DataBuffer.TYPE_FLOAT: {
0801 float fdata[] = (float[]) inData;
0802 float scalefactor = (float) ((1 << precision) - 1);
0803 if (needAlpha) {
0804 float f = fdata[numColorComponents];
0805 if (f != 0.0f) {
0806 return (int) (((fdata[idx] / f) * scalefactor) + 0.5f);
0807 } else {
0808 return 0;
0809 }
0810 } else {
0811 return (int) (fdata[idx] * scalefactor + 0.5f);
0812 }
0813 }
0814 case DataBuffer.TYPE_DOUBLE: {
0815 double ddata[] = (double[]) inData;
0816 double scalefactor = (double) ((1 << precision) - 1);
0817 if (needAlpha) {
0818 double d = ddata[numColorComponents];
0819 if (d != 0.0) {
0820 return (int) (((ddata[idx] / d) * scalefactor) + 0.5);
0821 } else {
0822 return 0;
0823 }
0824 } else {
0825 return (int) (ddata[idx] * scalefactor + 0.5);
0826 }
0827 }
0828 case DataBuffer.TYPE_BYTE:
0829 byte bdata[] = (byte[]) inData;
0830 comp = bdata[idx] & mask;
0831 precision = 8;
0832 if (needAlpha) {
0833 alp = bdata[numColorComponents] & mask;
0834 }
0835 break;
0836 case DataBuffer.TYPE_USHORT:
0837 short usdata[] = (short[]) inData;
0838 comp = usdata[idx] & mask;
0839 if (needAlpha) {
0840 alp = usdata[numColorComponents] & mask;
0841 }
0842 break;
0843 case DataBuffer.TYPE_INT:
0844 int idata[] = (int[]) inData;
0845 comp = idata[idx];
0846 if (needAlpha) {
0847 alp = idata[numColorComponents];
0848 }
0849 break;
0850 default:
0851 throw new UnsupportedOperationException(
0852 "This method has not "
0853 + "been implemented for transferType "
0854 + transferType);
0855 }
0856 if (needAlpha) {
0857 if (alp != 0) {
0858 float scalefactor = (float) ((1 << precision) - 1);
0859 float fcomp = ((float) comp) / ((float) mask);
0860 float invalp = ((float) ((1 << nBits[numColorComponents]) - 1))
0861 / ((float) alp);
0862 return (int) (fcomp * invalp * scalefactor + 0.5f);
0863 } else {
0864 return 0;
0865 }
0866 } else {
0867 if (nBits[idx] != precision) {
0868 float scalefactor = (float) ((1 << precision) - 1);
0869 float fcomp = ((float) comp) / ((float) mask);
0870 return (int) (fcomp * scalefactor + 0.5f);
0871 }
0872 return comp;
0873 }
0874 }
0875
0876 private int getRGBComponent(Object inData, int idx) {
0877 if (needScaleInit) {
0878 initScale();
0879 }
0880 if (is_sRGB_stdScale) {
0881 return extractComponent(inData, idx, 8);
0882 } else if (is_LinearRGB_stdScale) {
0883 int lutidx = extractComponent(inData, idx, 16);
0884 return tosRGB8LUT[lutidx] & 0xff;
0885 } else if (is_ICCGray_stdScale) {
0886 int lutidx = extractComponent(inData, 0, 16);
0887 return tosRGB8LUT[lutidx] & 0xff;
0888 }
0889
0890 // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace
0891 float[] norm = getNormalizedComponents(inData, null, 0);
0892 // Note that getNormalizedComponents returns non-premultiplied values
0893 float[] rgb = colorSpace.toRGB(norm);
0894 return (int) (rgb[idx] * 255.0f + 0.5f);
0895 }
0896
0897 /**
0898 * Returns the red color component for the specified pixel, scaled
0899 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
0900 * is done if necessary. The <CODE>pixel</CODE> value is specified by an array
0901 * of data elements of type <CODE>transferType</CODE> passed in as an object
0902 * reference. The returned value will be a non pre-multiplied value. If the
0903 * alpha is premultiplied, this method divides it out before returning
0904 * the value (if the alpha value is 0, the red value will be 0). Since
0905 * <code>ComponentColorModel</code> can be subclassed, subclasses
0906 * inherit the implementation of this method and if they don't override
0907 * it then they throw an exception if they use an unsupported
0908 * <code>transferType</code>.
0909 *
0910 * @param inData The pixel from which you want to get the red color component,
0911 * specified by an array of data elements of type <CODE>transferType</CODE>.
0912 *
0913 * @return The red color component for the specified pixel, as an int.
0914 *
0915 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
0916 * of type <CODE>transferType</CODE>.
0917 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
0918 * large enough to hold a pixel value for this
0919 * <CODE>ColorModel</CODE>.
0920 * @throws UnsupportedOperationException If the transfer type of
0921 * this <CODE>ComponentColorModel</CODE>
0922 * is not one of the supported transfer types:
0923 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
0924 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
0925 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
0926 */
0927 public int getRed(Object inData) {
0928 return getRGBComponent(inData, 0);
0929 }
0930
0931 /**
0932 * Returns the green color component for the specified pixel, scaled
0933 * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
0934 * A color conversion is done if necessary. The <CODE>pixel</CODE> value
0935 * is specified by an array of data elements of type <CODE>transferType</CODE>
0936 * passed in as an object reference. The returned value is a non pre-multiplied
0937 * value. If the alpha is premultiplied, this method divides it out before
0938 * returning the value (if the alpha value is 0, the green value will be 0).
0939 * Since <code>ComponentColorModel</code> can be subclassed,
0940 * subclasses inherit the implementation of this method and if they
0941 * don't override it then they throw an exception if they use an
0942 * unsupported <code>transferType</code>.
0943 *
0944 * @param inData The pixel from which you want to get the green color component,
0945 * specified by an array of data elements of type <CODE>transferType</CODE>.
0946 *
0947 * @return The green color component for the specified pixel, as an int.
0948 *
0949 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
0950 * of type <CODE>transferType</CODE>.
0951 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
0952 * large enough to hold a pixel value for this
0953 * <CODE>ColorModel</CODE>.
0954 * @throws UnsupportedOperationException If the transfer type of
0955 * this <CODE>ComponentColorModel</CODE>
0956 * is not one of the supported transfer types:
0957 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
0958 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
0959 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
0960 */
0961 public int getGreen(Object inData) {
0962 return getRGBComponent(inData, 1);
0963 }
0964
0965 /**
0966 * Returns the blue color component for the specified pixel, scaled
0967 * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
0968 * A color conversion is done if necessary. The <CODE>pixel</CODE> value is
0969 * specified by an array of data elements of type <CODE>transferType</CODE>
0970 * passed in as an object reference. The returned value is a non pre-multiplied
0971 * value. If the alpha is premultiplied, this method divides it out before
0972 * returning the value (if the alpha value is 0, the blue value will be 0).
0973 * Since <code>ComponentColorModel</code> can be subclassed,
0974 * subclasses inherit the implementation of this method and if they
0975 * don't override it then they throw an exception if they use an
0976 * unsupported <code>transferType</code>.
0977 *
0978 * @param inData The pixel from which you want to get the blue color component,
0979 * specified by an array of data elements of type <CODE>transferType</CODE>.
0980 *
0981 * @return The blue color component for the specified pixel, as an int.
0982 *
0983 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
0984 * of type <CODE>transferType</CODE>.
0985 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
0986 * large enough to hold a pixel value for this
0987 * <CODE>ColorModel</CODE>.
0988 * @throws UnsupportedOperationException If the transfer type of
0989 * this <CODE>ComponentColorModel</CODE>
0990 * is not one of the supported transfer types:
0991 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
0992 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
0993 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
0994 */
0995 public int getBlue(Object inData) {
0996 return getRGBComponent(inData, 2);
0997 }
0998
0999 /**
1000 * Returns the alpha component for the specified pixel, scaled from
1001 * 0 to 255. The pixel value is specified by an array of data
1002 * elements of type <CODE>transferType</CODE> passed in as an
1003 * object reference. Since <code>ComponentColorModel</code> can be
1004 * subclassed, subclasses inherit the
1005 * implementation of this method and if they don't override it then
1006 * they throw an exception if they use an unsupported
1007 * <code>transferType</code>.
1008 *
1009 * @param inData The pixel from which you want to get the alpha component,
1010 * specified by an array of data elements of type <CODE>transferType</CODE>.
1011 *
1012 * @return The alpha component for the specified pixel, as an int.
1013 *
1014 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1015 * of type <CODE>transferType</CODE>.
1016 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1017 * large enough to hold a pixel value for this
1018 * <CODE>ColorModel</CODE>.
1019 * @throws UnsupportedOperationException If the transfer type of
1020 * this <CODE>ComponentColorModel</CODE>
1021 * is not one of the supported transfer types:
1022 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1023 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1024 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1025 */
1026 public int getAlpha(Object inData) {
1027 if (supportsAlpha == false) {
1028 return 255;
1029 }
1030
1031 int alpha = 0;
1032 int aIdx = numColorComponents;
1033 int mask = (1 << nBits[aIdx]) - 1;
1034
1035 switch (transferType) {
1036 case DataBuffer.TYPE_SHORT:
1037 short sdata[] = (short[]) inData;
1038 alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f);
1039 return alpha;
1040 case DataBuffer.TYPE_FLOAT:
1041 float fdata[] = (float[]) inData;
1042 alpha = (int) (fdata[aIdx] * 255.0f + 0.5f);
1043 return alpha;
1044 case DataBuffer.TYPE_DOUBLE:
1045 double ddata[] = (double[]) inData;
1046 alpha = (int) (ddata[aIdx] * 255.0 + 0.5);
1047 return alpha;
1048 case DataBuffer.TYPE_BYTE:
1049 byte bdata[] = (byte[]) inData;
1050 alpha = bdata[aIdx] & mask;
1051 break;
1052 case DataBuffer.TYPE_USHORT:
1053 short usdata[] = (short[]) inData;
1054 alpha = usdata[aIdx] & mask;
1055 break;
1056 case DataBuffer.TYPE_INT:
1057 int idata[] = (int[]) inData;
1058 alpha = idata[aIdx];
1059 break;
1060 default:
1061 throw new UnsupportedOperationException(
1062 "This method has not "
1063 + "been implemented for transferType "
1064 + transferType);
1065 }
1066
1067 if (nBits[aIdx] == 8) {
1068 return alpha;
1069 } else {
1070 return (int) ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) * 255.0f + 0.5f);
1071 }
1072 }
1073
1074 /**
1075 * Returns the color/alpha components for the specified pixel in the
1076 * default RGB color model format. A color conversion is done if
1077 * necessary. The pixel value is specified by an
1078 * array of data elements of type <CODE>transferType</CODE> passed
1079 * in as an object reference.
1080 * The returned value is in a non pre-multiplied format. If
1081 * the alpha is premultiplied, this method divides it out of the
1082 * color components (if the alpha value is 0, the color values will be 0).
1083 * Since <code>ComponentColorModel</code> can be subclassed,
1084 * subclasses inherit the implementation of this method and if they
1085 * don't override it then they throw an exception if they use an
1086 * unsupported <code>transferType</code>.
1087 *
1088 * @param inData The pixel from which you want to get the color/alpha components,
1089 * specified by an array of data elements of type <CODE>transferType</CODE>.
1090 *
1091 * @return The color/alpha components for the specified pixel, as an int.
1092 *
1093 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1094 * of type <CODE>transferType</CODE>.
1095 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1096 * large enough to hold a pixel value for this
1097 * <CODE>ColorModel</CODE>.
1098 * @throws UnsupportedOperationException If the transfer type of
1099 * this <CODE>ComponentColorModel</CODE>
1100 * is not one of the supported transfer types:
1101 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1102 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1103 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1104 * @see ColorModel#getRGBdefault
1105 */
1106 public int getRGB(Object inData) {
1107 if (needScaleInit) {
1108 initScale();
1109 }
1110 if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1111 return (getAlpha(inData) << 24) | (getRed(inData) << 16)
1112 | (getGreen(inData) << 8) | (getBlue(inData));
1113 } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
1114 int gray = getRed(inData); // Red sRGB component should equal
1115 // green and blue components
1116 return (getAlpha(inData) << 24) | (gray << 16)
1117 | (gray << 8) | gray;
1118 }
1119 float[] norm = getNormalizedComponents(inData, null, 0);
1120 // Note that getNormalizedComponents returns non-premult values
1121 float[] rgb = colorSpace.toRGB(norm);
1122 return (getAlpha(inData) << 24)
1123 | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
1124 | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
1125 | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
1126 }
1127
1128 /**
1129 * Returns a data element array representation of a pixel in this
1130 * <CODE>ColorModel</CODE>, given an integer pixel representation
1131 * in the default RGB color model.
1132 * This array can then be passed to the <CODE>setDataElements</CODE>
1133 * method of a <CODE>WritableRaster</CODE> object. If the
1134 * <CODE>pixel</CODE>
1135 * parameter is null, a new array is allocated. Since
1136 * <code>ComponentColorModel</code> can be subclassed, subclasses
1137 * inherit the implementation of this method and if they don't
1138 * override it then
1139 * they throw an exception if they use an unsupported
1140 * <code>transferType</code>.
1141 *
1142 * @param rgb the integer representation of the pixel in the RGB
1143 * color model
1144 * @param pixel the specified pixel
1145 * @return The data element array representation of a pixel
1146 * in this <CODE>ColorModel</CODE>.
1147 * @throws ClassCastException If <CODE>pixel</CODE> is not null and
1148 * is not a primitive array of type <CODE>transferType</CODE>.
1149 * @throws ArrayIndexOutOfBoundsException If <CODE>pixel</CODE> is
1150 * not large enough to hold a pixel value for this
1151 * <CODE>ColorModel</CODE>.
1152 * @throws UnsupportedOperationException If the transfer type of
1153 * this <CODE>ComponentColorModel</CODE>
1154 * is not one of the supported transfer types:
1155 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1156 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1157 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1158 *
1159 * @see WritableRaster#setDataElements
1160 * @see SampleModel#setDataElements
1161 */
1162 public Object getDataElements(int rgb, Object pixel) {
1163 // REMIND: Use rendering hints?
1164
1165 int red, grn, blu, alp;
1166 red = (rgb >> 16) & 0xff;
1167 grn = (rgb >> 8) & 0xff;
1168 blu = rgb & 0xff;
1169
1170 if (needScaleInit) {
1171 initScale();
1172 }
1173 if (signed) {
1174 // Handle SHORT, FLOAT, & DOUBLE here
1175
1176 switch (transferType) {
1177 case DataBuffer.TYPE_SHORT: {
1178 short sdata[];
1179 if (pixel == null) {
1180 sdata = new short[numComponents];
1181 } else {
1182 sdata = (short[]) pixel;
1183 }
1184 float factor;
1185 if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1186 factor = 32767.0f / 255.0f;
1187 if (is_LinearRGB_stdScale) {
1188 red = fromsRGB8LUT16[red] & 0xffff;
1189 grn = fromsRGB8LUT16[grn] & 0xffff;
1190 blu = fromsRGB8LUT16[blu] & 0xffff;
1191 factor = 32767.0f / 65535.0f;
1192 }
1193 if (supportsAlpha) {
1194 alp = (rgb >> 24) & 0xff;
1195 sdata[3] = (short) (alp * (32767.0f / 255.0f) + 0.5f);
1196 if (isAlphaPremultiplied) {
1197 factor = alp * factor * (1.0f / 255.0f);
1198 }
1199 }
1200 sdata[0] = (short) (red * factor + 0.5f);
1201 sdata[1] = (short) (grn * factor + 0.5f);
1202 sdata[2] = (short) (blu * factor + 0.5f);
1203 } else if (is_LinearGray_stdScale) {
1204 red = fromsRGB8LUT16[red] & 0xffff;
1205 grn = fromsRGB8LUT16[grn] & 0xffff;
1206 blu = fromsRGB8LUT16[blu] & 0xffff;
1207 float gray = ((0.2125f * red) + (0.7154f * grn) + (0.0721f * blu)) / 65535.0f;
1208 factor = 32767.0f;
1209 if (supportsAlpha) {
1210 alp = (rgb >> 24) & 0xff;
1211 sdata[1] = (short) (alp * (32767.0f / 255.0f) + 0.5f);
1212 if (isAlphaPremultiplied) {
1213 factor = alp * factor * (1.0f / 255.0f);
1214 }
1215 }
1216 sdata[0] = (short) (gray * factor + 0.5f);
1217 } else if (is_ICCGray_stdScale) {
1218 red = fromsRGB8LUT16[red] & 0xffff;
1219 grn = fromsRGB8LUT16[grn] & 0xffff;
1220 blu = fromsRGB8LUT16[blu] & 0xffff;
1221 int gray = (int) ((0.2125f * red) + (0.7154f * grn)
1222 + (0.0721f * blu) + 0.5f);
1223 gray = fromLinearGray16ToOtherGray16LUT[gray] & 0xffff;
1224 factor = 32767.0f / 65535.0f;
1225 if (supportsAlpha) {
1226 alp = (rgb >> 24) & 0xff;
1227 sdata[1] = (short) (alp * (32767.0f / 255.0f) + 0.5f);
1228 if (isAlphaPremultiplied) {
1229 factor = alp * factor * (1.0f / 255.0f);
1230 }
1231 }
1232 sdata[0] = (short) (gray * factor + 0.5f);
1233 } else {
1234 factor = 1.0f / 255.0f;
1235 float norm[] = new float[3];
1236 norm[0] = red * factor;
1237 norm[1] = grn * factor;
1238 norm[2] = blu * factor;
1239 norm = colorSpace.fromRGB(norm);
1240 if (nonStdScale) {
1241 for (int i = 0; i < numColorComponents; i++) {
1242 norm[i] = (norm[i] - compOffset[i])
1243 * compScale[i];
1244 // REMIND: need to analyze whether this
1245 // clamping is necessary
1246 if (norm[i] < 0.0f) {
1247 norm[i] = 0.0f;
1248 }
1249 if (norm[i] > 1.0f) {
1250 norm[i] = 1.0f;
1251 }
1252 }
1253 }
1254 factor = 32767.0f;
1255 if (supportsAlpha) {
1256 alp = (rgb >> 24) & 0xff;
1257 sdata[numColorComponents] = (short) (alp
1258 * (32767.0f / 255.0f) + 0.5f);
1259 if (isAlphaPremultiplied) {
1260 factor *= alp * (1.0f / 255.0f);
1261 }
1262 }
1263 for (int i = 0; i < numColorComponents; i++) {
1264 sdata[i] = (short) (norm[i] * factor + 0.5f);
1265 }
1266 }
1267 return sdata;
1268 }
1269 case DataBuffer.TYPE_FLOAT: {
1270 float fdata[];
1271 if (pixel == null) {
1272 fdata = new float[numComponents];
1273 } else {
1274 fdata = (float[]) pixel;
1275 }
1276 float factor;
1277 if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1278 if (is_LinearRGB_stdScale) {
1279 red = fromsRGB8LUT16[red] & 0xffff;
1280 grn = fromsRGB8LUT16[grn] & 0xffff;
1281 blu = fromsRGB8LUT16[blu] & 0xffff;
1282 factor = 1.0f / 65535.0f;
1283 } else {
1284 factor = 1.0f / 255.0f;
1285 }
1286 if (supportsAlpha) {
1287 alp = (rgb >> 24) & 0xff;
1288 fdata[3] = alp * (1.0f / 255.0f);
1289 if (isAlphaPremultiplied) {
1290 factor *= fdata[3];
1291 }
1292 }
1293 fdata[0] = red * factor;
1294 fdata[1] = grn * factor;
1295 fdata[2] = blu * factor;
1296 } else if (is_LinearGray_stdScale) {
1297 red = fromsRGB8LUT16[red] & 0xffff;
1298 grn = fromsRGB8LUT16[grn] & 0xffff;
1299 blu = fromsRGB8LUT16[blu] & 0xffff;
1300 fdata[0] = ((0.2125f * red) + (0.7154f * grn) + (0.0721f * blu)) / 65535.0f;
1301 if (supportsAlpha) {
1302 alp = (rgb >> 24) & 0xff;
1303 fdata[1] = alp * (1.0f / 255.0f);
1304 if (isAlphaPremultiplied) {
1305 fdata[0] *= fdata[1];
1306 }
1307 }
1308 } else if (is_ICCGray_stdScale) {
1309 red = fromsRGB8LUT16[red] & 0xffff;
1310 grn = fromsRGB8LUT16[grn] & 0xffff;
1311 blu = fromsRGB8LUT16[blu] & 0xffff;
1312 int gray = (int) ((0.2125f * red) + (0.7154f * grn)
1313 + (0.0721f * blu) + 0.5f);
1314 fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & 0xffff) / 65535.0f;
1315 if (supportsAlpha) {
1316 alp = (rgb >> 24) & 0xff;
1317 fdata[1] = alp * (1.0f / 255.0f);
1318 if (isAlphaPremultiplied) {
1319 fdata[0] *= fdata[1];
1320 }
1321 }
1322 } else {
1323 float norm[] = new float[3];
1324 factor = 1.0f / 255.0f;
1325 norm[0] = red * factor;
1326 norm[1] = grn * factor;
1327 norm[2] = blu * factor;
1328 norm = colorSpace.fromRGB(norm);
1329 if (supportsAlpha) {
1330 alp = (rgb >> 24) & 0xff;
1331 fdata[numColorComponents] = alp * factor;
1332 if (isAlphaPremultiplied) {
1333 factor *= alp;
1334 for (int i = 0; i < numColorComponents; i++) {
1335 norm[i] *= factor;
1336 }
1337 }
1338 }
1339 for (int i = 0; i < numColorComponents; i++) {
1340 fdata[i] = norm[i];
1341 }
1342 }
1343 return fdata;
1344 }
1345 case DataBuffer.TYPE_DOUBLE: {
1346 double ddata[];
1347 if (pixel == null) {
1348 ddata = new double[numComponents];
1349 } else {
1350 ddata = (double[]) pixel;
1351 }
1352 if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1353 double factor;
1354 if (is_LinearRGB_stdScale) {
1355 red = fromsRGB8LUT16[red] & 0xffff;
1356 grn = fromsRGB8LUT16[grn] & 0xffff;
1357 blu = fromsRGB8LUT16[blu] & 0xffff;
1358 factor = 1.0 / 65535.0;
1359 } else {
1360 factor = 1.0 / 255.0;
1361 }
1362 if (supportsAlpha) {
1363 alp = (rgb >> 24) & 0xff;
1364 ddata[3] = alp * (1.0 / 255.0);
1365 if (isAlphaPremultiplied) {
1366 factor *= ddata[3];
1367 }
1368 }
1369 ddata[0] = red * factor;
1370 ddata[1] = grn * factor;
1371 ddata[2] = blu * factor;
1372 } else if (is_LinearGray_stdScale) {
1373 red = fromsRGB8LUT16[red] & 0xffff;
1374 grn = fromsRGB8LUT16[grn] & 0xffff;
1375 blu = fromsRGB8LUT16[blu] & 0xffff;
1376 ddata[0] = ((0.2125 * red) + (0.7154 * grn) + (0.0721 * blu)) / 65535.0;
1377 if (supportsAlpha) {
1378 alp = (rgb >> 24) & 0xff;
1379 ddata[1] = alp * (1.0 / 255.0);
1380 if (isAlphaPremultiplied) {
1381 ddata[0] *= ddata[1];
1382 }
1383 }
1384 } else if (is_ICCGray_stdScale) {
1385 red = fromsRGB8LUT16[red] & 0xffff;
1386 grn = fromsRGB8LUT16[grn] & 0xffff;
1387 blu = fromsRGB8LUT16[blu] & 0xffff;
1388 int gray = (int) ((0.2125f * red) + (0.7154f * grn)
1389 + (0.0721f * blu) + 0.5f);
1390 ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & 0xffff) / 65535.0;
1391 if (supportsAlpha) {
1392 alp = (rgb >> 24) & 0xff;
1393 ddata[1] = alp * (1.0 / 255.0);
1394 if (isAlphaPremultiplied) {
1395 ddata[0] *= ddata[1];
1396 }
1397 }
1398 } else {
1399 float factor = 1.0f / 255.0f;
1400 float norm[] = new float[3];
1401 norm[0] = red * factor;
1402 norm[1] = grn * factor;
1403 norm[2] = blu * factor;
1404 norm = colorSpace.fromRGB(norm);
1405 if (supportsAlpha) {
1406 alp = (rgb >> 24) & 0xff;
1407 ddata[numColorComponents] = alp * (1.0 / 255.0);
1408 if (isAlphaPremultiplied) {
1409 factor *= alp;
1410 for (int i = 0; i < numColorComponents; i++) {
1411 norm[i] *= factor;
1412 }
1413 }
1414 }
1415 for (int i = 0; i < numColorComponents; i++) {
1416 ddata[i] = norm[i];
1417 }
1418 }
1419 return ddata;
1420 }
1421 }
1422 }
1423
1424 // Handle BYTE, USHORT, & INT here
1425 //REMIND: maybe more efficient not to use int array for
1426 //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
1427 int intpixel[];
1428 if (transferType == DataBuffer.TYPE_INT && pixel != null) {
1429 intpixel = (int[]) pixel;
1430 } else {
1431 intpixel = new int[numComponents];
1432 }
1433
1434 if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1435 int precision;
1436 float factor;
1437 if (is_LinearRGB_stdScale) {
1438 if (transferType == DataBuffer.TYPE_BYTE) {
1439 red = fromsRGB8LUT8[red] & 0xff;
1440 grn = fromsRGB8LUT8[grn] & 0xff;
1441 blu = fromsRGB8LUT8[blu] & 0xff;
1442 precision = 8;
1443 factor = 1.0f / 255.0f;
1444 } else {
1445 red = fromsRGB8LUT16[red] & 0xffff;
1446 grn = fromsRGB8LUT16[grn] & 0xffff;
1447 blu = fromsRGB8LUT16[blu] & 0xffff;
1448 precision = 16;
1449 factor = 1.0f / 65535.0f;
1450 }
1451 } else {
1452 precision = 8;
1453 factor = 1.0f / 255.0f;
1454 }
1455 if (supportsAlpha) {
1456 alp = (rgb >> 24) & 0xff;
1457 if (nBits[3] == 8) {
1458 intpixel[3] = alp;
1459 } else {
1460 intpixel[3] = (int) (alp * (1.0f / 255.0f)
1461 * ((1 << nBits[3]) - 1) + 0.5f);
1462 }
1463 if (isAlphaPremultiplied) {
1464 factor *= (alp * (1.0f / 255.0f));
1465 precision = -1; // force component calculations below
1466 }
1467 }
1468 if (nBits[0] == precision) {
1469 intpixel[0] = red;
1470 } else {
1471 intpixel[0] = (int) (red * factor
1472 * ((1 << nBits[0]) - 1) + 0.5f);
1473 }
1474 if (nBits[1] == precision) {
1475 intpixel[1] = (int) (grn);
1476 } else {
1477 intpixel[1] = (int) (grn * factor
1478 * ((1 << nBits[1]) - 1) + 0.5f);
1479 }
1480 if (nBits[2] == precision) {
1481 intpixel[2] = (int) (blu);
1482 } else {
1483 intpixel[2] = (int) (blu * factor
1484 * ((1 << nBits[2]) - 1) + 0.5f);
1485 }
1486 } else if (is_LinearGray_stdScale) {
1487 red = fromsRGB8LUT16[red] & 0xffff;
1488 grn = fromsRGB8LUT16[grn] & 0xffff;
1489 blu = fromsRGB8LUT16[blu] & 0xffff;
1490 float gray = ((0.2125f * red) + (0.7154f * grn) + (0.0721f * blu)) / 65535.0f;
1491 if (supportsAlpha) {
1492 alp = (rgb >> 24) & 0xff;
1493 if (nBits[1] == 8) {
1494 intpixel[1] = alp;
1495 } else {
1496 intpixel[1] = (int) (alp * (1.0f / 255.0f)
1497 * ((1 << nBits[1]) - 1) + 0.5f);
1498 }
1499 if (isAlphaPremultiplied) {
1500 gray *= (alp * (1.0f / 255.0f));
1501 }
1502 }
1503 intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
1504 } else if (is_ICCGray_stdScale) {
1505 red = fromsRGB8LUT16[red] & 0xffff;
1506 grn = fromsRGB8LUT16[grn] & 0xffff;
1507 blu = fromsRGB8LUT16[blu] & 0xffff;
1508 int gray16 = (int) ((0.2125f * red) + (0.7154f * grn)
1509 + (0.0721f * blu) + 0.5f);
1510 float gray = (fromLinearGray16ToOtherGray16LUT[gray16] & 0xffff) / 65535.0f;
1511 if (supportsAlpha) {
1512 alp = (rgb >> 24) & 0xff;
1513 if (nBits[1] == 8) {
1514 intpixel[1] = alp;
1515 } else {
1516 intpixel[1] = (int) (alp * (1.0f / 255.0f)
1517 * ((1 << nBits[1]) - 1) + 0.5f);
1518 }
1519 if (isAlphaPremultiplied) {
1520 gray *= (alp * (1.0f / 255.0f));
1521 }
1522 }
1523 intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
1524 } else {
1525 // Need to convert the color
1526 float[] norm = new float[3];
1527 float factor = 1.0f / 255.0f;
1528 norm[0] = red * factor;
1529 norm[1] = grn * factor;
1530 norm[2] = blu * factor;
1531 norm = colorSpace.fromRGB(norm);
1532 if (nonStdScale) {
1533 for (int i = 0; i < numColorComponents; i++) {
1534 norm[i] = (norm[i] - compOffset[i]) * compScale[i];
1535 // REMIND: need to analyze whether this
1536 // clamping is necessary
1537 if (norm[i] < 0.0f) {
1538 norm[i] = 0.0f;
1539 }
1540 if (norm[i] > 1.0f) {
1541 norm[i] = 1.0f;
1542 }
1543 }
1544 }
1545 if (supportsAlpha) {
1546 alp = (rgb >> 24) & 0xff;
1547 if (nBits[numColorComponents] == 8) {
1548 intpixel[numColorComponents] = alp;
1549 } else {
1550 intpixel[numColorComponents] = (int) (alp * factor
1551 * ((1 << nBits[numColorComponents]) - 1) + 0.5f);
1552 }
1553 if (isAlphaPremultiplied) {
1554 factor *= alp;
1555 for (int i = 0; i < numColorComponents; i++) {
1556 norm[i] *= factor;
1557 }
1558 }
1559 }
1560 for (int i = 0; i < numColorComponents; i++) {
1561 intpixel[i] = (int) (norm[i] * ((1 << nBits[i]) - 1) + 0.5f);
1562 }
1563 }
1564
1565 switch (transferType) {
1566 case DataBuffer.TYPE_BYTE: {
1567 byte bdata[];
1568 if (pixel == null) {
1569 bdata = new byte[numComponents];
1570 } else {
1571 bdata = (byte[]) pixel;
1572 }
1573 for (int i = 0; i < numComponents; i++) {
1574 bdata[i] = (byte) (0xff & intpixel[i]);
1575 }
1576 return bdata;
1577 }
1578 case DataBuffer.TYPE_USHORT: {
1579 short sdata[];
1580 if (pixel == null) {
1581 sdata = new short[numComponents];
1582 } else {
1583 sdata = (short[]) pixel;
1584 }
1585 for (int i = 0; i < numComponents; i++) {
1586 sdata[i] = (short) (intpixel[i] & 0xffff);
1587 }
1588 return sdata;
1589 }
1590 case DataBuffer.TYPE_INT:
1591 if (maxBits > 23) {
1592 // fix 4412670 - for components of 24 or more bits
1593 // some calculations done above with float precision
1594 // may lose enough precision that the integer result
1595 // overflows nBits, so we need to clamp.
1596 for (int i = 0; i < numComponents; i++) {
1597 if (intpixel[i] > ((1 << nBits[i]) - 1)) {
1598 intpixel[i] = (1 << nBits[i]) - 1;
1599 }
1600 }
1601 }
1602 return intpixel;
1603 }
1604 throw new IllegalArgumentException("This method has not been "
1605 + "implemented for transferType " + transferType);
1606 }
1607
1608 /** Returns an array of unnormalized color/alpha components given a pixel
1609 * in this <CODE>ColorModel</CODE>.
1610 * An IllegalArgumentException is thrown if the component value for this
1611 * <CODE>ColorModel</CODE> is not conveniently representable in the
1612 * unnormalized form. Color/alpha components are stored
1613 * in the <CODE>components</CODE> array starting at <CODE>offset</CODE>
1614 * (even if the array is allocated by this method).
1615 *
1616 * @param pixel The pixel value specified as an integer.
1617 * @param components An integer array in which to store the unnormalized
1618 * color/alpha components. If the <CODE>components</CODE> array is null,
1619 * a new array is allocated.
1620 * @param offset An offset into the <CODE>components</CODE> array.
1621 *
1622 * @return The components array.
1623 *
1624 * @throws IllegalArgumentException If there is more than one
1625 * component in this <CODE>ColorModel</CODE>.
1626 * @throws IllegalArgumentException If this
1627 * <CODE>ColorModel</CODE> does not support the unnormalized form
1628 * @throws ArrayIndexOutOfBoundsException If the <CODE>components</CODE>
1629 * array is not null and is not large enough to hold all the color and
1630 * alpha components (starting at offset).
1631 */
1632 public int[] getComponents(int pixel, int[] components, int offset) {
1633 if (numComponents > 1) {
1634 throw new IllegalArgumentException(
1635 "More than one component per pixel");
1636 }
1637 if (needScaleInit) {
1638 initScale();
1639 }
1640 if (noUnnorm) {
1641 throw new IllegalArgumentException(
1642 "This ColorModel does not support the unnormalized form");
1643 }
1644 if (components == null) {
1645 components = new int[offset + 1];
1646 }
1647
1648 components[offset + 0] = (pixel & ((1 << nBits[0]) - 1));
1649 return components;
1650 }
1651
1652 /**
1653 * Returns an array of unnormalized color/alpha components given a pixel
1654 * in this <CODE>ColorModel</CODE>. The pixel value is specified by an
1655 * array of data elements of type <CODE>transferType</CODE> passed in as
1656 * an object reference.
1657 * An IllegalArgumentException is thrown if the component values for this
1658 * <CODE>ColorModel</CODE> are not conveniently representable in the
1659 * unnormalized form.
1660 * Color/alpha components are stored in the <CODE>components</CODE> array
1661 * starting at <CODE>offset</CODE> (even if the array is allocated by
1662 * this method). Since <code>ComponentColorModel</code> can be
1663 * subclassed, subclasses inherit the
1664 * implementation of this method and if they don't override it then
1665 * this method might throw an exception if they use an unsupported
1666 * <code>transferType</code>.
1667 *
1668 * @param pixel A pixel value specified by an array of data elements of
1669 * type <CODE>transferType</CODE>.
1670 * @param components An integer array in which to store the unnormalized
1671 * color/alpha components. If the <CODE>components</CODE> array is null,
1672 * a new array is allocated.
1673 * @param offset An offset into the <CODE>components</CODE> array.
1674 *
1675 * @return The <CODE>components</CODE> array.
1676 *
1677 * @throws IllegalArgumentException If this
1678 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1679 * @throws UnsupportedOperationException in some cases iff the
1680 * transfer type of this <CODE>ComponentColorModel</CODE>
1681 * is not one of the following transfer types:
1682 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1683 * or <CODE>DataBuffer.TYPE_INT</CODE>.
1684 * @throws ClassCastException If <CODE>pixel</CODE> is not a primitive
1685 * array of type <CODE>transferType</CODE>.
1686 * @throws IllegalArgumentException If the <CODE>components</CODE> array is
1687 * not null and is not large enough to hold all the color and alpha
1688 * components (starting at offset), or if <CODE>pixel</CODE> is not large
1689 * enough to hold a pixel value for this ColorModel.
1690 */
1691 public int[] getComponents(Object pixel, int[] components,
1692 int offset) {
1693 int intpixel[];
1694 if (needScaleInit) {
1695 initScale();
1696 }
1697 if (noUnnorm) {
1698 throw new IllegalArgumentException(
1699 "This ColorModel does not support the unnormalized form");
1700 }
1701 if (pixel instanceof int[]) {
1702 intpixel = (int[]) pixel;
1703 } else {
1704 intpixel = DataBuffer.toIntArray(pixel);
1705 if (intpixel == null) {
1706 throw new UnsupportedOperationException(
1707 "This method has not been "
1708 + "implemented for transferType "
1709 + transferType);
1710 }
1711 }
1712 if (intpixel.length < numComponents) {
1713 throw new IllegalArgumentException(
1714 "Length of pixel array < number of components in model");
1715 }
1716 if (components == null) {
1717 components = new int[offset + numComponents];
1718 } else if ((components.length - offset) < numComponents) {
1719 throw new IllegalArgumentException(
1720 "Length of components array < number of components in model");
1721 }
1722 System
1723 .arraycopy(intpixel, 0, components, offset,
1724 numComponents);
1725
1726 return components;
1727 }
1728
1729 /**
1730 * Returns an array of all of the color/alpha components in unnormalized
1731 * form, given a normalized component array. Unnormalized components
1732 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1733 * n is the number of bits for a particular component. Normalized
1734 * components are float values between a per component minimum and
1735 * maximum specified by the <code>ColorSpace</code> object for this
1736 * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
1737 * will be thrown if color component values for this
1738 * <code>ColorModel</code> are not conveniently representable in the
1739 * unnormalized form. If the
1740 * <code>components</code> array is <code>null</code>, a new array
1741 * will be allocated. The <code>components</code> array will
1742 * be returned. Color/alpha components are stored in the
1743 * <code>components</code> array starting at <code>offset</code> (even
1744 * if the array is allocated by this method). An
1745 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1746 * <code>components</code> array is not <code>null</code> and is not
1747 * large enough to hold all the color and alpha
1748 * components (starting at <code>offset</code>). An
1749 * <code>IllegalArgumentException</code> is thrown if the
1750 * <code>normComponents</code> array is not large enough to hold
1751 * all the color and alpha components starting at
1752 * <code>normOffset</code>.
1753 * @param normComponents an array containing normalized components
1754 * @param normOffset the offset into the <code>normComponents</code>
1755 * array at which to start retrieving normalized components
1756 * @param components an array that receives the components from
1757 * <code>normComponents</code>
1758 * @param offset the index into <code>components</code> at which to
1759 * begin storing normalized components from
1760 * <code>normComponents</code>
1761 * @return an array containing unnormalized color and alpha
1762 * components.
1763 * @throws IllegalArgumentException If this
1764 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1765 * @throws IllegalArgumentException if the length of
1766 * <code>normComponents</code> minus <code>normOffset</code>
1767 * is less than <code>numComponents</code>
1768 */
1769 public int[] getUnnormalizedComponents(float[] normComponents,
1770 int normOffset, int[] components, int offset) {
1771 if (needScaleInit) {
1772 initScale();
1773 }
1774 if (noUnnorm) {
1775 throw new IllegalArgumentException(
1776 "This ColorModel does not support the unnormalized form");
1777 }
1778 return super .getUnnormalizedComponents(normComponents,
1779 normOffset, components, offset);
1780 }
1781
1782 /**
1783 * Returns an array of all of the color/alpha components in normalized
1784 * form, given an unnormalized component array. Unnormalized components
1785 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1786 * n is the number of bits for a particular component. Normalized
1787 * components are float values between a per component minimum and
1788 * maximum specified by the <code>ColorSpace</code> object for this
1789 * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
1790 * will be thrown if color component values for this
1791 * <code>ColorModel</code> are not conveniently representable in the
1792 * unnormalized form. If the
1793 * <code>normComponents</code> array is <code>null</code>, a new array
1794 * will be allocated. The <code>normComponents</code> array
1795 * will be returned. Color/alpha components are stored in the
1796 * <code>normComponents</code> array starting at
1797 * <code>normOffset</code> (even if the array is allocated by this
1798 * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
1799 * if the <code>normComponents</code> array is not <code>null</code>
1800 * and is not large enough to hold all the color and alpha components
1801 * (starting at <code>normOffset</code>). An
1802 * <code>IllegalArgumentException</code> is thrown if the
1803 * <code>components</code> array is not large enough to hold all the
1804 * color and alpha components starting at <code>offset</code>.
1805 * @param components an array containing unnormalized components
1806 * @param offset the offset into the <code>components</code> array at
1807 * which to start retrieving unnormalized components
1808 * @param normComponents an array that receives the normalized components
1809 * @param normOffset the index into <code>normComponents</code> at
1810 * which to begin storing normalized components
1811 * @return an array containing normalized color and alpha
1812 * components.
1813 * @throws IllegalArgumentException If this
1814 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1815 */
1816 public float[] getNormalizedComponents(int[] components,
1817 int offset, float[] normComponents, int normOffset) {
1818 if (needScaleInit) {
1819 initScale();
1820 }
1821 if (noUnnorm) {
1822 throw new IllegalArgumentException(
1823 "This ColorModel does not support the unnormalized form");
1824 }
1825 return super .getNormalizedComponents(components, offset,
1826 normComponents, normOffset);
1827 }
1828
1829 /**
1830 * Returns a pixel value represented as an int in this <CODE>ColorModel</CODE>,
1831 * given an array of unnormalized color/alpha components.
1832 *
1833 * @param components An array of unnormalized color/alpha components.
1834 * @param offset An offset into the <CODE>components</CODE> array.
1835 *
1836 * @return A pixel value represented as an int.
1837 *
1838 * @throws IllegalArgumentException If there is more than one component
1839 * in this <CODE>ColorModel</CODE>.
1840 * @throws IllegalArgumentException If this
1841 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1842 */
1843 public int getDataElement(int[] components, int offset) {
1844 if (needScaleInit) {
1845 initScale();
1846 }
1847 if (numComponents == 1) {
1848 if (noUnnorm) {
1849 throw new IllegalArgumentException(
1850 "This ColorModel does not support the unnormalized form");
1851 }
1852 return components[offset + 0];
1853 }
1854 throw new IllegalArgumentException("This model returns "
1855 + numComponents + " elements in the pixel array.");
1856 }
1857
1858 /**
1859 * Returns a data element array representation of a pixel in this
1860 * <CODE>ColorModel</CODE>, given an array of unnormalized color/alpha
1861 * components. This array can then be passed to the <CODE>setDataElements</CODE>
1862 * method of a <CODE>WritableRaster</CODE> object.
1863 *
1864 * @param components An array of unnormalized color/alpha components.
1865 * @param offset The integer offset into the <CODE>components</CODE> array.
1866 * @param obj The object in which to store the data element array
1867 * representation of the pixel. If <CODE>obj</CODE> variable is null,
1868 * a new array is allocated. If <CODE>obj</CODE> is not null, it must
1869 * be a primitive array of type <CODE>transferType</CODE>. An
1870 * <CODE>ArrayIndexOutOfBoundsException</CODE> is thrown if
1871 * <CODE>obj</CODE> is not large enough to hold a pixel value
1872 * for this <CODE>ColorModel</CODE>. Since
1873 * <code>ComponentColorModel</code> can be subclassed, subclasses
1874 * inherit the implementation of this method and if they don't
1875 * override it then they throw an exception if they use an
1876 * unsupported <code>transferType</code>.
1877 *
1878 * @return The data element array representation of a pixel
1879 * in this <CODE>ColorModel</CODE>.
1880 *
1881 * @throws IllegalArgumentException If the components array
1882 * is not large enough to hold all the color and alpha components
1883 * (starting at offset).
1884 * @throws ClassCastException If <CODE>obj</CODE> is not null and is not a
1885 * primitive array of type <CODE>transferType</CODE>.
1886 * @throws ArrayIndexOutOfBoundsException If <CODE>obj</CODE> is not large
1887 * enough to hold a pixel value for this <CODE>ColorModel</CODE>.
1888 * @throws IllegalArgumentException If this
1889 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1890 * @throws UnsupportedOperationException If the transfer type of
1891 * this <CODE>ComponentColorModel</CODE>
1892 * is not one of the following transfer types:
1893 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1894 * or <CODE>DataBuffer.TYPE_INT</CODE>.
1895 *
1896 * @see WritableRaster#setDataElements
1897 * @see SampleModel#setDataElements
1898 */
1899 public Object getDataElements(int[] components, int offset,
1900 Object obj) {
1901 if (needScaleInit) {
1902 initScale();
1903 }
1904 if (noUnnorm) {
1905 throw new IllegalArgumentException(
1906 "This ColorModel does not support the unnormalized form");
1907 }
1908 if ((components.length - offset) < numComponents) {
1909 throw new IllegalArgumentException(
1910 "Component array too small" + " (should be "
1911 + numComponents);
1912 }
1913 switch (transferType) {
1914 case DataBuffer.TYPE_INT: {
1915 int[] pixel;
1916 if (obj == null) {
1917 pixel = new int[numComponents];
1918 } else {
1919 pixel = (int[]) obj;
1920 }
1921 System.arraycopy(components, offset, pixel, 0,
1922 numComponents);
1923 return pixel;
1924 }
1925
1926 case DataBuffer.TYPE_BYTE: {
1927 byte[] pixel;
1928 if (obj == null) {
1929 pixel = new byte[numComponents];
1930 } else {
1931 pixel = (byte[]) obj;
1932 }
1933 for (int i = 0; i < numComponents; i++) {
1934 pixel[i] = (byte) (components[offset + i] & 0xff);
1935 }
1936 return pixel;
1937 }
1938
1939 case DataBuffer.TYPE_USHORT: {
1940 short[] pixel;
1941 if (obj == null) {
1942 pixel = new short[numComponents];
1943 } else {
1944 pixel = (short[]) obj;
1945 }
1946 for (int i = 0; i < numComponents; i++) {
1947 pixel[i] = (short) (components[offset + i] & 0xffff);
1948 }
1949 return pixel;
1950 }
1951
1952 default:
1953 throw new UnsupportedOperationException(
1954 "This method has not been "
1955 + "implemented for transferType "
1956 + transferType);
1957 }
1958 }
1959
1960 /**
1961 * Returns a pixel value represented as an <code>int</code> in this
1962 * <code>ColorModel</code>, given an array of normalized color/alpha
1963 * components. This method will throw an
1964 * <code>IllegalArgumentException</code> if pixel values for this
1965 * <code>ColorModel</code> are not conveniently representable as a
1966 * single <code>int</code>. An
1967 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1968 * <code>normComponents</code> array is not large enough to hold all the
1969 * color and alpha components (starting at <code>normOffset</code>).
1970 * @param normComponents an array of normalized color and alpha
1971 * components
1972 * @param normOffset the index into <code>normComponents</code> at which to
1973 * begin retrieving the color and alpha components
1974 * @return an <code>int</code> pixel value in this
1975 * <code>ColorModel</code> corresponding to the specified components.
1976 * @throws IllegalArgumentException if
1977 * pixel values for this <code>ColorModel</code> are not
1978 * conveniently representable as a single <code>int</code>
1979 * @throws ArrayIndexOutOfBoundsException if
1980 * the <code>normComponents</code> array is not large enough to
1981 * hold all of the color and alpha components starting at
1982 * <code>normOffset</code>
1983 * @since 1.4
1984 */
1985 public int getDataElement(float[] normComponents, int normOffset) {
1986 if (numComponents > 1) {
1987 throw new IllegalArgumentException(
1988 "More than one component per pixel");
1989 }
1990 if (signed) {
1991 throw new IllegalArgumentException(
1992 "Component value is signed");
1993 }
1994 if (needScaleInit) {
1995 initScale();
1996 }
1997 Object pixel = getDataElements(normComponents, normOffset, null);
1998 switch (transferType) {
1999 case DataBuffer.TYPE_BYTE: {
2000 byte bpixel[] = (byte[]) pixel;
2001 return bpixel[0] & 0xff;
2002 }
2003 case DataBuffer.TYPE_USHORT: {
2004 short[] uspixel = (short[]) pixel;
2005 return uspixel[0] & 0xffff;
2006 }
2007 case DataBuffer.TYPE_INT: {
2008 int[] ipixel = (int[]) pixel;
2009 return ipixel[0];
2010 }
2011 default:
2012 throw new UnsupportedOperationException(
2013 "This method has not been "
2014 + "implemented for transferType "
2015 + transferType);
2016 }
2017 }
2018
2019 /**
2020 * Returns a data element array representation of a pixel in this
2021 * <code>ColorModel</code>, given an array of normalized color/alpha
2022 * components. This array can then be passed to the
2023 * <code>setDataElements</code> method of a <code>WritableRaster</code>
2024 * object. An <code>ArrayIndexOutOfBoundsException</code> is thrown
2025 * if the <code>normComponents</code> array is not large enough to hold
2026 * all the color and alpha components (starting at
2027 * <code>normOffset</code>). If the <code>obj</code> variable is
2028 * <code>null</code>, a new array will be allocated. If
2029 * <code>obj</code> is not <code>null</code>, it must be a primitive
2030 * array of type transferType; otherwise, a
2031 * <code>ClassCastException</code> is thrown. An
2032 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
2033 * <code>obj</code> is not large enough to hold a pixel value for this
2034 * <code>ColorModel</code>.
2035 * @param normComponents an array of normalized color and alpha
2036 * components
2037 * @param normOffset the index into <code>normComponents</code> at which to
2038 * begin retrieving color and alpha components
2039 * @param obj a primitive data array to hold the returned pixel
2040 * @return an <code>Object</code> which is a primitive data array
2041 * representation of a pixel
2042 * @throws ClassCastException if <code>obj</code>
2043 * is not a primitive array of type <code>transferType</code>
2044 * @throws ArrayIndexOutOfBoundsException if
2045 * <code>obj</code> is not large enough to hold a pixel value
2046 * for this <code>ColorModel</code> or the <code>normComponents</code>
2047 * array is not large enough to hold all of the color and alpha
2048 * components starting at <code>normOffset</code>
2049 * @see WritableRaster#setDataElements
2050 * @see SampleModel#setDataElements
2051 * @since 1.4
2052 */
2053 public Object getDataElements(float[] normComponents,
2054 int normOffset, Object obj) {
2055 boolean needAlpha = supportsAlpha && isAlphaPremultiplied;
2056 float[] stdNormComponents;
2057 if (needScaleInit) {
2058 initScale();
2059 }
2060 if (nonStdScale) {
2061 stdNormComponents = new float[numComponents];
2062 for (int c = 0, nc = normOffset; c < numColorComponents; c++, nc++) {
2063 stdNormComponents[c] = (normComponents[nc] - compOffset[c])
2064 * compScale[c];
2065 // REMIND: need to analyze whether this
2066 // clamping is necessary
2067 if (stdNormComponents[c] < 0.0f) {
2068 stdNormComponents[c] = 0.0f;
2069 }
2070 if (stdNormComponents[c] > 1.0f) {
2071 stdNormComponents[c] = 1.0f;
2072 }
2073 }
2074 if (supportsAlpha) {
2075 stdNormComponents[numColorComponents] = normComponents[numColorComponents
2076 + normOffset];
2077 }
2078 normOffset = 0;
2079 } else {
2080 stdNormComponents = normComponents;
2081 }
2082 switch (transferType) {
2083 case DataBuffer.TYPE_BYTE:
2084 byte[] bpixel;
2085 if (obj == null) {
2086 bpixel = new byte[numComponents];
2087 } else {
2088 bpixel = (byte[]) obj;
2089 }
2090 if (needAlpha) {
2091 float alpha = stdNormComponents[numColorComponents
2092 + normOffset];
2093 for (int c = 0, nc = normOffset; c < numColorComponents; c++, nc++) {
2094 bpixel[c] = (byte) ((stdNormComponents[nc] * alpha)
2095 * ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2096 }
2097 bpixel[numColorComponents] = (byte) (alpha
2098 * ((float) ((1 << nBits[numColorComponents]) - 1)) + 0.5f);
2099 } else {
2100 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2101 bpixel[c] = (byte) (stdNormComponents[nc]
2102 * ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2103 }
2104 }
2105 return bpixel;
2106 case DataBuffer.TYPE_USHORT:
2107 short[] uspixel;
2108 if (obj == null) {
2109 uspixel = new short[numComponents];
2110 } else {
2111 uspixel = (short[]) obj;
2112 }
2113 if (needAlpha) {
2114 float alpha = stdNormComponents[numColorComponents
2115 + normOffset];
2116 for (int c = 0, nc = normOffset; c < numColorComponents; c++, nc++) {
2117 uspixel[c] = (short) ((stdNormComponents[nc] * alpha)
2118 * ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2119 }
2120 uspixel[numColorComponents] = (short) (alpha
2121 * ((float) ((1 << nBits[numColorComponents]) - 1)) + 0.5f);
2122 } else {
2123 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2124 uspixel[c] = (short) (stdNormComponents[nc]
2125 * ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2126 }
2127 }
2128 return uspixel;
2129 case DataBuffer.TYPE_INT:
2130 int[] ipixel;
2131 if (obj == null) {
2132 ipixel = new int[numComponents];
2133 } else {
2134 ipixel = (int[]) obj;
2135 }
2136 if (needAlpha) {
2137 float alpha = stdNormComponents[numColorComponents
2138 + normOffset];
2139 for (int c = 0, nc = normOffset; c < numColorComponents; c++, nc++) {
2140 ipixel[c] = (int) ((stdNormComponents[nc] * alpha)
2141 * ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2142 }
2143 ipixel[numColorComponents] = (int) (alpha
2144 * ((float) ((1 << nBits[numColorComponents]) - 1)) + 0.5f);
2145 } else {
2146 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2147 ipixel[c] = (int) (stdNormComponents[nc]
2148 * ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2149 }
2150 }
2151 return ipixel;
2152 case DataBuffer.TYPE_SHORT:
2153 short[] spixel;
2154 if (obj == null) {
2155 spixel = new short[numComponents];
2156 } else {
2157 spixel = (short[]) obj;
2158 }
2159 if (needAlpha) {
2160 float alpha = stdNormComponents[numColorComponents
2161 + normOffset];
2162 for (int c = 0, nc = normOffset; c < numColorComponents; c++, nc++) {
2163 spixel[c] = (short) (stdNormComponents[nc] * alpha
2164 * 32767.0f + 0.5f);
2165 }
2166 spixel[numColorComponents] = (short) (alpha * 32767.0f + 0.5f);
2167 } else {
2168 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2169 spixel[c] = (short) (stdNormComponents[nc] * 32767.0f + 0.5f);
2170 }
2171 }
2172 return spixel;
2173 case DataBuffer.TYPE_FLOAT:
2174 float[] fpixel;
2175 if (obj == null) {
2176 fpixel = new float[numComponents];
2177 } else {
2178 fpixel = (float[]) obj;
2179 }
2180 if (needAlpha) {
2181 float alpha = normComponents[numColorComponents
2182 + normOffset];
2183 for (int c = 0, nc = normOffset; c < numColorComponents; c++, nc++) {
2184 fpixel[c] = normComponents[nc] * alpha;
2185 }
2186 fpixel[numColorComponents] = alpha;
2187 } else {
2188 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2189 fpixel[c] = normComponents[nc];
2190 }
2191 }
2192 return fpixel;
2193 case DataBuffer.TYPE_DOUBLE:
2194 double[] dpixel;
2195 if (obj == null) {
2196 dpixel = new double[numComponents];
2197 } else {
2198 dpixel = (double[]) obj;
2199 }
2200 if (needAlpha) {
2201 double alpha = (double) (normComponents[numColorComponents
2202 + normOffset]);
2203 for (int c = 0, nc = normOffset; c < numColorComponents; c++, nc++) {
2204 dpixel[c] = normComponents[nc] * alpha;
2205 }
2206 dpixel[numColorComponents] = alpha;
2207 } else {
2208 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2209 dpixel[c] = (double) normComponents[nc];
2210 }
2211 }
2212 return dpixel;
2213 default:
2214 throw new UnsupportedOperationException(
2215 "This method has not been "
2216 + "implemented for transferType "
2217 + transferType);
2218 }
2219 }
2220
2221 /**
2222 * Returns an array of all of the color/alpha components in normalized
2223 * form, given a pixel in this <code>ColorModel</code>. The pixel
2224 * value is specified by an array of data elements of type transferType
2225 * passed in as an object reference. If pixel is not a primitive array
2226 * of type transferType, a <code>ClassCastException</code> is thrown.
2227 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
2228 * <code>pixel</code> is not large enough to hold a pixel value for this
2229 * <code>ColorModel</code>.
2230 * Normalized components are float values between a per component minimum
2231 * and maximum specified by the <code>ColorSpace</code> object for this
2232 * <code>ColorModel</code>. If the
2233 * <code>normComponents</code> array is <code>null</code>, a new array
2234 * will be allocated. The <code>normComponents</code> array
2235 * will be returned. Color/alpha components are stored in the
2236 * <code>normComponents</code> array starting at
2237 * <code>normOffset</code> (even if the array is allocated by this
2238 * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
2239 * if the <code>normComponents</code> array is not <code>null</code>
2240 * and is not large enough to hold all the color and alpha components
2241 * (starting at <code>normOffset</code>).
2242 * <p>
2243 * This method must be overrridden by a subclass if that subclass
2244 * is designed to translate pixel sample values to color component values
2245 * in a non-default way. The default translations implemented by this
2246 * class is described in the class comments. Any subclass implementing
2247 * a non-default translation must follow the constraints on allowable
2248 * translations defined there.
2249 * @param pixel the specified pixel
2250 * @param normComponents an array to receive the normalized components
2251 * @param normOffset the offset into the <code>normComponents</code>
2252 * array at which to start storing normalized components
2253 * @return an array containing normalized color and alpha
2254 * components.
2255 * @throws ClassCastException if <code>pixel</code> is not a primitive
2256 * array of type transferType
2257 * @throws ArrayIndexOutOfBoundsException if
2258 * <code>normComponents</code> is not large enough to hold all
2259 * color and alpha components starting at <code>normOffset</code>
2260 * @throws ArrayIndexOutOfBoundsException if
2261 * <code>pixel</code> is not large enough to hold a pixel
2262 * value for this <code>ColorModel</code>.
2263 * @since 1.4
2264 */
2265 public float[] getNormalizedComponents(Object pixel,
2266 float[] normComponents, int normOffset) {
2267 if (normComponents == null) {
2268 normComponents = new float[numComponents + normOffset];
2269 }
2270 switch (transferType) {
2271 case DataBuffer.TYPE_BYTE:
2272 byte[] bpixel = (byte[]) pixel;
2273 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2274 normComponents[nc] = ((float) (bpixel[c] & 0xff))
2275 / ((float) ((1 << nBits[c]) - 1));
2276 }
2277 break;
2278 case DataBuffer.TYPE_USHORT:
2279 short[] uspixel = (short[]) pixel;
2280 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2281 normComponents[nc] = ((float) (uspixel[c] & 0xffff))
2282 / ((float) ((1 << nBits[c]) - 1));
2283 }
2284 break;
2285 case DataBuffer.TYPE_INT:
2286 int[] ipixel = (int[]) pixel;
2287 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2288 normComponents[nc] = ((float) ipixel[c])
2289 / ((float) ((1 << nBits[c]) - 1));
2290 }
2291 break;
2292 case DataBuffer.TYPE_SHORT:
2293 short[] spixel = (short[]) pixel;
2294 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2295 normComponents[nc] = ((float) spixel[c]) / 32767.0f;
2296 }
2297 break;
2298 case DataBuffer.TYPE_FLOAT:
2299 float[] fpixel = (float[]) pixel;
2300 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2301 normComponents[nc] = fpixel[c];
2302 }
2303 break;
2304 case DataBuffer.TYPE_DOUBLE:
2305 double[] dpixel = (double[]) pixel;
2306 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2307 normComponents[nc] = (float) dpixel[c];
2308 }
2309 break;
2310 default:
2311 throw new UnsupportedOperationException(
2312 "This method has not been "
2313 + "implemented for transferType "
2314 + transferType);
2315 }
2316
2317 if (supportsAlpha && isAlphaPremultiplied) {
2318 float alpha = normComponents[numColorComponents
2319 + normOffset];
2320 if (alpha != 0.0f) {
2321 float invAlpha = 1.0f / alpha;
2322 for (int c = normOffset; c < numColorComponents
2323 + normOffset; c++) {
2324 normComponents[c] *= invAlpha;
2325 }
2326 }
2327 }
2328 if (min != null) {
2329 // Normally (i.e. when this class is not subclassed to override
2330 // this method), the test (min != null) will be equivalent to
2331 // the test (nonStdScale). However, there is an unlikely, but
2332 // possible case, in which this method is overridden, nonStdScale
2333 // is set true by initScale(), the subclass method for some
2334 // reason calls this superclass method, but the min and
2335 // diffMinMax arrays were never initialized by setupLUTs(). In
2336 // that case, the right thing to do is follow the intended
2337 // semantics of this method, and rescale the color components
2338 // only if the ColorSpace min/max were detected to be other
2339 // than 0.0/1.0 by setupLUTs(). Note that this implies the
2340 // transferType is byte, ushort, int, or short - i.e. components
2341 // derived from float and double pixel data are never rescaled.
2342 for (int c = 0; c < numColorComponents; c++) {
2343 normComponents[c + normOffset] = min[c] + diffMinMax[c]
2344 * normComponents[c + normOffset];
2345 }
2346 }
2347 return normComponents;
2348 }
2349
2350 /**
2351 * Forces the raster data to match the state specified in the
2352 * <CODE>isAlphaPremultiplied</CODE> variable, assuming the data
2353 * is currently correctly described by this <CODE>ColorModel</CODE>.
2354 * It may multiply or divide the color raster data by alpha, or
2355 * do nothing if the data is in the correct state. If the data needs
2356 * to be coerced, this method also returns an instance of
2357 * this <CODE>ColorModel</CODE> with
2358 * the <CODE>isAlphaPremultiplied</CODE> flag set appropriately.
2359 * Since <code>ColorModel</code> can be subclassed, subclasses inherit
2360 * the implementation of this method and if they don't override it
2361 * then they throw an exception if they use an unsupported
2362 * <code>transferType</code>.
2363 *
2364 * @throws NullPointerException if <code>raster</code> is
2365 * <code>null</code> and data coercion is required.
2366 * @throws UnsupportedOperationException if the transfer type of
2367 * this <CODE>ComponentColorModel</CODE>
2368 * is not one of the supported transfer types:
2369 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
2370 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
2371 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
2372 */
2373 public ColorModel coerceData(WritableRaster raster,
2374 boolean isAlphaPremultiplied) {
2375 if ((supportsAlpha == false)
2376 || (this .isAlphaPremultiplied == isAlphaPremultiplied)) {
2377 // Nothing to do
2378 return this ;
2379 }
2380
2381 int w = raster.getWidth();
2382 int h = raster.getHeight();
2383 int aIdx = raster.getNumBands() - 1;
2384 float normAlpha;
2385 int rminX = raster.getMinX();
2386 int rY = raster.getMinY();
2387 int rX;
2388 if (isAlphaPremultiplied) {
2389 switch (transferType) {
2390 case DataBuffer.TYPE_BYTE: {
2391 byte pixel[] = null;
2392 byte zpixel[] = null;
2393 float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
2394 for (int y = 0; y < h; y++, rY++) {
2395 rX = rminX;
2396 for (int x = 0; x < w; x++, rX++) {
2397 pixel = (byte[]) raster.getDataElements(rX, rY,
2398 pixel);
2399 normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
2400 if (normAlpha != 0.0f) {
2401 for (int c = 0; c < aIdx; c++) {
2402 pixel[c] = (byte) ((pixel[c] & 0xff)
2403 * normAlpha + 0.5f);
2404 }
2405 raster.setDataElements(rX, rY, pixel);
2406 } else {
2407 if (zpixel == null) {
2408 zpixel = new byte[numComponents];
2409 java.util.Arrays.fill(zpixel, (byte) 0);
2410 }
2411 raster.setDataElements(rX, rY, zpixel);
2412 }
2413 }
2414 }
2415 }
2416 break;
2417 case DataBuffer.TYPE_USHORT: {
2418 short pixel[] = null;
2419 short zpixel[] = null;
2420 float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
2421 for (int y = 0; y < h; y++, rY++) {
2422 rX = rminX;
2423 for (int x = 0; x < w; x++, rX++) {
2424 pixel = (short[]) raster.getDataElements(rX,
2425 rY, pixel);
2426 normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
2427 if (normAlpha != 0.0f) {
2428 for (int c = 0; c < aIdx; c++) {
2429 pixel[c] = (short) ((pixel[c] & 0xffff)
2430 * normAlpha + 0.5f);
2431 }
2432 raster.setDataElements(rX, rY, pixel);
2433 } else {
2434 if (zpixel == null) {
2435 zpixel = new short[numComponents];
2436 java.util.Arrays
2437 .fill(zpixel, (short) 0);
2438 }
2439 raster.setDataElements(rX, rY, zpixel);
2440 }
2441 }
2442 }
2443 }
2444 break;
2445 case DataBuffer.TYPE_INT: {
2446 int pixel[] = null;
2447 int zpixel[] = null;
2448 float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
2449 for (int y = 0; y < h; y++, rY++) {
2450 rX = rminX;
2451 for (int x = 0; x < w; x++, rX++) {
2452 pixel = (int[]) raster.getDataElements(rX, rY,
2453 pixel);
2454 normAlpha = pixel[aIdx] * alphaScale;
2455 if (normAlpha != 0.0f) {
2456 for (int c = 0; c < aIdx; c++) {
2457 pixel[c] = (int) (pixel[c] * normAlpha + 0.5f);
2458 }
2459 raster.setDataElements(rX, rY, pixel);
2460 } else {
2461 if (zpixel == null) {
2462 zpixel = new int[numComponents];
2463 java.util.Arrays.fill(zpixel, 0);
2464 }
2465 raster.setDataElements(rX, rY, zpixel);
2466 }
2467 }
2468 }
2469 }
2470 break;
2471 case DataBuffer.TYPE_SHORT: {
2472 short pixel[] = null;
2473 short zpixel[] = null;
2474 float alphaScale = 1.0f / 32767.0f;
2475 for (int y = 0; y < h; y++, rY++) {
2476 rX = rminX;
2477 for (int x = 0; x < w; x++, rX++) {
2478 pixel = (short[]) raster.getDataElements(rX,
2479 rY, pixel);
2480 normAlpha = pixel[aIdx] * alphaScale;
2481 if (normAlpha != 0.0f) {
2482 for (int c = 0; c < aIdx; c++) {
2483 pixel[c] = (short) (pixel[c]
2484 * normAlpha + 0.5f);
2485 }
2486 raster.setDataElements(rX, rY, pixel);
2487 } else {
2488 if (zpixel == null) {
2489 zpixel = new short[numComponents];
2490 java.util.Arrays
2491 .fill(zpixel, (short) 0);
2492 }
2493 raster.setDataElements(rX, rY, zpixel);
2494 }
2495 }
2496 }
2497 }
2498 break;
2499 case DataBuffer.TYPE_FLOAT: {
2500 float pixel[] = null;
2501 float zpixel[] = null;
2502 for (int y = 0; y < h; y++, rY++) {
2503 rX = rminX;
2504 for (int x = 0; x < w; x++, rX++) {
2505 pixel = (float[]) raster.getDataElements(rX,
2506 rY, pixel);
2507 normAlpha = pixel[aIdx];
2508 if (normAlpha != 0.0f) {
2509 for (int c = 0; c < aIdx; c++) {
2510 pixel[c] *= normAlpha;
2511 }
2512 raster.setDataElements(rX, rY, pixel);
2513 } else {
2514 if (zpixel == null) {
2515 zpixel = new float[numComponents];
2516 java.util.Arrays.fill(zpixel, 0.0f);
2517 }
2518 raster.setDataElements(rX, rY, zpixel);
2519 }
2520 }
2521 }
2522 }
2523 break;
2524 case DataBuffer.TYPE_DOUBLE: {
2525 double pixel[] = null;
2526 double zpixel[] = null;
2527 for (int y = 0; y < h; y++, rY++) {
2528 rX = rminX;
2529 for (int x = 0; x < w; x++, rX++) {
2530 pixel = (double[]) raster.getDataElements(rX,
2531 rY, pixel);
2532 double dnormAlpha = pixel[aIdx];
2533 if (dnormAlpha != 0.0) {
2534 for (int c = 0; c < aIdx; c++) {
2535 pixel[c] *= dnormAlpha;
2536 }
2537 raster.setDataElements(rX, rY, pixel);
2538 } else {
2539 if (zpixel == null) {
2540 zpixel = new double[numComponents];
2541 java.util.Arrays.fill(zpixel, 0.0);
2542 }
2543 raster.setDataElements(rX, rY, zpixel);
2544 }
2545 }
2546 }
2547 }
2548 break;
2549 default:
2550 throw new UnsupportedOperationException(
2551 "This method has not been "
2552 + "implemented for transferType "
2553 + transferType);
2554 }
2555 } else {
2556 // We are premultiplied and want to divide it out
2557 switch (transferType) {
2558 case DataBuffer.TYPE_BYTE: {
2559 byte pixel[] = null;
2560 float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
2561 for (int y = 0; y < h; y++, rY++) {
2562 rX = rminX;
2563 for (int x = 0; x < w; x++, rX++) {
2564 pixel = (byte[]) raster.getDataElements(rX, rY,
2565 pixel);
2566 normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
2567 if (normAlpha != 0.0f) {
2568 float invAlpha = 1.0f / normAlpha;
2569 for (int c = 0; c < aIdx; c++) {
2570 pixel[c] = (byte) ((pixel[c] & 0xff)
2571 * invAlpha + 0.5f);
2572 }
2573 raster.setDataElements(rX, rY, pixel);
2574 }
2575 }
2576 }
2577 }
2578 break;
2579 case DataBuffer.TYPE_USHORT: {
2580 short pixel[] = null;
2581 float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
2582 for (int y = 0; y < h; y++, rY++) {
2583 rX = rminX;
2584 for (int x = 0; x < w; x++, rX++) {
2585 pixel = (short[]) raster.getDataElements(rX,
2586 rY, pixel);
2587 normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
2588 if (normAlpha != 0.0f) {
2589 float invAlpha = 1.0f / normAlpha;
2590 for (int c = 0; c < aIdx; c++) {
2591 pixel[c] = (short) ((pixel[c] & 0xffff)
2592 * invAlpha + 0.5f);
2593 }
2594 raster.setDataElements(rX, rY, pixel);
2595 }
2596 }
2597 }
2598 }
2599 break;
2600 case DataBuffer.TYPE_INT: {
2601 int pixel[] = null;
2602 float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
2603 for (int y = 0; y < h; y++, rY++) {
2604 rX = rminX;
2605 for (int x = 0; x < w; x++, rX++) {
2606 pixel = (int[]) raster.getDataElements(rX, rY,
2607 pixel);
2608 normAlpha = pixel[aIdx] * alphaScale;
2609 if (normAlpha != 0.0f) {
2610 float invAlpha = 1.0f / normAlpha;
2611 for (int c = 0; c < aIdx; c++) {
2612 pixel[c] = (int) (pixel[c] * invAlpha + 0.5f);
2613 }
2614 raster.setDataElements(rX, rY, pixel);
2615 }
2616 }
2617 }
2618 }
2619 break;
2620 case DataBuffer.TYPE_SHORT: {
2621 short pixel[] = null;
2622 float alphaScale = 1.0f / 32767.0f;
2623 for (int y = 0; y < h; y++, rY++) {
2624 rX = rminX;
2625 for (int x = 0; x < w; x++, rX++) {
2626 pixel = (short[]) raster.getDataElements(rX,
2627 rY, pixel);
2628 normAlpha = pixel[aIdx] * alphaScale;
2629 if (normAlpha != 0.0f) {
2630 float invAlpha = 1.0f / normAlpha;
2631 for (int c = 0; c < aIdx; c++) {
2632 pixel[c] = (short) (pixel[c] * invAlpha + 0.5f);
2633 }
2634 raster.setDataElements(rX, rY, pixel);
2635 }
2636 }
2637 }
2638 }
2639 break;
2640 case DataBuffer.TYPE_FLOAT: {
2641 float pixel[] = null;
2642 for (int y = 0; y < h; y++, rY++) {
2643 rX = rminX;
2644 for (int x = 0; x < w; x++, rX++) {
2645 pixel = (float[]) raster.getDataElements(rX,
2646 rY, pixel);
2647 normAlpha = pixel[aIdx];
2648 if (normAlpha != 0.0f) {
2649 float invAlpha = 1.0f / normAlpha;
2650 for (int c = 0; c < aIdx; c++) {
2651 pixel[c] *= invAlpha;
2652 }
2653 raster.setDataElements(rX, rY, pixel);
2654 }
2655 }
2656 }
2657 }
2658 break;
2659 case DataBuffer.TYPE_DOUBLE: {
2660 double pixel[] = null;
2661 for (int y = 0; y < h; y++, rY++) {
2662 rX = rminX;
2663 for (int x = 0; x < w; x++, rX++) {
2664 pixel = (double[]) raster.getDataElements(rX,
2665 rY, pixel);
2666 double dnormAlpha = pixel[aIdx];
2667 if (dnormAlpha != 0.0) {
2668 double invAlpha = 1.0 / dnormAlpha;
2669 for (int c = 0; c < aIdx; c++) {
2670 pixel[c] *= invAlpha;
2671 }
2672 raster.setDataElements(rX, rY, pixel);
2673 }
2674 }
2675 }
2676 }
2677 break;
2678 default:
2679 throw new UnsupportedOperationException(
2680 "This method has not been "
2681 + "implemented for transferType "
2682 + transferType);
2683 }
2684 }
2685
2686 // Return a new color model
2687 if (!signed) {
2688 return new ComponentColorModel(colorSpace, nBits,
2689 supportsAlpha, isAlphaPremultiplied, transparency,
2690 transferType);
2691 } else {
2692 return new ComponentColorModel(colorSpace, supportsAlpha,
2693 isAlphaPremultiplied, transparency, transferType);
2694 }
2695
2696 }
2697
2698 /**
2699 * Returns true if <CODE>raster</CODE> is compatible with this
2700 * <CODE>ColorModel</CODE>; false if it is not.
2701 *
2702 * @param raster The <CODE>Raster</CODE> object to test for compatibility.
2703 *
2704 * @return <CODE>true</CODE> if <CODE>raster</CODE> is compatible with this
2705 * <CODE>ColorModel</CODE>, <CODE>false</CODE> if it is not.
2706 */
2707 public boolean isCompatibleRaster(Raster raster) {
2708
2709 SampleModel sm = raster.getSampleModel();
2710
2711 if (sm instanceof ComponentSampleModel) {
2712 if (sm.getNumBands() != getNumComponents()) {
2713 return false;
2714 }
2715 for (int i = 0; i < nBits.length; i++) {
2716 if (sm.getSampleSize(i) < nBits[i]) {
2717 return false;
2718 }
2719 }
2720 return (raster.getTransferType() == transferType);
2721 } else {
2722 return false;
2723 }
2724 }
2725
2726 /**
2727 * Creates a <CODE>WritableRaster</CODE> with the specified width and height,
2728 * that has a data layout (<CODE>SampleModel</CODE>) compatible with
2729 * this <CODE>ColorModel</CODE>.
2730 *
2731 * @param w The width of the <CODE>WritableRaster</CODE> you want to create.
2732 * @param h The height of the <CODE>WritableRaster</CODE> you want to create.
2733 *
2734 * @return A <CODE>WritableRaster</CODE> that is compatible with
2735 * this <CODE>ColorModel</CODE>.
2736 * @see WritableRaster
2737 * @see SampleModel
2738 */
2739 public WritableRaster createCompatibleWritableRaster(int w, int h) {
2740 int dataSize = w * h * numComponents;
2741 WritableRaster raster = null;
2742
2743 switch (transferType) {
2744 case DataBuffer.TYPE_BYTE:
2745 case DataBuffer.TYPE_USHORT:
2746 raster = Raster.createInterleavedRaster(transferType, w, h,
2747 numComponents, null);
2748 break;
2749 default:
2750 SampleModel sm = createCompatibleSampleModel(w, h);
2751 DataBuffer db = sm.createDataBuffer();
2752 raster = Raster.createWritableRaster(sm, db, null);
2753 }
2754
2755 return raster;
2756 }
2757
2758 /**
2759 * Creates a <CODE>SampleModel</CODE> with the specified width and height,
2760 * that has a data layout compatible with this <CODE>ColorModel</CODE>.
2761 *
2762 * @param w The width of the <CODE>SampleModel</CODE> you want to create.
2763 * @param h The height of the <CODE>SampleModel</CODE> you want to create.
2764 *
2765 * @return A <CODE>SampleModel</CODE> that is compatible with this
2766 * <CODE>ColorModel</CODE>.
2767 *
2768 * @see SampleModel
2769 */
2770 public SampleModel createCompatibleSampleModel(int w, int h) {
2771 int[] bandOffsets = new int[numComponents];
2772 for (int i = 0; i < numComponents; i++) {
2773 bandOffsets[i] = i;
2774 }
2775 switch (transferType) {
2776 case DataBuffer.TYPE_BYTE:
2777 case DataBuffer.TYPE_USHORT:
2778 return new PixelInterleavedSampleModel(transferType, w, h,
2779 numComponents, w * numComponents, bandOffsets);
2780 default:
2781 return new ComponentSampleModel(transferType, w, h,
2782 numComponents, w * numComponents, bandOffsets);
2783 }
2784 }
2785
2786 /**
2787 * Checks whether or not the specified <CODE>SampleModel</CODE>
2788 * is compatible with this <CODE>ColorModel</CODE>.
2789 *
2790 * @param sm The <CODE>SampleModel</CODE> to test for compatibility.
2791 *
2792 * @return <CODE>true</CODE> if the <CODE>SampleModel</CODE> is
2793 * compatible with this <CODE>ColorModel</CODE>, <CODE>false</CODE>
2794 * if it is not.
2795 *
2796 * @see SampleModel
2797 */
2798 public boolean isCompatibleSampleModel(SampleModel sm) {
2799 if (!(sm instanceof ComponentSampleModel)) {
2800 return false;
2801 }
2802
2803 // Must have the same number of components
2804 if (numComponents != sm.getNumBands()) {
2805 return false;
2806 }
2807
2808 if (sm.getTransferType() != transferType) {
2809 return false;
2810 }
2811
2812 return true;
2813 }
2814
2815 /**
2816 * Returns a <CODE>Raster</CODE> representing the alpha channel of an image,
2817 * extracted from the input <CODE>Raster</CODE>.
2818 * This method assumes that <CODE>Raster</CODE> objects associated with
2819 * this <CODE>ColorModel</CODE> store the alpha band, if present, as
2820 * the last band of image data. Returns null if there is no separate spatial
2821 * alpha channel associated with this <CODE>ColorModel</CODE>.
2822 * This method creates a new <CODE>Raster</CODE>, but will share the data
2823 * array.
2824 *
2825 * @param raster The <CODE>WritableRaster</CODE> from which to extract the
2826 * alpha channel.
2827 *
2828 * @return A <CODE>WritableRaster</CODE> containing the image's alpha channel.
2829 *
2830 */
2831 public WritableRaster getAlphaRaster(WritableRaster raster) {
2832 if (hasAlpha() == false) {
2833 return null;
2834 }
2835
2836 int x = raster.getMinX();
2837 int y = raster.getMinY();
2838 int[] band = new int[1];
2839 band[0] = raster.getNumBands() - 1;
2840 return raster.createWritableChild(x, y, raster.getWidth(),
2841 raster.getHeight(), x, y, band);
2842 }
2843
2844 /**
2845 * Compares this color model with another for equality.
2846 *
2847 * @param obj The object to compare with this color model.
2848 * @return <CODE>true</CODE> if the color model objects are equal,
2849 * <CODE>false</CODE> if they are not.
2850 */
2851 public boolean equals(Object obj) {
2852 if (!super .equals(obj)) {
2853 return false;
2854 }
2855
2856 if (obj.getClass() != getClass()) {
2857 return false;
2858 }
2859
2860 return true;
2861 }
2862
2863 }
|