src/java.desktop/share/classes/java/awt/image/ComponentColorModel.java
changeset 47216 71c04702a3d5
parent 43827 a02bc4e52007
child 52248 2e330da7cbf4
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1997, 2017, 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 import java.util.Arrays;
       
    31 
       
    32 /**
       
    33  * A {@code ColorModel} class that works with pixel values that
       
    34  * represent color and alpha information as separate samples and that
       
    35  * store each sample in a separate data element.  This class can be
       
    36  * used with an arbitrary {@code ColorSpace}.  The number of
       
    37  * color samples in the pixel values must be same as the number of
       
    38  * color components in the {@code ColorSpace}. There may be a
       
    39  * single alpha sample.
       
    40  * <p>
       
    41  * For those methods that use
       
    42  * a primitive array pixel representation of type {@code transferType},
       
    43  * the array length is the same as the number of color and alpha samples.
       
    44  * Color samples are stored first in the array followed by the alpha
       
    45  * sample, if present.  The order of the color samples is specified
       
    46  * by the {@code ColorSpace}.  Typically, this order reflects the
       
    47  * name of the color space type. For example, for {@code TYPE_RGB},
       
    48  * index 0 corresponds to red, index 1 to green, and index 2 to blue.
       
    49  * <p>
       
    50  * The translation from pixel sample values to color/alpha components for
       
    51  * display or processing purposes is based on a one-to-one correspondence of
       
    52  * samples to components.
       
    53  * Depending on the transfer type used to create an instance of
       
    54  * {@code ComponentColorModel}, the pixel sample values
       
    55  * represented by that instance may be signed or unsigned and may
       
    56  * be of integral type or float or double (see below for details).
       
    57  * The translation from sample values to normalized color/alpha components
       
    58  * must follow certain rules.  For float and double samples, the translation
       
    59  * is an identity, i.e. normalized component values are equal to the
       
    60  * corresponding sample values.  For integral samples, the translation
       
    61  * should be only a simple scale and offset, where the scale and offset
       
    62  * constants may be different for each component.  The result of
       
    63  * applying the scale and offset constants is a set of color/alpha
       
    64  * component values, which are guaranteed to fall within a certain
       
    65  * range.  Typically, the range for a color component will be the range
       
    66  * defined by the {@code getMinValue} and {@code getMaxValue}
       
    67  * methods of the {@code ColorSpace} class.  The range for an
       
    68  * alpha component should be 0.0 to 1.0.
       
    69  * <p>
       
    70  * Instances of {@code ComponentColorModel} created with transfer types
       
    71  * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
    72  * and {@code DataBuffer.TYPE_INT} have pixel sample values which
       
    73  * are treated as unsigned integral values.
       
    74  * The number of bits in a color or alpha sample of a pixel value might not
       
    75  * be the same as the number of bits for the corresponding color or alpha
       
    76  * sample passed to the
       
    77  * {@code ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)}
       
    78  * constructor.  In
       
    79  * that case, this class assumes that the least significant n bits of a sample
       
    80  * value hold the component value, where n is the number of significant bits
       
    81  * for the component passed to the constructor.  It also assumes that
       
    82  * any higher-order bits in a sample value are zero.  Thus, sample values
       
    83  * range from 0 to 2<sup>n</sup> - 1.  This class maps these sample values
       
    84  * to normalized color component values such that 0 maps to the value
       
    85  * obtained from the {@code ColorSpace's getMinValue}
       
    86  * method for each component and 2<sup>n</sup> - 1 maps to the value
       
    87  * obtained from {@code getMaxValue}.  To create a
       
    88  * {@code ComponentColorModel} with a different color sample mapping
       
    89  * requires subclassing this class and overriding the
       
    90  * {@code getNormalizedComponents(Object, float[], int)} method.
       
    91  * The mapping for an alpha sample always maps 0 to 0.0 and
       
    92  * 2<sup>n</sup> - 1 to 1.0.
       
    93  * <p>
       
    94  * For instances with unsigned sample values,
       
    95  * the unnormalized color/alpha component representation is only
       
    96  * supported if two conditions hold.  First, sample value 0 must
       
    97  * map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1
       
    98  * to 1.0.  Second the min/max range of all color components of the
       
    99  * {@code ColorSpace} must be 0.0 to 1.0.  In this case, the
       
   100  * component representation is the n least
       
   101  * significant bits of the corresponding sample.  Thus each component is
       
   102  * an unsigned integral value between 0 and 2<sup>n</sup> - 1, where
       
   103  * n is the number of significant bits for a particular component.
       
   104  * If these conditions are not met, any method taking an unnormalized
       
   105  * component argument will throw an {@code IllegalArgumentException}.
       
   106  * <p>
       
   107  * Instances of {@code ComponentColorModel} created with transfer types
       
   108  * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, and
       
   109  * {@code DataBuffer.TYPE_DOUBLE} have pixel sample values which
       
   110  * are treated as signed short, float, or double values.
       
   111  * Such instances do not support the unnormalized color/alpha component
       
   112  * representation, so any methods taking such a representation as an argument
       
   113  * will throw an {@code IllegalArgumentException} when called on one
       
   114  * of these instances.  The normalized component values of instances
       
   115  * of this class have a range which depends on the transfer
       
   116  * type as follows: for float samples, the full range of the float data
       
   117  * type; for double samples, the full range of the float data type
       
   118  * (resulting from casting double to float); for short samples,
       
   119  * from approximately -maxVal to +maxVal, where maxVal is the per
       
   120  * component maximum value for the {@code ColorSpace}
       
   121  * (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps
       
   122  * to +maxVal).  A subclass may override the scaling for short sample
       
   123  * values to normalized component values by overriding the
       
   124  * {@code getNormalizedComponents(Object, float[], int)} method.
       
   125  * For float and double samples, the normalized component values are
       
   126  * taken to be equal to the corresponding sample values, and subclasses
       
   127  * should not attempt to add any non-identity scaling for these transfer
       
   128  * types.
       
   129  * <p>
       
   130  * Instances of {@code ComponentColorModel} created with transfer types
       
   131  * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, and
       
   132  * {@code DataBuffer.TYPE_DOUBLE}
       
   133  * use all the bits of all sample values.  Thus all color/alpha components
       
   134  * have 16 bits when using {@code DataBuffer.TYPE_SHORT}, 32 bits when
       
   135  * using {@code DataBuffer.TYPE_FLOAT}, and 64 bits when using
       
   136  * {@code DataBuffer.TYPE_DOUBLE}.  When the
       
   137  * {@code ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)}
       
   138  * form of constructor is used with one of these transfer types, the
       
   139  * bits array argument is ignored.
       
   140  * <p>
       
   141  * It is possible to have color/alpha sample values
       
   142  * which cannot be reasonably interpreted as component values for rendering.
       
   143  * This can happen when {@code ComponentColorModel} is subclassed to
       
   144  * override the mapping of unsigned sample values to normalized color
       
   145  * component values or when signed sample values outside a certain range
       
   146  * are used.  (As an example, specifying an alpha component as a signed
       
   147  * short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can
       
   148  * lead to unexpected results.) It is the
       
   149  * responsibility of applications to appropriately scale pixel data before
       
   150  * rendering such that color components fall within the normalized range
       
   151  * of the {@code ColorSpace} (obtained using the {@code getMinValue}
       
   152  * and {@code getMaxValue} methods of the {@code ColorSpace} class)
       
   153  * and the alpha component is between 0.0 and 1.0.  If color or alpha
       
   154  * component values fall outside these ranges, rendering results are
       
   155  * indeterminate.
       
   156  * <p>
       
   157  * Methods that use a single int pixel representation throw
       
   158  * an {@code IllegalArgumentException}, unless the number of components
       
   159  * for the {@code ComponentColorModel} is one and the component
       
   160  * value is unsigned -- in other words,  a single color component using
       
   161  * a transfer type of {@code DataBuffer.TYPE_BYTE},
       
   162  * {@code DataBuffer.TYPE_USHORT}, or {@code DataBuffer.TYPE_INT}
       
   163  * and no alpha.
       
   164  * <p>
       
   165  * A {@code ComponentColorModel} can be used in conjunction with a
       
   166  * {@code ComponentSampleModel}, a {@code BandedSampleModel},
       
   167  * or a {@code PixelInterleavedSampleModel} to construct a
       
   168  * {@code BufferedImage}.
       
   169  *
       
   170  * @see ColorModel
       
   171  * @see ColorSpace
       
   172  * @see ComponentSampleModel
       
   173  * @see BandedSampleModel
       
   174  * @see PixelInterleavedSampleModel
       
   175  * @see BufferedImage
       
   176  *
       
   177  */
       
   178 public class ComponentColorModel extends ColorModel {
       
   179 
       
   180     /**
       
   181      * {@code signed}  is {@code true} for {@code short},
       
   182      * {@code float}, and {@code double} transfer types; it
       
   183      * is {@code false} for {@code byte}, {@code ushort},
       
   184      * and {@code int} transfer types.
       
   185      */
       
   186     private boolean signed; // true for transfer types short, float, double
       
   187                             // false for byte, ushort, int
       
   188     private boolean is_sRGB_stdScale;
       
   189     private boolean is_LinearRGB_stdScale;
       
   190     private boolean is_LinearGray_stdScale;
       
   191     private boolean is_ICCGray_stdScale;
       
   192     private byte[] tosRGB8LUT;
       
   193     private byte[] fromsRGB8LUT8;
       
   194     private short[] fromsRGB8LUT16;
       
   195     private byte[] fromLinearGray16ToOtherGray8LUT;
       
   196     private short[] fromLinearGray16ToOtherGray16LUT;
       
   197     private boolean needScaleInit;
       
   198     private boolean noUnnorm;
       
   199     private boolean nonStdScale;
       
   200     private float[] min;
       
   201     private float[] diffMinMax;
       
   202     private float[] compOffset;
       
   203     private float[] compScale;
       
   204     private volatile int hashCode;
       
   205 
       
   206     /**
       
   207      * Constructs a {@code ComponentColorModel} from the specified
       
   208      * parameters. Color components will be in the specified
       
   209      * {@code ColorSpace}.  The supported transfer types are
       
   210      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
   211      * {@code DataBuffer.TYPE_INT},
       
   212      * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT},
       
   213      * and {@code DataBuffer.TYPE_DOUBLE}.
       
   214      * If not null, the {@code bits} array specifies the
       
   215      * number of significant bits per color and alpha component and its
       
   216      * length should be at least the number of components in the
       
   217      * {@code ColorSpace} if there is no alpha
       
   218      * information in the pixel values, or one more than this number if
       
   219      * there is alpha information.  When the {@code transferType} is
       
   220      * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT},
       
   221      * or {@code DataBuffer.TYPE_DOUBLE} the {@code bits} array
       
   222      * argument is ignored.  {@code hasAlpha} indicates whether alpha
       
   223      * information is present.  If {@code hasAlpha} is true, then
       
   224      * the boolean {@code isAlphaPremultiplied}
       
   225      * specifies how to interpret color and alpha samples in pixel values.
       
   226      * If the boolean is true, color samples are assumed to have been
       
   227      * multiplied by the alpha sample. The {@code transparency}
       
   228      * specifies what alpha values can be represented by this color model.
       
   229      * The acceptable {@code transparency} values are
       
   230      * {@code OPAQUE}, {@code BITMASK} or {@code TRANSLUCENT}.
       
   231      * The {@code transferType} is the type of primitive array used
       
   232      * to represent pixel values.
       
   233      *
       
   234      * @param colorSpace       The {@code ColorSpace} associated
       
   235      *                         with this color model.
       
   236      * @param bits             The number of significant bits per component.
       
   237      *                         May be null, in which case all bits of all
       
   238      *                         component samples will be significant.
       
   239      *                         Ignored if transferType is one of
       
   240      *                         {@code DataBuffer.TYPE_SHORT},
       
   241      *                         {@code DataBuffer.TYPE_FLOAT}, or
       
   242      *                         {@code DataBuffer.TYPE_DOUBLE},
       
   243      *                         in which case all bits of all component
       
   244      *                         samples will be significant.
       
   245      * @param hasAlpha         If true, this color model supports alpha.
       
   246      * @param isAlphaPremultiplied If true, alpha is premultiplied.
       
   247      * @param transparency     Specifies what alpha values can be represented
       
   248      *                         by this color model.
       
   249      * @param transferType     Specifies the type of primitive array used to
       
   250      *                         represent pixel values.
       
   251      *
       
   252      * @throws IllegalArgumentException If the {@code bits} array
       
   253      *         argument is not null, its length is less than the number of
       
   254      *         color and alpha components, and transferType is one of
       
   255      *         {@code DataBuffer.TYPE_BYTE},
       
   256      *         {@code DataBuffer.TYPE_USHORT}, or
       
   257      *         {@code DataBuffer.TYPE_INT}.
       
   258      * @throws IllegalArgumentException If transferType is not one of
       
   259      *         {@code DataBuffer.TYPE_BYTE},
       
   260      *         {@code DataBuffer.TYPE_USHORT},
       
   261      *         {@code DataBuffer.TYPE_INT},
       
   262      *         {@code DataBuffer.TYPE_SHORT},
       
   263      *         {@code DataBuffer.TYPE_FLOAT}, or
       
   264      *         {@code DataBuffer.TYPE_DOUBLE}.
       
   265      *
       
   266      * @see ColorSpace
       
   267      * @see java.awt.Transparency
       
   268      */
       
   269     public ComponentColorModel (ColorSpace colorSpace,
       
   270                                 int[] bits,
       
   271                                 boolean hasAlpha,
       
   272                                 boolean isAlphaPremultiplied,
       
   273                                 int transparency,
       
   274                                 int transferType) {
       
   275         super (bitsHelper(transferType, colorSpace, hasAlpha),
       
   276                bitsArrayHelper(bits, transferType, colorSpace, hasAlpha),
       
   277                colorSpace, hasAlpha, isAlphaPremultiplied, transparency,
       
   278                transferType);
       
   279         switch(transferType) {
       
   280             case DataBuffer.TYPE_BYTE:
       
   281             case DataBuffer.TYPE_USHORT:
       
   282             case DataBuffer.TYPE_INT:
       
   283                 signed = false;
       
   284                 needScaleInit = true;
       
   285                 break;
       
   286             case DataBuffer.TYPE_SHORT:
       
   287                 signed = true;
       
   288                 needScaleInit = true;
       
   289                 break;
       
   290             case DataBuffer.TYPE_FLOAT:
       
   291             case DataBuffer.TYPE_DOUBLE:
       
   292                 signed = true;
       
   293                 needScaleInit = false;
       
   294                 noUnnorm = true;
       
   295                 nonStdScale = false;
       
   296                 break;
       
   297             default:
       
   298                 throw new IllegalArgumentException("This constructor is not "+
       
   299                          "compatible with transferType " + transferType);
       
   300         }
       
   301         setupLUTs();
       
   302     }
       
   303 
       
   304     /**
       
   305      * Constructs a {@code ComponentColorModel} from the specified
       
   306      * parameters. Color components will be in the specified
       
   307      * {@code ColorSpace}.  The supported transfer types are
       
   308      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
   309      * {@code DataBuffer.TYPE_INT},
       
   310      * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT},
       
   311      * and {@code DataBuffer.TYPE_DOUBLE}.  The number of significant
       
   312      * bits per color and alpha component will be 8, 16, 32, 16, 32,  or 64,
       
   313      * respectively.  The number of color components will be the
       
   314      * number of components in the {@code ColorSpace}.  There will be
       
   315      * an alpha component if {@code hasAlpha} is {@code true}.
       
   316      * If {@code hasAlpha} is true, then
       
   317      * the boolean {@code isAlphaPremultiplied}
       
   318      * specifies how to interpret color and alpha samples in pixel values.
       
   319      * If the boolean is true, color samples are assumed to have been
       
   320      * multiplied by the alpha sample. The {@code transparency}
       
   321      * specifies what alpha values can be represented by this color model.
       
   322      * The acceptable {@code transparency} values are
       
   323      * {@code OPAQUE}, {@code BITMASK} or {@code TRANSLUCENT}.
       
   324      * The {@code transferType} is the type of primitive array used
       
   325      * to represent pixel values.
       
   326      *
       
   327      * @param colorSpace       The {@code ColorSpace} associated
       
   328      *                         with this color model.
       
   329      * @param hasAlpha         If true, this color model supports alpha.
       
   330      * @param isAlphaPremultiplied If true, alpha is premultiplied.
       
   331      * @param transparency     Specifies what alpha values can be represented
       
   332      *                         by this color model.
       
   333      * @param transferType     Specifies the type of primitive array used to
       
   334      *                         represent pixel values.
       
   335      *
       
   336      * @throws IllegalArgumentException If transferType is not one of
       
   337      *         {@code DataBuffer.TYPE_BYTE},
       
   338      *         {@code DataBuffer.TYPE_USHORT},
       
   339      *         {@code DataBuffer.TYPE_INT},
       
   340      *         {@code DataBuffer.TYPE_SHORT},
       
   341      *         {@code DataBuffer.TYPE_FLOAT}, or
       
   342      *         {@code DataBuffer.TYPE_DOUBLE}.
       
   343      *
       
   344      * @see ColorSpace
       
   345      * @see java.awt.Transparency
       
   346      * @since 1.4
       
   347      */
       
   348     public ComponentColorModel (ColorSpace colorSpace,
       
   349                                 boolean hasAlpha,
       
   350                                 boolean isAlphaPremultiplied,
       
   351                                 int transparency,
       
   352                                 int transferType) {
       
   353         this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
       
   354              transparency, transferType);
       
   355     }
       
   356 
       
   357     private static int bitsHelper(int transferType,
       
   358                                   ColorSpace colorSpace,
       
   359                                   boolean hasAlpha) {
       
   360         int numBits = DataBuffer.getDataTypeSize(transferType);
       
   361         int numComponents = colorSpace.getNumComponents();
       
   362         if (hasAlpha) {
       
   363             ++numComponents;
       
   364         }
       
   365         return numBits * numComponents;
       
   366     }
       
   367 
       
   368     private static int[] bitsArrayHelper(int[] origBits,
       
   369                                          int transferType,
       
   370                                          ColorSpace colorSpace,
       
   371                                          boolean hasAlpha) {
       
   372         switch(transferType) {
       
   373             case DataBuffer.TYPE_BYTE:
       
   374             case DataBuffer.TYPE_USHORT:
       
   375             case DataBuffer.TYPE_INT:
       
   376                 if (origBits != null) {
       
   377                     return origBits;
       
   378                 }
       
   379                 break;
       
   380             default:
       
   381                 break;
       
   382         }
       
   383         int numBits = DataBuffer.getDataTypeSize(transferType);
       
   384         int numComponents = colorSpace.getNumComponents();
       
   385         if (hasAlpha) {
       
   386             ++numComponents;
       
   387         }
       
   388         int[] bits = new int[numComponents];
       
   389         for (int i = 0; i < numComponents; i++) {
       
   390             bits[i] = numBits;
       
   391         }
       
   392         return bits;
       
   393     }
       
   394 
       
   395     private void setupLUTs() {
       
   396         // REMIND: there is potential to accelerate sRGB, LinearRGB,
       
   397         // LinearGray, ICCGray, and non-ICC Gray spaces with non-standard
       
   398         // scaling, if that becomes important
       
   399         //
       
   400         // NOTE: The is_xxx_stdScale and nonStdScale booleans are provisionally
       
   401         // set here when this method is called at construction time.  These
       
   402         // variables may be set again when initScale is called later.
       
   403         // When setupLUTs returns, nonStdScale is true if (the transferType
       
   404         // is not float or double) AND (some minimum ColorSpace component
       
   405         // value is not 0.0 OR some maximum ColorSpace component value
       
   406         // is not 1.0).  This is correct for the calls to
       
   407         // getNormalizedComponents(Object, float[], int) from initScale().
       
   408         // initScale() may change the value nonStdScale based on the
       
   409         // return value of getNormalizedComponents() - this will only
       
   410         // happen if getNormalizedComponents() has been overridden by a
       
   411         // subclass to make the mapping of min/max pixel sample values
       
   412         // something different from min/max color component values.
       
   413         if (is_sRGB) {
       
   414             is_sRGB_stdScale = true;
       
   415             nonStdScale = false;
       
   416         } else if (ColorModel.isLinearRGBspace(colorSpace)) {
       
   417             // Note that the built-in Linear RGB space has a normalized
       
   418             // range of 0.0 - 1.0 for each coordinate.  Usage of these
       
   419             // LUTs makes that assumption.
       
   420             is_LinearRGB_stdScale = true;
       
   421             nonStdScale = false;
       
   422             if (transferType == DataBuffer.TYPE_BYTE) {
       
   423                 tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
       
   424                 fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
       
   425             } else {
       
   426                 tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
       
   427                 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
       
   428             }
       
   429         } else if ((colorSpaceType == ColorSpace.TYPE_GRAY) &&
       
   430                    (colorSpace instanceof ICC_ColorSpace) &&
       
   431                    (colorSpace.getMinValue(0) == 0.0f) &&
       
   432                    (colorSpace.getMaxValue(0) == 1.0f)) {
       
   433             // Note that a normalized range of 0.0 - 1.0 for the gray
       
   434             // component is required, because usage of these LUTs makes
       
   435             // that assumption.
       
   436             ICC_ColorSpace ics = (ICC_ColorSpace) colorSpace;
       
   437             is_ICCGray_stdScale = true;
       
   438             nonStdScale = false;
       
   439             fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
       
   440             if (ColorModel.isLinearGRAYspace(ics)) {
       
   441                 is_LinearGray_stdScale = true;
       
   442                 if (transferType == DataBuffer.TYPE_BYTE) {
       
   443                     tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
       
   444                 } else {
       
   445                     tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
       
   446                 }
       
   447             } else {
       
   448                 if (transferType == DataBuffer.TYPE_BYTE) {
       
   449                     tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
       
   450                     fromLinearGray16ToOtherGray8LUT =
       
   451                         ColorModel.getLinearGray16ToOtherGray8LUT(ics);
       
   452                 } else {
       
   453                     tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
       
   454                     fromLinearGray16ToOtherGray16LUT =
       
   455                         ColorModel.getLinearGray16ToOtherGray16LUT(ics);
       
   456                 }
       
   457             }
       
   458         } else if (needScaleInit) {
       
   459             // if transferType is byte, ushort, int, or short and we
       
   460             // don't already know the ColorSpace has minVlaue == 0.0f and
       
   461             // maxValue == 1.0f for all components, we need to check that
       
   462             // now and setup the min[] and diffMinMax[] arrays if necessary.
       
   463             nonStdScale = false;
       
   464             for (int i = 0; i < numColorComponents; i++) {
       
   465                 if ((colorSpace.getMinValue(i) != 0.0f) ||
       
   466                     (colorSpace.getMaxValue(i) != 1.0f)) {
       
   467                     nonStdScale = true;
       
   468                     break;
       
   469                 }
       
   470             }
       
   471             if (nonStdScale) {
       
   472                 min = new float[numColorComponents];
       
   473                 diffMinMax = new float[numColorComponents];
       
   474                 for (int i = 0; i < numColorComponents; i++) {
       
   475                     min[i] = colorSpace.getMinValue(i);
       
   476                     diffMinMax[i] = colorSpace.getMaxValue(i) - min[i];
       
   477                 }
       
   478             }
       
   479         }
       
   480     }
       
   481 
       
   482     private void initScale() {
       
   483         // This method is called the first time any method which uses
       
   484         // pixel sample value to color component value scaling information
       
   485         // is called if the transferType supports non-standard scaling
       
   486         // as defined above (byte, ushort, int, and short), unless the
       
   487         // method is getNormalizedComponents(Object, float[], int) (that
       
   488         // method must be overridden to use non-standard scaling).  This
       
   489         // method also sets up the noUnnorm boolean variable for these
       
   490         // transferTypes.  After this method is called, the nonStdScale
       
   491         // variable will be true if getNormalizedComponents() maps a
       
   492         // sample value of 0 to anything other than 0.0f OR maps a
       
   493         // sample value of 2^^n - 1 (2^^15 - 1 for short transferType)
       
   494         // to anything other than 1.0f.  Note that this can be independent
       
   495         // of the colorSpace min/max component values, if the
       
   496         // getNormalizedComponents() method has been overridden for some
       
   497         // reason, e.g. to provide greater dynamic range in the sample
       
   498         // values than in the color component values.  Unfortunately,
       
   499         // this method can't be called at construction time, since a
       
   500         // subclass may still have uninitialized state that would cause
       
   501         // getNormalizedComponents() to return an incorrect result.
       
   502         needScaleInit = false; // only needs to called once
       
   503         if (nonStdScale || signed) {
       
   504             // The unnormalized form is only supported for unsigned
       
   505             // transferTypes and when the ColorSpace min/max values
       
   506             // are 0.0/1.0.  When this method is called nonStdScale is
       
   507             // true if the latter condition does not hold.  In addition,
       
   508             // the unnormalized form requires that the full range of
       
   509             // the pixel sample values map to the full 0.0 - 1.0 range
       
   510             // of color component values.  That condition is checked
       
   511             // later in this method.
       
   512             noUnnorm = true;
       
   513         } else {
       
   514             noUnnorm = false;
       
   515         }
       
   516         float[] lowVal, highVal;
       
   517         switch (transferType) {
       
   518         case DataBuffer.TYPE_BYTE:
       
   519             {
       
   520                 byte[] bpixel = new byte[numComponents];
       
   521                 for (int i = 0; i < numColorComponents; i++) {
       
   522                     bpixel[i] = 0;
       
   523                 }
       
   524                 if (supportsAlpha) {
       
   525                     bpixel[numColorComponents] =
       
   526                         (byte) ((1 << nBits[numColorComponents]) - 1);
       
   527                 }
       
   528                 lowVal = getNormalizedComponents(bpixel, null, 0);
       
   529                 for (int i = 0; i < numColorComponents; i++) {
       
   530                     bpixel[i] = (byte) ((1 << nBits[i]) - 1);
       
   531                 }
       
   532                 highVal = getNormalizedComponents(bpixel, null, 0);
       
   533             }
       
   534             break;
       
   535         case DataBuffer.TYPE_USHORT:
       
   536             {
       
   537                 short[] uspixel = new short[numComponents];
       
   538                 for (int i = 0; i < numColorComponents; i++) {
       
   539                     uspixel[i] = 0;
       
   540                 }
       
   541                 if (supportsAlpha) {
       
   542                     uspixel[numColorComponents] =
       
   543                         (short) ((1 << nBits[numColorComponents]) - 1);
       
   544                 }
       
   545                 lowVal = getNormalizedComponents(uspixel, null, 0);
       
   546                 for (int i = 0; i < numColorComponents; i++) {
       
   547                     uspixel[i] = (short) ((1 << nBits[i]) - 1);
       
   548                 }
       
   549                 highVal = getNormalizedComponents(uspixel, null, 0);
       
   550             }
       
   551             break;
       
   552         case DataBuffer.TYPE_INT:
       
   553             {
       
   554                 int[] ipixel = new int[numComponents];
       
   555                 for (int i = 0; i < numColorComponents; i++) {
       
   556                     ipixel[i] = 0;
       
   557                 }
       
   558                 if (supportsAlpha) {
       
   559                     ipixel[numColorComponents] =
       
   560                         ((1 << nBits[numColorComponents]) - 1);
       
   561                 }
       
   562                 lowVal = getNormalizedComponents(ipixel, null, 0);
       
   563                 for (int i = 0; i < numColorComponents; i++) {
       
   564                     ipixel[i] = ((1 << nBits[i]) - 1);
       
   565                 }
       
   566                 highVal = getNormalizedComponents(ipixel, null, 0);
       
   567             }
       
   568             break;
       
   569         case DataBuffer.TYPE_SHORT:
       
   570             {
       
   571                 short[] spixel = new short[numComponents];
       
   572                 for (int i = 0; i < numColorComponents; i++) {
       
   573                     spixel[i] = 0;
       
   574                 }
       
   575                 if (supportsAlpha) {
       
   576                     spixel[numColorComponents] = 32767;
       
   577                 }
       
   578                 lowVal = getNormalizedComponents(spixel, null, 0);
       
   579                 for (int i = 0; i < numColorComponents; i++) {
       
   580                     spixel[i] = 32767;
       
   581                 }
       
   582                 highVal = getNormalizedComponents(spixel, null, 0);
       
   583             }
       
   584             break;
       
   585         default:
       
   586             lowVal = highVal = null;  // to keep the compiler from complaining
       
   587             break;
       
   588         }
       
   589         nonStdScale = false;
       
   590         for (int i = 0; i < numColorComponents; i++) {
       
   591             if ((lowVal[i] != 0.0f) || (highVal[i] != 1.0f)) {
       
   592                 nonStdScale = true;
       
   593                 break;
       
   594             }
       
   595         }
       
   596         if (nonStdScale) {
       
   597             noUnnorm = true;
       
   598             is_sRGB_stdScale = false;
       
   599             is_LinearRGB_stdScale = false;
       
   600             is_LinearGray_stdScale = false;
       
   601             is_ICCGray_stdScale = false;
       
   602             compOffset = new float[numColorComponents];
       
   603             compScale = new float[numColorComponents];
       
   604             for (int i = 0; i < numColorComponents; i++) {
       
   605                 compOffset[i] = lowVal[i];
       
   606                 compScale[i] = 1.0f / (highVal[i] - lowVal[i]);
       
   607             }
       
   608         }
       
   609     }
       
   610 
       
   611     private int getRGBComponent(int pixel, int idx) {
       
   612         if (numComponents > 1) {
       
   613             throw new
       
   614                 IllegalArgumentException("More than one component per pixel");
       
   615         }
       
   616         if (signed) {
       
   617             throw new
       
   618                 IllegalArgumentException("Component value is signed");
       
   619         }
       
   620         if (needScaleInit) {
       
   621             initScale();
       
   622         }
       
   623         // Since there is only 1 component, there is no alpha
       
   624 
       
   625         // Normalize the pixel in order to convert it
       
   626         Object opixel = null;
       
   627         switch (transferType) {
       
   628         case DataBuffer.TYPE_BYTE:
       
   629             {
       
   630                 byte[] bpixel = { (byte) pixel };
       
   631                 opixel = bpixel;
       
   632             }
       
   633             break;
       
   634         case DataBuffer.TYPE_USHORT:
       
   635             {
       
   636                 short[] spixel = { (short) pixel };
       
   637                 opixel = spixel;
       
   638             }
       
   639             break;
       
   640         case DataBuffer.TYPE_INT:
       
   641             {
       
   642                 int[] ipixel = { pixel };
       
   643                 opixel = ipixel;
       
   644             }
       
   645             break;
       
   646         }
       
   647         float[] norm = getNormalizedComponents(opixel, null, 0);
       
   648         float[] rgb = colorSpace.toRGB(norm);
       
   649 
       
   650         return (int) (rgb[idx] * 255.0f + 0.5f);
       
   651     }
       
   652 
       
   653     /**
       
   654      * Returns the red color component for the specified pixel, scaled
       
   655      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
       
   656      * is done if necessary.  The pixel value is specified as an int.
       
   657      * The returned value will be a non pre-multiplied value.
       
   658      * If the alpha is premultiplied, this method divides
       
   659      * it out before returning the value (if the alpha value is 0,
       
   660      * the red value will be 0).
       
   661      *
       
   662      * @param pixel The pixel from which you want to get the red color component.
       
   663      *
       
   664      * @return The red color component for the specified pixel, as an int.
       
   665      *
       
   666      * @throws IllegalArgumentException If there is more than
       
   667      * one component in this {@code ColorModel}.
       
   668      * @throws IllegalArgumentException If the component value for this
       
   669      * {@code ColorModel} is signed
       
   670      */
       
   671     public int getRed(int pixel) {
       
   672         return getRGBComponent(pixel, 0);
       
   673     }
       
   674 
       
   675     /**
       
   676      * Returns the green color component for the specified pixel, scaled
       
   677      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
       
   678      * is done if necessary.  The pixel value is specified as an int.
       
   679      * The returned value will be a non
       
   680      * pre-multiplied value. If the alpha is premultiplied, this method
       
   681      * divides it out before returning the value (if the alpha value is 0,
       
   682      * the green value will be 0).
       
   683      *
       
   684      * @param pixel The pixel from which you want to get the green color component.
       
   685      *
       
   686      * @return The green color component for the specified pixel, as an int.
       
   687      *
       
   688      * @throws IllegalArgumentException If there is more than
       
   689      * one component in this {@code ColorModel}.
       
   690      * @throws IllegalArgumentException If the component value for this
       
   691      * {@code ColorModel} is signed
       
   692      */
       
   693     public int getGreen(int pixel) {
       
   694         return getRGBComponent(pixel, 1);
       
   695     }
       
   696 
       
   697     /**
       
   698      * Returns the blue color component for the specified pixel, scaled
       
   699      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
       
   700      * is done if necessary.  The pixel value is specified as an int.
       
   701      * The returned value will be a non
       
   702      * pre-multiplied value. If the alpha is premultiplied, this method
       
   703      * divides it out before returning the value (if the alpha value is 0,
       
   704      * the blue value will be 0).
       
   705      *
       
   706      * @param pixel The pixel from which you want to get the blue color component.
       
   707      *
       
   708      * @return The blue color component for the specified pixel, as an int.
       
   709      *
       
   710      * @throws IllegalArgumentException If there is more than
       
   711      * one component in this {@code ColorModel}.
       
   712      * @throws IllegalArgumentException If the component value for this
       
   713      * {@code ColorModel} is signed
       
   714      */
       
   715     public int getBlue(int pixel) {
       
   716         return getRGBComponent(pixel, 2);
       
   717     }
       
   718 
       
   719     /**
       
   720      * Returns the alpha component for the specified pixel, scaled
       
   721      * from 0 to 255.   The pixel value is specified as an int.
       
   722      *
       
   723      * @param pixel The pixel from which you want to get the alpha component.
       
   724      *
       
   725      * @return The alpha component for the specified pixel, as an int.
       
   726      *
       
   727      * @throws IllegalArgumentException If there is more than
       
   728      * one component in this {@code ColorModel}.
       
   729      * @throws IllegalArgumentException If the component value for this
       
   730      * {@code ColorModel} is signed
       
   731      */
       
   732     public int getAlpha(int pixel) {
       
   733         if (supportsAlpha == false) {
       
   734             return 255;
       
   735         }
       
   736         if (numComponents > 1) {
       
   737             throw new
       
   738                 IllegalArgumentException("More than one component per pixel");
       
   739         }
       
   740         if (signed) {
       
   741             throw new
       
   742                 IllegalArgumentException("Component value is signed");
       
   743         }
       
   744 
       
   745         return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f);
       
   746     }
       
   747 
       
   748     /**
       
   749      * Returns the color/alpha components of the pixel in the default
       
   750      * RGB color model format.  A color conversion is done if necessary.
       
   751      * The returned value will be in a non pre-multiplied format. If
       
   752      * the alpha is premultiplied, this method divides it out of the
       
   753      * color components (if the alpha value is 0, the color values will be 0).
       
   754      *
       
   755      * @param pixel The pixel from which you want to get the color/alpha components.
       
   756      *
       
   757      * @return The color/alpha components for the specified pixel, as an int.
       
   758      *
       
   759      * @throws IllegalArgumentException If there is more than
       
   760      * one component in this {@code ColorModel}.
       
   761      * @throws IllegalArgumentException If the component value for this
       
   762      * {@code ColorModel} is signed
       
   763      */
       
   764     public int getRGB(int pixel) {
       
   765         if (numComponents > 1) {
       
   766             throw new
       
   767                 IllegalArgumentException("More than one component per pixel");
       
   768         }
       
   769         if (signed) {
       
   770             throw new
       
   771                 IllegalArgumentException("Component value is signed");
       
   772         }
       
   773 
       
   774         return (getAlpha(pixel) << 24)
       
   775             | (getRed(pixel) << 16)
       
   776             | (getGreen(pixel) << 8)
       
   777             | (getBlue(pixel) << 0);
       
   778     }
       
   779 
       
   780     private int extractComponent(Object inData, int idx, int precision) {
       
   781         // Extract component idx from inData.  The precision argument
       
   782         // should be either 8 or 16.  If it's 8, this method will return
       
   783         // an 8-bit value.  If it's 16, this method will return a 16-bit
       
   784         // value for transferTypes other than TYPE_BYTE.  For TYPE_BYTE,
       
   785         // an 8-bit value will be returned.
       
   786 
       
   787         // This method maps the input value corresponding to a
       
   788         // normalized ColorSpace component value of 0.0 to 0, and the
       
   789         // input value corresponding to a normalized ColorSpace
       
   790         // component value of 1.0 to 2^n - 1 (where n is 8 or 16), so
       
   791         // it is appropriate only for ColorSpaces with min/max component
       
   792         // values of 0.0/1.0.  This will be true for sRGB, the built-in
       
   793         // Linear RGB and Linear Gray spaces, and any other ICC grayscale
       
   794         // spaces for which we have precomputed LUTs.
       
   795 
       
   796         boolean needAlpha = (supportsAlpha && isAlphaPremultiplied);
       
   797         int alp = 0;
       
   798         int comp;
       
   799         int mask = (1 << nBits[idx]) - 1;
       
   800 
       
   801         switch (transferType) {
       
   802             // Note: we do no clamping of the pixel data here - we
       
   803             // assume that the data is scaled properly
       
   804             case DataBuffer.TYPE_SHORT: {
       
   805                 short sdata[] = (short[]) inData;
       
   806                 float scalefactor = (float) ((1 << precision) - 1);
       
   807                 if (needAlpha) {
       
   808                     short s = sdata[numColorComponents];
       
   809                     if (s != (short) 0) {
       
   810                         return (int) ((((float) sdata[idx]) /
       
   811                                        ((float) s)) * scalefactor + 0.5f);
       
   812                     } else {
       
   813                         return 0;
       
   814                     }
       
   815                 } else {
       
   816                     return (int) ((sdata[idx] / 32767.0f) * scalefactor + 0.5f);
       
   817                 }
       
   818             }
       
   819             case DataBuffer.TYPE_FLOAT: {
       
   820                 float fdata[] = (float[]) inData;
       
   821                 float scalefactor = (float) ((1 << precision) - 1);
       
   822                 if (needAlpha) {
       
   823                     float f = fdata[numColorComponents];
       
   824                     if (f != 0.0f) {
       
   825                         return (int) (((fdata[idx] / f) * scalefactor) + 0.5f);
       
   826                     } else {
       
   827                         return 0;
       
   828                     }
       
   829                 } else {
       
   830                     return (int) (fdata[idx] * scalefactor + 0.5f);
       
   831                 }
       
   832             }
       
   833             case DataBuffer.TYPE_DOUBLE: {
       
   834                 double ddata[] = (double[]) inData;
       
   835                 double scalefactor = (double) ((1 << precision) - 1);
       
   836                 if (needAlpha) {
       
   837                     double d = ddata[numColorComponents];
       
   838                     if (d != 0.0) {
       
   839                         return (int) (((ddata[idx] / d) * scalefactor) + 0.5);
       
   840                     } else {
       
   841                         return 0;
       
   842                     }
       
   843                 } else {
       
   844                     return (int) (ddata[idx] * scalefactor + 0.5);
       
   845                 }
       
   846             }
       
   847             case DataBuffer.TYPE_BYTE:
       
   848                byte bdata[] = (byte[])inData;
       
   849                comp = bdata[idx] & mask;
       
   850                precision = 8;
       
   851                if (needAlpha) {
       
   852                    alp = bdata[numColorComponents] & mask;
       
   853                }
       
   854             break;
       
   855             case DataBuffer.TYPE_USHORT:
       
   856                short usdata[] = (short[])inData;
       
   857                comp = usdata[idx] & mask;
       
   858                if (needAlpha) {
       
   859                    alp = usdata[numColorComponents] & mask;
       
   860                }
       
   861             break;
       
   862             case DataBuffer.TYPE_INT:
       
   863                int idata[] = (int[])inData;
       
   864                comp = idata[idx];
       
   865                if (needAlpha) {
       
   866                    alp = idata[numColorComponents];
       
   867                }
       
   868             break;
       
   869             default:
       
   870                throw new
       
   871                    UnsupportedOperationException("This method has not "+
       
   872                    "been implemented for transferType " + transferType);
       
   873         }
       
   874         if (needAlpha) {
       
   875             if (alp != 0) {
       
   876                 float scalefactor = (float) ((1 << precision) - 1);
       
   877                 float fcomp = ((float) comp) / ((float)mask);
       
   878                 float invalp = ((float) ((1<<nBits[numColorComponents]) - 1)) /
       
   879                                ((float) alp);
       
   880                 return (int) (fcomp * invalp * scalefactor + 0.5f);
       
   881             } else {
       
   882                 return 0;
       
   883             }
       
   884         } else {
       
   885             if (nBits[idx] != precision) {
       
   886                 float scalefactor = (float) ((1 << precision) - 1);
       
   887                 float fcomp = ((float) comp) / ((float)mask);
       
   888                 return (int) (fcomp * scalefactor + 0.5f);
       
   889             }
       
   890             return comp;
       
   891         }
       
   892     }
       
   893 
       
   894     private int getRGBComponent(Object inData, int idx) {
       
   895         if (needScaleInit) {
       
   896             initScale();
       
   897         }
       
   898         if (is_sRGB_stdScale) {
       
   899             return extractComponent(inData, idx, 8);
       
   900         } else if (is_LinearRGB_stdScale) {
       
   901             int lutidx = extractComponent(inData, idx, 16);
       
   902             return tosRGB8LUT[lutidx] & 0xff;
       
   903         } else if (is_ICCGray_stdScale) {
       
   904             int lutidx = extractComponent(inData, 0, 16);
       
   905             return tosRGB8LUT[lutidx] & 0xff;
       
   906         }
       
   907 
       
   908         // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace
       
   909         float[] norm = getNormalizedComponents(inData, null, 0);
       
   910         // Note that getNormalizedComponents returns non-premultiplied values
       
   911         float[] rgb = colorSpace.toRGB(norm);
       
   912         return (int) (rgb[idx] * 255.0f + 0.5f);
       
   913     }
       
   914 
       
   915     /**
       
   916      * Returns the red color component for the specified pixel, scaled
       
   917      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
       
   918      * is done if necessary.  The {@code pixel} value is specified by an array
       
   919      * of data elements of type {@code transferType} passed in as an object
       
   920      * reference. The returned value will be a non pre-multiplied value. If the
       
   921      * alpha is premultiplied, this method divides it out before returning
       
   922      * the value (if the alpha value is 0, the red value will be 0). Since
       
   923      * {@code ComponentColorModel} can be subclassed, subclasses
       
   924      * inherit the implementation of this method and if they don't override
       
   925      * it then they throw an exception if they use an unsupported
       
   926      * {@code transferType}.
       
   927      *
       
   928      * @param inData The pixel from which you want to get the red color component,
       
   929      * specified by an array of data elements of type {@code transferType}.
       
   930      *
       
   931      * @return The red color component for the specified pixel, as an int.
       
   932      *
       
   933      * @throws ClassCastException If {@code inData} is not a primitive array
       
   934      * of type {@code transferType}.
       
   935      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
       
   936      * large enough to hold a pixel value for this
       
   937      * {@code ColorModel}.
       
   938      * @throws UnsupportedOperationException If the transfer type of
       
   939      * this {@code ComponentColorModel}
       
   940      * is not one of the supported transfer types:
       
   941      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
   942      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
       
   943      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
       
   944      */
       
   945     public int getRed(Object inData) {
       
   946         return getRGBComponent(inData, 0);
       
   947     }
       
   948 
       
   949 
       
   950     /**
       
   951      * Returns the green color component for the specified pixel, scaled
       
   952      * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB.
       
   953      * A color conversion is done if necessary.  The {@code pixel} value
       
   954      * is specified by an array of data elements of type {@code transferType}
       
   955      * passed in as an object reference. The returned value is a non pre-multiplied
       
   956      * value. If the alpha is premultiplied, this method divides it out before
       
   957      * returning the value (if the alpha value is 0, the green value will be 0).
       
   958      * Since {@code ComponentColorModel} can be subclassed,
       
   959      * subclasses inherit the implementation of this method and if they
       
   960      * don't override it then they throw an exception if they use an
       
   961      * unsupported {@code transferType}.
       
   962      *
       
   963      * @param inData The pixel from which you want to get the green color component,
       
   964      * specified by an array of data elements of type {@code transferType}.
       
   965      *
       
   966      * @return The green color component for the specified pixel, as an int.
       
   967      *
       
   968      * @throws ClassCastException If {@code inData} is not a primitive array
       
   969      * of type {@code transferType}.
       
   970      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
       
   971      * large enough to hold a pixel value for this
       
   972      * {@code ColorModel}.
       
   973      * @throws UnsupportedOperationException If the transfer type of
       
   974      * this {@code ComponentColorModel}
       
   975      * is not one of the supported transfer types:
       
   976      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
   977      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
       
   978      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
       
   979      */
       
   980     public int getGreen(Object inData) {
       
   981         return getRGBComponent(inData, 1);
       
   982     }
       
   983 
       
   984 
       
   985     /**
       
   986      * Returns the blue color component for the specified pixel, scaled
       
   987      * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB.
       
   988      * A color conversion is done if necessary.  The {@code pixel} value is
       
   989      * specified by an array of data elements of type {@code transferType}
       
   990      * passed in as an object reference. The returned value is a non pre-multiplied
       
   991      * value. If the alpha is premultiplied, this method divides it out before
       
   992      * returning the value (if the alpha value is 0, the blue value will be 0).
       
   993      * Since {@code ComponentColorModel} can be subclassed,
       
   994      * subclasses inherit the implementation of this method and if they
       
   995      * don't override it then they throw an exception if they use an
       
   996      * unsupported {@code transferType}.
       
   997      *
       
   998      * @param inData The pixel from which you want to get the blue color component,
       
   999      * specified by an array of data elements of type {@code transferType}.
       
  1000      *
       
  1001      * @return The blue color component for the specified pixel, as an int.
       
  1002      *
       
  1003      * @throws ClassCastException If {@code inData} is not a primitive array
       
  1004      * of type {@code transferType}.
       
  1005      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
       
  1006      * large enough to hold a pixel value for this
       
  1007      * {@code ColorModel}.
       
  1008      * @throws UnsupportedOperationException If the transfer type of
       
  1009      * this {@code ComponentColorModel}
       
  1010      * is not one of the supported transfer types:
       
  1011      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
  1012      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
       
  1013      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
       
  1014      */
       
  1015     public int getBlue(Object inData) {
       
  1016         return getRGBComponent(inData, 2);
       
  1017     }
       
  1018 
       
  1019     /**
       
  1020      * Returns the alpha component for the specified pixel, scaled from
       
  1021      * 0 to 255.  The pixel value is specified by an array of data
       
  1022      * elements of type {@code transferType} passed in as an
       
  1023      * object reference.  Since {@code ComponentColorModel} can be
       
  1024      * subclassed, subclasses inherit the
       
  1025      * implementation of this method and if they don't override it then
       
  1026      * they throw an exception if they use an unsupported
       
  1027      * {@code transferType}.
       
  1028      *
       
  1029      * @param inData The pixel from which you want to get the alpha component,
       
  1030      * specified by an array of data elements of type {@code transferType}.
       
  1031      *
       
  1032      * @return The alpha component for the specified pixel, as an int.
       
  1033      *
       
  1034      * @throws ClassCastException If {@code inData} is not a primitive array
       
  1035      * of type {@code transferType}.
       
  1036      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
       
  1037      * large enough to hold a pixel value for this
       
  1038      * {@code ColorModel}.
       
  1039      * @throws UnsupportedOperationException If the transfer type of
       
  1040      * this {@code ComponentColorModel}
       
  1041      * is not one of the supported transfer types:
       
  1042      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
  1043      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
       
  1044      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
       
  1045      */
       
  1046     public int getAlpha(Object inData) {
       
  1047         if (supportsAlpha == false) {
       
  1048             return 255;
       
  1049         }
       
  1050 
       
  1051         int alpha = 0;
       
  1052         int aIdx = numColorComponents;
       
  1053         int mask = (1 << nBits[aIdx]) - 1;
       
  1054 
       
  1055         switch (transferType) {
       
  1056             case DataBuffer.TYPE_SHORT:
       
  1057                 short sdata[] = (short[])inData;
       
  1058                 alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f);
       
  1059                 return alpha;
       
  1060             case DataBuffer.TYPE_FLOAT:
       
  1061                 float fdata[] = (float[])inData;
       
  1062                 alpha = (int) (fdata[aIdx] * 255.0f + 0.5f);
       
  1063                 return alpha;
       
  1064             case DataBuffer.TYPE_DOUBLE:
       
  1065                 double ddata[] = (double[])inData;
       
  1066                 alpha = (int) (ddata[aIdx] * 255.0 + 0.5);
       
  1067                 return alpha;
       
  1068             case DataBuffer.TYPE_BYTE:
       
  1069                byte bdata[] = (byte[])inData;
       
  1070                alpha = bdata[aIdx] & mask;
       
  1071             break;
       
  1072             case DataBuffer.TYPE_USHORT:
       
  1073                short usdata[] = (short[])inData;
       
  1074                alpha = usdata[aIdx] & mask;
       
  1075             break;
       
  1076             case DataBuffer.TYPE_INT:
       
  1077                int idata[] = (int[])inData;
       
  1078                alpha = idata[aIdx];
       
  1079             break;
       
  1080             default:
       
  1081                throw new
       
  1082                    UnsupportedOperationException("This method has not "+
       
  1083                    "been implemented for transferType " + transferType);
       
  1084         }
       
  1085 
       
  1086         if (nBits[aIdx] == 8) {
       
  1087             return alpha;
       
  1088         } else {
       
  1089             return (int)
       
  1090                 ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) *
       
  1091                  255.0f + 0.5f);
       
  1092         }
       
  1093     }
       
  1094 
       
  1095     /**
       
  1096      * Returns the color/alpha components for the specified pixel in the
       
  1097      * default RGB color model format.  A color conversion is done if
       
  1098      * necessary.  The pixel value is specified by an
       
  1099      * array of data elements of type {@code transferType} passed
       
  1100      * in as an object reference.
       
  1101      * The returned value is in a non pre-multiplied format. If
       
  1102      * the alpha is premultiplied, this method divides it out of the
       
  1103      * color components (if the alpha value is 0, the color values will be 0).
       
  1104      * Since {@code ComponentColorModel} can be subclassed,
       
  1105      * subclasses inherit the implementation of this method and if they
       
  1106      * don't override it then they throw an exception if they use an
       
  1107      * unsupported {@code transferType}.
       
  1108      *
       
  1109      * @param inData The pixel from which you want to get the color/alpha components,
       
  1110      * specified by an array of data elements of type {@code transferType}.
       
  1111      *
       
  1112      * @return The color/alpha components for the specified pixel, as an int.
       
  1113      *
       
  1114      * @throws ClassCastException If {@code inData} is not a primitive array
       
  1115      * of type {@code transferType}.
       
  1116      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
       
  1117      * large enough to hold a pixel value for this
       
  1118      * {@code ColorModel}.
       
  1119      * @throws UnsupportedOperationException If the transfer type of
       
  1120      * this {@code ComponentColorModel}
       
  1121      * is not one of the supported transfer types:
       
  1122      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
  1123      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
       
  1124      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
       
  1125      * @see ColorModel#getRGBdefault
       
  1126      */
       
  1127     public int getRGB(Object inData) {
       
  1128         if (needScaleInit) {
       
  1129             initScale();
       
  1130         }
       
  1131         if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
       
  1132             return (getAlpha(inData) << 24)
       
  1133                 | (getRed(inData) << 16)
       
  1134                 | (getGreen(inData) << 8)
       
  1135                 | (getBlue(inData));
       
  1136         } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
       
  1137             int gray = getRed(inData); // Red sRGB component should equal
       
  1138                                        // green and blue components
       
  1139             return (getAlpha(inData) << 24)
       
  1140                 | (gray << 16)
       
  1141                 | (gray <<  8)
       
  1142                 | gray;
       
  1143         }
       
  1144         float[] norm = getNormalizedComponents(inData, null, 0);
       
  1145         // Note that getNormalizedComponents returns non-premult values
       
  1146         float[] rgb = colorSpace.toRGB(norm);
       
  1147         return (getAlpha(inData) << 24)
       
  1148             | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
       
  1149             | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
       
  1150             | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
       
  1151     }
       
  1152 
       
  1153     /**
       
  1154      * Returns a data element array representation of a pixel in this
       
  1155      * {@code ColorModel}, given an integer pixel representation
       
  1156      * in the default RGB color model.
       
  1157      * This array can then be passed to the {@code setDataElements}
       
  1158      * method of a {@code WritableRaster} object.  If the
       
  1159      * {@code pixel}
       
  1160      * parameter is null, a new array is allocated.  Since
       
  1161      * {@code ComponentColorModel} can be subclassed, subclasses
       
  1162      * inherit the implementation of this method and if they don't
       
  1163      * override it then
       
  1164      * they throw an exception if they use an unsupported
       
  1165      * {@code transferType}.
       
  1166      *
       
  1167      * @param rgb the integer representation of the pixel in the RGB
       
  1168      *            color model
       
  1169      * @param pixel the specified pixel
       
  1170      * @return The data element array representation of a pixel
       
  1171      * in this {@code ColorModel}.
       
  1172      * @throws ClassCastException If {@code pixel} is not null and
       
  1173      * is not a primitive array of type {@code transferType}.
       
  1174      * @throws ArrayIndexOutOfBoundsException If {@code pixel} is
       
  1175      * not large enough to hold a pixel value for this
       
  1176      * {@code ColorModel}.
       
  1177      * @throws UnsupportedOperationException If the transfer type of
       
  1178      * this {@code ComponentColorModel}
       
  1179      * is not one of the supported transfer types:
       
  1180      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
  1181      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
       
  1182      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
       
  1183      *
       
  1184      * @see WritableRaster#setDataElements
       
  1185      * @see SampleModel#setDataElements
       
  1186      */
       
  1187     public Object getDataElements(int rgb, Object pixel) {
       
  1188         // REMIND: Use rendering hints?
       
  1189 
       
  1190         int red, grn, blu, alp;
       
  1191         red = (rgb>>16) & 0xff;
       
  1192         grn = (rgb>>8) & 0xff;
       
  1193         blu = rgb & 0xff;
       
  1194 
       
  1195         if (needScaleInit) {
       
  1196             initScale();
       
  1197         }
       
  1198         if (signed) {
       
  1199             // Handle SHORT, FLOAT, & DOUBLE here
       
  1200 
       
  1201             switch(transferType) {
       
  1202             case DataBuffer.TYPE_SHORT:
       
  1203                 {
       
  1204                     short sdata[];
       
  1205                     if (pixel == null) {
       
  1206                         sdata = new short[numComponents];
       
  1207                     } else {
       
  1208                         sdata = (short[])pixel;
       
  1209                     }
       
  1210                     float factor;
       
  1211                     if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
       
  1212                         factor = 32767.0f / 255.0f;
       
  1213                         if (is_LinearRGB_stdScale) {
       
  1214                             red = fromsRGB8LUT16[red] & 0xffff;
       
  1215                             grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1216                             blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1217                             factor = 32767.0f / 65535.0f;
       
  1218                         }
       
  1219                         if (supportsAlpha) {
       
  1220                             alp = (rgb>>24) & 0xff;
       
  1221                             sdata[3] =
       
  1222                                 (short) (alp * (32767.0f / 255.0f) + 0.5f);
       
  1223                             if (isAlphaPremultiplied) {
       
  1224                                 factor = alp * factor * (1.0f / 255.0f);
       
  1225                             }
       
  1226                         }
       
  1227                         sdata[0] = (short) (red * factor + 0.5f);
       
  1228                         sdata[1] = (short) (grn * factor + 0.5f);
       
  1229                         sdata[2] = (short) (blu * factor + 0.5f);
       
  1230                     } else if (is_LinearGray_stdScale) {
       
  1231                         red = fromsRGB8LUT16[red] & 0xffff;
       
  1232                         grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1233                         blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1234                         float gray = ((0.2125f * red) +
       
  1235                                       (0.7154f * grn) +
       
  1236                                       (0.0721f * blu)) / 65535.0f;
       
  1237                         factor = 32767.0f;
       
  1238                         if (supportsAlpha) {
       
  1239                             alp = (rgb>>24) & 0xff;
       
  1240                             sdata[1] =
       
  1241                                 (short) (alp * (32767.0f / 255.0f) + 0.5f);
       
  1242                             if (isAlphaPremultiplied) {
       
  1243                                 factor = alp * factor * (1.0f / 255.0f);
       
  1244                             }
       
  1245                         }
       
  1246                         sdata[0] = (short) (gray * factor + 0.5f);
       
  1247                     } else if (is_ICCGray_stdScale) {
       
  1248                         red = fromsRGB8LUT16[red] & 0xffff;
       
  1249                         grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1250                         blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1251                         int gray = (int) ((0.2125f * red) +
       
  1252                                           (0.7154f * grn) +
       
  1253                                           (0.0721f * blu) + 0.5f);
       
  1254                         gray = fromLinearGray16ToOtherGray16LUT[gray] & 0xffff;
       
  1255                         factor = 32767.0f / 65535.0f;
       
  1256                         if (supportsAlpha) {
       
  1257                             alp = (rgb>>24) & 0xff;
       
  1258                             sdata[1] =
       
  1259                                 (short) (alp * (32767.0f / 255.0f) + 0.5f);
       
  1260                             if (isAlphaPremultiplied) {
       
  1261                                 factor = alp * factor * (1.0f / 255.0f);
       
  1262                             }
       
  1263                         }
       
  1264                         sdata[0] = (short) (gray * factor + 0.5f);
       
  1265                     } else {
       
  1266                         factor = 1.0f / 255.0f;
       
  1267                         float norm[] = new float[3];
       
  1268                         norm[0] = red * factor;
       
  1269                         norm[1] = grn * factor;
       
  1270                         norm[2] = blu * factor;
       
  1271                         norm = colorSpace.fromRGB(norm);
       
  1272                         if (nonStdScale) {
       
  1273                             for (int i = 0; i < numColorComponents; i++) {
       
  1274                                 norm[i] = (norm[i] - compOffset[i]) *
       
  1275                                           compScale[i];
       
  1276                                 // REMIND: need to analyze whether this
       
  1277                                 // clamping is necessary
       
  1278                                 if (norm[i] < 0.0f) {
       
  1279                                     norm[i] = 0.0f;
       
  1280                                 }
       
  1281                                 if (norm[i] > 1.0f) {
       
  1282                                     norm[i] = 1.0f;
       
  1283                                 }
       
  1284                             }
       
  1285                         }
       
  1286                         factor = 32767.0f;
       
  1287                         if (supportsAlpha) {
       
  1288                             alp = (rgb>>24) & 0xff;
       
  1289                             sdata[numColorComponents] =
       
  1290                                 (short) (alp * (32767.0f / 255.0f) + 0.5f);
       
  1291                             if (isAlphaPremultiplied) {
       
  1292                                 factor *= alp * (1.0f / 255.0f);
       
  1293                             }
       
  1294                         }
       
  1295                         for (int i = 0; i < numColorComponents; i++) {
       
  1296                             sdata[i] = (short) (norm[i] * factor + 0.5f);
       
  1297                         }
       
  1298                     }
       
  1299                     return sdata;
       
  1300                 }
       
  1301             case DataBuffer.TYPE_FLOAT:
       
  1302                 {
       
  1303                     float fdata[];
       
  1304                     if (pixel == null) {
       
  1305                         fdata = new float[numComponents];
       
  1306                     } else {
       
  1307                         fdata = (float[])pixel;
       
  1308                     }
       
  1309                     float factor;
       
  1310                     if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
       
  1311                         if (is_LinearRGB_stdScale) {
       
  1312                             red = fromsRGB8LUT16[red] & 0xffff;
       
  1313                             grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1314                             blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1315                             factor = 1.0f / 65535.0f;
       
  1316                         } else {
       
  1317                             factor = 1.0f / 255.0f;
       
  1318                         }
       
  1319                         if (supportsAlpha) {
       
  1320                             alp = (rgb>>24) & 0xff;
       
  1321                             fdata[3] = alp * (1.0f / 255.0f);
       
  1322                             if (isAlphaPremultiplied) {
       
  1323                                 factor *= fdata[3];
       
  1324                             }
       
  1325                         }
       
  1326                         fdata[0] = red * factor;
       
  1327                         fdata[1] = grn * factor;
       
  1328                         fdata[2] = blu * factor;
       
  1329                     } else if (is_LinearGray_stdScale) {
       
  1330                         red = fromsRGB8LUT16[red] & 0xffff;
       
  1331                         grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1332                         blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1333                         fdata[0] = ((0.2125f * red) +
       
  1334                                     (0.7154f * grn) +
       
  1335                                     (0.0721f * blu)) / 65535.0f;
       
  1336                         if (supportsAlpha) {
       
  1337                             alp = (rgb>>24) & 0xff;
       
  1338                             fdata[1] = alp * (1.0f / 255.0f);
       
  1339                             if (isAlphaPremultiplied) {
       
  1340                                 fdata[0] *= fdata[1];
       
  1341                             }
       
  1342                         }
       
  1343                     } else if (is_ICCGray_stdScale) {
       
  1344                         red = fromsRGB8LUT16[red] & 0xffff;
       
  1345                         grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1346                         blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1347                         int gray = (int) ((0.2125f * red) +
       
  1348                                           (0.7154f * grn) +
       
  1349                                           (0.0721f * blu) + 0.5f);
       
  1350                         fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
       
  1351                                     0xffff) / 65535.0f;
       
  1352                         if (supportsAlpha) {
       
  1353                             alp = (rgb>>24) & 0xff;
       
  1354                             fdata[1] = alp * (1.0f / 255.0f);
       
  1355                             if (isAlphaPremultiplied) {
       
  1356                                 fdata[0] *= fdata[1];
       
  1357                             }
       
  1358                         }
       
  1359                     } else {
       
  1360                         float norm[] = new float[3];
       
  1361                         factor = 1.0f / 255.0f;
       
  1362                         norm[0] = red * factor;
       
  1363                         norm[1] = grn * factor;
       
  1364                         norm[2] = blu * factor;
       
  1365                         norm = colorSpace.fromRGB(norm);
       
  1366                         if (supportsAlpha) {
       
  1367                             alp = (rgb>>24) & 0xff;
       
  1368                             fdata[numColorComponents] = alp * factor;
       
  1369                             if (isAlphaPremultiplied) {
       
  1370                                 factor *= alp;
       
  1371                                 for (int i = 0; i < numColorComponents; i++) {
       
  1372                                     norm[i] *= factor;
       
  1373                                 }
       
  1374                             }
       
  1375                         }
       
  1376                         for (int i = 0; i < numColorComponents; i++) {
       
  1377                             fdata[i] = norm[i];
       
  1378                         }
       
  1379                     }
       
  1380                     return fdata;
       
  1381                 }
       
  1382             case DataBuffer.TYPE_DOUBLE:
       
  1383                 {
       
  1384                     double ddata[];
       
  1385                     if (pixel == null) {
       
  1386                         ddata = new double[numComponents];
       
  1387                     } else {
       
  1388                         ddata = (double[])pixel;
       
  1389                     }
       
  1390                     if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
       
  1391                         double factor;
       
  1392                         if (is_LinearRGB_stdScale) {
       
  1393                             red = fromsRGB8LUT16[red] & 0xffff;
       
  1394                             grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1395                             blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1396                             factor = 1.0 / 65535.0;
       
  1397                         } else {
       
  1398                             factor = 1.0 / 255.0;
       
  1399                         }
       
  1400                         if (supportsAlpha) {
       
  1401                             alp = (rgb>>24) & 0xff;
       
  1402                             ddata[3] = alp * (1.0 / 255.0);
       
  1403                             if (isAlphaPremultiplied) {
       
  1404                                 factor *= ddata[3];
       
  1405                             }
       
  1406                         }
       
  1407                         ddata[0] = red * factor;
       
  1408                         ddata[1] = grn * factor;
       
  1409                         ddata[2] = blu * factor;
       
  1410                     } else if (is_LinearGray_stdScale) {
       
  1411                         red = fromsRGB8LUT16[red] & 0xffff;
       
  1412                         grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1413                         blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1414                         ddata[0] = ((0.2125 * red) +
       
  1415                                     (0.7154 * grn) +
       
  1416                                     (0.0721 * blu)) / 65535.0;
       
  1417                         if (supportsAlpha) {
       
  1418                             alp = (rgb>>24) & 0xff;
       
  1419                             ddata[1] = alp * (1.0 / 255.0);
       
  1420                             if (isAlphaPremultiplied) {
       
  1421                                 ddata[0] *= ddata[1];
       
  1422                             }
       
  1423                         }
       
  1424                     } else if (is_ICCGray_stdScale) {
       
  1425                         red = fromsRGB8LUT16[red] & 0xffff;
       
  1426                         grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1427                         blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1428                         int gray = (int) ((0.2125f * red) +
       
  1429                                           (0.7154f * grn) +
       
  1430                                           (0.0721f * blu) + 0.5f);
       
  1431                         ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
       
  1432                                     0xffff) / 65535.0;
       
  1433                         if (supportsAlpha) {
       
  1434                             alp = (rgb>>24) & 0xff;
       
  1435                             ddata[1] = alp * (1.0 / 255.0);
       
  1436                             if (isAlphaPremultiplied) {
       
  1437                                 ddata[0] *= ddata[1];
       
  1438                             }
       
  1439                         }
       
  1440                     } else {
       
  1441                         float factor = 1.0f / 255.0f;
       
  1442                         float norm[] = new float[3];
       
  1443                         norm[0] = red * factor;
       
  1444                         norm[1] = grn * factor;
       
  1445                         norm[2] = blu * factor;
       
  1446                         norm = colorSpace.fromRGB(norm);
       
  1447                         if (supportsAlpha) {
       
  1448                             alp = (rgb>>24) & 0xff;
       
  1449                             ddata[numColorComponents] = alp * (1.0 / 255.0);
       
  1450                             if (isAlphaPremultiplied) {
       
  1451                                 factor *= alp;
       
  1452                                 for (int i = 0; i < numColorComponents; i++) {
       
  1453                                     norm[i] *= factor;
       
  1454                                 }
       
  1455                             }
       
  1456                         }
       
  1457                         for (int i = 0; i < numColorComponents; i++) {
       
  1458                             ddata[i] = norm[i];
       
  1459                         }
       
  1460                     }
       
  1461                     return ddata;
       
  1462                 }
       
  1463             }
       
  1464         }
       
  1465 
       
  1466         // Handle BYTE, USHORT, & INT here
       
  1467         //REMIND: maybe more efficient not to use int array for
       
  1468         //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
       
  1469         int intpixel[];
       
  1470         if (transferType == DataBuffer.TYPE_INT &&
       
  1471             pixel != null) {
       
  1472            intpixel = (int[])pixel;
       
  1473         } else {
       
  1474             intpixel = new int[numComponents];
       
  1475         }
       
  1476 
       
  1477         if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
       
  1478             int precision;
       
  1479             float factor;
       
  1480             if (is_LinearRGB_stdScale) {
       
  1481                 if (transferType == DataBuffer.TYPE_BYTE) {
       
  1482                     red = fromsRGB8LUT8[red] & 0xff;
       
  1483                     grn = fromsRGB8LUT8[grn] & 0xff;
       
  1484                     blu = fromsRGB8LUT8[blu] & 0xff;
       
  1485                     precision = 8;
       
  1486                     factor = 1.0f / 255.0f;
       
  1487                 } else {
       
  1488                     red = fromsRGB8LUT16[red] & 0xffff;
       
  1489                     grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1490                     blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1491                     precision = 16;
       
  1492                     factor = 1.0f / 65535.0f;
       
  1493                 }
       
  1494             } else {
       
  1495                 precision = 8;
       
  1496                 factor = 1.0f / 255.0f;
       
  1497             }
       
  1498             if (supportsAlpha) {
       
  1499                 alp = (rgb>>24)&0xff;
       
  1500                 if (nBits[3] == 8) {
       
  1501                     intpixel[3] = alp;
       
  1502                 }
       
  1503                 else {
       
  1504                     intpixel[3] = (int)
       
  1505                         (alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1) + 0.5f);
       
  1506                 }
       
  1507                 if (isAlphaPremultiplied) {
       
  1508                     factor *= (alp * (1.0f / 255.0f));
       
  1509                     precision = -1;  // force component calculations below
       
  1510                 }
       
  1511             }
       
  1512             if (nBits[0] == precision) {
       
  1513                 intpixel[0] = red;
       
  1514             }
       
  1515             else {
       
  1516                 intpixel[0] = (int) (red * factor * ((1<<nBits[0]) - 1) + 0.5f);
       
  1517             }
       
  1518             if (nBits[1] == precision) {
       
  1519                 intpixel[1] = grn;
       
  1520             }
       
  1521             else {
       
  1522                 intpixel[1] = (int) (grn * factor * ((1<<nBits[1]) - 1) + 0.5f);
       
  1523             }
       
  1524             if (nBits[2] == precision) {
       
  1525                 intpixel[2] = blu;
       
  1526             }
       
  1527             else {
       
  1528                 intpixel[2] = (int) (blu * factor * ((1<<nBits[2]) - 1) + 0.5f);
       
  1529             }
       
  1530         } else if (is_LinearGray_stdScale) {
       
  1531             red = fromsRGB8LUT16[red] & 0xffff;
       
  1532             grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1533             blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1534             float gray = ((0.2125f * red) +
       
  1535                           (0.7154f * grn) +
       
  1536                           (0.0721f * blu)) / 65535.0f;
       
  1537             if (supportsAlpha) {
       
  1538                 alp = (rgb>>24) & 0xff;
       
  1539                 if (nBits[1] == 8) {
       
  1540                     intpixel[1] = alp;
       
  1541                 } else {
       
  1542                     intpixel[1] = (int) (alp * (1.0f / 255.0f) *
       
  1543                                          ((1 << nBits[1]) - 1) + 0.5f);
       
  1544                 }
       
  1545                 if (isAlphaPremultiplied) {
       
  1546                     gray *= (alp * (1.0f / 255.0f));
       
  1547                 }
       
  1548             }
       
  1549             intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
       
  1550         } else if (is_ICCGray_stdScale) {
       
  1551             red = fromsRGB8LUT16[red] & 0xffff;
       
  1552             grn = fromsRGB8LUT16[grn] & 0xffff;
       
  1553             blu = fromsRGB8LUT16[blu] & 0xffff;
       
  1554             int gray16 = (int) ((0.2125f * red) +
       
  1555                                 (0.7154f * grn) +
       
  1556                                 (0.0721f * blu) + 0.5f);
       
  1557             float gray = (fromLinearGray16ToOtherGray16LUT[gray16] &
       
  1558                           0xffff) / 65535.0f;
       
  1559             if (supportsAlpha) {
       
  1560                 alp = (rgb>>24) & 0xff;
       
  1561                 if (nBits[1] == 8) {
       
  1562                     intpixel[1] = alp;
       
  1563                 } else {
       
  1564                     intpixel[1] = (int) (alp * (1.0f / 255.0f) *
       
  1565                                          ((1 << nBits[1]) - 1) + 0.5f);
       
  1566                 }
       
  1567                 if (isAlphaPremultiplied) {
       
  1568                     gray *= (alp * (1.0f / 255.0f));
       
  1569                 }
       
  1570             }
       
  1571             intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
       
  1572         } else {
       
  1573             // Need to convert the color
       
  1574             float[] norm = new float[3];
       
  1575             float factor = 1.0f / 255.0f;
       
  1576             norm[0] = red * factor;
       
  1577             norm[1] = grn * factor;
       
  1578             norm[2] = blu * factor;
       
  1579             norm = colorSpace.fromRGB(norm);
       
  1580             if (nonStdScale) {
       
  1581                 for (int i = 0; i < numColorComponents; i++) {
       
  1582                     norm[i] = (norm[i] - compOffset[i]) *
       
  1583                               compScale[i];
       
  1584                     // REMIND: need to analyze whether this
       
  1585                     // clamping is necessary
       
  1586                     if (norm[i] < 0.0f) {
       
  1587                         norm[i] = 0.0f;
       
  1588                     }
       
  1589                     if (norm[i] > 1.0f) {
       
  1590                         norm[i] = 1.0f;
       
  1591                     }
       
  1592                 }
       
  1593             }
       
  1594             if (supportsAlpha) {
       
  1595                 alp = (rgb>>24) & 0xff;
       
  1596                 if (nBits[numColorComponents] == 8) {
       
  1597                     intpixel[numColorComponents] = alp;
       
  1598                 }
       
  1599                 else {
       
  1600                     intpixel[numColorComponents] =
       
  1601                         (int) (alp * factor *
       
  1602                                ((1<<nBits[numColorComponents]) - 1) + 0.5f);
       
  1603                 }
       
  1604                 if (isAlphaPremultiplied) {
       
  1605                     factor *= alp;
       
  1606                     for (int i = 0; i < numColorComponents; i++) {
       
  1607                         norm[i] *= factor;
       
  1608                     }
       
  1609                 }
       
  1610             }
       
  1611             for (int i = 0; i < numColorComponents; i++) {
       
  1612                 intpixel[i] = (int) (norm[i] * ((1<<nBits[i]) - 1) + 0.5f);
       
  1613             }
       
  1614         }
       
  1615 
       
  1616         switch (transferType) {
       
  1617             case DataBuffer.TYPE_BYTE: {
       
  1618                byte bdata[];
       
  1619                if (pixel == null) {
       
  1620                    bdata = new byte[numComponents];
       
  1621                } else {
       
  1622                    bdata = (byte[])pixel;
       
  1623                }
       
  1624                for (int i = 0; i < numComponents; i++) {
       
  1625                    bdata[i] = (byte)(0xff&intpixel[i]);
       
  1626                }
       
  1627                return bdata;
       
  1628             }
       
  1629             case DataBuffer.TYPE_USHORT:{
       
  1630                short sdata[];
       
  1631                if (pixel == null) {
       
  1632                    sdata = new short[numComponents];
       
  1633                } else {
       
  1634                    sdata = (short[])pixel;
       
  1635                }
       
  1636                for (int i = 0; i < numComponents; i++) {
       
  1637                    sdata[i] = (short)(intpixel[i]&0xffff);
       
  1638                }
       
  1639                return sdata;
       
  1640             }
       
  1641             case DataBuffer.TYPE_INT:
       
  1642                 if (maxBits > 23) {
       
  1643                     // fix 4412670 - for components of 24 or more bits
       
  1644                     // some calculations done above with float precision
       
  1645                     // may lose enough precision that the integer result
       
  1646                     // overflows nBits, so we need to clamp.
       
  1647                     for (int i = 0; i < numComponents; i++) {
       
  1648                         if (intpixel[i] > ((1<<nBits[i]) - 1)) {
       
  1649                             intpixel[i] = (1<<nBits[i]) - 1;
       
  1650                         }
       
  1651                     }
       
  1652                 }
       
  1653                 return intpixel;
       
  1654         }
       
  1655         throw new IllegalArgumentException("This method has not been "+
       
  1656                  "implemented for transferType " + transferType);
       
  1657     }
       
  1658 
       
  1659    /** Returns an array of unnormalized color/alpha components given a pixel
       
  1660      * in this {@code ColorModel}.
       
  1661      * An IllegalArgumentException is thrown if the component value for this
       
  1662      * {@code ColorModel} is not conveniently representable in the
       
  1663      * unnormalized form.  Color/alpha components are stored
       
  1664      * in the {@code components} array starting at {@code offset}
       
  1665      * (even if the array is allocated by this method).
       
  1666      *
       
  1667      * @param pixel The pixel value specified as an integer.
       
  1668      * @param components An integer array in which to store the unnormalized
       
  1669      * color/alpha components. If the {@code components} array is null,
       
  1670      * a new array is allocated.
       
  1671      * @param offset An offset into the {@code components} array.
       
  1672      *
       
  1673      * @return The components array.
       
  1674      *
       
  1675      * @throws IllegalArgumentException If there is more than one
       
  1676      * component in this {@code ColorModel}.
       
  1677      * @throws IllegalArgumentException If this
       
  1678      * {@code ColorModel} does not support the unnormalized form
       
  1679      * @throws ArrayIndexOutOfBoundsException If the {@code components}
       
  1680      * array is not null and is not large enough to hold all the color and
       
  1681      * alpha components (starting at offset).
       
  1682      */
       
  1683     public int[] getComponents(int pixel, int[] components, int offset) {
       
  1684         if (numComponents > 1) {
       
  1685             throw new
       
  1686                 IllegalArgumentException("More than one component per pixel");
       
  1687         }
       
  1688         if (needScaleInit) {
       
  1689             initScale();
       
  1690         }
       
  1691         if (noUnnorm) {
       
  1692             throw new
       
  1693                 IllegalArgumentException(
       
  1694                     "This ColorModel does not support the unnormalized form");
       
  1695         }
       
  1696         if (components == null) {
       
  1697             components = new int[offset+1];
       
  1698         }
       
  1699 
       
  1700         components[offset+0] = (pixel & ((1<<nBits[0]) - 1));
       
  1701         return components;
       
  1702     }
       
  1703 
       
  1704     /**
       
  1705      * Returns an array of unnormalized color/alpha components given a pixel
       
  1706      * in this {@code ColorModel}.  The pixel value is specified by an
       
  1707      * array of data elements of type {@code transferType} passed in as
       
  1708      * an object reference.
       
  1709      * An IllegalArgumentException is thrown if the component values for this
       
  1710      * {@code ColorModel} are not conveniently representable in the
       
  1711      * unnormalized form.
       
  1712      * Color/alpha components are stored in the {@code components} array
       
  1713      * starting at  {@code offset} (even if the array is allocated by
       
  1714      * this method).  Since {@code ComponentColorModel} can be
       
  1715      * subclassed, subclasses inherit the
       
  1716      * implementation of this method and if they don't override it then
       
  1717      * this method might throw an exception if they use an unsupported
       
  1718      * {@code transferType}.
       
  1719      *
       
  1720      * @param pixel A pixel value specified by an array of data elements of
       
  1721      * type {@code transferType}.
       
  1722      * @param components An integer array in which to store the unnormalized
       
  1723      * color/alpha components. If the {@code components} array is null,
       
  1724      * a new array is allocated.
       
  1725      * @param offset An offset into the {@code components} array.
       
  1726      *
       
  1727      * @return The {@code components} array.
       
  1728      *
       
  1729      * @throws IllegalArgumentException If this
       
  1730      * {@code ComponentColorModel} does not support the unnormalized form
       
  1731      * @throws UnsupportedOperationException in some cases iff the
       
  1732      * transfer type of this {@code ComponentColorModel}
       
  1733      * is not one of the following transfer types:
       
  1734      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
  1735      * or {@code DataBuffer.TYPE_INT}.
       
  1736      * @throws ClassCastException If {@code pixel} is not a primitive
       
  1737      * array of type {@code transferType}.
       
  1738      * @throws IllegalArgumentException If the {@code components} array is
       
  1739      * not null and is not large enough to hold all the color and alpha
       
  1740      * components (starting at offset), or if {@code pixel} is not large
       
  1741      * enough to hold a pixel value for this ColorModel.
       
  1742      */
       
  1743     public int[] getComponents(Object pixel, int[] components, int offset) {
       
  1744         int intpixel[];
       
  1745         if (needScaleInit) {
       
  1746             initScale();
       
  1747         }
       
  1748         if (noUnnorm) {
       
  1749             throw new
       
  1750                 IllegalArgumentException(
       
  1751                     "This ColorModel does not support the unnormalized form");
       
  1752         }
       
  1753         if (pixel instanceof int[]) {
       
  1754             intpixel = (int[])pixel;
       
  1755         } else {
       
  1756             intpixel = DataBuffer.toIntArray(pixel);
       
  1757             if (intpixel == null) {
       
  1758                throw new UnsupportedOperationException("This method has not been "+
       
  1759                    "implemented for transferType " + transferType);
       
  1760             }
       
  1761         }
       
  1762         if (intpixel.length < numComponents) {
       
  1763             throw new IllegalArgumentException
       
  1764                 ("Length of pixel array < number of components in model");
       
  1765         }
       
  1766         if (components == null) {
       
  1767             components = new int[offset+numComponents];
       
  1768         }
       
  1769         else if ((components.length-offset) < numComponents) {
       
  1770             throw new IllegalArgumentException
       
  1771                 ("Length of components array < number of components in model");
       
  1772         }
       
  1773         System.arraycopy(intpixel, 0, components, offset, numComponents);
       
  1774 
       
  1775         return components;
       
  1776     }
       
  1777 
       
  1778     /**
       
  1779      * Returns an array of all of the color/alpha components in unnormalized
       
  1780      * form, given a normalized component array.  Unnormalized components
       
  1781      * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
       
  1782      * n is the number of bits for a particular component.  Normalized
       
  1783      * components are float values between a per component minimum and
       
  1784      * maximum specified by the {@code ColorSpace} object for this
       
  1785      * {@code ColorModel}.  An {@code IllegalArgumentException}
       
  1786      * will be thrown if color component values for this
       
  1787      * {@code ColorModel} are not conveniently representable in the
       
  1788      * unnormalized form.  If the
       
  1789      * {@code components} array is {@code null}, a new array
       
  1790      * will be allocated.  The {@code components} array will
       
  1791      * be returned.  Color/alpha components are stored in the
       
  1792      * {@code components} array starting at {@code offset} (even
       
  1793      * if the array is allocated by this method). An
       
  1794      * {@code ArrayIndexOutOfBoundsException} is thrown if the
       
  1795      * {@code components} array is not {@code null} and is not
       
  1796      * large enough to hold all the color and alpha
       
  1797      * components (starting at {@code offset}).  An
       
  1798      * {@code IllegalArgumentException} is thrown if the
       
  1799      * {@code normComponents} array is not large enough to hold
       
  1800      * all the color and alpha components starting at
       
  1801      * {@code normOffset}.
       
  1802      * @param normComponents an array containing normalized components
       
  1803      * @param normOffset the offset into the {@code normComponents}
       
  1804      * array at which to start retrieving normalized components
       
  1805      * @param components an array that receives the components from
       
  1806      * {@code normComponents}
       
  1807      * @param offset the index into {@code components} at which to
       
  1808      * begin storing normalized components from
       
  1809      * {@code normComponents}
       
  1810      * @return an array containing unnormalized color and alpha
       
  1811      * components.
       
  1812      * @throws IllegalArgumentException If this
       
  1813      * {@code ComponentColorModel} does not support the unnormalized form
       
  1814      * @throws IllegalArgumentException if the length of
       
  1815      *          {@code normComponents} minus {@code normOffset}
       
  1816      *          is less than {@code numComponents}
       
  1817      */
       
  1818     public int[] getUnnormalizedComponents(float[] normComponents,
       
  1819                                            int normOffset,
       
  1820                                            int[] components, int offset) {
       
  1821         if (needScaleInit) {
       
  1822             initScale();
       
  1823         }
       
  1824         if (noUnnorm) {
       
  1825             throw new
       
  1826                 IllegalArgumentException(
       
  1827                     "This ColorModel does not support the unnormalized form");
       
  1828         }
       
  1829         return super.getUnnormalizedComponents(normComponents, normOffset,
       
  1830                                                components, offset);
       
  1831     }
       
  1832 
       
  1833     /**
       
  1834      * Returns an array of all of the color/alpha components in normalized
       
  1835      * form, given an unnormalized component array.  Unnormalized components
       
  1836      * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
       
  1837      * n is the number of bits for a particular component.  Normalized
       
  1838      * components are float values between a per component minimum and
       
  1839      * maximum specified by the {@code ColorSpace} object for this
       
  1840      * {@code ColorModel}.  An {@code IllegalArgumentException}
       
  1841      * will be thrown if color component values for this
       
  1842      * {@code ColorModel} are not conveniently representable in the
       
  1843      * unnormalized form.  If the
       
  1844      * {@code normComponents} array is {@code null}, a new array
       
  1845      * will be allocated.  The {@code normComponents} array
       
  1846      * will be returned.  Color/alpha components are stored in the
       
  1847      * {@code normComponents} array starting at
       
  1848      * {@code normOffset} (even if the array is allocated by this
       
  1849      * method).  An {@code ArrayIndexOutOfBoundsException} is thrown
       
  1850      * if the {@code normComponents} array is not {@code null}
       
  1851      * and is not large enough to hold all the color and alpha components
       
  1852      * (starting at {@code normOffset}).  An
       
  1853      * {@code IllegalArgumentException} is thrown if the
       
  1854      * {@code components} array is not large enough to hold all the
       
  1855      * color and alpha components starting at {@code offset}.
       
  1856      * @param components an array containing unnormalized components
       
  1857      * @param offset the offset into the {@code components} array at
       
  1858      * which to start retrieving unnormalized components
       
  1859      * @param normComponents an array that receives the normalized components
       
  1860      * @param normOffset the index into {@code normComponents} at
       
  1861      * which to begin storing normalized components
       
  1862      * @return an array containing normalized color and alpha
       
  1863      * components.
       
  1864      * @throws IllegalArgumentException If this
       
  1865      * {@code ComponentColorModel} does not support the unnormalized form
       
  1866      */
       
  1867     public float[] getNormalizedComponents(int[] components, int offset,
       
  1868                                            float[] normComponents,
       
  1869                                            int normOffset) {
       
  1870         if (needScaleInit) {
       
  1871             initScale();
       
  1872         }
       
  1873         if (noUnnorm) {
       
  1874             throw new
       
  1875                 IllegalArgumentException(
       
  1876                     "This ColorModel does not support the unnormalized form");
       
  1877         }
       
  1878         return super.getNormalizedComponents(components, offset,
       
  1879                                              normComponents, normOffset);
       
  1880     }
       
  1881 
       
  1882     /**
       
  1883      * Returns a pixel value represented as an int in this {@code ColorModel},
       
  1884      * given an array of unnormalized color/alpha components.
       
  1885      *
       
  1886      * @param components An array of unnormalized color/alpha components.
       
  1887      * @param offset An offset into the {@code components} array.
       
  1888      *
       
  1889      * @return A pixel value represented as an int.
       
  1890      *
       
  1891      * @throws IllegalArgumentException If there is more than one component
       
  1892      * in this {@code ColorModel}.
       
  1893      * @throws IllegalArgumentException If this
       
  1894      * {@code ComponentColorModel} does not support the unnormalized form
       
  1895      */
       
  1896     public int getDataElement(int[] components, int offset) {
       
  1897         if (needScaleInit) {
       
  1898             initScale();
       
  1899         }
       
  1900         if (numComponents == 1) {
       
  1901             if (noUnnorm) {
       
  1902                 throw new
       
  1903                     IllegalArgumentException(
       
  1904                     "This ColorModel does not support the unnormalized form");
       
  1905             }
       
  1906             return components[offset+0];
       
  1907         }
       
  1908         throw new IllegalArgumentException("This model returns "+
       
  1909                                            numComponents+
       
  1910                                            " elements in the pixel array.");
       
  1911     }
       
  1912 
       
  1913     /**
       
  1914      * Returns a data element array representation of a pixel in this
       
  1915      * {@code ColorModel}, given an array of unnormalized color/alpha
       
  1916      * components. This array can then be passed to the {@code setDataElements}
       
  1917      * method of a {@code WritableRaster} object.
       
  1918      *
       
  1919      * @param components An array of unnormalized color/alpha components.
       
  1920      * @param offset The integer offset into the {@code components} array.
       
  1921      * @param obj The object in which to store the data element array
       
  1922      * representation of the pixel. If {@code obj} variable is null,
       
  1923      * a new array is allocated.  If {@code obj} is not null, it must
       
  1924      * be a primitive array of type {@code transferType}. An
       
  1925      * {@code ArrayIndexOutOfBoundsException} is thrown if
       
  1926      * {@code obj} is not large enough to hold a pixel value
       
  1927      * for this {@code ColorModel}.  Since
       
  1928      * {@code ComponentColorModel} can be subclassed, subclasses
       
  1929      * inherit the implementation of this method and if they don't
       
  1930      * override it then they throw an exception if they use an
       
  1931      * unsupported {@code transferType}.
       
  1932      *
       
  1933      * @return The data element array representation of a pixel
       
  1934      * in this {@code ColorModel}.
       
  1935      *
       
  1936      * @throws IllegalArgumentException If the components array
       
  1937      * is not large enough to hold all the color and alpha components
       
  1938      * (starting at offset).
       
  1939      * @throws ClassCastException If {@code obj} is not null and is not a
       
  1940      * primitive  array of type {@code transferType}.
       
  1941      * @throws ArrayIndexOutOfBoundsException If {@code obj} is not large
       
  1942      * enough to hold a pixel value for this {@code ColorModel}.
       
  1943      * @throws IllegalArgumentException If this
       
  1944      * {@code ComponentColorModel} does not support the unnormalized form
       
  1945      * @throws UnsupportedOperationException If the transfer type of
       
  1946      * this {@code ComponentColorModel}
       
  1947      * is not one of the following transfer types:
       
  1948      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
  1949      * or {@code DataBuffer.TYPE_INT}.
       
  1950      *
       
  1951      * @see WritableRaster#setDataElements
       
  1952      * @see SampleModel#setDataElements
       
  1953      */
       
  1954     public Object getDataElements(int[] components, int offset, Object obj) {
       
  1955         if (needScaleInit) {
       
  1956             initScale();
       
  1957         }
       
  1958         if (noUnnorm) {
       
  1959             throw new
       
  1960                 IllegalArgumentException(
       
  1961                     "This ColorModel does not support the unnormalized form");
       
  1962         }
       
  1963         if ((components.length-offset) < numComponents) {
       
  1964             throw new IllegalArgumentException("Component array too small"+
       
  1965                                                " (should be "+numComponents);
       
  1966         }
       
  1967         switch(transferType) {
       
  1968         case DataBuffer.TYPE_INT:
       
  1969             {
       
  1970                 int[] pixel;
       
  1971                 if (obj == null) {
       
  1972                     pixel = new int[numComponents];
       
  1973                 }
       
  1974                 else {
       
  1975                     pixel = (int[]) obj;
       
  1976                 }
       
  1977                 System.arraycopy(components, offset, pixel, 0,
       
  1978                                  numComponents);
       
  1979                 return pixel;
       
  1980             }
       
  1981 
       
  1982         case DataBuffer.TYPE_BYTE:
       
  1983             {
       
  1984                 byte[] pixel;
       
  1985                 if (obj == null) {
       
  1986                     pixel = new byte[numComponents];
       
  1987                 }
       
  1988                 else {
       
  1989                     pixel = (byte[]) obj;
       
  1990                 }
       
  1991                 for (int i=0; i < numComponents; i++) {
       
  1992                     pixel[i] = (byte) (components[offset+i]&0xff);
       
  1993                 }
       
  1994                 return pixel;
       
  1995             }
       
  1996 
       
  1997         case DataBuffer.TYPE_USHORT:
       
  1998             {
       
  1999                 short[] pixel;
       
  2000                 if (obj == null) {
       
  2001                     pixel = new short[numComponents];
       
  2002                 }
       
  2003                 else {
       
  2004                     pixel = (short[]) obj;
       
  2005                 }
       
  2006                 for (int i=0; i < numComponents; i++) {
       
  2007                     pixel[i] = (short) (components[offset+i]&0xffff);
       
  2008                 }
       
  2009                 return pixel;
       
  2010             }
       
  2011 
       
  2012         default:
       
  2013             throw new UnsupportedOperationException("This method has not been "+
       
  2014                                         "implemented for transferType " +
       
  2015                                         transferType);
       
  2016         }
       
  2017     }
       
  2018 
       
  2019     /**
       
  2020      * Returns a pixel value represented as an {@code int} in this
       
  2021      * {@code ColorModel}, given an array of normalized color/alpha
       
  2022      * components.  This method will throw an
       
  2023      * {@code IllegalArgumentException} if pixel values for this
       
  2024      * {@code ColorModel} are not conveniently representable as a
       
  2025      * single {@code int}.  An
       
  2026      * {@code ArrayIndexOutOfBoundsException} is thrown if  the
       
  2027      * {@code normComponents} array is not large enough to hold all the
       
  2028      * color and alpha components (starting at {@code normOffset}).
       
  2029      * @param normComponents an array of normalized color and alpha
       
  2030      * components
       
  2031      * @param normOffset the index into {@code normComponents} at which to
       
  2032      * begin retrieving the color and alpha components
       
  2033      * @return an {@code int} pixel value in this
       
  2034      * {@code ColorModel} corresponding to the specified components.
       
  2035      * @throws IllegalArgumentException if
       
  2036      *  pixel values for this {@code ColorModel} are not
       
  2037      *  conveniently representable as a single {@code int}
       
  2038      * @throws ArrayIndexOutOfBoundsException if
       
  2039      *  the {@code normComponents} array is not large enough to
       
  2040      *  hold all of the color and alpha components starting at
       
  2041      *  {@code normOffset}
       
  2042      * @since 1.4
       
  2043      */
       
  2044     public int getDataElement(float[] normComponents, int normOffset) {
       
  2045         if (numComponents > 1) {
       
  2046             throw new
       
  2047                 IllegalArgumentException("More than one component per pixel");
       
  2048         }
       
  2049         if (signed) {
       
  2050             throw new
       
  2051                 IllegalArgumentException("Component value is signed");
       
  2052         }
       
  2053         if (needScaleInit) {
       
  2054             initScale();
       
  2055         }
       
  2056         Object pixel = getDataElements(normComponents, normOffset, null);
       
  2057         switch (transferType) {
       
  2058         case DataBuffer.TYPE_BYTE:
       
  2059             {
       
  2060                 byte bpixel[] = (byte[]) pixel;
       
  2061                 return bpixel[0] & 0xff;
       
  2062             }
       
  2063         case DataBuffer.TYPE_USHORT:
       
  2064             {
       
  2065                 short[] uspixel = (short[]) pixel;
       
  2066                 return uspixel[0] & 0xffff;
       
  2067             }
       
  2068         case DataBuffer.TYPE_INT:
       
  2069             {
       
  2070                 int[] ipixel = (int[]) pixel;
       
  2071                 return ipixel[0];
       
  2072             }
       
  2073         default:
       
  2074             throw new UnsupportedOperationException("This method has not been "
       
  2075                 + "implemented for transferType " + transferType);
       
  2076         }
       
  2077     }
       
  2078 
       
  2079     /**
       
  2080      * Returns a data element array representation of a pixel in this
       
  2081      * {@code ColorModel}, given an array of normalized color/alpha
       
  2082      * components.  This array can then be passed to the
       
  2083      * {@code setDataElements} method of a {@code WritableRaster}
       
  2084      * object.  An {@code ArrayIndexOutOfBoundsException} is thrown
       
  2085      * if the {@code normComponents} array is not large enough to hold
       
  2086      * all the color and alpha components (starting at
       
  2087      * {@code normOffset}).  If the {@code obj} variable is
       
  2088      * {@code null}, a new array will be allocated.  If
       
  2089      * {@code obj} is not {@code null}, it must be a primitive
       
  2090      * array of type transferType; otherwise, a
       
  2091      * {@code ClassCastException} is thrown.  An
       
  2092      * {@code ArrayIndexOutOfBoundsException} is thrown if
       
  2093      * {@code obj} is not large enough to hold a pixel value for this
       
  2094      * {@code ColorModel}.
       
  2095      * @param normComponents an array of normalized color and alpha
       
  2096      * components
       
  2097      * @param normOffset the index into {@code normComponents} at which to
       
  2098      * begin retrieving color and alpha components
       
  2099      * @param obj a primitive data array to hold the returned pixel
       
  2100      * @return an {@code Object} which is a primitive data array
       
  2101      * representation of a pixel
       
  2102      * @throws ClassCastException if {@code obj}
       
  2103      *  is not a primitive array of type {@code transferType}
       
  2104      * @throws ArrayIndexOutOfBoundsException if
       
  2105      *  {@code obj} is not large enough to hold a pixel value
       
  2106      *  for this {@code ColorModel} or the {@code normComponents}
       
  2107      *  array is not large enough to hold all of the color and alpha
       
  2108      *  components starting at {@code normOffset}
       
  2109      * @see WritableRaster#setDataElements
       
  2110      * @see SampleModel#setDataElements
       
  2111      * @since 1.4
       
  2112      */
       
  2113     public Object getDataElements(float[] normComponents, int normOffset,
       
  2114                                   Object obj) {
       
  2115         boolean needAlpha = supportsAlpha && isAlphaPremultiplied;
       
  2116         float[] stdNormComponents;
       
  2117         if (needScaleInit) {
       
  2118             initScale();
       
  2119         }
       
  2120         if (nonStdScale) {
       
  2121             stdNormComponents = new float[numComponents];
       
  2122             for (int c = 0, nc = normOffset; c < numColorComponents;
       
  2123                  c++, nc++) {
       
  2124                 stdNormComponents[c] = (normComponents[nc] - compOffset[c]) *
       
  2125                                        compScale[c];
       
  2126                 // REMIND: need to analyze whether this
       
  2127                 // clamping is necessary
       
  2128                 if (stdNormComponents[c] < 0.0f) {
       
  2129                     stdNormComponents[c] = 0.0f;
       
  2130                 }
       
  2131                 if (stdNormComponents[c] > 1.0f) {
       
  2132                     stdNormComponents[c] = 1.0f;
       
  2133                 }
       
  2134             }
       
  2135             if (supportsAlpha) {
       
  2136                 stdNormComponents[numColorComponents] =
       
  2137                     normComponents[numColorComponents + normOffset];
       
  2138             }
       
  2139             normOffset = 0;
       
  2140         } else {
       
  2141             stdNormComponents = normComponents;
       
  2142         }
       
  2143         switch (transferType) {
       
  2144         case DataBuffer.TYPE_BYTE:
       
  2145             byte[] bpixel;
       
  2146             if (obj == null) {
       
  2147                 bpixel = new byte[numComponents];
       
  2148             } else {
       
  2149                 bpixel = (byte[]) obj;
       
  2150             }
       
  2151             if (needAlpha) {
       
  2152                 float alpha =
       
  2153                     stdNormComponents[numColorComponents + normOffset];
       
  2154                 for (int c = 0, nc = normOffset; c < numColorComponents;
       
  2155                      c++, nc++) {
       
  2156                     bpixel[c] = (byte) ((stdNormComponents[nc] * alpha) *
       
  2157                                         ((float) ((1 << nBits[c]) - 1)) + 0.5f);
       
  2158                 }
       
  2159                 bpixel[numColorComponents] =
       
  2160                     (byte) (alpha *
       
  2161                             ((float) ((1 << nBits[numColorComponents]) - 1)) +
       
  2162                             0.5f);
       
  2163             } else {
       
  2164                 for (int c = 0, nc = normOffset; c < numComponents;
       
  2165                      c++, nc++) {
       
  2166                     bpixel[c] = (byte) (stdNormComponents[nc] *
       
  2167                                         ((float) ((1 << nBits[c]) - 1)) + 0.5f);
       
  2168                 }
       
  2169             }
       
  2170             return bpixel;
       
  2171         case DataBuffer.TYPE_USHORT:
       
  2172             short[] uspixel;
       
  2173             if (obj == null) {
       
  2174                 uspixel = new short[numComponents];
       
  2175             } else {
       
  2176                 uspixel = (short[]) obj;
       
  2177             }
       
  2178             if (needAlpha) {
       
  2179                 float alpha =
       
  2180                     stdNormComponents[numColorComponents + normOffset];
       
  2181                 for (int c = 0, nc = normOffset; c < numColorComponents;
       
  2182                      c++, nc++) {
       
  2183                     uspixel[c] = (short) ((stdNormComponents[nc] * alpha) *
       
  2184                                           ((float) ((1 << nBits[c]) - 1)) +
       
  2185                                           0.5f);
       
  2186                 }
       
  2187                 uspixel[numColorComponents] =
       
  2188                     (short) (alpha *
       
  2189                              ((float) ((1 << nBits[numColorComponents]) - 1)) +
       
  2190                              0.5f);
       
  2191             } else {
       
  2192                 for (int c = 0, nc = normOffset; c < numComponents;
       
  2193                      c++, nc++) {
       
  2194                     uspixel[c] = (short) (stdNormComponents[nc] *
       
  2195                                           ((float) ((1 << nBits[c]) - 1)) +
       
  2196                                           0.5f);
       
  2197                 }
       
  2198             }
       
  2199             return uspixel;
       
  2200         case DataBuffer.TYPE_INT:
       
  2201             int[] ipixel;
       
  2202             if (obj == null) {
       
  2203                 ipixel = new int[numComponents];
       
  2204             } else {
       
  2205                 ipixel = (int[]) obj;
       
  2206             }
       
  2207             if (needAlpha) {
       
  2208                 float alpha =
       
  2209                     stdNormComponents[numColorComponents + normOffset];
       
  2210                 for (int c = 0, nc = normOffset; c < numColorComponents;
       
  2211                      c++, nc++) {
       
  2212                     ipixel[c] = (int) ((stdNormComponents[nc] * alpha) *
       
  2213                                        ((float) ((1 << nBits[c]) - 1)) + 0.5f);
       
  2214                 }
       
  2215                 ipixel[numColorComponents] =
       
  2216                     (int) (alpha *
       
  2217                            ((float) ((1 << nBits[numColorComponents]) - 1)) +
       
  2218                            0.5f);
       
  2219             } else {
       
  2220                 for (int c = 0, nc = normOffset; c < numComponents;
       
  2221                      c++, nc++) {
       
  2222                     ipixel[c] = (int) (stdNormComponents[nc] *
       
  2223                                        ((float) ((1 << nBits[c]) - 1)) + 0.5f);
       
  2224                 }
       
  2225             }
       
  2226             return ipixel;
       
  2227         case DataBuffer.TYPE_SHORT:
       
  2228             short[] spixel;
       
  2229             if (obj == null) {
       
  2230                 spixel = new short[numComponents];
       
  2231             } else {
       
  2232                 spixel = (short[]) obj;
       
  2233             }
       
  2234             if (needAlpha) {
       
  2235                 float alpha =
       
  2236                     stdNormComponents[numColorComponents + normOffset];
       
  2237                 for (int c = 0, nc = normOffset; c < numColorComponents;
       
  2238                      c++, nc++) {
       
  2239                     spixel[c] = (short)
       
  2240                         (stdNormComponents[nc] * alpha * 32767.0f + 0.5f);
       
  2241                 }
       
  2242                 spixel[numColorComponents] = (short) (alpha * 32767.0f + 0.5f);
       
  2243             } else {
       
  2244                 for (int c = 0, nc = normOffset; c < numComponents;
       
  2245                      c++, nc++) {
       
  2246                     spixel[c] = (short)
       
  2247                         (stdNormComponents[nc] * 32767.0f + 0.5f);
       
  2248                 }
       
  2249             }
       
  2250             return spixel;
       
  2251         case DataBuffer.TYPE_FLOAT:
       
  2252             float[] fpixel;
       
  2253             if (obj == null) {
       
  2254                 fpixel = new float[numComponents];
       
  2255             } else {
       
  2256                 fpixel = (float[]) obj;
       
  2257             }
       
  2258             if (needAlpha) {
       
  2259                 float alpha = normComponents[numColorComponents + normOffset];
       
  2260                 for (int c = 0, nc = normOffset; c < numColorComponents;
       
  2261                      c++, nc++) {
       
  2262                     fpixel[c] = normComponents[nc] * alpha;
       
  2263                 }
       
  2264                 fpixel[numColorComponents] = alpha;
       
  2265             } else {
       
  2266                 for (int c = 0, nc = normOffset; c < numComponents;
       
  2267                      c++, nc++) {
       
  2268                     fpixel[c] = normComponents[nc];
       
  2269                 }
       
  2270             }
       
  2271             return fpixel;
       
  2272         case DataBuffer.TYPE_DOUBLE:
       
  2273             double[] dpixel;
       
  2274             if (obj == null) {
       
  2275                 dpixel = new double[numComponents];
       
  2276             } else {
       
  2277                 dpixel = (double[]) obj;
       
  2278             }
       
  2279             if (needAlpha) {
       
  2280                 double alpha =
       
  2281                     (double) (normComponents[numColorComponents + normOffset]);
       
  2282                 for (int c = 0, nc = normOffset; c < numColorComponents;
       
  2283                      c++, nc++) {
       
  2284                     dpixel[c] = normComponents[nc] * alpha;
       
  2285                 }
       
  2286                 dpixel[numColorComponents] = alpha;
       
  2287             } else {
       
  2288                 for (int c = 0, nc = normOffset; c < numComponents;
       
  2289                      c++, nc++) {
       
  2290                     dpixel[c] = (double) normComponents[nc];
       
  2291                 }
       
  2292             }
       
  2293             return dpixel;
       
  2294         default:
       
  2295             throw new UnsupportedOperationException("This method has not been "+
       
  2296                                         "implemented for transferType " +
       
  2297                                         transferType);
       
  2298         }
       
  2299     }
       
  2300 
       
  2301     /**
       
  2302      * Returns an array of all of the color/alpha components in normalized
       
  2303      * form, given a pixel in this {@code ColorModel}.  The pixel
       
  2304      * value is specified by an array of data elements of type transferType
       
  2305      * passed in as an object reference.  If pixel is not a primitive array
       
  2306      * of type transferType, a {@code ClassCastException} is thrown.
       
  2307      * An {@code ArrayIndexOutOfBoundsException} is thrown if
       
  2308      * {@code pixel} is not large enough to hold a pixel value for this
       
  2309      * {@code ColorModel}.
       
  2310      * Normalized components are float values between a per component minimum
       
  2311      * and maximum specified by the {@code ColorSpace} object for this
       
  2312      * {@code ColorModel}.  If the
       
  2313      * {@code normComponents} array is {@code null}, a new array
       
  2314      * will be allocated.  The {@code normComponents} array
       
  2315      * will be returned.  Color/alpha components are stored in the
       
  2316      * {@code normComponents} array starting at
       
  2317      * {@code normOffset} (even if the array is allocated by this
       
  2318      * method).  An {@code ArrayIndexOutOfBoundsException} is thrown
       
  2319      * if the {@code normComponents} array is not {@code null}
       
  2320      * and is not large enough to hold all the color and alpha components
       
  2321      * (starting at {@code normOffset}).
       
  2322      * <p>
       
  2323      * This method must be overridden by a subclass if that subclass
       
  2324      * is designed to translate pixel sample values to color component values
       
  2325      * in a non-default way.  The default translations implemented by this
       
  2326      * class is described in the class comments.  Any subclass implementing
       
  2327      * a non-default translation must follow the constraints on allowable
       
  2328      * translations defined there.
       
  2329      * @param pixel the specified pixel
       
  2330      * @param normComponents an array to receive the normalized components
       
  2331      * @param normOffset the offset into the {@code normComponents}
       
  2332      * array at which to start storing normalized components
       
  2333      * @return an array containing normalized color and alpha
       
  2334      * components.
       
  2335      * @throws ClassCastException if {@code pixel} is not a primitive
       
  2336      *          array of type transferType
       
  2337      * @throws ArrayIndexOutOfBoundsException if
       
  2338      *          {@code normComponents} is not large enough to hold all
       
  2339      *          color and alpha components starting at {@code normOffset}
       
  2340      * @throws ArrayIndexOutOfBoundsException if
       
  2341      *          {@code pixel} is not large enough to hold a pixel
       
  2342      *          value for this {@code ColorModel}.
       
  2343      * @since 1.4
       
  2344      */
       
  2345     public float[] getNormalizedComponents(Object pixel,
       
  2346                                            float[] normComponents,
       
  2347                                            int normOffset) {
       
  2348         if (normComponents == null) {
       
  2349             normComponents = new float[numComponents+normOffset];
       
  2350         }
       
  2351         switch (transferType) {
       
  2352         case DataBuffer.TYPE_BYTE:
       
  2353             byte[] bpixel = (byte[]) pixel;
       
  2354             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
       
  2355                 normComponents[nc] = ((float) (bpixel[c] & 0xff)) /
       
  2356                                      ((float) ((1 << nBits[c]) - 1));
       
  2357             }
       
  2358             break;
       
  2359         case DataBuffer.TYPE_USHORT:
       
  2360             short[] uspixel = (short[]) pixel;
       
  2361             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
       
  2362                 normComponents[nc] = ((float) (uspixel[c] & 0xffff)) /
       
  2363                                      ((float) ((1 << nBits[c]) - 1));
       
  2364             }
       
  2365             break;
       
  2366         case DataBuffer.TYPE_INT:
       
  2367             int[] ipixel = (int[]) pixel;
       
  2368             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
       
  2369                 normComponents[nc] = ((float) ipixel[c]) /
       
  2370                                      ((float) ((1 << nBits[c]) - 1));
       
  2371             }
       
  2372             break;
       
  2373         case DataBuffer.TYPE_SHORT:
       
  2374             short[] spixel = (short[]) pixel;
       
  2375             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
       
  2376                 normComponents[nc] = ((float) spixel[c]) / 32767.0f;
       
  2377             }
       
  2378             break;
       
  2379         case DataBuffer.TYPE_FLOAT:
       
  2380             float[] fpixel = (float[]) pixel;
       
  2381             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
       
  2382                 normComponents[nc] = fpixel[c];
       
  2383             }
       
  2384             break;
       
  2385         case DataBuffer.TYPE_DOUBLE:
       
  2386             double[] dpixel = (double[]) pixel;
       
  2387             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
       
  2388                 normComponents[nc] = (float) dpixel[c];
       
  2389             }
       
  2390             break;
       
  2391         default:
       
  2392             throw new UnsupportedOperationException("This method has not been "+
       
  2393                                         "implemented for transferType " +
       
  2394                                         transferType);
       
  2395         }
       
  2396 
       
  2397         if (supportsAlpha && isAlphaPremultiplied) {
       
  2398             float alpha = normComponents[numColorComponents + normOffset];
       
  2399             if (alpha != 0.0f) {
       
  2400                 float invAlpha = 1.0f / alpha;
       
  2401                 for (int c = normOffset; c < numColorComponents + normOffset;
       
  2402                      c++) {
       
  2403                     normComponents[c] *= invAlpha;
       
  2404                 }
       
  2405             }
       
  2406         }
       
  2407         if (min != null) {
       
  2408             // Normally (i.e. when this class is not subclassed to override
       
  2409             // this method), the test (min != null) will be equivalent to
       
  2410             // the test (nonStdScale).  However, there is an unlikely, but
       
  2411             // possible case, in which this method is overridden, nonStdScale
       
  2412             // is set true by initScale(), the subclass method for some
       
  2413             // reason calls this superclass method, but the min and
       
  2414             // diffMinMax arrays were never initialized by setupLUTs().  In
       
  2415             // that case, the right thing to do is follow the intended
       
  2416             // semantics of this method, and rescale the color components
       
  2417             // only if the ColorSpace min/max were detected to be other
       
  2418             // than 0.0/1.0 by setupLUTs().  Note that this implies the
       
  2419             // transferType is byte, ushort, int, or short - i.e. components
       
  2420             // derived from float and double pixel data are never rescaled.
       
  2421             for (int c = 0; c < numColorComponents; c++) {
       
  2422                 normComponents[c + normOffset] = min[c] +
       
  2423                     diffMinMax[c] * normComponents[c + normOffset];
       
  2424             }
       
  2425         }
       
  2426         return normComponents;
       
  2427     }
       
  2428 
       
  2429     /**
       
  2430      * Forces the raster data to match the state specified in the
       
  2431      * {@code isAlphaPremultiplied} variable, assuming the data
       
  2432      * is currently correctly described by this {@code ColorModel}.
       
  2433      * It may multiply or divide the color raster data by alpha, or
       
  2434      * do nothing if the data is in the correct state.  If the data needs
       
  2435      * to be coerced, this method also returns an instance of
       
  2436      * this {@code ColorModel} with
       
  2437      * the {@code isAlphaPremultiplied} flag set appropriately.
       
  2438      * Since {@code ColorModel} can be subclassed, subclasses inherit
       
  2439      * the implementation of this method and if they don't override it
       
  2440      * then they throw an exception if they use an unsupported
       
  2441      * {@code transferType}.
       
  2442      *
       
  2443      * @throws NullPointerException if {@code raster} is
       
  2444      * {@code null} and data coercion is required.
       
  2445      * @throws UnsupportedOperationException if the transfer type of
       
  2446      * this {@code ComponentColorModel}
       
  2447      * is not one of the supported transfer types:
       
  2448      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
       
  2449      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
       
  2450      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
       
  2451      */
       
  2452     public ColorModel coerceData (WritableRaster raster,
       
  2453                                   boolean isAlphaPremultiplied) {
       
  2454         if ((supportsAlpha == false) ||
       
  2455             (this.isAlphaPremultiplied == isAlphaPremultiplied))
       
  2456         {
       
  2457             // Nothing to do
       
  2458             return this;
       
  2459         }
       
  2460 
       
  2461         int w = raster.getWidth();
       
  2462         int h = raster.getHeight();
       
  2463         int aIdx = raster.getNumBands() - 1;
       
  2464         float normAlpha;
       
  2465         int rminX = raster.getMinX();
       
  2466         int rY = raster.getMinY();
       
  2467         int rX;
       
  2468         if (isAlphaPremultiplied) {
       
  2469             switch (transferType) {
       
  2470                 case DataBuffer.TYPE_BYTE: {
       
  2471                     byte pixel[] = null;
       
  2472                     byte zpixel[] = null;
       
  2473                     float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
       
  2474                     for (int y = 0; y < h; y++, rY++) {
       
  2475                         rX = rminX;
       
  2476                         for (int x = 0; x < w; x++, rX++) {
       
  2477                             pixel = (byte[])raster.getDataElements(rX, rY,
       
  2478                                                                    pixel);
       
  2479                             normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
       
  2480                             if (normAlpha != 0.0f) {
       
  2481                                 for (int c=0; c < aIdx; c++) {
       
  2482                                     pixel[c] = (byte)((pixel[c] & 0xff) *
       
  2483                                                       normAlpha + 0.5f);
       
  2484                                 }
       
  2485                                 raster.setDataElements(rX, rY, pixel);
       
  2486                             } else {
       
  2487                                 if (zpixel == null) {
       
  2488                                     zpixel = new byte[numComponents];
       
  2489                                     java.util.Arrays.fill(zpixel, (byte) 0);
       
  2490                                 }
       
  2491                                 raster.setDataElements(rX, rY, zpixel);
       
  2492                             }
       
  2493                         }
       
  2494                     }
       
  2495                 }
       
  2496                 break;
       
  2497                 case DataBuffer.TYPE_USHORT: {
       
  2498                     short pixel[] = null;
       
  2499                     short zpixel[] = null;
       
  2500                     float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
       
  2501                     for (int y = 0; y < h; y++, rY++) {
       
  2502                         rX = rminX;
       
  2503                         for (int x = 0; x < w; x++, rX++) {
       
  2504                             pixel = (short[])raster.getDataElements(rX, rY,
       
  2505                                                                     pixel);
       
  2506                             normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
       
  2507                             if (normAlpha != 0.0f) {
       
  2508                                 for (int c=0; c < aIdx; c++) {
       
  2509                                     pixel[c] = (short)
       
  2510                                         ((pixel[c] & 0xffff) * normAlpha +
       
  2511                                          0.5f);
       
  2512                                 }
       
  2513                                 raster.setDataElements(rX, rY, pixel);
       
  2514                             } else {
       
  2515                                 if (zpixel == null) {
       
  2516                                     zpixel = new short[numComponents];
       
  2517                                     java.util.Arrays.fill(zpixel, (short) 0);
       
  2518                                 }
       
  2519                                 raster.setDataElements(rX, rY, zpixel);
       
  2520                             }
       
  2521                         }
       
  2522                     }
       
  2523                 }
       
  2524                 break;
       
  2525                 case DataBuffer.TYPE_INT: {
       
  2526                     int pixel[] = null;
       
  2527                     int zpixel[] = null;
       
  2528                     float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
       
  2529                     for (int y = 0; y < h; y++, rY++) {
       
  2530                         rX = rminX;
       
  2531                         for (int x = 0; x < w; x++, rX++) {
       
  2532                             pixel = (int[])raster.getDataElements(rX, rY,
       
  2533                                                                   pixel);
       
  2534                             normAlpha = pixel[aIdx] * alphaScale;
       
  2535                             if (normAlpha != 0.0f) {
       
  2536                                 for (int c=0; c < aIdx; c++) {
       
  2537                                     pixel[c] = (int) (pixel[c] * normAlpha +
       
  2538                                                       0.5f);
       
  2539                                 }
       
  2540                                 raster.setDataElements(rX, rY, pixel);
       
  2541                             } else {
       
  2542                                 if (zpixel == null) {
       
  2543                                     zpixel = new int[numComponents];
       
  2544                                     java.util.Arrays.fill(zpixel, 0);
       
  2545                                 }
       
  2546                                 raster.setDataElements(rX, rY, zpixel);
       
  2547                             }
       
  2548                         }
       
  2549                     }
       
  2550                 }
       
  2551                 break;
       
  2552                 case DataBuffer.TYPE_SHORT: {
       
  2553                     short pixel[] = null;
       
  2554                     short zpixel[] = null;
       
  2555                     float alphaScale = 1.0f / 32767.0f;
       
  2556                     for (int y = 0; y < h; y++, rY++) {
       
  2557                         rX = rminX;
       
  2558                         for (int x = 0; x < w; x++, rX++) {
       
  2559                             pixel = (short[]) raster.getDataElements(rX, rY,
       
  2560                                                                      pixel);
       
  2561                             normAlpha = pixel[aIdx] * alphaScale;
       
  2562                             if (normAlpha != 0.0f) {
       
  2563                                 for (int c=0; c < aIdx; c++) {
       
  2564                                     pixel[c] = (short) (pixel[c] * normAlpha +
       
  2565                                                         0.5f);
       
  2566                                 }
       
  2567                                 raster.setDataElements(rX, rY, pixel);
       
  2568                             } else {
       
  2569                                 if (zpixel == null) {
       
  2570                                     zpixel = new short[numComponents];
       
  2571                                     java.util.Arrays.fill(zpixel, (short) 0);
       
  2572                                 }
       
  2573                                 raster.setDataElements(rX, rY, zpixel);
       
  2574                             }
       
  2575                         }
       
  2576                     }
       
  2577                 }
       
  2578                 break;
       
  2579                 case DataBuffer.TYPE_FLOAT: {
       
  2580                     float pixel[] = null;
       
  2581                     float zpixel[] = null;
       
  2582                     for (int y = 0; y < h; y++, rY++) {
       
  2583                         rX = rminX;
       
  2584                         for (int x = 0; x < w; x++, rX++) {
       
  2585                             pixel = (float[]) raster.getDataElements(rX, rY,
       
  2586                                                                      pixel);
       
  2587                             normAlpha = pixel[aIdx];
       
  2588                             if (normAlpha != 0.0f) {
       
  2589                                 for (int c=0; c < aIdx; c++) {
       
  2590                                     pixel[c] *= normAlpha;
       
  2591                                 }
       
  2592                                 raster.setDataElements(rX, rY, pixel);
       
  2593                             } else {
       
  2594                                 if (zpixel == null) {
       
  2595                                     zpixel = new float[numComponents];
       
  2596                                     java.util.Arrays.fill(zpixel, 0.0f);
       
  2597                                 }
       
  2598                                 raster.setDataElements(rX, rY, zpixel);
       
  2599                             }
       
  2600                         }
       
  2601                     }
       
  2602                 }
       
  2603                 break;
       
  2604                 case DataBuffer.TYPE_DOUBLE: {
       
  2605                     double pixel[] = null;
       
  2606                     double zpixel[] = null;
       
  2607                     for (int y = 0; y < h; y++, rY++) {
       
  2608                         rX = rminX;
       
  2609                         for (int x = 0; x < w; x++, rX++) {
       
  2610                             pixel = (double[]) raster.getDataElements(rX, rY,
       
  2611                                                                       pixel);
       
  2612                             double dnormAlpha = pixel[aIdx];
       
  2613                             if (dnormAlpha != 0.0) {
       
  2614                                 for (int c=0; c < aIdx; c++) {
       
  2615                                     pixel[c] *= dnormAlpha;
       
  2616                                 }
       
  2617                                 raster.setDataElements(rX, rY, pixel);
       
  2618                             } else {
       
  2619                                 if (zpixel == null) {
       
  2620                                     zpixel = new double[numComponents];
       
  2621                                     java.util.Arrays.fill(zpixel, 0.0);
       
  2622                                 }
       
  2623                                 raster.setDataElements(rX, rY, zpixel);
       
  2624                             }
       
  2625                         }
       
  2626                     }
       
  2627                 }
       
  2628                 break;
       
  2629                 default:
       
  2630                     throw new UnsupportedOperationException("This method has not been "+
       
  2631                          "implemented for transferType " + transferType);
       
  2632             }
       
  2633         }
       
  2634         else {
       
  2635             // We are premultiplied and want to divide it out
       
  2636             switch (transferType) {
       
  2637                 case DataBuffer.TYPE_BYTE: {
       
  2638                     byte pixel[] = null;
       
  2639                     float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
       
  2640                     for (int y = 0; y < h; y++, rY++) {
       
  2641                         rX = rminX;
       
  2642                         for (int x = 0; x < w; x++, rX++) {
       
  2643                             pixel = (byte[])raster.getDataElements(rX, rY,
       
  2644                                                                    pixel);
       
  2645                             normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
       
  2646                             if (normAlpha != 0.0f) {
       
  2647                                 float invAlpha = 1.0f / normAlpha;
       
  2648                                 for (int c=0; c < aIdx; c++) {
       
  2649                                     pixel[c] = (byte)
       
  2650                                         ((pixel[c] & 0xff) * invAlpha + 0.5f);
       
  2651                                 }
       
  2652                                 raster.setDataElements(rX, rY, pixel);
       
  2653                             }
       
  2654                         }
       
  2655                     }
       
  2656                 }
       
  2657                 break;
       
  2658                 case DataBuffer.TYPE_USHORT: {
       
  2659                     short pixel[] = null;
       
  2660                     float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
       
  2661                     for (int y = 0; y < h; y++, rY++) {
       
  2662                         rX = rminX;
       
  2663                         for (int x = 0; x < w; x++, rX++) {
       
  2664                             pixel = (short[])raster.getDataElements(rX, rY,
       
  2665                                                                     pixel);
       
  2666                             normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
       
  2667                             if (normAlpha != 0.0f) {
       
  2668                                 float invAlpha = 1.0f / normAlpha;
       
  2669                                 for (int c=0; c < aIdx; c++) {
       
  2670                                     pixel[c] = (short)
       
  2671                                         ((pixel[c] & 0xffff) * invAlpha + 0.5f);
       
  2672                                 }
       
  2673                                 raster.setDataElements(rX, rY, pixel);
       
  2674                             }
       
  2675                         }
       
  2676                     }
       
  2677                 }
       
  2678                 break;
       
  2679                 case DataBuffer.TYPE_INT: {
       
  2680                     int pixel[] = null;
       
  2681                     float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
       
  2682                     for (int y = 0; y < h; y++, rY++) {
       
  2683                         rX = rminX;
       
  2684                         for (int x = 0; x < w; x++, rX++) {
       
  2685                             pixel = (int[])raster.getDataElements(rX, rY,
       
  2686                                                                   pixel);
       
  2687                             normAlpha = pixel[aIdx] * alphaScale;
       
  2688                             if (normAlpha != 0.0f) {
       
  2689                                 float invAlpha = 1.0f / normAlpha;
       
  2690                                 for (int c=0; c < aIdx; c++) {
       
  2691                                     pixel[c] = (int)
       
  2692                                         (pixel[c] * invAlpha + 0.5f);
       
  2693                                 }
       
  2694                                 raster.setDataElements(rX, rY, pixel);
       
  2695                             }
       
  2696                         }
       
  2697                     }
       
  2698                 }
       
  2699                 break;
       
  2700                 case DataBuffer.TYPE_SHORT: {
       
  2701                     short pixel[] = null;
       
  2702                     float alphaScale = 1.0f / 32767.0f;
       
  2703                     for (int y = 0; y < h; y++, rY++) {
       
  2704                         rX = rminX;
       
  2705                         for (int x = 0; x < w; x++, rX++) {
       
  2706                             pixel = (short[])raster.getDataElements(rX, rY,
       
  2707                                                                     pixel);
       
  2708                             normAlpha = pixel[aIdx] * alphaScale;
       
  2709                             if (normAlpha != 0.0f) {
       
  2710                                 float invAlpha = 1.0f / normAlpha;
       
  2711                                 for (int c=0; c < aIdx; c++) {
       
  2712                                     pixel[c] = (short)
       
  2713                                         (pixel[c] * invAlpha + 0.5f);
       
  2714                                 }
       
  2715                                 raster.setDataElements(rX, rY, pixel);
       
  2716                             }
       
  2717                         }
       
  2718                     }
       
  2719                 }
       
  2720                 break;
       
  2721                 case DataBuffer.TYPE_FLOAT: {
       
  2722                     float pixel[] = null;
       
  2723                     for (int y = 0; y < h; y++, rY++) {
       
  2724                         rX = rminX;
       
  2725                         for (int x = 0; x < w; x++, rX++) {
       
  2726                             pixel = (float[])raster.getDataElements(rX, rY,
       
  2727                                                                     pixel);
       
  2728                             normAlpha = pixel[aIdx];
       
  2729                             if (normAlpha != 0.0f) {
       
  2730                                 float invAlpha = 1.0f / normAlpha;
       
  2731                                 for (int c=0; c < aIdx; c++) {
       
  2732                                     pixel[c] *= invAlpha;
       
  2733                                 }
       
  2734                                 raster.setDataElements(rX, rY, pixel);
       
  2735                             }
       
  2736                         }
       
  2737                     }
       
  2738                 }
       
  2739                 break;
       
  2740                 case DataBuffer.TYPE_DOUBLE: {
       
  2741                     double pixel[] = null;
       
  2742                     for (int y = 0; y < h; y++, rY++) {
       
  2743                         rX = rminX;
       
  2744                         for (int x = 0; x < w; x++, rX++) {
       
  2745                             pixel = (double[])raster.getDataElements(rX, rY,
       
  2746                                                                      pixel);
       
  2747                             double dnormAlpha = pixel[aIdx];
       
  2748                             if (dnormAlpha != 0.0) {
       
  2749                                 double invAlpha = 1.0 / dnormAlpha;
       
  2750                                 for (int c=0; c < aIdx; c++) {
       
  2751                                     pixel[c] *= invAlpha;
       
  2752                                 }
       
  2753                                 raster.setDataElements(rX, rY, pixel);
       
  2754                             }
       
  2755                         }
       
  2756                     }
       
  2757                 }
       
  2758                 break;
       
  2759                 default:
       
  2760                     throw new UnsupportedOperationException("This method has not been "+
       
  2761                          "implemented for transferType " + transferType);
       
  2762             }
       
  2763         }
       
  2764 
       
  2765         // Return a new color model
       
  2766         if (!signed) {
       
  2767             return new ComponentColorModel(colorSpace, nBits, supportsAlpha,
       
  2768                                            isAlphaPremultiplied, transparency,
       
  2769                                            transferType);
       
  2770         } else {
       
  2771             return new ComponentColorModel(colorSpace, supportsAlpha,
       
  2772                                            isAlphaPremultiplied, transparency,
       
  2773                                            transferType);
       
  2774         }
       
  2775 
       
  2776     }
       
  2777 
       
  2778     /**
       
  2779       * Returns true if {@code raster} is compatible with this
       
  2780       * {@code ColorModel}; false if it is not.
       
  2781       *
       
  2782       * @param raster The {@code Raster} object to test for compatibility.
       
  2783       *
       
  2784       * @return {@code true} if {@code raster} is compatible with this
       
  2785       * {@code ColorModel}, {@code false} if it is not.
       
  2786       */
       
  2787     public boolean isCompatibleRaster(Raster raster) {
       
  2788 
       
  2789         SampleModel sm = raster.getSampleModel();
       
  2790 
       
  2791         if (sm instanceof ComponentSampleModel) {
       
  2792             if (sm.getNumBands() != getNumComponents()) {
       
  2793                 return false;
       
  2794             }
       
  2795             for (int i=0; i<nBits.length; i++) {
       
  2796                 if (sm.getSampleSize(i) < nBits[i]) {
       
  2797                     return false;
       
  2798                 }
       
  2799             }
       
  2800             return (raster.getTransferType() == transferType);
       
  2801         }
       
  2802         else {
       
  2803             return false;
       
  2804         }
       
  2805     }
       
  2806 
       
  2807     /**
       
  2808      * Creates a {@code WritableRaster} with the specified width and height,
       
  2809      * that  has a data layout ({@code SampleModel}) compatible with
       
  2810      * this {@code ColorModel}.
       
  2811      *
       
  2812      * @param w The width of the {@code WritableRaster} you want to create.
       
  2813      * @param h The height of the {@code WritableRaster} you want to create.
       
  2814      *
       
  2815      * @return A {@code WritableRaster} that is compatible with
       
  2816      * this {@code ColorModel}.
       
  2817      * @see WritableRaster
       
  2818      * @see SampleModel
       
  2819      */
       
  2820     public WritableRaster createCompatibleWritableRaster (int w, int h) {
       
  2821         int dataSize = w*h*numComponents;
       
  2822         WritableRaster raster = null;
       
  2823 
       
  2824         switch (transferType) {
       
  2825         case DataBuffer.TYPE_BYTE:
       
  2826         case DataBuffer.TYPE_USHORT:
       
  2827             raster = Raster.createInterleavedRaster(transferType,
       
  2828                                                     w, h,
       
  2829                                                     numComponents, null);
       
  2830             break;
       
  2831         default:
       
  2832             SampleModel sm = createCompatibleSampleModel(w, h);
       
  2833             DataBuffer db = sm.createDataBuffer();
       
  2834             raster = Raster.createWritableRaster(sm, db, null);
       
  2835         }
       
  2836 
       
  2837         return raster;
       
  2838     }
       
  2839 
       
  2840     /**
       
  2841      * Creates a {@code SampleModel} with the specified width and height,
       
  2842      * that  has a data layout compatible with this {@code ColorModel}.
       
  2843      *
       
  2844      * @param w The width of the {@code SampleModel} you want to create.
       
  2845      * @param h The height of the {@code SampleModel} you want to create.
       
  2846      *
       
  2847      * @return A {@code SampleModel} that is compatible with this
       
  2848      * {@code ColorModel}.
       
  2849      *
       
  2850      * @see SampleModel
       
  2851      */
       
  2852     public SampleModel createCompatibleSampleModel(int w, int h) {
       
  2853         int[] bandOffsets = new int[numComponents];
       
  2854         for (int i=0; i < numComponents; i++) {
       
  2855             bandOffsets[i] = i;
       
  2856         }
       
  2857         switch (transferType) {
       
  2858         case DataBuffer.TYPE_BYTE:
       
  2859         case DataBuffer.TYPE_USHORT:
       
  2860             return new PixelInterleavedSampleModel(transferType, w, h,
       
  2861                                                    numComponents,
       
  2862                                                    w*numComponents,
       
  2863                                                    bandOffsets);
       
  2864         default:
       
  2865             return new ComponentSampleModel(transferType, w, h,
       
  2866                                             numComponents,
       
  2867                                             w*numComponents,
       
  2868                                             bandOffsets);
       
  2869         }
       
  2870     }
       
  2871 
       
  2872     /**
       
  2873      * Checks whether or not the specified {@code SampleModel}
       
  2874      * is compatible with this {@code ColorModel}.
       
  2875      *
       
  2876      * @param sm The {@code SampleModel} to test for compatibility.
       
  2877      *
       
  2878      * @return {@code true} if the {@code SampleModel} is
       
  2879      * compatible with this {@code ColorModel}, {@code false}
       
  2880      * if it is not.
       
  2881      *
       
  2882      * @see SampleModel
       
  2883      */
       
  2884     public boolean isCompatibleSampleModel(SampleModel sm) {
       
  2885         if (!(sm instanceof ComponentSampleModel)) {
       
  2886             return false;
       
  2887         }
       
  2888 
       
  2889         // Must have the same number of components
       
  2890         if (numComponents != sm.getNumBands()) {
       
  2891             return false;
       
  2892         }
       
  2893 
       
  2894         if (sm.getTransferType() != transferType) {
       
  2895             return false;
       
  2896         }
       
  2897 
       
  2898         return true;
       
  2899     }
       
  2900 
       
  2901     /**
       
  2902      * Returns a {@code Raster} representing the alpha channel of an image,
       
  2903      * extracted from the input {@code Raster}.
       
  2904      * This method assumes that {@code Raster} objects associated with
       
  2905      * this {@code ColorModel} store the alpha band, if present, as
       
  2906      * the last band of image data. Returns null if there is no separate spatial
       
  2907      * alpha channel associated with this {@code ColorModel}.
       
  2908      * This method creates a new {@code Raster}, but will share the data
       
  2909      * array.
       
  2910      *
       
  2911      * @param raster The {@code WritableRaster} from which to extract the
       
  2912      * alpha  channel.
       
  2913      *
       
  2914      * @return A {@code WritableRaster} containing the image's alpha channel.
       
  2915      *
       
  2916      */
       
  2917     public WritableRaster getAlphaRaster(WritableRaster raster) {
       
  2918         if (hasAlpha() == false) {
       
  2919             return null;
       
  2920         }
       
  2921 
       
  2922         int x = raster.getMinX();
       
  2923         int y = raster.getMinY();
       
  2924         int[] band = new int[1];
       
  2925         band[0] = raster.getNumBands() - 1;
       
  2926         return raster.createWritableChild(x, y, raster.getWidth(),
       
  2927                                           raster.getHeight(), x, y,
       
  2928                                           band);
       
  2929     }
       
  2930 
       
  2931     /**
       
  2932      * Tests if the specified {@code Object} is an instance
       
  2933      * of {@code ComponentColorModel} and equals this
       
  2934      * {@code ComponentColorModel}.
       
  2935      * @param obj the {@code Object} to test for equality
       
  2936      * @return {@code true} if the specified {@code Object}
       
  2937      * is an instance of {@code ComponentColorModel} and equals this
       
  2938      * {@code ComponentColorModel}; {@code false} otherwise.
       
  2939      */
       
  2940     @Override
       
  2941     public boolean equals(Object obj) {
       
  2942         if (!(obj instanceof ComponentColorModel)) {
       
  2943             return false;
       
  2944         }
       
  2945 
       
  2946         ComponentColorModel cm = (ComponentColorModel) obj;
       
  2947         if (supportsAlpha != cm.hasAlpha() ||
       
  2948             isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
       
  2949             pixel_bits != cm.getPixelSize() ||
       
  2950             transparency != cm.getTransparency() ||
       
  2951             numComponents != cm.getNumComponents() ||
       
  2952             (!(colorSpace.equals(cm.colorSpace))) ||
       
  2953             transferType != cm.transferType)
       
  2954         {
       
  2955             return false;
       
  2956         }
       
  2957 
       
  2958         if (!(Arrays.equals(nBits, cm.getComponentSize()))) {
       
  2959             return false;
       
  2960         }
       
  2961 
       
  2962         return true;
       
  2963     }
       
  2964 
       
  2965     /**
       
  2966      * Returns the hash code for this ComponentColorModel.
       
  2967      *
       
  2968      * @return    a hash code for this ComponentColorModel.
       
  2969      */
       
  2970     @Override
       
  2971     public int hashCode() {
       
  2972         int result = hashCode;
       
  2973         if (result == 0) {
       
  2974             result = 7;
       
  2975             result = 89 * result + this.pixel_bits;
       
  2976             result = 89 * result + Arrays.hashCode(this.nBits);
       
  2977             result = 89 * result + this.transparency;
       
  2978             result = 89 * result + (this.supportsAlpha ? 1 : 0);
       
  2979             result = 89 * result + (this.isAlphaPremultiplied ? 1 : 0);
       
  2980             result = 89 * result + this.numComponents;
       
  2981             result = 89 * result + this.colorSpace.hashCode();
       
  2982             result = 89 * result + this.transferType;
       
  2983             hashCode = result;
       
  2984         }
       
  2985         return result;
       
  2986     }
       
  2987 }