Home » openjdk-7 » java » awt » image » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2003, Oracle and/or its affiliates. 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * 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        * <code>IllegalArgumentException</code> if pixel values for this
 2022        * <code>ColorModel</code> are not conveniently representable as a
 2023        * single <code>int</code>.  An
 2024        * <code>ArrayIndexOutOfBoundsException</code> is thrown if  the
 2025        * <code>normComponents</code> array is not large enough to hold all the
 2026        * color and alpha components (starting at <code>normOffset</code>).
 2027        * @param normComponents an array of normalized color and alpha
 2028        * components
 2029        * @param normOffset the index into <code>normComponents</code> at which to
 2030        * begin retrieving the color and alpha components
 2031        * @return an <code>int</code> pixel value in this
 2032        * <code>ColorModel</code> corresponding to the specified components.
 2033        * @throws IllegalArgumentException if
 2034        *  pixel values for this <code>ColorModel</code> are not
 2035        *  conveniently representable as a single <code>int</code>
 2036        * @throws ArrayIndexOutOfBoundsException if
 2037        *  the <code>normComponents</code> array is not large enough to
 2038        *  hold all of the color and alpha components starting at
 2039        *  <code>normOffset</code>
 2040        * @since 1.4
 2041        */
 2042       public int getDataElement(float[] normComponents, int normOffset) {
 2043           if (numComponents > 1) {
 2044               throw new
 2045                   IllegalArgumentException("More than one component per pixel");
 2046           }
 2047           if (signed) {
 2048               throw new
 2049                   IllegalArgumentException("Component value is signed");
 2050           }
 2051           if (needScaleInit) {
 2052               initScale();
 2053           }
 2054           Object pixel = getDataElements(normComponents, normOffset, null);
 2055           switch (transferType) {
 2056           case DataBuffer.TYPE_BYTE:
 2057               {
 2058                   byte bpixel[] = (byte[]) pixel;
 2059                   return bpixel[0] & 0xff;
 2060               }
 2061           case DataBuffer.TYPE_USHORT:
 2062               {
 2063                   short[] uspixel = (short[]) pixel;
 2064                   return uspixel[0] & 0xffff;
 2065               }
 2066           case DataBuffer.TYPE_INT:
 2067               {
 2068                   int[] ipixel = (int[]) pixel;
 2069                   return ipixel[0];
 2070               }
 2071           default:
 2072               throw new UnsupportedOperationException("This method has not been "
 2073                   + "implemented for transferType " + transferType);
 2074           }
 2075       }
 2076   
 2077       /**
 2078        * Returns a data element array representation of a pixel in this
 2079        * <code>ColorModel</code>, given an array of normalized color/alpha
 2080        * components.  This array can then be passed to the
 2081        * <code>setDataElements</code> method of a <code>WritableRaster</code>
 2082        * object.  An <code>ArrayIndexOutOfBoundsException</code> is thrown
 2083        * if the <code>normComponents</code> array is not large enough to hold
 2084        * all the color and alpha components (starting at
 2085        * <code>normOffset</code>).  If the <code>obj</code> variable is
 2086        * <code>null</code>, a new array will be allocated.  If
 2087        * <code>obj</code> is not <code>null</code>, it must be a primitive
 2088        * array of type transferType; otherwise, a
 2089        * <code>ClassCastException</code> is thrown.  An
 2090        * <code>ArrayIndexOutOfBoundsException</code> is thrown if
 2091        * <code>obj</code> is not large enough to hold a pixel value for this
 2092        * <code>ColorModel</code>.
 2093        * @param normComponents an array of normalized color and alpha
 2094        * components
 2095        * @param normOffset the index into <code>normComponents</code> at which to
 2096        * begin retrieving color and alpha components
 2097        * @param obj a primitive data array to hold the returned pixel
 2098        * @return an <code>Object</code> which is a primitive data array
 2099        * representation of a pixel
 2100        * @throws ClassCastException if <code>obj</code>
 2101        *  is not a primitive array of type <code>transferType</code>
 2102        * @throws ArrayIndexOutOfBoundsException if
 2103        *  <code>obj</code> is not large enough to hold a pixel value
 2104        *  for this <code>ColorModel</code> or the <code>normComponents</code>
 2105        *  array is not large enough to hold all of the color and alpha
 2106        *  components starting at <code>normOffset</code>
 2107        * @see WritableRaster#setDataElements
 2108        * @see SampleModel#setDataElements
 2109        * @since 1.4
 2110        */
 2111       public Object getDataElements(float[] normComponents, int normOffset,
 2112                                     Object obj) {
 2113           boolean needAlpha = supportsAlpha && isAlphaPremultiplied;
 2114           float[] stdNormComponents;
 2115           if (needScaleInit) {
 2116               initScale();
 2117           }
 2118           if (nonStdScale) {
 2119               stdNormComponents = new float[numComponents];
 2120               for (int c = 0, nc = normOffset; c < numColorComponents;
 2121                    c++, nc++) {
 2122                   stdNormComponents[c] = (normComponents[nc] - compOffset[c]) *
 2123                                          compScale[c];
 2124                   // REMIND: need to analyze whether this
 2125                   // clamping is necessary
 2126                   if (stdNormComponents[c] < 0.0f) {
 2127                       stdNormComponents[c] = 0.0f;
 2128                   }
 2129                   if (stdNormComponents[c] > 1.0f) {
 2130                       stdNormComponents[c] = 1.0f;
 2131                   }
 2132               }
 2133               if (supportsAlpha) {
 2134                   stdNormComponents[numColorComponents] =
 2135                       normComponents[numColorComponents + normOffset];
 2136               }
 2137               normOffset = 0;
 2138           } else {
 2139               stdNormComponents = normComponents;
 2140           }
 2141           switch (transferType) {
 2142           case DataBuffer.TYPE_BYTE:
 2143               byte[] bpixel;
 2144               if (obj == null) {
 2145                   bpixel = new byte[numComponents];
 2146               } else {
 2147                   bpixel = (byte[]) obj;
 2148               }
 2149               if (needAlpha) {
 2150                   float alpha =
 2151                       stdNormComponents[numColorComponents + normOffset];
 2152                   for (int c = 0, nc = normOffset; c < numColorComponents;
 2153                        c++, nc++) {
 2154                       bpixel[c] = (byte) ((stdNormComponents[nc] * alpha) *
 2155                                           ((float) ((1 << nBits[c]) - 1)) + 0.5f);
 2156                   }
 2157                   bpixel[numColorComponents] =
 2158                       (byte) (alpha *
 2159                               ((float) ((1 << nBits[numColorComponents]) - 1)) +
 2160                               0.5f);
 2161               } else {
 2162                   for (int c = 0, nc = normOffset; c < numComponents;
 2163                        c++, nc++) {
 2164                       bpixel[c] = (byte) (stdNormComponents[nc] *
 2165                                           ((float) ((1 << nBits[c]) - 1)) + 0.5f);
 2166                   }
 2167               }
 2168               return bpixel;
 2169           case DataBuffer.TYPE_USHORT:
 2170               short[] uspixel;
 2171               if (obj == null) {
 2172                   uspixel = new short[numComponents];
 2173               } else {
 2174                   uspixel = (short[]) obj;
 2175               }
 2176               if (needAlpha) {
 2177                   float alpha =
 2178                       stdNormComponents[numColorComponents + normOffset];
 2179                   for (int c = 0, nc = normOffset; c < numColorComponents;
 2180                        c++, nc++) {
 2181                       uspixel[c] = (short) ((stdNormComponents[nc] * alpha) *
 2182                                             ((float) ((1 << nBits[c]) - 1)) +
 2183                                             0.5f);
 2184                   }
 2185                   uspixel[numColorComponents] =
 2186                       (short) (alpha *
 2187                                ((float) ((1 << nBits[numColorComponents]) - 1)) +
 2188                                0.5f);
 2189               } else {
 2190                   for (int c = 0, nc = normOffset; c < numComponents;
 2191                        c++, nc++) {
 2192                       uspixel[c] = (short) (stdNormComponents[nc] *
 2193                                             ((float) ((1 << nBits[c]) - 1)) +
 2194                                             0.5f);
 2195                   }
 2196               }
 2197               return uspixel;
 2198           case DataBuffer.TYPE_INT:
 2199               int[] ipixel;
 2200               if (obj == null) {
 2201                   ipixel = new int[numComponents];
 2202               } else {
 2203                   ipixel = (int[]) obj;
 2204               }
 2205               if (needAlpha) {
 2206                   float alpha =
 2207                       stdNormComponents[numColorComponents + normOffset];
 2208                   for (int c = 0, nc = normOffset; c < numColorComponents;
 2209                        c++, nc++) {
 2210                       ipixel[c] = (int) ((stdNormComponents[nc] * alpha) *
 2211                                          ((float) ((1 << nBits[c]) - 1)) + 0.5f);
 2212                   }
 2213                   ipixel[numColorComponents] =
 2214                       (int) (alpha *
 2215                              ((float) ((1 << nBits[numColorComponents]) - 1)) +
 2216                              0.5f);
 2217               } else {
 2218                   for (int c = 0, nc = normOffset; c < numComponents;
 2219                        c++, nc++) {
 2220                       ipixel[c] = (int) (stdNormComponents[nc] *
 2221                                          ((float) ((1 << nBits[c]) - 1)) + 0.5f);
 2222                   }
 2223               }
 2224               return ipixel;
 2225           case DataBuffer.TYPE_SHORT:
 2226               short[] spixel;
 2227               if (obj == null) {
 2228                   spixel = new short[numComponents];
 2229               } else {
 2230                   spixel = (short[]) obj;
 2231               }
 2232               if (needAlpha) {
 2233                   float alpha =
 2234                       stdNormComponents[numColorComponents + normOffset];
 2235                   for (int c = 0, nc = normOffset; c < numColorComponents;
 2236                        c++, nc++) {
 2237                       spixel[c] = (short)
 2238                           (stdNormComponents[nc] * alpha * 32767.0f + 0.5f);
 2239                   }
 2240                   spixel[numColorComponents] = (short) (alpha * 32767.0f + 0.5f);
 2241               } else {
 2242                   for (int c = 0, nc = normOffset; c < numComponents;
 2243                        c++, nc++) {
 2244                       spixel[c] = (short)
 2245                           (stdNormComponents[nc] * 32767.0f + 0.5f);
 2246                   }
 2247               }
 2248               return spixel;
 2249           case DataBuffer.TYPE_FLOAT:
 2250               float[] fpixel;
 2251               if (obj == null) {
 2252                   fpixel = new float[numComponents];
 2253               } else {
 2254                   fpixel = (float[]) obj;
 2255               }
 2256               if (needAlpha) {
 2257                   float alpha = normComponents[numColorComponents + normOffset];
 2258                   for (int c = 0, nc = normOffset; c < numColorComponents;
 2259                        c++, nc++) {
 2260                       fpixel[c] = normComponents[nc] * alpha;
 2261                   }
 2262                   fpixel[numColorComponents] = alpha;
 2263               } else {
 2264                   for (int c = 0, nc = normOffset; c < numComponents;
 2265                        c++, nc++) {
 2266                       fpixel[c] = normComponents[nc];
 2267                   }
 2268               }
 2269               return fpixel;
 2270           case DataBuffer.TYPE_DOUBLE:
 2271               double[] dpixel;
 2272               if (obj == null) {
 2273                   dpixel = new double[numComponents];
 2274               } else {
 2275                   dpixel = (double[]) obj;
 2276               }
 2277               if (needAlpha) {
 2278                   double alpha =
 2279                       (double) (normComponents[numColorComponents + normOffset]);
 2280                   for (int c = 0, nc = normOffset; c < numColorComponents;
 2281                        c++, nc++) {
 2282                       dpixel[c] = normComponents[nc] * alpha;
 2283                   }
 2284                   dpixel[numColorComponents] = alpha;
 2285               } else {
 2286                   for (int c = 0, nc = normOffset; c < numComponents;
 2287                        c++, nc++) {
 2288                       dpixel[c] = (double) normComponents[nc];
 2289                   }
 2290               }
 2291               return dpixel;
 2292           default:
 2293               throw new UnsupportedOperationException("This method has not been "+
 2294                                           "implemented for transferType " +
 2295                                           transferType);
 2296           }
 2297       }
 2298   
 2299       /**
 2300        * Returns an array of all of the color/alpha components in normalized
 2301        * form, given a pixel in this <code>ColorModel</code>.  The pixel
 2302        * value is specified by an array of data elements of type transferType
 2303        * passed in as an object reference.  If pixel is not a primitive array
 2304        * of type transferType, a <code>ClassCastException</code> is thrown.
 2305        * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
 2306        * <code>pixel</code> is not large enough to hold a pixel value for this
 2307        * <code>ColorModel</code>.
 2308        * Normalized components are float values between a per component minimum
 2309        * and maximum specified by the <code>ColorSpace</code> object for this
 2310        * <code>ColorModel</code>.  If the
 2311        * <code>normComponents</code> array is <code>null</code>, a new array
 2312        * will be allocated.  The <code>normComponents</code> array
 2313        * will be returned.  Color/alpha components are stored in the
 2314        * <code>normComponents</code> array starting at
 2315        * <code>normOffset</code> (even if the array is allocated by this
 2316        * method).  An <code>ArrayIndexOutOfBoundsException</code> is thrown
 2317        * if the <code>normComponents</code> array is not <code>null</code>
 2318        * and is not large enough to hold all the color and alpha components
 2319        * (starting at <code>normOffset</code>).
 2320        * <p>
 2321        * This method must be overrridden by a subclass if that subclass
 2322        * is designed to translate pixel sample values to color component values
 2323        * in a non-default way.  The default translations implemented by this
 2324        * class is described in the class comments.  Any subclass implementing
 2325        * a non-default translation must follow the constraints on allowable
 2326        * translations defined there.
 2327        * @param pixel the specified pixel
 2328        * @param normComponents an array to receive the normalized components
 2329        * @param normOffset the offset into the <code>normComponents</code>
 2330        * array at which to start storing normalized components
 2331        * @return an array containing normalized color and alpha
 2332        * components.
 2333        * @throws ClassCastException if <code>pixel</code> is not a primitive
 2334        *          array of type transferType
 2335        * @throws ArrayIndexOutOfBoundsException if
 2336        *          <code>normComponents</code> is not large enough to hold all
 2337        *          color and alpha components starting at <code>normOffset</code>
 2338        * @throws ArrayIndexOutOfBoundsException if
 2339        *          <code>pixel</code> is not large enough to hold a pixel
 2340        *          value for this <code>ColorModel</code>.
 2341        * @since 1.4
 2342        */
 2343       public float[] getNormalizedComponents(Object pixel,
 2344                                              float[] normComponents,
 2345                                              int normOffset) {
 2346           if (normComponents == null) {
 2347               normComponents = new float[numComponents+normOffset];
 2348           }
 2349           switch (transferType) {
 2350           case DataBuffer.TYPE_BYTE:
 2351               byte[] bpixel = (byte[]) pixel;
 2352               for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
 2353                   normComponents[nc] = ((float) (bpixel[c] & 0xff)) /
 2354                                        ((float) ((1 << nBits[c]) - 1));
 2355               }
 2356               break;
 2357           case DataBuffer.TYPE_USHORT:
 2358               short[] uspixel = (short[]) pixel;
 2359               for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
 2360                   normComponents[nc] = ((float) (uspixel[c] & 0xffff)) /
 2361                                        ((float) ((1 << nBits[c]) - 1));
 2362               }
 2363               break;
 2364           case DataBuffer.TYPE_INT:
 2365               int[] ipixel = (int[]) pixel;
 2366               for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
 2367                   normComponents[nc] = ((float) ipixel[c]) /
 2368                                        ((float) ((1 << nBits[c]) - 1));
 2369               }
 2370               break;
 2371           case DataBuffer.TYPE_SHORT:
 2372               short[] spixel = (short[]) pixel;
 2373               for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
 2374                   normComponents[nc] = ((float) spixel[c]) / 32767.0f;
 2375               }
 2376               break;
 2377           case DataBuffer.TYPE_FLOAT:
 2378               float[] fpixel = (float[]) pixel;
 2379               for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
 2380                   normComponents[nc] = fpixel[c];
 2381               }
 2382               break;
 2383           case DataBuffer.TYPE_DOUBLE:
 2384               double[] dpixel = (double[]) pixel;
 2385               for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
 2386                   normComponents[nc] = (float) dpixel[c];
 2387               }
 2388               break;
 2389           default:
 2390               throw new UnsupportedOperationException("This method has not been "+
 2391                                           "implemented for transferType " +
 2392                                           transferType);
 2393           }
 2394   
 2395           if (supportsAlpha && isAlphaPremultiplied) {
 2396               float alpha = normComponents[numColorComponents + normOffset];
 2397               if (alpha != 0.0f) {
 2398                   float invAlpha = 1.0f / alpha;
 2399                   for (int c = normOffset; c < numColorComponents + normOffset;
 2400                        c++) {
 2401                       normComponents[c] *= invAlpha;
 2402                   }
 2403               }
 2404           }
 2405           if (min != null) {
 2406               // Normally (i.e. when this class is not subclassed to override
 2407               // this method), the test (min != null) will be equivalent to
 2408               // the test (nonStdScale).  However, there is an unlikely, but
 2409               // possible case, in which this method is overridden, nonStdScale
 2410               // is set true by initScale(), the subclass method for some
 2411               // reason calls this superclass method, but the min and
 2412               // diffMinMax arrays were never initialized by setupLUTs().  In
 2413               // that case, the right thing to do is follow the intended
 2414               // semantics of this method, and rescale the color components
 2415               // only if the ColorSpace min/max were detected to be other
 2416               // than 0.0/1.0 by setupLUTs().  Note that this implies the
 2417               // transferType is byte, ushort, int, or short - i.e. components
 2418               // derived from float and double pixel data are never rescaled.
 2419               for (int c = 0; c < numColorComponents; c++) {
 2420                   normComponents[c + normOffset] = min[c] +
 2421                       diffMinMax[c] * normComponents[c + normOffset];
 2422               }
 2423           }
 2424           return normComponents;
 2425       }
 2426   
 2427       /**
 2428        * Forces the raster data to match the state specified in the
 2429        * <CODE>isAlphaPremultiplied</CODE> variable, assuming the data
 2430        * is currently correctly described by this <CODE>ColorModel</CODE>.
 2431        * It may multiply or divide the color raster data by alpha, or
 2432        * do nothing if the data is in the correct state.  If the data needs
 2433        * to be coerced, this method also returns an instance of
 2434        * this <CODE>ColorModel</CODE> with
 2435        * the <CODE>isAlphaPremultiplied</CODE> flag set appropriately.
 2436        * Since <code>ColorModel</code> can be subclassed, subclasses inherit
 2437        * the implementation of this method and if they don't override it
 2438        * then they throw an exception if they use an unsupported
 2439        * <code>transferType</code>.
 2440        *
 2441        * @throws NullPointerException if <code>raster</code> is
 2442        * <code>null</code> and data coercion is required.
 2443        * @throws UnsupportedOperationException if the transfer type of
 2444        * this <CODE>ComponentColorModel</CODE>
 2445        * is not one of the supported transfer types:
 2446        * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 2447        * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
 2448        * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 2449        */
 2450       public ColorModel coerceData (WritableRaster raster,
 2451                                     boolean isAlphaPremultiplied) {
 2452           if ((supportsAlpha == false) ||
 2453               (this.isAlphaPremultiplied == isAlphaPremultiplied))
 2454           {
 2455               // Nothing to do
 2456               return this;
 2457           }
 2458   
 2459           int w = raster.getWidth();
 2460           int h = raster.getHeight();
 2461           int aIdx = raster.getNumBands() - 1;
 2462           float normAlpha;
 2463           int rminX = raster.getMinX();
 2464           int rY = raster.getMinY();
 2465           int rX;
 2466           if (isAlphaPremultiplied) {
 2467               switch (transferType) {
 2468                   case DataBuffer.TYPE_BYTE: {
 2469                       byte pixel[] = null;
 2470                       byte zpixel[] = null;
 2471                       float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
 2472                       for (int y = 0; y < h; y++, rY++) {
 2473                           rX = rminX;
 2474                           for (int x = 0; x < w; x++, rX++) {
 2475                               pixel = (byte[])raster.getDataElements(rX, rY,
 2476                                                                      pixel);
 2477                               normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
 2478                               if (normAlpha != 0.0f) {
 2479                                   for (int c=0; c < aIdx; c++) {
 2480                                       pixel[c] = (byte)((pixel[c] & 0xff) *
 2481                                                         normAlpha + 0.5f);
 2482                                   }
 2483                                   raster.setDataElements(rX, rY, pixel);
 2484                               } else {
 2485                                   if (zpixel == null) {
 2486                                       zpixel = new byte[numComponents];
 2487                                       java.util.Arrays.fill(zpixel, (byte) 0);
 2488                                   }
 2489                                   raster.setDataElements(rX, rY, zpixel);
 2490                               }
 2491                           }
 2492                       }
 2493                   }
 2494                   break;
 2495                   case DataBuffer.TYPE_USHORT: {
 2496                       short pixel[] = null;
 2497                       short zpixel[] = null;
 2498                       float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
 2499                       for (int y = 0; y < h; y++, rY++) {
 2500                           rX = rminX;
 2501                           for (int x = 0; x < w; x++, rX++) {
 2502                               pixel = (short[])raster.getDataElements(rX, rY,
 2503                                                                       pixel);
 2504                               normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
 2505                               if (normAlpha != 0.0f) {
 2506                                   for (int c=0; c < aIdx; c++) {
 2507                                       pixel[c] = (short)
 2508                                           ((pixel[c] & 0xffff) * normAlpha +
 2509                                            0.5f);
 2510                                   }
 2511                                   raster.setDataElements(rX, rY, pixel);
 2512                               } else {
 2513                                   if (zpixel == null) {
 2514                                       zpixel = new short[numComponents];
 2515                                       java.util.Arrays.fill(zpixel, (short) 0);
 2516                                   }
 2517                                   raster.setDataElements(rX, rY, zpixel);
 2518                               }
 2519                           }
 2520                       }
 2521                   }
 2522                   break;
 2523                   case DataBuffer.TYPE_INT: {
 2524                       int pixel[] = null;
 2525                       int zpixel[] = null;
 2526                       float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
 2527                       for (int y = 0; y < h; y++, rY++) {
 2528                           rX = rminX;
 2529                           for (int x = 0; x < w; x++, rX++) {
 2530                               pixel = (int[])raster.getDataElements(rX, rY,
 2531                                                                     pixel);
 2532                               normAlpha = pixel[aIdx] * alphaScale;
 2533                               if (normAlpha != 0.0f) {
 2534                                   for (int c=0; c < aIdx; c++) {
 2535                                       pixel[c] = (int) (pixel[c] * normAlpha +
 2536                                                         0.5f);
 2537                                   }
 2538                                   raster.setDataElements(rX, rY, pixel);
 2539                               } else {
 2540                                   if (zpixel == null) {
 2541                                       zpixel = new int[numComponents];
 2542                                       java.util.Arrays.fill(zpixel, 0);
 2543                                   }
 2544                                   raster.setDataElements(rX, rY, zpixel);
 2545                               }
 2546                           }
 2547                       }
 2548                   }
 2549                   break;
 2550                   case DataBuffer.TYPE_SHORT: {
 2551                       short pixel[] = null;
 2552                       short zpixel[] = null;
 2553                       float alphaScale = 1.0f / 32767.0f;
 2554                       for (int y = 0; y < h; y++, rY++) {
 2555                           rX = rminX;
 2556                           for (int x = 0; x < w; x++, rX++) {
 2557                               pixel = (short[]) raster.getDataElements(rX, rY,
 2558                                                                        pixel);
 2559                               normAlpha = pixel[aIdx] * alphaScale;
 2560                               if (normAlpha != 0.0f) {
 2561                                   for (int c=0; c < aIdx; c++) {
 2562                                       pixel[c] = (short) (pixel[c] * normAlpha +
 2563                                                           0.5f);
 2564                                   }
 2565                                   raster.setDataElements(rX, rY, pixel);
 2566                               } else {
 2567                                   if (zpixel == null) {
 2568                                       zpixel = new short[numComponents];
 2569                                       java.util.Arrays.fill(zpixel, (short) 0);
 2570                                   }
 2571                                   raster.setDataElements(rX, rY, zpixel);
 2572                               }
 2573                           }
 2574                       }
 2575                   }
 2576                   break;
 2577                   case DataBuffer.TYPE_FLOAT: {
 2578                       float pixel[] = null;
 2579                       float zpixel[] = null;
 2580                       for (int y = 0; y < h; y++, rY++) {
 2581                           rX = rminX;
 2582                           for (int x = 0; x < w; x++, rX++) {
 2583                               pixel = (float[]) raster.getDataElements(rX, rY,
 2584                                                                        pixel);
 2585                               normAlpha = pixel[aIdx];
 2586                               if (normAlpha != 0.0f) {
 2587                                   for (int c=0; c < aIdx; c++) {
 2588                                       pixel[c] *= normAlpha;
 2589                                   }
 2590                                   raster.setDataElements(rX, rY, pixel);
 2591                               } else {
 2592                                   if (zpixel == null) {
 2593                                       zpixel = new float[numComponents];
 2594                                       java.util.Arrays.fill(zpixel, 0.0f);
 2595                                   }
 2596                                   raster.setDataElements(rX, rY, zpixel);
 2597                               }
 2598                           }
 2599                       }
 2600                   }
 2601                   break;
 2602                   case DataBuffer.TYPE_DOUBLE: {
 2603                       double pixel[] = null;
 2604                       double zpixel[] = null;
 2605                       for (int y = 0; y < h; y++, rY++) {
 2606                           rX = rminX;
 2607                           for (int x = 0; x < w; x++, rX++) {
 2608                               pixel = (double[]) raster.getDataElements(rX, rY,
 2609                                                                         pixel);
 2610                               double dnormAlpha = pixel[aIdx];
 2611                               if (dnormAlpha != 0.0) {
 2612                                   for (int c=0; c < aIdx; c++) {
 2613                                       pixel[c] *= dnormAlpha;
 2614                                   }
 2615                                   raster.setDataElements(rX, rY, pixel);
 2616                               } else {
 2617                                   if (zpixel == null) {
 2618                                       zpixel = new double[numComponents];
 2619                                       java.util.Arrays.fill(zpixel, 0.0);
 2620                                   }
 2621                                   raster.setDataElements(rX, rY, zpixel);
 2622                               }
 2623                           }
 2624                       }
 2625                   }
 2626                   break;
 2627                   default:
 2628                       throw new UnsupportedOperationException("This method has not been "+
 2629                            "implemented for transferType " + transferType);
 2630               }
 2631           }
 2632           else {
 2633               // We are premultiplied and want to divide it out
 2634               switch (transferType) {
 2635                   case DataBuffer.TYPE_BYTE: {
 2636                       byte pixel[] = null;
 2637                       float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
 2638                       for (int y = 0; y < h; y++, rY++) {
 2639                           rX = rminX;
 2640                           for (int x = 0; x < w; x++, rX++) {
 2641                               pixel = (byte[])raster.getDataElements(rX, rY,
 2642                                                                      pixel);
 2643                               normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
 2644                               if (normAlpha != 0.0f) {
 2645                                   float invAlpha = 1.0f / normAlpha;
 2646                                   for (int c=0; c < aIdx; c++) {
 2647                                       pixel[c] = (byte)
 2648                                           ((pixel[c] & 0xff) * invAlpha + 0.5f);
 2649                                   }
 2650                                   raster.setDataElements(rX, rY, pixel);
 2651                               }
 2652                           }
 2653                       }
 2654                   }
 2655                   break;
 2656                   case DataBuffer.TYPE_USHORT: {
 2657                       short pixel[] = null;
 2658                       float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
 2659                       for (int y = 0; y < h; y++, rY++) {
 2660                           rX = rminX;
 2661                           for (int x = 0; x < w; x++, rX++) {
 2662                               pixel = (short[])raster.getDataElements(rX, rY,
 2663                                                                       pixel);
 2664                               normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
 2665                               if (normAlpha != 0.0f) {
 2666                                   float invAlpha = 1.0f / normAlpha;
 2667                                   for (int c=0; c < aIdx; c++) {
 2668                                       pixel[c] = (short)
 2669                                           ((pixel[c] & 0xffff) * invAlpha + 0.5f);
 2670                                   }
 2671                                   raster.setDataElements(rX, rY, pixel);
 2672                               }
 2673                           }
 2674                       }
 2675                   }
 2676                   break;
 2677                   case DataBuffer.TYPE_INT: {
 2678                       int pixel[] = null;
 2679                       float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
 2680                       for (int y = 0; y < h; y++, rY++) {
 2681                           rX = rminX;
 2682                           for (int x = 0; x < w; x++, rX++) {
 2683                               pixel = (int[])raster.getDataElements(rX, rY,
 2684                                                                     pixel);
 2685                               normAlpha = pixel[aIdx] * alphaScale;
 2686                               if (normAlpha != 0.0f) {
 2687                                   float invAlpha = 1.0f / normAlpha;
 2688                                   for (int c=0; c < aIdx; c++) {
 2689                                       pixel[c] = (int)
 2690                                           (pixel[c] * invAlpha + 0.5f);
 2691                                   }
 2692                                   raster.setDataElements(rX, rY, pixel);
 2693                               }
 2694                           }
 2695                       }
 2696                   }
 2697                   break;
 2698                   case DataBuffer.TYPE_SHORT: {
 2699                       short pixel[] = null;
 2700                       float alphaScale = 1.0f / 32767.0f;
 2701                       for (int y = 0; y < h; y++, rY++) {
 2702                           rX = rminX;
 2703                           for (int x = 0; x < w; x++, rX++) {
 2704                               pixel = (short[])raster.getDataElements(rX, rY,
 2705                                                                       pixel);
 2706                               normAlpha = pixel[aIdx] * alphaScale;
 2707                               if (normAlpha != 0.0f) {
 2708                                   float invAlpha = 1.0f / normAlpha;
 2709                                   for (int c=0; c < aIdx; c++) {
 2710                                       pixel[c] = (short)
 2711                                           (pixel[c] * invAlpha + 0.5f);
 2712                                   }
 2713                                   raster.setDataElements(rX, rY, pixel);
 2714                               }
 2715                           }
 2716                       }
 2717                   }
 2718                   break;
 2719                   case DataBuffer.TYPE_FLOAT: {
 2720                       float pixel[] = null;
 2721                       for (int y = 0; y < h; y++, rY++) {
 2722                           rX = rminX;
 2723                           for (int x = 0; x < w; x++, rX++) {
 2724                               pixel = (float[])raster.getDataElements(rX, rY,
 2725                                                                       pixel);
 2726                               normAlpha = pixel[aIdx];
 2727                               if (normAlpha != 0.0f) {
 2728                                   float invAlpha = 1.0f / normAlpha;
 2729                                   for (int c=0; c < aIdx; c++) {
 2730                                       pixel[c] *= invAlpha;
 2731                                   }
 2732                                   raster.setDataElements(rX, rY, pixel);
 2733                               }
 2734                           }
 2735                       }
 2736                   }
 2737                   break;
 2738                   case DataBuffer.TYPE_DOUBLE: {
 2739                       double pixel[] = null;
 2740                       for (int y = 0; y < h; y++, rY++) {
 2741                           rX = rminX;
 2742                           for (int x = 0; x < w; x++, rX++) {
 2743                               pixel = (double[])raster.getDataElements(rX, rY,
 2744                                                                        pixel);
 2745                               double dnormAlpha = pixel[aIdx];
 2746                               if (dnormAlpha != 0.0) {
 2747                                   double invAlpha = 1.0 / dnormAlpha;
 2748                                   for (int c=0; c < aIdx; c++) {
 2749                                       pixel[c] *= invAlpha;
 2750                                   }
 2751                                   raster.setDataElements(rX, rY, pixel);
 2752                               }
 2753                           }
 2754                       }
 2755                   }
 2756                   break;
 2757                   default:
 2758                       throw new UnsupportedOperationException("This method has not been "+
 2759                            "implemented for transferType " + transferType);
 2760               }
 2761           }
 2762   
 2763           // Return a new color model
 2764           if (!signed) {
 2765               return new ComponentColorModel(colorSpace, nBits, supportsAlpha,
 2766                                              isAlphaPremultiplied, transparency,
 2767                                              transferType);
 2768           } else {
 2769               return new ComponentColorModel(colorSpace, supportsAlpha,
 2770                                              isAlphaPremultiplied, transparency,
 2771                                              transferType);
 2772           }
 2773   
 2774       }
 2775   
 2776       /**
 2777         * Returns true if <CODE>raster</CODE> is compatible with this
 2778         * <CODE>ColorModel</CODE>; false if it is not.
 2779         *
 2780         * @param raster The <CODE>Raster</CODE> object to test for compatibility.
 2781         *
 2782         * @return <CODE>true</CODE> if <CODE>raster</CODE> is compatible with this
 2783         * <CODE>ColorModel</CODE>, <CODE>false</CODE> if it is not.
 2784         */
 2785       public boolean isCompatibleRaster(Raster raster) {
 2786   
 2787           SampleModel sm = raster.getSampleModel();
 2788   
 2789           if (sm instanceof ComponentSampleModel) {
 2790               if (sm.getNumBands() != getNumComponents()) {
 2791                   return false;
 2792               }
 2793               for (int i=0; i<nBits.length; i++) {
 2794                   if (sm.getSampleSize(i) < nBits[i]) {
 2795                       return false;
 2796                   }
 2797               }
 2798               return (raster.getTransferType() == transferType);
 2799           }
 2800           else {
 2801               return false;
 2802           }
 2803       }
 2804   
 2805       /**
 2806        * Creates a <CODE>WritableRaster</CODE> with the specified width and height,
 2807        * that  has a data layout (<CODE>SampleModel</CODE>) compatible with
 2808        * this <CODE>ColorModel</CODE>.
 2809        *
 2810        * @param w The width of the <CODE>WritableRaster</CODE> you want to create.
 2811        * @param h The height of the <CODE>WritableRaster</CODE> you want to create.
 2812        *
 2813        * @return A <CODE>WritableRaster</CODE> that is compatible with
 2814        * this <CODE>ColorModel</CODE>.
 2815        * @see WritableRaster
 2816        * @see SampleModel
 2817        */
 2818       public WritableRaster createCompatibleWritableRaster (int w, int h) {
 2819           int dataSize = w*h*numComponents;
 2820           WritableRaster raster = null;
 2821   
 2822           switch (transferType) {
 2823           case DataBuffer.TYPE_BYTE:
 2824           case DataBuffer.TYPE_USHORT:
 2825               raster = Raster.createInterleavedRaster(transferType,
 2826                                                       w, h,
 2827                                                       numComponents, null);
 2828               break;
 2829           default:
 2830               SampleModel sm = createCompatibleSampleModel(w, h);
 2831               DataBuffer db = sm.createDataBuffer();
 2832               raster = Raster.createWritableRaster(sm, db, null);
 2833           }
 2834   
 2835           return raster;
 2836       }
 2837   
 2838       /**
 2839        * Creates a <CODE>SampleModel</CODE> with the specified width and height,
 2840        * that  has a data layout compatible with this <CODE>ColorModel</CODE>.
 2841        *
 2842        * @param w The width of the <CODE>SampleModel</CODE> you want to create.
 2843        * @param h The height of the <CODE>SampleModel</CODE> you want to create.
 2844        *
 2845        * @return A <CODE>SampleModel</CODE> that is compatible with this
 2846        * <CODE>ColorModel</CODE>.
 2847        *
 2848        * @see SampleModel
 2849        */
 2850       public SampleModel createCompatibleSampleModel(int w, int h) {
 2851           int[] bandOffsets = new int[numComponents];
 2852           for (int i=0; i < numComponents; i++) {
 2853               bandOffsets[i] = i;
 2854           }
 2855           switch (transferType) {
 2856           case DataBuffer.TYPE_BYTE:
 2857           case DataBuffer.TYPE_USHORT:
 2858               return new PixelInterleavedSampleModel(transferType, w, h,
 2859                                                      numComponents,
 2860                                                      w*numComponents,
 2861                                                      bandOffsets);
 2862           default:
 2863               return new ComponentSampleModel(transferType, w, h,
 2864                                               numComponents,
 2865                                               w*numComponents,
 2866                                               bandOffsets);
 2867           }
 2868       }
 2869   
 2870       /**
 2871        * Checks whether or not the specified <CODE>SampleModel</CODE>
 2872        * is compatible with this <CODE>ColorModel</CODE>.
 2873        *
 2874        * @param sm The <CODE>SampleModel</CODE> to test for compatibility.
 2875        *
 2876        * @return <CODE>true</CODE> if the <CODE>SampleModel</CODE> is
 2877        * compatible with this <CODE>ColorModel</CODE>, <CODE>false</CODE>
 2878        * if it is not.
 2879        *
 2880        * @see SampleModel
 2881        */
 2882       public boolean isCompatibleSampleModel(SampleModel sm) {
 2883           if (!(sm instanceof ComponentSampleModel)) {
 2884               return false;
 2885           }
 2886   
 2887           // Must have the same number of components
 2888           if (numComponents != sm.getNumBands()) {
 2889               return false;
 2890           }
 2891   
 2892           if (sm.getTransferType() != transferType) {
 2893               return false;
 2894           }
 2895   
 2896           return true;
 2897       }
 2898   
 2899       /**
 2900        * Returns a <CODE>Raster</CODE> representing the alpha channel of an image,
 2901        * extracted from the input <CODE>Raster</CODE>.
 2902        * This method assumes that <CODE>Raster</CODE> objects associated with
 2903        * this <CODE>ColorModel</CODE> store the alpha band, if present, as
 2904        * the last band of image data. Returns null if there is no separate spatial
 2905        * alpha channel associated with this <CODE>ColorModel</CODE>.
 2906        * This method creates a new <CODE>Raster</CODE>, but will share the data
 2907        * array.
 2908        *
 2909        * @param raster The <CODE>WritableRaster</CODE> from which to extract the
 2910        * alpha  channel.
 2911        *
 2912        * @return A <CODE>WritableRaster</CODE> containing the image's alpha channel.
 2913        *
 2914        */
 2915       public WritableRaster getAlphaRaster(WritableRaster raster) {
 2916           if (hasAlpha() == false) {
 2917               return null;
 2918           }
 2919   
 2920           int x = raster.getMinX();
 2921           int y = raster.getMinY();
 2922           int[] band = new int[1];
 2923           band[0] = raster.getNumBands() - 1;
 2924           return raster.createWritableChild(x, y, raster.getWidth(),
 2925                                             raster.getHeight(), x, y,
 2926                                             band);
 2927       }
 2928   
 2929       /**
 2930        * Compares this color model with another for equality.
 2931        *
 2932        * @param obj The object to compare with this color model.
 2933        * @return <CODE>true</CODE> if the color model objects are equal,
 2934        * <CODE>false</CODE> if they are not.
 2935        */
 2936       public boolean equals(Object obj) {
 2937           if (!super.equals(obj)) {
 2938               return false;
 2939           }
 2940   
 2941           if (obj.getClass() !=  getClass()) {
 2942               return false;
 2943           }
 2944   
 2945           return true;
 2946       }
 2947   
 2948   }

Home » openjdk-7 » java » awt » image » [javadoc | source]