Source Code Cross Referenced for ComponentColorModel.java in  » 6.0-JDK-Core » AWT » java » awt » image » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt.image 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.