Save This Page
Home » openjdk-7 » java » awt » image » [javadoc | source]
    1   /*
    2    * Copyright 1997-2003 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.awt.image;
   27   
   28   import java.awt.color.ColorSpace;
   29   import java.awt.color.ICC_ColorSpace;
   30   
   31   /**
   32    * A <CODE>ColorModel</CODE> class that works with pixel values that
   33    * represent color and alpha information as separate samples and that
   34    * store each sample in a separate data element.  This class can be
   35    * used with an arbitrary <CODE>ColorSpace</CODE>.  The number of
   36    * color samples in the pixel values must be same as the number of
   37    * color components in the <CODE>ColorSpace</CODE>. There may be a
   38    * single alpha sample.
   39    * <p>
   40    * For those methods that use
   41    * a primitive array pixel representation of type <CODE>transferType</CODE>,
   42    * the array length is the same as the number of color and alpha samples.
   43    * Color samples are stored first in the array followed by the alpha
   44    * sample, if present.  The order of the color samples is specified
   45    * by the <CODE>ColorSpace</CODE>.  Typically, this order reflects the
   46    * name of the color space type. For example, for <CODE>TYPE_RGB</CODE>,
   47    * index 0 corresponds to red, index 1 to green, and index 2 to blue.
   48    * <p>
   49    * The translation from pixel sample values to color/alpha components for
   50    * display or processing purposes is based on a one-to-one correspondence of
   51    * samples to components.
   52    * Depending on the transfer type used to create an instance of
   53    * <code>ComponentColorModel</code>, the pixel sample values
   54    * represented by that instance may be signed or unsigned and may
   55    * be of integral type or float or double (see below for details).
   56    * The translation from sample values to normalized color/alpha components
   57    * must follow certain rules.  For float and double samples, the translation
   58    * is an identity, i.e. normalized component values are equal to the
   59    * corresponding sample values.  For integral samples, the translation
   60    * should be only a simple scale and offset, where the scale and offset
   61    * constants may be different for each component.  The result of
   62    * applying the scale and offset constants is a set of color/alpha
   63    * component values, which are guaranteed to fall within a certain
   64    * range.  Typically, the range for a color component will be the range
   65    * defined by the <code>getMinValue</code> and <code>getMaxValue</code>
   66    * methods of the <code>ColorSpace</code> class.  The range for an
   67    * alpha component should be 0.0 to 1.0.
   68    * <p>
   69    * Instances of <code>ComponentColorModel</code> created with transfer types
   70    * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
   71    * and <CODE>DataBuffer.TYPE_INT</CODE> have pixel sample values which
   72    * are treated as unsigned integral values.
   73    * The number of bits in a color or alpha sample of a pixel value might not
   74    * be the same as the number of bits for the corresponding color or alpha
   75    * sample passed to the
   76    * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
   77    * constructor.  In
   78    * that case, this class assumes that the least significant n bits of a sample
   79    * value hold the component value, where n is the number of significant bits
   80    * for the component passed to the constructor.  It also assumes that
   81    * any higher-order bits in a sample value are zero.  Thus, sample values
   82    * range from 0 to 2<sup>n</sup> - 1.  This class maps these sample values
   83    * to normalized color component values such that 0 maps to the value
   84    * obtained from the <code>ColorSpace's</code> <code>getMinValue</code>
   85    * method for each component and 2<sup>n</sup> - 1 maps to the value
   86    * obtained from <code>getMaxValue</code>.  To create a
   87    * <code>ComponentColorModel</code> with a different color sample mapping
   88    * requires subclassing this class and overriding the
   89    * <code>getNormalizedComponents(Object, float[], int)</code> method.
   90    * The mapping for an alpha sample always maps 0 to 0.0 and
   91    * 2<sup>n</sup> - 1 to 1.0.
   92    * <p>
   93    * For instances with unsigned sample values,
   94    * the unnormalized color/alpha component representation is only
   95    * supported if two conditions hold.  First, sample value value 0 must
   96    * map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1
   97    * to 1.0.  Second the min/max range of all color components of the
   98    * <code>ColorSpace</code> must be 0.0 to 1.0.  In this case, the
   99    * component representation is the n least
  100    * significant bits of the corresponding sample.  Thus each component is
  101    * an unsigned integral value between 0 and 2<sup>n</sup> - 1, where
  102    * n is the number of significant bits for a particular component.
  103    * If these conditions are not met, any method taking an unnormalized
  104    * component argument will throw an <code>IllegalArgumentException</code>.
  105    * <p>
  106    * Instances of <code>ComponentColorModel</code> created with transfer types
  107    * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
  108    * <CODE>DataBuffer.TYPE_DOUBLE</CODE> have pixel sample values which
  109    * are treated as signed short, float, or double values.
  110    * Such instances do not support the unnormalized color/alpha component
  111    * representation, so any methods taking such a representation as an argument
  112    * will throw an <code>IllegalArgumentException</code> when called on one
  113    * of these instances.  The normalized component values of instances
  114    * of this class have a range which depends on the transfer
  115    * type as follows: for float samples, the full range of the float data
  116    * type; for double samples, the full range of the float data type
  117    * (resulting from casting double to float); for short samples,
  118    * from approximately -maxVal to +maxVal, where maxVal is the per
  119    * component maximum value for the <code>ColorSpace</code>
  120    * (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps
  121    * to +maxVal).  A subclass may override the scaling for short sample
  122    * values to normalized component values by overriding the
  123    * <code>getNormalizedComponents(Object, float[], int)</code> method.
  124    * For float and double samples, the normalized component values are
  125    * taken to be equal to the corresponding sample values, and subclasses
  126    * should not attempt to add any non-identity scaling for these transfer
  127    * types.
  128    * <p>
  129    * Instances of <code>ComponentColorModel</code> created with transfer types
  130    * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
  131    * <CODE>DataBuffer.TYPE_DOUBLE</CODE>
  132    * use all the bits of all sample values.  Thus all color/alpha components
  133    * have 16 bits when using <CODE>DataBuffer.TYPE_SHORT</CODE>, 32 bits when
  134    * using <CODE>DataBuffer.TYPE_FLOAT</CODE>, and 64 bits when using
  135    * <CODE>DataBuffer.TYPE_DOUBLE</CODE>.  When the
  136    * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
  137    * form of constructor is used with one of these transfer types, the
  138    * bits array argument is ignored.
  139    * <p>
  140    * It is possible to have color/alpha sample values
  141    * which cannot be reasonably interpreted as component values for rendering.
  142    * This can happen when <code>ComponentColorModel</code> is subclassed to
  143    * override the mapping of unsigned sample values to normalized color
  144    * component values or when signed sample values outside a certain range
  145    * are used.  (As an example, specifying an alpha component as a signed
  146    * short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can
  147    * lead to unexpected results.) It is the
  148    * responsibility of applications to appropriately scale pixel data before
  149    * rendering such that color components fall within the normalized range
  150    * of the <code>ColorSpace</code> (obtained using the <code>getMinValue</code>
  151    * and <code>getMaxValue</code> methods of the <code>ColorSpace</code> class)
  152    * and the alpha component is between 0.0 and 1.0.  If color or alpha
  153    * component values fall outside these ranges, rendering results are
  154    * indeterminate.
  155    * <p>
  156    * Methods that use a single int pixel representation throw
  157    * an <CODE>IllegalArgumentException</CODE>, unless the number of components
  158    * for the <CODE>ComponentColorModel</CODE> is one and the component
  159    * value is unsigned -- in other words,  a single color component using
  160    * a transfer type of <CODE>DataBuffer.TYPE_BYTE</CODE>,
  161    * <CODE>DataBuffer.TYPE_USHORT</CODE>, or <CODE>DataBuffer.TYPE_INT</CODE>
  162    * and no alpha.
  163    * <p>
  164    * A <CODE>ComponentColorModel</CODE> can be used in conjunction with a
  165    * <CODE>ComponentSampleModel</CODE>, a <CODE>BandedSampleModel</CODE>,
  166    * or a <CODE>PixelInterleavedSampleModel</CODE> to construct a
  167    * <CODE>BufferedImage</CODE>.
  168    *
  169    * @see ColorModel
  170    * @see ColorSpace
  171    * @see ComponentSampleModel
  172    * @see BandedSampleModel
  173    * @see PixelInterleavedSampleModel
  174    * @see BufferedImage
  175    *
  176    */
  177   public class ComponentColorModel extends ColorModel {
  178   
  179       /**
  180        * <code>signed</code>  is <code>true</code> for <code>short</code>,
  181        * <code>float</code>, and <code>double</code> transfer types; it
  182        * is <code>false</code> for <code>byte</code>, <code>ushort</code>,
  183        * and <code>int</code> transfer types.
  184        */
  185       private boolean signed; // true for transfer types short, float, double
  186                               // false for byte, ushort, int
  187       private boolean is_sRGB_stdScale;
  188       private boolean is_LinearRGB_stdScale;
  189       private boolean is_LinearGray_stdScale;
  190       private boolean is_ICCGray_stdScale;
  191       private byte[] tosRGB8LUT;
  192       private byte[] fromsRGB8LUT8;
  193       private short[] fromsRGB8LUT16;
  194       private byte[] fromLinearGray16ToOtherGray8LUT;
  195       private short[] fromLinearGray16ToOtherGray16LUT;
  196       private boolean needScaleInit;
  197       private boolean noUnnorm;
  198       private boolean nonStdScale;
  199       private float[] min;
  200       private float[] diffMinMax;
  201       private float[] compOffset;
  202       private float[] compScale;
  203   
  204       /**
  205        * Constructs a <CODE>ComponentColorModel</CODE> from the specified
  206        * parameters. Color components will be in the specified
  207        * <CODE>ColorSpace</CODE>.  The supported transfer types are
  208        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
  209        * <CODE>DataBuffer.TYPE_INT</CODE>,
  210        * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
  211        * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
  212        * If not null, the <CODE>bits</CODE> array specifies the
  213        * number of significant bits per color and alpha component and its
  214        * length should be at least the number of components in the
  215        * <CODE>ColorSpace</CODE> if there is no alpha
  216        * information in the pixel values, or one more than this number if
  217        * there is alpha information.  When the <CODE>transferType</CODE> is
  218        * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
  219        * or <CODE>DataBuffer.TYPE_DOUBLE</CODE> the <CODE>bits</CODE> array
  220        * argument is ignored.  <CODE>hasAlpha</CODE> indicates whether alpha
  221        * information is present.  If <CODE>hasAlpha</CODE> is true, then
  222        * the boolean <CODE>isAlphaPremultiplied</CODE>
  223        * specifies how to interpret color and alpha samples in pixel values.
  224        * If the boolean is true, color samples are assumed to have been
  225        * multiplied by the alpha sample. The <CODE>transparency</CODE>
  226        * specifies what alpha values can be represented by this color model.
  227        * The acceptable <code>transparency</code> values are
  228        * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
  229        * The <CODE>transferType</CODE> is the type of primitive array used
  230        * to represent pixel values.
  231        *
  232        * @param colorSpace       The <CODE>ColorSpace</CODE> associated
  233        *                         with this color model.
  234        * @param bits             The number of significant bits per component.
  235        *                         May be null, in which case all bits of all
  236        *                         component samples will be significant.
  237        *                         Ignored if transferType is one of
  238        *                         <CODE>DataBuffer.TYPE_SHORT</CODE>,
  239        *                         <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
  240        *                         <CODE>DataBuffer.TYPE_DOUBLE</CODE>,
  241        *                         in which case all bits of all component
  242        *                         samples will be significant.
  243        * @param hasAlpha         If true, this color model supports alpha.
  244        * @param isAlphaPremultiplied If true, alpha is premultiplied.
  245        * @param transparency     Specifies what alpha values can be represented
  246        *                         by this color model.
  247        * @param transferType     Specifies the type of primitive array used to
  248        *                         represent pixel values.
  249        *
  250        * @throws IllegalArgumentException If the <CODE>bits</CODE> array
  251        *         argument is not null, its length is less than the number of
  252        *         color and alpha components, and transferType is one of
  253        *         <CODE>DataBuffer.TYPE_BYTE</CODE>,
  254        *         <CODE>DataBuffer.TYPE_USHORT</CODE>, or
  255        *         <CODE>DataBuffer.TYPE_INT</CODE>.
  256        * @throws IllegalArgumentException If transferType is not one of
  257        *         <CODE>DataBuffer.TYPE_BYTE</CODE>,
  258        *         <CODE>DataBuffer.TYPE_USHORT</CODE>,
  259        *         <CODE>DataBuffer.TYPE_INT</CODE>,
  260        *         <CODE>DataBuffer.TYPE_SHORT</CODE>,
  261        *         <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
  262        *         <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
  263        *
  264        * @see ColorSpace
  265        * @see java.awt.Transparency
  266        */
  267       public ComponentColorModel (ColorSpace colorSpace,
  268                                   int[] bits,
  269                                   boolean hasAlpha,
  270                                   boolean isAlphaPremultiplied,
  271                                   int transparency,
  272                                   int transferType) {
  273           super (bitsHelper(transferType, colorSpace, hasAlpha),
  274                  bitsArrayHelper(bits, transferType, colorSpace, hasAlpha),
  275                  colorSpace, hasAlpha, isAlphaPremultiplied, transparency,
  276                  transferType);
  277           switch(transferType) {
  278               case DataBuffer.TYPE_BYTE:
  279               case DataBuffer.TYPE_USHORT:
  280               case DataBuffer.TYPE_INT:
  281                   signed = false;
  282                   needScaleInit = true;
  283                   break;
  284               case DataBuffer.TYPE_SHORT:
  285                   signed = true;
  286                   needScaleInit = true;
  287                   break;
  288               case DataBuffer.TYPE_FLOAT:
  289               case DataBuffer.TYPE_DOUBLE:
  290                   signed = true;
  291                   needScaleInit = false;
  292                   noUnnorm = true;
  293                   nonStdScale = false;
  294                   break;
  295               default:
  296                   throw new IllegalArgumentException("This constructor is not "+
  297                            "compatible with transferType " + transferType);
  298           }
  299           setupLUTs();
  300       }
  301   
  302       /**
  303        * Constructs a <CODE>ComponentColorModel</CODE> from the specified
  304        * parameters. Color components will be in the specified
  305        * <CODE>ColorSpace</CODE>.  The supported transfer types are
  306        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
  307        * <CODE>DataBuffer.TYPE_INT</CODE>,
  308        * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
  309        * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>.  The number of significant
  310        * bits per color and alpha component will be 8, 16, 32, 16, 32,  or 64,
  311        * respectively.  The number of color components will be the
  312        * number of components in the <CODE>ColorSpace</CODE>.  There will be
  313        * an alpha component if <CODE>hasAlpha</CODE> is <CODE>true</CODE>.
  314        * If <CODE>hasAlpha</CODE> is true, then
  315        * the boolean <CODE>isAlphaPremultiplied</CODE>
  316        * specifies how to interpret color and alpha samples in pixel values.
  317        * If the boolean is true, color samples are assumed to have been
  318        * multiplied by the alpha sample. The <CODE>transparency</CODE>
  319        * specifies what alpha values can be represented by this color model.
  320        * The acceptable <code>transparency</code> values are
  321        * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
  322        * The <CODE>transferType</CODE> is the type of primitive array used
  323        * to represent pixel values.
  324        *
  325        * @param colorSpace       The <CODE>ColorSpace</CODE> associated
  326        *                         with this color model.
  327        * @param hasAlpha         If true, this color model supports alpha.
  328        * @param isAlphaPremultiplied If true, alpha is premultiplied.
  329        * @param transparency     Specifies what alpha values can be represented
  330        *                         by this color model.
  331        * @param transferType     Specifies the type of primitive array used to
  332        *                         represent pixel values.
  333        *
  334        * @throws IllegalArgumentException If transferType is not one of
  335        *         <CODE>DataBuffer.TYPE_BYTE</CODE>,
  336        *         <CODE>DataBuffer.TYPE_USHORT</CODE>,
  337        *         <CODE>DataBuffer.TYPE_INT</CODE>,
  338        *         <CODE>DataBuffer.TYPE_SHORT</CODE>,
  339        *         <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
  340        *         <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
  341        *
  342        * @see ColorSpace
  343        * @see java.awt.Transparency
  344        * @since 1.4
  345        */
  346       public ComponentColorModel (ColorSpace colorSpace,
  347                                   boolean hasAlpha,
  348                                   boolean isAlphaPremultiplied,
  349                                   int transparency,
  350                                   int transferType) {
  351           this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
  352                transparency, transferType);
  353       }
  354   
  355       private static int bitsHelper(int transferType,
  356                                     ColorSpace colorSpace,
  357                                     boolean hasAlpha) {
  358           int numBits = DataBuffer.getDataTypeSize(transferType);
  359           int numComponents = colorSpace.getNumComponents();
  360           if (hasAlpha) {
  361               ++numComponents;
  362           }
  363           return numBits * numComponents;
  364       }
  365   
  366       private static int[] bitsArrayHelper(int[] origBits,
  367                                            int transferType,
  368                                            ColorSpace colorSpace,
  369                                            boolean hasAlpha) {
  370           switch(transferType) {
  371               case DataBuffer.TYPE_BYTE:
  372               case DataBuffer.TYPE_USHORT:
  373               case DataBuffer.TYPE_INT:
  374                   if (origBits != null) {
  375                       return origBits;
  376                   }
  377                   break;
  378               default:
  379                   break;
  380           }
  381           int numBits = DataBuffer.getDataTypeSize(transferType);
  382           int numComponents = colorSpace.getNumComponents();
  383           if (hasAlpha) {
  384               ++numComponents;
  385           }
  386           int[] bits = new int[numComponents];
  387           for (int i = 0; i < numComponents; i++) {
  388               bits[i] = numBits;
  389           }
  390           return bits;
  391       }
  392   
  393       private void setupLUTs() {
  394           // REMIND: there is potential to accelerate sRGB, LinearRGB,
  395           // LinearGray, ICCGray, and non-ICC Gray spaces with non-standard
  396           // scaling, if that becomes important
  397           //
  398           // NOTE: The is_xxx_stdScale and nonStdScale booleans are provisionally
  399           // set here when this method is called at construction time.  These
  400           // variables may be set again when initScale is called later.
  401           // When setupLUTs returns, nonStdScale is true if (the transferType
  402           // is not float or double) AND (some minimum ColorSpace component
  403           // value is not 0.0 OR some maximum ColorSpace component value
  404           // is not 1.0).  This is correct for the calls to
  405           // getNormalizedComponents(Object, float[], int) from initScale().
  406           // initScale() may change the value nonStdScale based on the
  407           // return value of getNormalizedComponents() - this will only
  408           // happen if getNormalizedComponents() has been overridden by a
  409           // subclass to make the mapping of min/max pixel sample values
  410           // something different from min/max color component values.
  411           if (is_sRGB) {
  412               is_sRGB_stdScale = true;
  413               nonStdScale = false;
  414           } else if (ColorModel.isLinearRGBspace(colorSpace)) {
  415               // Note that the built-in Linear RGB space has a normalized
  416               // range of 0.0 - 1.0 for each coordinate.  Usage of these
  417               // LUTs makes that assumption.
  418               is_LinearRGB_stdScale = true;
  419               nonStdScale = false;
  420               if (transferType == DataBuffer.TYPE_BYTE) {
  421                   tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
  422                   fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
  423               } else {
  424                   tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
  425                   fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
  426               }
  427           } else if ((colorSpaceType == ColorSpace.TYPE_GRAY) &&
  428                      (colorSpace instanceof ICC_ColorSpace) &&
  429                      (colorSpace.getMinValue(0) == 0.0f) &&
  430                      (colorSpace.getMaxValue(0) == 1.0f)) {
  431               // Note that a normalized range of 0.0 - 1.0 for the gray
  432               // component is required, because usage of these LUTs makes
  433               // that assumption.
  434               ICC_ColorSpace ics = (ICC_ColorSpace) colorSpace;
  435               is_ICCGray_stdScale = true;
  436               nonStdScale = false;
  437               fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
  438               if (ColorModel.isLinearGRAYspace(ics)) {
  439                   is_LinearGray_stdScale = true;
  440                   if (transferType == DataBuffer.TYPE_BYTE) {
  441                       tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
  442                   } else {
  443                       tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
  444                   }
  445               } else {
  446                   if (transferType == DataBuffer.TYPE_BYTE) {
  447                       tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
  448                       fromLinearGray16ToOtherGray8LUT =
  449                           ColorModel.getLinearGray16ToOtherGray8LUT(ics);
  450                   } else {
  451                       tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
  452                       fromLinearGray16ToOtherGray16LUT =
  453                           ColorModel.getLinearGray16ToOtherGray16LUT(ics);
  454                   }
  455               }
  456           } else if (needScaleInit) {
  457               // if transferType is byte, ushort, int, or short and we
  458               // don't already know the ColorSpace has minVlaue == 0.0f and
  459               // maxValue == 1.0f for all components, we need to check that
  460               // now and setup the min[] and diffMinMax[] arrays if necessary.
  461               nonStdScale = false;
  462               for (int i = 0; i < numColorComponents; i++) {
  463                   if ((colorSpace.getMinValue(i) != 0.0f) ||
  464                       (colorSpace.getMaxValue(i) != 1.0f)) {
  465                       nonStdScale = true;
  466                       break;
  467                   }
  468               }
  469               if (nonStdScale) {
  470                   min = new float[numColorComponents];
  471                   diffMinMax = new float[numColorComponents];
  472                   for (int i = 0; i < numColorComponents; i++) {
  473                       min[i] = colorSpace.getMinValue(i);
  474                       diffMinMax[i] = colorSpace.getMaxValue(i) - min[i];
  475                   }
  476               }
  477           }
  478       }
  479   
  480       private void initScale() {
  481           // This method is called the first time any method which uses
  482           // pixel sample value to color component value scaling information
  483           // is called if the transferType supports non-standard scaling
  484           // as defined above (byte, ushort, int, and short), unless the
  485           // method is getNormalizedComponents(Object, float[], int) (that
  486           // method must be overridden to use non-standard scaling).  This
  487           // method also sets up the noUnnorm boolean variable for these
  488           // transferTypes.  After this method is called, the nonStdScale
  489           // variable will be true if getNormalizedComponents() maps a
  490           // sample value of 0 to anything other than 0.0f OR maps a
  491           // sample value of 2^^n - 1 (2^^15 - 1 for short transferType)
  492           // to anything other than 1.0f.  Note that this can be independent
  493           // of the colorSpace min/max component values, if the
  494           // getNormalizedComponents() method has been overridden for some
  495           // reason, e.g. to provide greater dynamic range in the sample
  496           // values than in the color component values.  Unfortunately,
  497           // this method can't be called at construction time, since a
  498           // subclass may still have uninitialized state that would cause
  499           // getNormalizedComponents() to return an incorrect result.
  500           needScaleInit = false; // only needs to called once
  501           if (nonStdScale || signed) {
  502               // The unnormalized form is only supported for unsigned
  503               // transferTypes and when the ColorSpace min/max values
  504               // are 0.0/1.0.  When this method is called nonStdScale is
  505               // true if the latter condition does not hold.  In addition,
  506               // the unnormalized form requires that the full range of
  507               // the pixel sample values map to the full 0.0 - 1.0 range
  508               // of color component values.  That condition is checked
  509               // later in this method.
  510               noUnnorm = true;
  511           } else {
  512               noUnnorm = false;
  513           }
  514           float[] lowVal, highVal;
  515           switch (transferType) {
  516           case DataBuffer.TYPE_BYTE:
  517               {
  518                   byte[] bpixel = new byte[numComponents];
  519                   for (int i = 0; i < numColorComponents; i++) {
  520                       bpixel[i] = 0;
  521                   }
  522                   if (supportsAlpha) {
  523                       bpixel[numColorComponents] =
  524                           (byte) ((1 << nBits[numColorComponents]) - 1);
  525                   }
  526                   lowVal = getNormalizedComponents(bpixel, null, 0);
  527                   for (int i = 0; i < numColorComponents; i++) {
  528                       bpixel[i] = (byte) ((1 << nBits[i]) - 1);
  529                   }
  530                   highVal = getNormalizedComponents(bpixel, null, 0);
  531               }
  532               break;
  533           case DataBuffer.TYPE_USHORT:
  534               {
  535                   short[] uspixel = new short[numComponents];
  536                   for (int i = 0; i < numColorComponents; i++) {
  537                       uspixel[i] = 0;
  538                   }
  539                   if (supportsAlpha) {
  540                       uspixel[numColorComponents] =
  541                           (short) ((1 << nBits[numColorComponents]) - 1);
  542                   }
  543                   lowVal = getNormalizedComponents(uspixel, null, 0);
  544                   for (int i = 0; i < numColorComponents; i++) {
  545                       uspixel[i] = (short) ((1 << nBits[i]) - 1);
  546                   }
  547                   highVal = getNormalizedComponents(uspixel, null, 0);
  548               }
  549               break;
  550           case DataBuffer.TYPE_INT:
  551               {
  552                   int[] ipixel = new int[numComponents];
  553                   for (int i = 0; i < numColorComponents; i++) {
  554                       ipixel[i] = 0;
  555                   }
  556                   if (supportsAlpha) {
  557                       ipixel[numColorComponents] =
  558                           ((1 << nBits[numColorComponents]) - 1);
  559                   }
  560                   lowVal = getNormalizedComponents(ipixel, null, 0);
  561                   for (int i = 0; i < numColorComponents; i++) {
  562                       ipixel[i] = ((1 << nBits[i]) - 1);
  563                   }
  564                   highVal = getNormalizedComponents(ipixel, null, 0);
  565               }
  566               break;
  567           case DataBuffer.TYPE_SHORT:
  568               {
  569                   short[] spixel = new short[numComponents];
  570                   for (int i = 0; i < numColorComponents; i++) {
  571                       spixel[i] = 0;
  572                   }
  573                   if (supportsAlpha) {
  574                       spixel[numColorComponents] = 32767;
  575                   }
  576                   lowVal = getNormalizedComponents(spixel, null, 0);
  577                   for (int i = 0; i < numColorComponents; i++) {
  578                       spixel[i] = 32767;
  579                   }
  580                   highVal = getNormalizedComponents(spixel, null, 0);
  581               }
  582               break;
  583           default:
  584               lowVal = highVal = null;  // to keep the compiler from complaining
  585               break;
  586           }
  587           nonStdScale = false;
  588           for (int i = 0; i < numColorComponents; i++) {
  589               if ((lowVal[i] != 0.0f) || (highVal[i] != 1.0f)) {
  590                   nonStdScale = true;
  591                   break;
  592               }
  593           }
  594           if (nonStdScale) {
  595               noUnnorm = true;
  596               is_sRGB_stdScale = false;
  597               is_LinearRGB_stdScale = false;
  598               is_LinearGray_stdScale = false;
  599               is_ICCGray_stdScale = false;
  600               compOffset = new float[numColorComponents];
  601               compScale = new float[numColorComponents];
  602               for (int i = 0; i < numColorComponents; i++) {
  603                   compOffset[i] = lowVal[i];
  604                   compScale[i] = 1.0f / (highVal[i] - lowVal[i]);
  605               }
  606           }
  607       }
  608   
  609       private int getRGBComponent(int pixel, int idx) {
  610           if (numComponents > 1) {
  611               throw new
  612                   IllegalArgumentException("More than one component per pixel");
  613           }
  614           if (signed) {
  615               throw new
  616                   IllegalArgumentException("Component value is signed");
  617           }
  618           if (needScaleInit) {
  619               initScale();
  620           }
  621           // Since there is only 1 component, there is no alpha
  622   
  623           // Normalize the pixel in order to convert it
  624           Object opixel = null;
  625           switch (transferType) {
  626           case DataBuffer.TYPE_BYTE:
  627               {
  628                   byte[] bpixel = { (byte) pixel };
  629                   opixel = bpixel;
  630               }
  631               break;
  632           case DataBuffer.TYPE_USHORT:
  633               {
  634                   short[] spixel = { (short) pixel };
  635                   opixel = spixel;
  636               }
  637               break;
  638           case DataBuffer.TYPE_INT:
  639               {
  640                   int[] ipixel = { pixel };
  641                   opixel = ipixel;
  642               }
  643               break;
  644           }
  645           float[] norm = getNormalizedComponents(opixel, null, 0);
  646           float[] rgb = colorSpace.toRGB(norm);
  647   
  648           return (int) (rgb[idx] * 255.0f + 0.5f);
  649       }
  650   
  651       /**
  652        * Returns the red color component for the specified pixel, scaled
  653        * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
  654        * is done if necessary.  The pixel value is specified as an int.
  655        * The returned value will be a non pre-multiplied value.
  656        * If the alpha is premultiplied, this method divides
  657        * it out before returning the value (if the alpha value is 0,
  658        * the red value will be 0).
  659        *
  660        * @param pixel The pixel from which you want to get the red color component.
  661        *
  662        * @return The red color component for the specified pixel, as an int.
  663        *
  664        * @throws IllegalArgumentException If there is more than
  665        * one component in this <CODE>ColorModel</CODE>.
  666        * @throws IllegalArgumentException If the component value for this
  667        * <CODE>ColorModel</CODE> is signed
  668        */
  669       public int getRed(int pixel) {
  670           return getRGBComponent(pixel, 0);
  671       }
  672   
  673       /**
  674        * Returns the green color component for the specified pixel, scaled
  675        * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
  676        * is done if necessary.  The pixel value is specified as an int.
  677        * The returned value will be a non
  678        * pre-multiplied value. If the alpha is premultiplied, this method
  679        * divides it out before returning the value (if the alpha value is 0,
  680        * the green value will be 0).
  681        *
  682        * @param pixel The pixel from which you want to get the green color component.
  683        *
  684        * @return The green color component for the specified pixel, as an int.
  685        *
  686        * @throws IllegalArgumentException If there is more than
  687        * one component in this <CODE>ColorModel</CODE>.
  688        * @throws IllegalArgumentException If the component value for this
  689        * <CODE>ColorModel</CODE> is signed
  690        */
  691       public int getGreen(int pixel) {
  692           return getRGBComponent(pixel, 1);
  693       }
  694   
  695       /**
  696        * Returns the blue color component for the specified pixel, scaled
  697        * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
  698        * is done if necessary.  The pixel value is specified as an int.
  699        * The returned value will be a non
  700        * pre-multiplied value. If the alpha is premultiplied, this method
  701        * divides it out before returning the value (if the alpha value is 0,
  702        * the blue value will be 0).
  703        *
  704        * @param pixel The pixel from which you want to get the blue color component.
  705        *
  706        * @return The blue color component for the specified pixel, as an int.
  707        *
  708        * @throws IllegalArgumentException If there is more than
  709        * one component in this <CODE>ColorModel</CODE>.
  710        * @throws IllegalArgumentException If the component value for this
  711        * <CODE>ColorModel</CODE> is signed
  712        */
  713       public int getBlue(int pixel) {
  714           return getRGBComponent(pixel, 2);
  715       }
  716   
  717       /**
  718        * Returns the alpha component for the specified pixel, scaled
  719        * from 0 to 255.   The pixel value is specified as an int.
  720        *
  721        * @param pixel The pixel from which you want to get the alpha component.
  722        *
  723        * @return The alpha component for the specified pixel, as an int.
  724        *
  725        * @throws IllegalArgumentException If there is more than
  726        * one component in this <CODE>ColorModel</CODE>.
  727        * @throws IllegalArgumentException If the component value for this
  728        * <CODE>ColorModel</CODE> is signed
  729        */
  730       public int getAlpha(int pixel) {
  731           if (supportsAlpha == false) {
  732               return 255;
  733           }
  734           if (numComponents > 1) {
  735               throw new
  736                   IllegalArgumentException("More than one component per pixel");
  737           }
  738           if (signed) {
  739               throw new
  740                   IllegalArgumentException("Component value is signed");
  741           }
  742   
  743           return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f);
  744       }
  745   
  746       /**
  747        * Returns the color/alpha components of the pixel in the default
  748        * RGB color model format.  A color conversion is done if necessary.
  749        * The returned value will be in a non pre-multiplied format. If
  750        * the alpha is premultiplied, this method divides it out of the
  751        * color components (if the alpha value is 0, the color values will be 0).
  752        *
  753        * @param pixel The pixel from which you want to get the color/alpha components.
  754        *
  755        * @return The color/alpha components for the specified pixel, as an int.
  756        *
  757        * @throws IllegalArgumentException If there is more than
  758        * one component in this <CODE>ColorModel</CODE>.
  759        * @throws IllegalArgumentException If the component value for this
  760        * <CODE>ColorModel</CODE> is signed
  761        */
  762       public int getRGB(int pixel) {
  763           if (numComponents > 1) {
  764               throw new
  765                   IllegalArgumentException("More than one component per pixel");
  766           }
  767           if (signed) {
  768               throw new
  769                   IllegalArgumentException("Component value is signed");
  770           }
  771   
  772           return (getAlpha(pixel) << 24)
  773               | (getRed(pixel) << 16)
  774               | (getGreen(pixel) << 8)
  775               | (getBlue(pixel) << 0);
  776       }
  777   
  778       private int extractComponent(Object inData, int idx, int precision) {
  779           // Extract component idx from inData.  The precision argument
  780           // should be either 8 or 16.  If it's 8, this method will return
  781           // an 8-bit value.  If it's 16, this method will return a 16-bit
  782           // value for transferTypes other than TYPE_BYTE.  For TYPE_BYTE,
  783           // an 8-bit value will be returned.
  784   
  785           // This method maps the input value corresponding to a
  786           // normalized ColorSpace component value of 0.0 to 0, and the
  787           // input value corresponding to a normalized ColorSpace
  788           // component value of 1.0 to 2^n - 1 (where n is 8 or 16), so
  789           // it is appropriate only for ColorSpaces with min/max component
  790           // values of 0.0/1.0.  This will be true for sRGB, the built-in
  791           // Linear RGB and Linear Gray spaces, and any other ICC grayscale
  792           // spaces for which we have precomputed LUTs.
  793   
  794           boolean needAlpha = (supportsAlpha && isAlphaPremultiplied);
  795           int alp = 0;
  796           int comp;
  797           int mask = (1 << nBits[idx]) - 1;
  798   
  799           switch (transferType) {
  800               // Note: we do no clamping of the pixel data here - we
  801               // assume that the data is scaled properly
  802               case DataBuffer.TYPE_SHORT: {
  803                   short sdata[] = (short[]) inData;
  804                   float scalefactor = (float) ((1 << precision) - 1);
  805                   if (needAlpha) {
  806                       short s = sdata[numColorComponents];
  807                       if (s != (short) 0) {
  808                           return (int) ((((float) sdata[idx]) /
  809                                          ((float) s)) * scalefactor + 0.5f);
  810                       } else {
  811                           return 0;
  812                       }
  813                   } else {
  814                       return (int) ((sdata[idx] / 32767.0f) * scalefactor + 0.5f);
  815                   }
  816               }
  817               case DataBuffer.TYPE_FLOAT: {
  818                   float fdata[] = (float[]) inData;
  819                   float scalefactor = (float) ((1 << precision) - 1);
  820                   if (needAlpha) {
  821                       float f = fdata[numColorComponents];
  822                       if (f != 0.0f) {
  823                           return (int) (((fdata[idx] / f) * scalefactor) + 0.5f);
  824                       } else {
  825                           return 0;
  826                       }
  827                   } else {
  828                       return (int) (fdata[idx] * scalefactor + 0.5f);
  829                   }
  830               }
  831               case DataBuffer.TYPE_DOUBLE: {
  832                   double ddata[] = (double[]) inData;
  833                   double scalefactor = (double) ((1 << precision) - 1);
  834                   if (needAlpha) {
  835                       double d = ddata[numColorComponents];
  836                       if (d != 0.0) {
  837                           return (int) (((ddata[idx] / d) * scalefactor) + 0.5);
  838                       } else {
  839                           return 0;
  840                       }
  841                   } else {
  842                       return (int) (ddata[idx] * scalefactor + 0.5);
  843                   }
  844               }
  845               case DataBuffer.TYPE_BYTE:
  846                  byte bdata[] = (byte[])inData;
  847                  comp = bdata[idx] & mask;
  848                  precision = 8;
  849                  if (needAlpha) {
  850                      alp = bdata[numColorComponents] & mask;
  851                  }
  852               break;
  853               case DataBuffer.TYPE_USHORT:
  854                  short usdata[] = (short[])inData;
  855                  comp = usdata[idx] & mask;
  856                  if (needAlpha) {
  857                      alp = usdata[numColorComponents] & mask;
  858                  }
  859               break;
  860               case DataBuffer.TYPE_INT:
  861                  int idata[] = (int[])inData;
  862                  comp = idata[idx];
  863                  if (needAlpha) {
  864                      alp = idata[numColorComponents];
  865                  }
  866               break;
  867               default:
  868                  throw new
  869                      UnsupportedOperationException("This method has not "+
  870                      "been implemented for transferType " + transferType);
  871           }
  872           if (needAlpha) {
  873               if (alp != 0) {
  874                   float scalefactor = (float) ((1 << precision) - 1);
  875                   float fcomp = ((float) comp) / ((float)mask);
  876                   float invalp = ((float) ((1<<nBits[numColorComponents]) - 1)) /
  877                                  ((float) alp);
  878                   return (int) (fcomp * invalp * scalefactor + 0.5f);
  879               } else {
  880                   return 0;
  881               }
  882           } else {
  883               if (nBits[idx] != precision) {
  884                   float scalefactor = (float) ((1 << precision) - 1);
  885                   float fcomp = ((float) comp) / ((float)mask);
  886                   return (int) (fcomp * scalefactor + 0.5f);
  887               }
  888               return comp;
  889           }
  890       }
  891   
  892       private int getRGBComponent(Object inData, int idx) {
  893           if (needScaleInit) {
  894               initScale();
  895           }
  896           if (is_sRGB_stdScale) {
  897               return extractComponent(inData, idx, 8);
  898           } else if (is_LinearRGB_stdScale) {
  899               int lutidx = extractComponent(inData, idx, 16);
  900               return tosRGB8LUT[lutidx] & 0xff;
  901           } else if (is_ICCGray_stdScale) {
  902               int lutidx = extractComponent(inData, 0, 16);
  903               return tosRGB8LUT[lutidx] & 0xff;
  904           }
  905   
  906           // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace
  907           float[] norm = getNormalizedComponents(inData, null, 0);
  908           // Note that getNormalizedComponents returns non-premultiplied values
  909           float[] rgb = colorSpace.toRGB(norm);
  910           return (int) (rgb[idx] * 255.0f + 0.5f);
  911       }
  912   
  913       /**
  914        * Returns the red color component for the specified pixel, scaled
  915        * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
  916        * is done if necessary.  The <CODE>pixel</CODE> value is specified by an array
  917        * of data elements of type <CODE>transferType</CODE> passed in as an object
  918        * reference. The returned value will be a non pre-multiplied value. If the
  919        * alpha is premultiplied, this method divides it out before returning
  920        * the value (if the alpha value is 0, the red value will be 0). Since
  921        * <code>ComponentColorModel</code> can be subclassed, subclasses
  922        * inherit the implementation of this method and if they don't override
  923        * it then they throw an exception if they use an unsupported
  924        * <code>transferType</code>.
  925        *
  926        * @param inData The pixel from which you want to get the red color component,
  927        * specified by an array of data elements of type <CODE>transferType</CODE>.
  928        *
  929        * @return The red color component for the specified pixel, as an int.
  930        *
  931        * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
  932        * of type <CODE>transferType</CODE>.
  933        * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
  934        * large enough to hold a pixel value for this
  935        * <CODE>ColorModel</CODE>.
  936        * @throws UnsupportedOperationException If the transfer type of
  937        * this <CODE>ComponentColorModel</CODE>
  938        * is not one of the supported transfer types:
  939        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
  940        * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
  941        * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
  942        */
  943       public int getRed(Object inData) {
  944           return getRGBComponent(inData, 0);
  945       }
  946   
  947   
  948       /**
  949        * Returns the green color component for the specified pixel, scaled
  950        * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
  951        * A color conversion is done if necessary.  The <CODE>pixel</CODE> value
  952        * is specified by an array of data elements of type <CODE>transferType</CODE>
  953        * passed in as an object reference. The returned value is a non pre-multiplied
  954        * value. If the alpha is premultiplied, this method divides it out before
  955        * returning the value (if the alpha value is 0, the green value will be 0).
  956        * Since <code>ComponentColorModel</code> can be subclassed,
  957        * subclasses inherit the implementation of this method and if they
  958        * don't override it then they throw an exception if they use an
  959        * unsupported <code>transferType</code>.
  960        *
  961        * @param inData The pixel from which you want to get the green color component,
  962        * specified by an array of data elements of type <CODE>transferType</CODE>.
  963        *
  964        * @return The green color component for the specified pixel, as an int.
  965        *
  966        * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
  967        * of type <CODE>transferType</CODE>.
  968        * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
  969        * large enough to hold a pixel value for this
  970        * <CODE>ColorModel</CODE>.
  971        * @throws UnsupportedOperationException If the transfer type of
  972        * this <CODE>ComponentColorModel</CODE>
  973        * is not one of the supported transfer types:
  974        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
  975        * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
  976        * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
  977        */
  978       public int getGreen(Object inData) {
  979           return getRGBComponent(inData, 1);
  980       }
  981   
  982   
  983       /**
  984        * Returns the blue color component for the specified pixel, scaled
  985        * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
  986        * A color conversion is done if necessary.  The <CODE>pixel</CODE> value is
  987        * specified by an array of data elements of type <CODE>transferType</CODE>
  988        * passed in as an object reference. The returned value is a non pre-multiplied
  989        * value. If the alpha is premultiplied, this method divides it out before
  990        * returning the value (if the alpha value is 0, the blue value will be 0).
  991        * Since <code>ComponentColorModel</code> can be subclassed,
  992        * subclasses inherit the implementation of this method and if they
  993        * don't override it then they throw an exception if they use an
  994        * unsupported <code>transferType</code>.
  995        *
  996        * @param inData The pixel from which you want to get the blue color component,
  997        * specified by an array of data elements of type <CODE>transferType</CODE>.
  998        *
  999        * @return The blue color component for the specified pixel, as an int.
 1000        *
 1001        * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
 1002        * of type <CODE>transferType</CODE>.
 1003        * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
 1004        * large enough to hold a pixel value for this
 1005        * <CODE>ColorModel</CODE>.
 1006        * @throws UnsupportedOperationException If the transfer type of
 1007        * this <CODE>ComponentColorModel</CODE>
 1008        * is not one of the supported transfer types:
 1009        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 1010        * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
 1011        * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 1012        */
 1013       public int getBlue(Object inData) {
 1014           return getRGBComponent(inData, 2);
 1015       }
 1016   
 1017       /**
 1018        * Returns the alpha component for the specified pixel, scaled from
 1019        * 0 to 255.  The pixel value is specified by an array of data
 1020        * elements of type <CODE>transferType</CODE> passed in as an
 1021        * object reference.  Since <code>ComponentColorModel</code> can be
 1022        * subclassed, subclasses inherit the
 1023        * implementation of this method and if they don't override it then
 1024        * they throw an exception if they use an unsupported
 1025        * <code>transferType</code>.
 1026        *
 1027        * @param inData The pixel from which you want to get the alpha component,
 1028        * specified by an array of data elements of type <CODE>transferType</CODE>.
 1029        *
 1030        * @return The alpha component for the specified pixel, as an int.
 1031        *
 1032        * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
 1033        * of type <CODE>transferType</CODE>.
 1034        * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
 1035        * large enough to hold a pixel value for this
 1036        * <CODE>ColorModel</CODE>.
 1037        * @throws UnsupportedOperationException If the transfer type of
 1038        * this <CODE>ComponentColorModel</CODE>
 1039        * is not one of the supported transfer types:
 1040        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 1041        * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
 1042        * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 1043        */
 1044       public int getAlpha(Object inData) {
 1045           if (supportsAlpha == false) {
 1046               return 255;
 1047           }
 1048   
 1049           int alpha = 0;
 1050           int aIdx = numColorComponents;
 1051           int mask = (1 << nBits[aIdx]) - 1;
 1052   
 1053           switch (transferType) {
 1054               case DataBuffer.TYPE_SHORT:
 1055                   short sdata[] = (short[])inData;
 1056                   alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f);
 1057                   return alpha;
 1058               case DataBuffer.TYPE_FLOAT:
 1059                   float fdata[] = (float[])inData;
 1060                   alpha = (int) (fdata[aIdx] * 255.0f + 0.5f);
 1061                   return alpha;
 1062               case DataBuffer.TYPE_DOUBLE:
 1063                   double ddata[] = (double[])inData;
 1064                   alpha = (int) (ddata[aIdx] * 255.0 + 0.5);
 1065                   return alpha;
 1066               case DataBuffer.TYPE_BYTE:
 1067                  byte bdata[] = (byte[])inData;
 1068                  alpha = bdata[aIdx] & mask;
 1069               break;
 1070               case DataBuffer.TYPE_USHORT:
 1071                  short usdata[] = (short[])inData;
 1072                  alpha = usdata[aIdx] & mask;
 1073               break;
 1074               case DataBuffer.TYPE_INT:
 1075                  int idata[] = (int[])inData;
 1076                  alpha = idata[aIdx];
 1077               break;
 1078               default:
 1079                  throw new
 1080                      UnsupportedOperationException("This method has not "+
 1081                      "been implemented for transferType " + transferType);
 1082           }
 1083   
 1084           if (nBits[aIdx] == 8) {
 1085               return alpha;
 1086           } else {
 1087               return (int)
 1088                   ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) *
 1089                    255.0f + 0.5f);
 1090           }
 1091       }
 1092   
 1093       /**
 1094        * Returns the color/alpha components for the specified pixel in the
 1095        * default RGB color model format.  A color conversion is done if
 1096        * necessary.  The pixel value is specified by an
 1097        * array of data elements of type <CODE>transferType</CODE> passed
 1098        * in as an object reference.
 1099        * The returned value is in a non pre-multiplied format. If
 1100        * the alpha is premultiplied, this method divides it out of the
 1101        * color components (if the alpha value is 0, the color values will be 0).
 1102        * Since <code>ComponentColorModel</code> can be subclassed,
 1103        * subclasses inherit the implementation of this method and if they
 1104        * don't override it then they throw an exception if they use an
 1105        * unsupported <code>transferType</code>.
 1106        *
 1107        * @param inData The pixel from which you want to get the color/alpha components,
 1108        * specified by an array of data elements of type <CODE>transferType</CODE>.
 1109        *
 1110        * @return The color/alpha components for the specified pixel, as an int.
 1111        *
 1112        * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
 1113        * of type <CODE>transferType</CODE>.
 1114        * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
 1115        * large enough to hold a pixel value for this
 1116        * <CODE>ColorModel</CODE>.
 1117        * @throws UnsupportedOperationException If the transfer type of
 1118        * this <CODE>ComponentColorModel</CODE>
 1119        * is not one of the supported transfer types:
 1120        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 1121        * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
 1122        * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 1123        * @see ColorModel#getRGBdefault
 1124        */
 1125       public int getRGB(Object inData) {
 1126           if (needScaleInit) {
 1127               initScale();
 1128           }
 1129           if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
 1130               return (getAlpha(inData) << 24)
 1131                   | (getRed(inData) << 16)
 1132                   | (getGreen(inData) << 8)
 1133                   | (getBlue(inData));
 1134           } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
 1135               int gray = getRed(inData); // Red sRGB component should equal
 1136                                          // green and blue components
 1137               return (getAlpha(inData) << 24)
 1138                   | (gray << 16)
 1139                   | (gray <<  8)
 1140                   | gray;
 1141           }
 1142           float[] norm = getNormalizedComponents(inData, null, 0);
 1143           // Note that getNormalizedComponents returns non-premult values
 1144           float[] rgb = colorSpace.toRGB(norm);
 1145           return (getAlpha(inData) << 24)
 1146               | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
 1147               | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
 1148               | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
 1149       }
 1150   
 1151       /**
 1152        * Returns a data element array representation of a pixel in this
 1153        * <CODE>ColorModel</CODE>, given an integer pixel representation
 1154        * in the default RGB color model.
 1155        * This array can then be passed to the <CODE>setDataElements</CODE>
 1156        * method of a <CODE>WritableRaster</CODE> object.  If the
 1157        * <CODE>pixel</CODE>
 1158        * parameter is null, a new array is allocated.  Since
 1159        * <code>ComponentColorModel</code> can be subclassed, subclasses
 1160        * inherit the implementation of this method and if they don't
 1161        * override it then
 1162        * they throw an exception if they use an unsupported
 1163        * <code>transferType</code>.
 1164        *
 1165        * @param rgb the integer representation of the pixel in the RGB
 1166        *            color model
 1167        * @param pixel the specified pixel
 1168        * @return The data element array representation of a pixel
 1169        * in this <CODE>ColorModel</CODE>.
 1170        * @throws ClassCastException If <CODE>pixel</CODE> is not null and
 1171        * is not a primitive array of type <CODE>transferType</CODE>.
 1172        * @throws ArrayIndexOutOfBoundsException If <CODE>pixel</CODE> is
 1173        * not large enough to hold a pixel value for this
 1174        * <CODE>ColorModel</CODE>.
 1175        * @throws UnsupportedOperationException If the transfer type of
 1176        * this <CODE>ComponentColorModel</CODE>
 1177        * is not one of the supported transfer types:
 1178        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 1179        * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
 1180        * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 1181        *
 1182        * @see WritableRaster#setDataElements
 1183        * @see SampleModel#setDataElements
 1184        */
 1185       public Object getDataElements(int rgb, Object pixel) {
 1186           // REMIND: Use rendering hints?
 1187   
 1188           int red, grn, blu, alp;
 1189           red = (rgb>>16) & 0xff;
 1190           grn = (rgb>>8) & 0xff;
 1191           blu = rgb & 0xff;
 1192   
 1193           if (needScaleInit) {
 1194               initScale();
 1195           }
 1196           if (signed) {
 1197               // Handle SHORT, FLOAT, & DOUBLE here
 1198   
 1199               switch(transferType) {
 1200               case DataBuffer.TYPE_SHORT:
 1201                   {
 1202                       short sdata[];
 1203                       if (pixel == null) {
 1204                           sdata = new short[numComponents];
 1205                       } else {
 1206                           sdata = (short[])pixel;
 1207                       }
 1208                       float factor;
 1209                       if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
 1210                           factor = 32767.0f / 255.0f;
 1211                           if (is_LinearRGB_stdScale) {
 1212                               red = fromsRGB8LUT16[red] & 0xffff;
 1213                               grn = fromsRGB8LUT16[grn] & 0xffff;
 1214                               blu = fromsRGB8LUT16[blu] & 0xffff;
 1215                               factor = 32767.0f / 65535.0f;
 1216                           }
 1217                           if (supportsAlpha) {
 1218                               alp = (rgb>>24) & 0xff;
 1219                               sdata[3] =
 1220                                   (short) (alp * (32767.0f / 255.0f) + 0.5f);
 1221                               if (isAlphaPremultiplied) {
 1222                                   factor = alp * factor * (1.0f / 255.0f);
 1223                               }
 1224                           }
 1225                           sdata[0] = (short) (red * factor + 0.5f);
 1226                           sdata[1] = (short) (grn * factor + 0.5f);
 1227                           sdata[2] = (short) (blu * factor + 0.5f);
 1228                       } else if (is_LinearGray_stdScale) {
 1229                           red = fromsRGB8LUT16[red] & 0xffff;
 1230                           grn = fromsRGB8LUT16[grn] & 0xffff;
 1231                           blu = fromsRGB8LUT16[blu] & 0xffff;
 1232                           float gray = ((0.2125f * red) +
 1233                                         (0.7154f * grn) +
 1234                                         (0.0721f * blu)) / 65535.0f;
 1235                           factor = 32767.0f;
 1236                           if (supportsAlpha) {
 1237                               alp = (rgb>>24) & 0xff;
 1238                               sdata[1] =
 1239                                   (short) (alp * (32767.0f / 255.0f) + 0.5f);
 1240                               if (isAlphaPremultiplied) {
 1241                                   factor = alp * factor * (1.0f / 255.0f);
 1242                               }
 1243                           }
 1244                           sdata[0] = (short) (gray * factor + 0.5f);
 1245                       } else if (is_ICCGray_stdScale) {
 1246                           red = fromsRGB8LUT16[red] & 0xffff;
 1247                           grn = fromsRGB8LUT16[grn] & 0xffff;
 1248                           blu = fromsRGB8LUT16[blu] & 0xffff;
 1249                           int gray = (int) ((0.2125f * red) +
 1250                                             (0.7154f * grn) +
 1251                                             (0.0721f * blu) + 0.5f);
 1252                           gray = fromLinearGray16ToOtherGray16LUT[gray] & 0xffff;
 1253                           factor = 32767.0f / 65535.0f;
 1254                           if (supportsAlpha) {
 1255                               alp = (rgb>>24) & 0xff;
 1256                               sdata[1] =
 1257                                   (short) (alp * (32767.0f / 255.0f) + 0.5f);
 1258                               if (isAlphaPremultiplied) {
 1259                                   factor = alp * factor * (1.0f / 255.0f);
 1260                               }
 1261                           }
 1262                           sdata[0] = (short) (gray * factor + 0.5f);
 1263                       } else {
 1264                           factor = 1.0f / 255.0f;
 1265                           float norm[] = new float[3];
 1266                           norm[0] = red * factor;
 1267                           norm[1] = grn * factor;
 1268                           norm[2] = blu * factor;
 1269                           norm = colorSpace.fromRGB(norm);
 1270                           if (nonStdScale) {
 1271                               for (int i = 0; i < numColorComponents; i++) {
 1272                                   norm[i] = (norm[i] - compOffset[i]) *
 1273                                             compScale[i];
 1274                                   // REMIND: need to analyze whether this
 1275                                   // clamping is necessary
 1276                                   if (norm[i] < 0.0f) {
 1277                                       norm[i] = 0.0f;
 1278                                   }
 1279                                   if (norm[i] > 1.0f) {
 1280                                       norm[i] = 1.0f;
 1281                                   }
 1282                               }
 1283                           }
 1284                           factor = 32767.0f;
 1285                           if (supportsAlpha) {
 1286                               alp = (rgb>>24) & 0xff;
 1287                               sdata[numColorComponents] =
 1288                                   (short) (alp * (32767.0f / 255.0f) + 0.5f);
 1289                               if (isAlphaPremultiplied) {
 1290                                   factor *= alp * (1.0f / 255.0f);
 1291                               }
 1292                           }
 1293                           for (int i = 0; i < numColorComponents; i++) {
 1294                               sdata[i] = (short) (norm[i] * factor + 0.5f);
 1295                           }
 1296                       }
 1297                       return sdata;
 1298                   }
 1299               case DataBuffer.TYPE_FLOAT:
 1300                   {
 1301                       float fdata[];
 1302                       if (pixel == null) {
 1303                           fdata = new float[numComponents];
 1304                       } else {
 1305                           fdata = (float[])pixel;
 1306                       }
 1307                       float factor;
 1308                       if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
 1309                           if (is_LinearRGB_stdScale) {
 1310                               red = fromsRGB8LUT16[red] & 0xffff;
 1311                               grn = fromsRGB8LUT16[grn] & 0xffff;
 1312                               blu = fromsRGB8LUT16[blu] & 0xffff;
 1313                               factor = 1.0f / 65535.0f;
 1314                           } else {
 1315                               factor = 1.0f / 255.0f;
 1316                           }
 1317                           if (supportsAlpha) {
 1318                               alp = (rgb>>24) & 0xff;
 1319                               fdata[3] = alp * (1.0f / 255.0f);
 1320                               if (isAlphaPremultiplied) {
 1321                                   factor *= fdata[3];
 1322                               }
 1323                           }
 1324                           fdata[0] = red * factor;
 1325                           fdata[1] = grn * factor;
 1326                           fdata[2] = blu * factor;
 1327                       } else if (is_LinearGray_stdScale) {
 1328                           red = fromsRGB8LUT16[red] & 0xffff;
 1329                           grn = fromsRGB8LUT16[grn] & 0xffff;
 1330                           blu = fromsRGB8LUT16[blu] & 0xffff;
 1331                           fdata[0] = ((0.2125f * red) +
 1332                                       (0.7154f * grn) +
 1333                                       (0.0721f * blu)) / 65535.0f;
 1334                           if (supportsAlpha) {
 1335                               alp = (rgb>>24) & 0xff;
 1336                               fdata[1] = alp * (1.0f / 255.0f);
 1337                               if (isAlphaPremultiplied) {
 1338                                   fdata[0] *= fdata[1];
 1339                               }
 1340                           }
 1341                       } else if (is_ICCGray_stdScale) {
 1342                           red = fromsRGB8LUT16[red] & 0xffff;
 1343                           grn = fromsRGB8LUT16[grn] & 0xffff;
 1344                           blu = fromsRGB8LUT16[blu] & 0xffff;
 1345                           int gray = (int) ((0.2125f * red) +
 1346                                             (0.7154f * grn) +
 1347                                             (0.0721f * blu) + 0.5f);
 1348                           fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
 1349                                       0xffff) / 65535.0f;
 1350                           if (supportsAlpha) {
 1351                               alp = (rgb>>24) & 0xff;
 1352                               fdata[1] = alp * (1.0f / 255.0f);
 1353                               if (isAlphaPremultiplied) {
 1354                                   fdata[0] *= fdata[1];
 1355                               }
 1356                           }
 1357                       } else {
 1358                           float norm[] = new float[3];
 1359                           factor = 1.0f / 255.0f;
 1360                           norm[0] = red * factor;
 1361                           norm[1] = grn * factor;
 1362                           norm[2] = blu * factor;
 1363                           norm = colorSpace.fromRGB(norm);
 1364                           if (supportsAlpha) {
 1365                               alp = (rgb>>24) & 0xff;
 1366                               fdata[numColorComponents] = alp * factor;
 1367                               if (isAlphaPremultiplied) {
 1368                                   factor *= alp;
 1369                                   for (int i = 0; i < numColorComponents; i++) {
 1370                                       norm[i] *= factor;
 1371                                   }
 1372                               }
 1373                           }
 1374                           for (int i = 0; i < numColorComponents; i++) {
 1375                               fdata[i] = norm[i];
 1376                           }
 1377                       }
 1378                       return fdata;
 1379                   }
 1380               case DataBuffer.TYPE_DOUBLE:
 1381                   {
 1382                       double ddata[];
 1383                       if (pixel == null) {
 1384                           ddata = new double[numComponents];
 1385                       } else {
 1386                           ddata = (double[])pixel;
 1387                       }
 1388                       if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
 1389                           double factor;
 1390                           if (is_LinearRGB_stdScale) {
 1391                               red = fromsRGB8LUT16[red] & 0xffff;
 1392                               grn = fromsRGB8LUT16[grn] & 0xffff;
 1393                               blu = fromsRGB8LUT16[blu] & 0xffff;
 1394                               factor = 1.0 / 65535.0;
 1395                           } else {
 1396                               factor = 1.0 / 255.0;
 1397                           }
 1398                           if (supportsAlpha) {
 1399                               alp = (rgb>>24) & 0xff;
 1400                               ddata[3] = alp * (1.0 / 255.0);
 1401                               if (isAlphaPremultiplied) {
 1402                                   factor *= ddata[3];
 1403                               }
 1404                           }
 1405                           ddata[0] = red * factor;
 1406                           ddata[1] = grn * factor;
 1407                           ddata[2] = blu * factor;
 1408                       } else if (is_LinearGray_stdScale) {
 1409                           red = fromsRGB8LUT16[red] & 0xffff;
 1410                           grn = fromsRGB8LUT16[grn] & 0xffff;
 1411                           blu = fromsRGB8LUT16[blu] & 0xffff;
 1412                           ddata[0] = ((0.2125 * red) +
 1413                                       (0.7154 * grn) +
 1414                                       (0.0721 * blu)) / 65535.0;
 1415                           if (supportsAlpha) {
 1416                               alp = (rgb>>24) & 0xff;
 1417                               ddata[1] = alp * (1.0 / 255.0);
 1418                               if (isAlphaPremultiplied) {
 1419                                   ddata[0] *= ddata[1];
 1420                               }
 1421                           }
 1422                       } else if (is_ICCGray_stdScale) {
 1423                           red = fromsRGB8LUT16[red] & 0xffff;
 1424                           grn = fromsRGB8LUT16[grn] & 0xffff;
 1425                           blu = fromsRGB8LUT16[blu] & 0xffff;
 1426                           int gray = (int) ((0.2125f * red) +
 1427                                             (0.7154f * grn) +
 1428                                             (0.0721f * blu) + 0.5f);
 1429                           ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
 1430                                       0xffff) / 65535.0;
 1431                           if (supportsAlpha) {
 1432                               alp = (rgb>>24) & 0xff;
 1433                               ddata[1] = alp * (1.0 / 255.0);
 1434                               if (isAlphaPremultiplied) {
 1435                                   ddata[0] *= ddata[1];
 1436                               }
 1437                           }
 1438                       } else {
 1439                           float factor = 1.0f / 255.0f;
 1440                           float norm[] = new float[3];
 1441                           norm[0] = red * factor;
 1442                           norm[1] = grn * factor;
 1443                           norm[2] = blu * factor;
 1444                           norm = colorSpace.fromRGB(norm);
 1445                           if (supportsAlpha) {
 1446                               alp = (rgb>>24) & 0xff;
 1447                               ddata[numColorComponents] = alp * (1.0 / 255.0);
 1448                               if (isAlphaPremultiplied) {
 1449                                   factor *= alp;
 1450                                   for (int i = 0; i < numColorComponents; i++) {
 1451                                       norm[i] *= factor;
 1452                                   }
 1453                               }
 1454                           }
 1455                           for (int i = 0; i < numColorComponents; i++) {
 1456                               ddata[i] = norm[i];
 1457                           }
 1458                       }
 1459                       return ddata;
 1460                   }
 1461               }
 1462           }
 1463   
 1464           // Handle BYTE, USHORT, & INT here
 1465           //REMIND: maybe more efficient not to use int array for
 1466           //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
 1467           int intpixel[];
 1468           if (transferType == DataBuffer.TYPE_INT &&
 1469               pixel != null) {
 1470              intpixel = (int[])pixel;
 1471           } else {
 1472               intpixel = new int[numComponents];
 1473           }
 1474   
 1475           if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
 1476               int precision;
 1477               float factor;
 1478               if (is_LinearRGB_stdScale) {
 1479                   if (transferType == DataBuffer.TYPE_BYTE) {
 1480                       red = fromsRGB8LUT8[red] & 0xff;
 1481                       grn = fromsRGB8LUT8[grn] & 0xff;
 1482                       blu = fromsRGB8LUT8[blu] & 0xff;
 1483                       precision = 8;
 1484                       factor = 1.0f / 255.0f;
 1485                   } else {
 1486                       red = fromsRGB8LUT16[red] & 0xffff;
 1487                       grn = fromsRGB8LUT16[grn] & 0xffff;
 1488                       blu = fromsRGB8LUT16[blu] & 0xffff;
 1489                       precision = 16;
 1490                       factor = 1.0f / 65535.0f;
 1491                   }
 1492               } else {
 1493                   precision = 8;
 1494                   factor = 1.0f / 255.0f;
 1495               }
 1496               if (supportsAlpha) {
 1497                   alp = (rgb>>24)&0xff;
 1498                   if (nBits[3] == 8) {
 1499                       intpixel[3] = alp;
 1500                   }
 1501                   else {
 1502                       intpixel[3] = (int)
 1503                           (alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1) + 0.5f);
 1504                   }
 1505                   if (isAlphaPremultiplied) {
 1506                       factor *= (alp * (1.0f / 255.0f));
 1507                       precision = -1;  // force component calculations below
 1508                   }
 1509               }
 1510               if (nBits[0] == precision) {
 1511                   intpixel[0] = red;
 1512               }
 1513               else {
 1514                   intpixel[0] = (int) (red * factor * ((1<<nBits[0]) - 1) + 0.5f);
 1515               }
 1516               if (nBits[1] == precision) {
 1517                   intpixel[1] = (int)(grn);
 1518               }
 1519               else {
 1520                   intpixel[1] = (int) (grn * factor * ((1<<nBits[1]) - 1) + 0.5f);
 1521               }
 1522               if (nBits[2] == precision) {
 1523                   intpixel[2] = (int)(blu);
 1524               }
 1525               else {
 1526                   intpixel[2] = (int) (blu * factor * ((1<<nBits[2]) - 1) + 0.5f);
 1527               }
 1528           } else if (is_LinearGray_stdScale) {
 1529               red = fromsRGB8LUT16[red] & 0xffff;
 1530               grn = fromsRGB8LUT16[grn] & 0xffff;
 1531               blu = fromsRGB8LUT16[blu] & 0xffff;
 1532               float gray = ((0.2125f * red) +
 1533                             (0.7154f * grn) +
 1534                             (0.0721f * blu)) / 65535.0f;
 1535               if (supportsAlpha) {
 1536                   alp = (rgb>>24) & 0xff;
 1537                   if (nBits[1] == 8) {
 1538                       intpixel[1] = alp;
 1539                   } else {
 1540                       intpixel[1] = (int) (alp * (1.0f / 255.0f) *
 1541                                            ((1 << nBits[1]) - 1) + 0.5f);
 1542                   }
 1543                   if (isAlphaPremultiplied) {
 1544                       gray *= (alp * (1.0f / 255.0f));
 1545                   }
 1546               }
 1547               intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
 1548           } else if (is_ICCGray_stdScale) {
 1549               red = fromsRGB8LUT16[red] & 0xffff;
 1550               grn = fromsRGB8LUT16[grn] & 0xffff;
 1551               blu = fromsRGB8LUT16[blu] & 0xffff;
 1552               int gray16 = (int) ((0.2125f * red) +
 1553                                   (0.7154f * grn) +
 1554                                   (0.0721f * blu) + 0.5f);
 1555               float gray = (fromLinearGray16ToOtherGray16LUT[gray16] &
 1556                             0xffff) / 65535.0f;
 1557               if (supportsAlpha) {
 1558                   alp = (rgb>>24) & 0xff;
 1559                   if (nBits[1] == 8) {
 1560                       intpixel[1] = alp;
 1561                   } else {
 1562                       intpixel[1] = (int) (alp * (1.0f / 255.0f) *
 1563                                            ((1 << nBits[1]) - 1) + 0.5f);
 1564                   }
 1565                   if (isAlphaPremultiplied) {
 1566                       gray *= (alp * (1.0f / 255.0f));
 1567                   }
 1568               }
 1569               intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
 1570           } else {
 1571               // Need to convert the color
 1572               float[] norm = new float[3];
 1573               float factor = 1.0f / 255.0f;
 1574               norm[0] = red * factor;
 1575               norm[1] = grn * factor;
 1576               norm[2] = blu * factor;
 1577               norm = colorSpace.fromRGB(norm);
 1578               if (nonStdScale) {
 1579                   for (int i = 0; i < numColorComponents; i++) {
 1580                       norm[i] = (norm[i] - compOffset[i]) *
 1581                                 compScale[i];
 1582                       // REMIND: need to analyze whether this
 1583                       // clamping is necessary
 1584                       if (norm[i] < 0.0f) {
 1585                           norm[i] = 0.0f;
 1586                       }
 1587                       if (norm[i] > 1.0f) {
 1588                           norm[i] = 1.0f;
 1589                       }
 1590                   }
 1591               }
 1592               if (supportsAlpha) {
 1593                   alp = (rgb>>24) & 0xff;
 1594                   if (nBits[numColorComponents] == 8) {
 1595                       intpixel[numColorComponents] = alp;
 1596                   }
 1597                   else {
 1598                       intpixel[numColorComponents] =
 1599                           (int) (alp * factor *
 1600                                  ((1<<nBits[numColorComponents]) - 1) + 0.5f);
 1601                   }
 1602                   if (isAlphaPremultiplied) {
 1603                       factor *= alp;
 1604                       for (int i = 0; i < numColorComponents; i++) {
 1605                           norm[i] *= factor;
 1606                       }
 1607                   }
 1608               }
 1609               for (int i = 0; i < numColorComponents; i++) {
 1610                   intpixel[i] = (int) (norm[i] * ((1<<nBits[i]) - 1) + 0.5f);
 1611               }
 1612           }
 1613   
 1614           switch (transferType) {
 1615               case DataBuffer.TYPE_BYTE: {
 1616                  byte bdata[];
 1617                  if (pixel == null) {
 1618                      bdata = new byte[numComponents];
 1619                  } else {
 1620                      bdata = (byte[])pixel;
 1621                  }
 1622                  for (int i = 0; i < numComponents; i++) {
 1623                      bdata[i] = (byte)(0xff&intpixel[i]);
 1624                  }
 1625                  return bdata;
 1626               }
 1627               case DataBuffer.TYPE_USHORT:{
 1628                  short sdata[];
 1629                  if (pixel == null) {
 1630                      sdata = new short[numComponents];
 1631                  } else {
 1632                      sdata = (short[])pixel;
 1633                  }
 1634                  for (int i = 0; i < numComponents; i++) {
 1635                      sdata[i] = (short)(intpixel[i]&0xffff);
 1636                  }
 1637                  return sdata;
 1638               }
 1639               case DataBuffer.TYPE_INT:
 1640                   if (maxBits > 23) {
 1641                       // fix 4412670 - for components of 24 or more bits
 1642                       // some calculations done above with float precision
 1643                       // may lose enough precision that the integer result
 1644                       // overflows nBits, so we need to clamp.
 1645                       for (int i = 0; i < numComponents; i++) {
 1646                           if (intpixel[i] > ((1<<nBits[i]) - 1)) {
 1647                               intpixel[i] = (1<<nBits[i]) - 1;
 1648                           }
 1649                       }
 1650                   }
 1651                   return intpixel;
 1652           }
 1653           throw new IllegalArgumentException("This method has not been "+
 1654                    "implemented for transferType " + transferType);
 1655       }
 1656   
 1657      /** Returns an array of unnormalized color/alpha components given a pixel
 1658        * in this <CODE>ColorModel</CODE>.
 1659        * An IllegalArgumentException is thrown if the component value for this
 1660        * <CODE>ColorModel</CODE> is not conveniently representable in the
 1661        * unnormalized form.  Color/alpha components are stored
 1662        * in the <CODE>components</CODE> array starting at <CODE>offset</CODE>
 1663        * (even if the array is allocated by this method).
 1664        *
 1665        * @param pixel The pixel value specified as an integer.
 1666        * @param components An integer array in which to store the unnormalized
 1667        * color/alpha components. If the <CODE>components</CODE> array is null,
 1668        * a new array is allocated.
 1669        * @param offset An offset into the <CODE>components</CODE> array.
 1670        *
 1671        * @return The components array.
 1672        *
 1673        * @throws IllegalArgumentException If there is more than one
 1674        * component in this <CODE>ColorModel</CODE>.
 1675        * @throws IllegalArgumentException If this
 1676        * <CODE>ColorModel</CODE> does not support the unnormalized form
 1677        * @throws ArrayIndexOutOfBoundsException If the <CODE>components</CODE>
 1678        * array is not null and is not large enough to hold all the color and
 1679        * alpha components (starting at offset).
 1680        */
 1681       public int[] getComponents(int pixel, int[] components, int offset) {
 1682           if (numComponents > 1) {
 1683               throw new
 1684                   IllegalArgumentException("More than one component per pixel");
 1685           }
 1686           if (needScaleInit) {
 1687               initScale();
 1688           }
 1689           if (noUnnorm) {
 1690               throw new
 1691                   IllegalArgumentException(
 1692                       "This ColorModel does not support the unnormalized form");
 1693           }
 1694           if (components == null) {
 1695               components = new int[offset+1];
 1696           }
 1697   
 1698           components[offset+0] = (pixel & ((1<<nBits[0]) - 1));
 1699           return components;
 1700       }
 1701   
 1702       /**
 1703        * Returns an array of unnormalized color/alpha components given a pixel
 1704        * in this <CODE>ColorModel</CODE>.  The pixel value is specified by an
 1705        * array of data elements of type <CODE>transferType</CODE> passed in as
 1706        * an object reference.
 1707        * An IllegalArgumentException is thrown if the component values for this
 1708        * <CODE>ColorModel</CODE> are not conveniently representable in the
 1709        * unnormalized form.
 1710        * Color/alpha components are stored in the <CODE>components</CODE> array
 1711        * starting at  <CODE>offset</CODE> (even if the array is allocated by
 1712        * this method).  Since <code>ComponentColorModel</code> can be
 1713        * subclassed, subclasses inherit the
 1714        * implementation of this method and if they don't override it then
 1715        * this method might throw an exception if they use an unsupported
 1716        * <code>transferType</code>.
 1717        *
 1718        * @param pixel A pixel value specified by an array of data elements of
 1719        * type <CODE>transferType</CODE>.
 1720        * @param components An integer array in which to store the unnormalized
 1721        * color/alpha components. If the <CODE>components</CODE> array is null,
 1722        * a new array is allocated.
 1723        * @param offset An offset into the <CODE>components</CODE> array.
 1724        *
 1725        * @return The <CODE>components</CODE> array.
 1726        *
 1727        * @throws IllegalArgumentException If this
 1728        * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
 1729        * @throws UnsupportedOperationException in some cases iff the
 1730        * transfer type of this <CODE>ComponentColorModel</CODE>
 1731        * is not one of the following transfer types:
 1732        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 1733        * or <CODE>DataBuffer.TYPE_INT</CODE>.
 1734        * @throws ClassCastException If <CODE>pixel</CODE> is not a primitive
 1735        * array of type <CODE>transferType</CODE>.
 1736        * @throws IllegalArgumentException If the <CODE>components</CODE> array is
 1737        * not null and is not large enough to hold all the color and alpha
 1738        * components (starting at offset), or if <CODE>pixel</CODE> is not large
 1739        * enough to hold a pixel value for this ColorModel.
 1740        */
 1741       public int[] getComponents(Object pixel, int[] components, int offset) {
 1742           int intpixel[];
 1743           if (needScaleInit) {
 1744               initScale();
 1745           }
 1746           if (noUnnorm) {
 1747               throw new
 1748                   IllegalArgumentException(
 1749                       "This ColorModel does not support the unnormalized form");
 1750           }
 1751           if (pixel instanceof int[]) {
 1752               intpixel = (int[])pixel;
 1753           } else {
 1754               intpixel = DataBuffer.toIntArray(pixel);
 1755               if (intpixel == null) {
 1756                  throw new UnsupportedOperationException("This method has not been "+
 1757                      "implemented for transferType " + transferType);
 1758               }
 1759           }
 1760           if (intpixel.length < numComponents) {
 1761               throw new IllegalArgumentException
 1762                   ("Length of pixel array < number of components in model");
 1763           }
 1764           if (components == null) {
 1765               components = new int[offset+numComponents];
 1766           }
 1767           else if ((components.length-offset) < numComponents) {
 1768               throw new IllegalArgumentException
 1769                   ("Length of components array < number of components in model");
 1770           }
 1771           System.arraycopy(intpixel, 0, components, offset, numComponents);
 1772   
 1773           return components;
 1774       }
 1775   
 1776       /**
 1777        * Returns an array of all of the color/alpha components in unnormalized
 1778        * form, given a normalized component array.  Unnormalized components
 1779        * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
 1780        * n is the number of bits for a particular component.  Normalized
 1781        * components are float values between a per component minimum and
 1782        * maximum specified by the <code>ColorSpace</code> object for this
 1783        * <code>ColorModel</code>.  An <code>IllegalArgumentException</code>
 1784        * will be thrown if color component values for this
 1785        * <code>ColorModel</code> are not conveniently representable in the
 1786        * unnormalized form.  If the
 1787        * <code>components</code> array is <code>null</code>, a new array
 1788        * will be allocated.  The <code>components</code> array will
 1789        * be returned.  Color/alpha components are stored in the
 1790        * <code>components</code> array starting at <code>offset</code> (even
 1791        * if the array is allocated by this method). An
 1792        * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
 1793        * <code>components</code> array is not <code>null</code> and is not
 1794        * large enough to hold all the color and alpha
 1795        * components (starting at <code>offset</code>).  An
 1796        * <code>IllegalArgumentException</code> is thrown if the
 1797        * <code>normComponents</code> array is not large enough to hold
 1798        * all the color and alpha components starting at
 1799        * <code>normOffset</code>.
 1800        * @param normComponents an array containing normalized components
 1801        * @param normOffset the offset into the <code>normComponents</code>
 1802        * array at which to start retrieving normalized components
 1803        * @param components an array that receives the components from
 1804        * <code>normComponents</code>
 1805        * @param offset the index into <code>components</code> at which to
 1806        * begin storing normalized components from
 1807        * <code>normComponents</code>
 1808        * @return an array containing unnormalized color and alpha
 1809        * components.
 1810        * @throws IllegalArgumentException If this
 1811        * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
 1812        * @throws IllegalArgumentException if the length of
 1813        *          <code>normComponents</code> minus <code>normOffset</code>
 1814        *          is less than <code>numComponents</code>
 1815        */
 1816       public int[] getUnnormalizedComponents(float[] normComponents,
 1817                                              int normOffset,
 1818                                              int[] components, int offset) {
 1819           if (needScaleInit) {
 1820               initScale();
 1821           }
 1822           if (noUnnorm) {
 1823               throw new
 1824                   IllegalArgumentException(
 1825                       "This ColorModel does not support the unnormalized form");
 1826           }
 1827           return super.getUnnormalizedComponents(normComponents, normOffset,
 1828                                                  components, offset);
 1829       }
 1830   
 1831       /**
 1832        * Returns an array of all of the color/alpha components in normalized
 1833        * form, given an unnormalized component array.  Unnormalized components
 1834        * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
 1835        * n is the number of bits for a particular component.  Normalized
 1836        * components are float values between a per component minimum and
 1837        * maximum specified by the <code>ColorSpace</code> object for this
 1838        * <code>ColorModel</code>.  An <code>IllegalArgumentException</code>
 1839        * will be thrown if color component values for this
 1840        * <code>ColorModel</code> are not conveniently representable in the
 1841        * unnormalized form.  If the
 1842        * <code>normComponents</code> array is <code>null</code>, a new array
 1843        * will be allocated.  The <code>normComponents</code> array
 1844        * will be returned.  Color/alpha components are stored in the
 1845        * <code>normComponents</code> array starting at
 1846        * <code>normOffset</code> (even if the array is allocated by this
 1847        * method).  An <code>ArrayIndexOutOfBoundsException</code> is thrown
 1848        * if the <code>normComponents</code> array is not <code>null</code>
 1849        * and is not large enough to hold all the color and alpha components
 1850        * (starting at <code>normOffset</code>).  An
 1851        * <code>IllegalArgumentException</code> is thrown if the
 1852        * <code>components</code> array is not large enough to hold all the
 1853        * color and alpha components starting at <code>offset</code>.
 1854        * @param components an array containing unnormalized components
 1855        * @param offset the offset into the <code>components</code> array at
 1856        * which to start retrieving unnormalized components
 1857        * @param normComponents an array that receives the normalized components
 1858        * @param normOffset the index into <code>normComponents</code> at
 1859        * which to begin storing normalized components
 1860        * @return an array containing normalized color and alpha
 1861        * components.
 1862        * @throws IllegalArgumentException If this
 1863        * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
 1864        */
 1865       public float[] getNormalizedComponents(int[] components, int offset,
 1866                                              float[] normComponents,
 1867                                              int normOffset) {
 1868           if (needScaleInit) {
 1869               initScale();
 1870           }
 1871           if (noUnnorm) {
 1872               throw new
 1873                   IllegalArgumentException(
 1874                       "This ColorModel does not support the unnormalized form");
 1875           }
 1876           return super.getNormalizedComponents(components, offset,
 1877                                                normComponents, normOffset);
 1878       }
 1879   
 1880       /**
 1881        * Returns a pixel value represented as an int in this <CODE>ColorModel</CODE>,
 1882        * given an array of unnormalized color/alpha components.
 1883        *
 1884        * @param components An array of unnormalized color/alpha components.
 1885        * @param offset An offset into the <CODE>components</CODE> array.
 1886        *
 1887        * @return A pixel value represented as an int.
 1888        *
 1889        * @throws IllegalArgumentException If there is more than one component
 1890        * in this <CODE>ColorModel</CODE>.
 1891        * @throws IllegalArgumentException If this
 1892        * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
 1893        */
 1894       public int getDataElement(int[] components, int offset) {
 1895           if (needScaleInit) {
 1896               initScale();
 1897           }
 1898           if (numComponents == 1) {
 1899               if (noUnnorm) {
 1900                   throw new
 1901                       IllegalArgumentException(
 1902                       "This ColorModel does not support the unnormalized form");
 1903               }
 1904               return components[offset+0];
 1905           }
 1906           throw new IllegalArgumentException("This model returns "+
 1907                                              numComponents+
 1908                                              " elements in the pixel array.");
 1909       }
 1910   
 1911       /**
 1912        * Returns a data element array representation of a pixel in this
 1913        * <CODE>ColorModel</CODE>, given an array of unnormalized color/alpha
 1914        * components. This array can then be passed to the <CODE>setDataElements</CODE>
 1915        * method of a <CODE>WritableRaster</CODE> object.
 1916        *
 1917        * @param components An array of unnormalized color/alpha components.
 1918        * @param offset The integer offset into the <CODE>components</CODE> array.
 1919        * @param obj The object in which to store the data element array
 1920        * representation of the pixel. If <CODE>obj</CODE> variable is null,
 1921        * a new array is allocated.  If <CODE>obj</CODE> is not null, it must
 1922        * be a primitive array of type <CODE>transferType</CODE>. An
 1923        * <CODE>ArrayIndexOutOfBoundsException</CODE> is thrown if
 1924        * <CODE>obj</CODE> is not large enough to hold a pixel value
 1925        * for this <CODE>ColorModel</CODE>.  Since
 1926        * <code>ComponentColorModel</code> can be subclassed, subclasses
 1927        * inherit the implementation of this method and if they don't
 1928        * override it then they throw an exception if they use an
 1929        * unsupported <code>transferType</code>.
 1930        *
 1931        * @return The data element array representation of a pixel
 1932        * in this <CODE>ColorModel</CODE>.
 1933        *
 1934        * @throws IllegalArgumentException If the components array
 1935        * is not large enough to hold all the color and alpha components
 1936        * (starting at offset).
 1937        * @throws ClassCastException If <CODE>obj</CODE> is not null and is not a
 1938        * primitive  array of type <CODE>transferType</CODE>.
 1939        * @throws ArrayIndexOutOfBoundsException If <CODE>obj</CODE> is not large
 1940        * enough to hold a pixel value for this <CODE>ColorModel</CODE>.
 1941        * @throws IllegalArgumentException If this
 1942        * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
 1943        * @throws UnsupportedOperationException If the transfer type of
 1944        * this <CODE>ComponentColorModel</CODE>
 1945        * is not one of the following transfer types:
 1946        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 1947        * or <CODE>DataBuffer.TYPE_INT</CODE>.
 1948        *
 1949        * @see WritableRaster#setDataElements
 1950        * @see SampleModel#setDataElements
 1951        */
 1952       public Object getDataElements(int[] components, int offset, Object obj) {
 1953           if (needScaleInit) {
 1954               initScale();
 1955           }
 1956           if (noUnnorm) {
 1957               throw new
 1958                   IllegalArgumentException(
 1959                       "This ColorModel does not support the unnormalized form");
 1960           }
 1961           if ((components.length-offset) < numComponents) {
 1962               throw new IllegalArgumentException("Component array too small"+
 1963                                                  " (should be "+numComponents);
 1964           }
 1965           switch(transferType) {
 1966           case DataBuffer.TYPE_INT:
 1967               {
 1968                   int[] pixel;
 1969                   if (obj == null) {
 1970                       pixel = new int[numComponents];
 1971                   }
 1972                   else {
 1973                       pixel = (int[]) obj;
 1974                   }
 1975                   System.arraycopy(components, offset, pixel, 0,
 1976                                    numComponents);
 1977                   return pixel;
 1978               }
 1979   
 1980           case DataBuffer.TYPE_BYTE:
 1981               {
 1982                   byte[] pixel;
 1983                   if (obj == null) {
 1984                       pixel = new byte[numComponents];
 1985                   }
 1986                   else {
 1987                       pixel = (byte[]) obj;
 1988                   }
 1989                   for (int i=0; i < numComponents; i++) {
 1990                       pixel[i] = (byte) (components[offset+i]&0xff);
 1991                   }
 1992                   return pixel;
 1993               }
 1994   
 1995           case DataBuffer.TYPE_USHORT:
 1996               {
 1997                   short[] pixel;
 1998                   if (obj == null) {
 1999                       pixel = new short[numComponents];
 2000                   }
 2001                   else {
 2002                       pixel = (short[]) obj;
 2003                   }
 2004                   for (int i=0; i < numComponents; i++) {
 2005                       pixel[i] = (short) (components[offset+i]&0xffff);
 2006                   }
 2007                   return pixel;
 2008               }
 2009   
 2010           default:
 2011               throw new UnsupportedOperationException("This method has not been "+
 2012                                           "implemented for transferType " +
 2013                                           transferType);
 2014           }
 2015       }
 2016   
 2017       /**
 2018        * Returns a pixel value represented as an <code>int</code> in this
 2019        * <code>ColorModel</code>, given an array of normalized color/alpha
 2020        * components.  This method will throw an
 2021