< prev index next >

src/java.desktop/share/classes/java/awt/image/ComponentColorModel.java

Print this page




  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.image;
  27 
  28 import java.awt.color.ColorSpace;
  29 import java.awt.color.ICC_ColorSpace;
  30 
  31 /**
  32  * A <CODE>ColorModel</CODE> class that works with pixel values that
  33  * represent color and alpha information as separate samples and that
  34  * store each sample in a separate data element.  This class can be
  35  * used with an arbitrary <CODE>ColorSpace</CODE>.  The number of
  36  * color samples in the pixel values must be same as the number of
  37  * color components in the <CODE>ColorSpace</CODE>. There may be a
  38  * single alpha sample.
  39  * <p>
  40  * For those methods that use
  41  * a primitive array pixel representation of type <CODE>transferType</CODE>,
  42  * the array length is the same as the number of color and alpha samples.
  43  * Color samples are stored first in the array followed by the alpha
  44  * sample, if present.  The order of the color samples is specified
  45  * by the <CODE>ColorSpace</CODE>.  Typically, this order reflects the
  46  * name of the color space type. For example, for <CODE>TYPE_RGB</CODE>,
  47  * index 0 corresponds to red, index 1 to green, and index 2 to blue.
  48  * <p>
  49  * The translation from pixel sample values to color/alpha components for
  50  * display or processing purposes is based on a one-to-one correspondence of
  51  * samples to components.
  52  * Depending on the transfer type used to create an instance of
  53  * <code>ComponentColorModel</code>, the pixel sample values
  54  * represented by that instance may be signed or unsigned and may
  55  * be of integral type or float or double (see below for details).
  56  * The translation from sample values to normalized color/alpha components
  57  * must follow certain rules.  For float and double samples, the translation
  58  * is an identity, i.e. normalized component values are equal to the
  59  * corresponding sample values.  For integral samples, the translation
  60  * should be only a simple scale and offset, where the scale and offset
  61  * constants may be different for each component.  The result of
  62  * applying the scale and offset constants is a set of color/alpha
  63  * component values, which are guaranteed to fall within a certain
  64  * range.  Typically, the range for a color component will be the range
  65  * defined by the <code>getMinValue</code> and <code>getMaxValue</code>
  66  * methods of the <code>ColorSpace</code> class.  The range for an
  67  * alpha component should be 0.0 to 1.0.
  68  * <p>
  69  * Instances of <code>ComponentColorModel</code> created with transfer types
  70  * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
  71  * and <CODE>DataBuffer.TYPE_INT</CODE> have pixel sample values which
  72  * are treated as unsigned integral values.
  73  * The number of bits in a color or alpha sample of a pixel value might not
  74  * be the same as the number of bits for the corresponding color or alpha
  75  * sample passed to the
  76  * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
  77  * constructor.  In
  78  * that case, this class assumes that the least significant n bits of a sample
  79  * value hold the component value, where n is the number of significant bits
  80  * for the component passed to the constructor.  It also assumes that
  81  * any higher-order bits in a sample value are zero.  Thus, sample values
  82  * range from 0 to 2<sup>n</sup> - 1.  This class maps these sample values
  83  * to normalized color component values such that 0 maps to the value
  84  * obtained from the <code>ColorSpace's</code> <code>getMinValue</code>
  85  * method for each component and 2<sup>n</sup> - 1 maps to the value
  86  * obtained from <code>getMaxValue</code>.  To create a
  87  * <code>ComponentColorModel</code> with a different color sample mapping
  88  * requires subclassing this class and overriding the
  89  * <code>getNormalizedComponents(Object, float[], int)</code> method.
  90  * The mapping for an alpha sample always maps 0 to 0.0 and
  91  * 2<sup>n</sup> - 1 to 1.0.
  92  * <p>
  93  * For instances with unsigned sample values,
  94  * the unnormalized color/alpha component representation is only
  95  * supported if two conditions hold.  First, sample value 0 must
  96  * map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1
  97  * to 1.0.  Second the min/max range of all color components of the
  98  * <code>ColorSpace</code> must be 0.0 to 1.0.  In this case, the
  99  * component representation is the n least
 100  * significant bits of the corresponding sample.  Thus each component is
 101  * an unsigned integral value between 0 and 2<sup>n</sup> - 1, where
 102  * n is the number of significant bits for a particular component.
 103  * If these conditions are not met, any method taking an unnormalized
 104  * component argument will throw an <code>IllegalArgumentException</code>.
 105  * <p>
 106  * Instances of <code>ComponentColorModel</code> created with transfer types
 107  * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
 108  * <CODE>DataBuffer.TYPE_DOUBLE</CODE> have pixel sample values which
 109  * are treated as signed short, float, or double values.
 110  * Such instances do not support the unnormalized color/alpha component
 111  * representation, so any methods taking such a representation as an argument
 112  * will throw an <code>IllegalArgumentException</code> when called on one
 113  * of these instances.  The normalized component values of instances
 114  * of this class have a range which depends on the transfer
 115  * type as follows: for float samples, the full range of the float data
 116  * type; for double samples, the full range of the float data type
 117  * (resulting from casting double to float); for short samples,
 118  * from approximately -maxVal to +maxVal, where maxVal is the per
 119  * component maximum value for the <code>ColorSpace</code>
 120  * (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps
 121  * to +maxVal).  A subclass may override the scaling for short sample
 122  * values to normalized component values by overriding the
 123  * <code>getNormalizedComponents(Object, float[], int)</code> method.
 124  * For float and double samples, the normalized component values are
 125  * taken to be equal to the corresponding sample values, and subclasses
 126  * should not attempt to add any non-identity scaling for these transfer
 127  * types.
 128  * <p>
 129  * Instances of <code>ComponentColorModel</code> created with transfer types
 130  * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
 131  * <CODE>DataBuffer.TYPE_DOUBLE</CODE>
 132  * use all the bits of all sample values.  Thus all color/alpha components
 133  * have 16 bits when using <CODE>DataBuffer.TYPE_SHORT</CODE>, 32 bits when
 134  * using <CODE>DataBuffer.TYPE_FLOAT</CODE>, and 64 bits when using
 135  * <CODE>DataBuffer.TYPE_DOUBLE</CODE>.  When the
 136  * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
 137  * form of constructor is used with one of these transfer types, the
 138  * bits array argument is ignored.
 139  * <p>
 140  * It is possible to have color/alpha sample values
 141  * which cannot be reasonably interpreted as component values for rendering.
 142  * This can happen when <code>ComponentColorModel</code> is subclassed to
 143  * override the mapping of unsigned sample values to normalized color
 144  * component values or when signed sample values outside a certain range
 145  * are used.  (As an example, specifying an alpha component as a signed
 146  * short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can
 147  * lead to unexpected results.) It is the
 148  * responsibility of applications to appropriately scale pixel data before
 149  * rendering such that color components fall within the normalized range
 150  * of the <code>ColorSpace</code> (obtained using the <code>getMinValue</code>
 151  * and <code>getMaxValue</code> methods of the <code>ColorSpace</code> class)
 152  * and the alpha component is between 0.0 and 1.0.  If color or alpha
 153  * component values fall outside these ranges, rendering results are
 154  * indeterminate.
 155  * <p>
 156  * Methods that use a single int pixel representation throw
 157  * an <CODE>IllegalArgumentException</CODE>, unless the number of components
 158  * for the <CODE>ComponentColorModel</CODE> is one and the component
 159  * value is unsigned -- in other words,  a single color component using
 160  * a transfer type of <CODE>DataBuffer.TYPE_BYTE</CODE>,
 161  * <CODE>DataBuffer.TYPE_USHORT</CODE>, or <CODE>DataBuffer.TYPE_INT</CODE>
 162  * and no alpha.
 163  * <p>
 164  * A <CODE>ComponentColorModel</CODE> can be used in conjunction with a
 165  * <CODE>ComponentSampleModel</CODE>, a <CODE>BandedSampleModel</CODE>,
 166  * or a <CODE>PixelInterleavedSampleModel</CODE> to construct a
 167  * <CODE>BufferedImage</CODE>.
 168  *
 169  * @see ColorModel
 170  * @see ColorSpace
 171  * @see ComponentSampleModel
 172  * @see BandedSampleModel
 173  * @see PixelInterleavedSampleModel
 174  * @see BufferedImage
 175  *
 176  */
 177 public class ComponentColorModel extends ColorModel {
 178 
 179     /**
 180      * <code>signed</code>  is <code>true</code> for <code>short</code>,
 181      * <code>float</code>, and <code>double</code> transfer types; it
 182      * is <code>false</code> for <code>byte</code>, <code>ushort</code>,
 183      * and <code>int</code> transfer types.
 184      */
 185     private boolean signed; // true for transfer types short, float, double
 186                             // false for byte, ushort, int
 187     private boolean is_sRGB_stdScale;
 188     private boolean is_LinearRGB_stdScale;
 189     private boolean is_LinearGray_stdScale;
 190     private boolean is_ICCGray_stdScale;
 191     private byte[] tosRGB8LUT;
 192     private byte[] fromsRGB8LUT8;
 193     private short[] fromsRGB8LUT16;
 194     private byte[] fromLinearGray16ToOtherGray8LUT;
 195     private short[] fromLinearGray16ToOtherGray16LUT;
 196     private boolean needScaleInit;
 197     private boolean noUnnorm;
 198     private boolean nonStdScale;
 199     private float[] min;
 200     private float[] diffMinMax;
 201     private float[] compOffset;
 202     private float[] compScale;
 203 
 204     /**
 205      * Constructs a <CODE>ComponentColorModel</CODE> from the specified
 206      * parameters. Color components will be in the specified
 207      * <CODE>ColorSpace</CODE>.  The supported transfer types are
 208      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 209      * <CODE>DataBuffer.TYPE_INT</CODE>,
 210      * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
 211      * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 212      * If not null, the <CODE>bits</CODE> array specifies the
 213      * number of significant bits per color and alpha component and its
 214      * length should be at least the number of components in the
 215      * <CODE>ColorSpace</CODE> if there is no alpha
 216      * information in the pixel values, or one more than this number if
 217      * there is alpha information.  When the <CODE>transferType</CODE> is
 218      * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
 219      * or <CODE>DataBuffer.TYPE_DOUBLE</CODE> the <CODE>bits</CODE> array
 220      * argument is ignored.  <CODE>hasAlpha</CODE> indicates whether alpha
 221      * information is present.  If <CODE>hasAlpha</CODE> is true, then
 222      * the boolean <CODE>isAlphaPremultiplied</CODE>
 223      * specifies how to interpret color and alpha samples in pixel values.
 224      * If the boolean is true, color samples are assumed to have been
 225      * multiplied by the alpha sample. The <CODE>transparency</CODE>
 226      * specifies what alpha values can be represented by this color model.
 227      * The acceptable <code>transparency</code> values are
 228      * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
 229      * The <CODE>transferType</CODE> is the type of primitive array used
 230      * to represent pixel values.
 231      *
 232      * @param colorSpace       The <CODE>ColorSpace</CODE> associated
 233      *                         with this color model.
 234      * @param bits             The number of significant bits per component.
 235      *                         May be null, in which case all bits of all
 236      *                         component samples will be significant.
 237      *                         Ignored if transferType is one of
 238      *                         <CODE>DataBuffer.TYPE_SHORT</CODE>,
 239      *                         <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
 240      *                         <CODE>DataBuffer.TYPE_DOUBLE</CODE>,
 241      *                         in which case all bits of all component
 242      *                         samples will be significant.
 243      * @param hasAlpha         If true, this color model supports alpha.
 244      * @param isAlphaPremultiplied If true, alpha is premultiplied.
 245      * @param transparency     Specifies what alpha values can be represented
 246      *                         by this color model.
 247      * @param transferType     Specifies the type of primitive array used to
 248      *                         represent pixel values.
 249      *
 250      * @throws IllegalArgumentException If the <CODE>bits</CODE> array
 251      *         argument is not null, its length is less than the number of
 252      *         color and alpha components, and transferType is one of
 253      *         <CODE>DataBuffer.TYPE_BYTE</CODE>,
 254      *         <CODE>DataBuffer.TYPE_USHORT</CODE>, or
 255      *         <CODE>DataBuffer.TYPE_INT</CODE>.
 256      * @throws IllegalArgumentException If transferType is not one of
 257      *         <CODE>DataBuffer.TYPE_BYTE</CODE>,
 258      *         <CODE>DataBuffer.TYPE_USHORT</CODE>,
 259      *         <CODE>DataBuffer.TYPE_INT</CODE>,
 260      *         <CODE>DataBuffer.TYPE_SHORT</CODE>,
 261      *         <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
 262      *         <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 263      *
 264      * @see ColorSpace
 265      * @see java.awt.Transparency
 266      */
 267     public ComponentColorModel (ColorSpace colorSpace,
 268                                 int[] bits,
 269                                 boolean hasAlpha,
 270                                 boolean isAlphaPremultiplied,
 271                                 int transparency,
 272                                 int transferType) {
 273         super (bitsHelper(transferType, colorSpace, hasAlpha),
 274                bitsArrayHelper(bits, transferType, colorSpace, hasAlpha),
 275                colorSpace, hasAlpha, isAlphaPremultiplied, transparency,
 276                transferType);
 277         switch(transferType) {
 278             case DataBuffer.TYPE_BYTE:
 279             case DataBuffer.TYPE_USHORT:
 280             case DataBuffer.TYPE_INT:
 281                 signed = false;
 282                 needScaleInit = true;
 283                 break;
 284             case DataBuffer.TYPE_SHORT:
 285                 signed = true;
 286                 needScaleInit = true;
 287                 break;
 288             case DataBuffer.TYPE_FLOAT:
 289             case DataBuffer.TYPE_DOUBLE:
 290                 signed = true;
 291                 needScaleInit = false;
 292                 noUnnorm = true;
 293                 nonStdScale = false;
 294                 break;
 295             default:
 296                 throw new IllegalArgumentException("This constructor is not "+
 297                          "compatible with transferType " + transferType);
 298         }
 299         setupLUTs();
 300     }
 301 
 302     /**
 303      * Constructs a <CODE>ComponentColorModel</CODE> from the specified
 304      * parameters. Color components will be in the specified
 305      * <CODE>ColorSpace</CODE>.  The supported transfer types are
 306      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 307      * <CODE>DataBuffer.TYPE_INT</CODE>,
 308      * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
 309      * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>.  The number of significant
 310      * bits per color and alpha component will be 8, 16, 32, 16, 32,  or 64,
 311      * respectively.  The number of color components will be the
 312      * number of components in the <CODE>ColorSpace</CODE>.  There will be
 313      * an alpha component if <CODE>hasAlpha</CODE> is <CODE>true</CODE>.
 314      * If <CODE>hasAlpha</CODE> is true, then
 315      * the boolean <CODE>isAlphaPremultiplied</CODE>
 316      * specifies how to interpret color and alpha samples in pixel values.
 317      * If the boolean is true, color samples are assumed to have been
 318      * multiplied by the alpha sample. The <CODE>transparency</CODE>
 319      * specifies what alpha values can be represented by this color model.
 320      * The acceptable <code>transparency</code> values are
 321      * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
 322      * The <CODE>transferType</CODE> is the type of primitive array used
 323      * to represent pixel values.
 324      *
 325      * @param colorSpace       The <CODE>ColorSpace</CODE> associated
 326      *                         with this color model.
 327      * @param hasAlpha         If true, this color model supports alpha.
 328      * @param isAlphaPremultiplied If true, alpha is premultiplied.
 329      * @param transparency     Specifies what alpha values can be represented
 330      *                         by this color model.
 331      * @param transferType     Specifies the type of primitive array used to
 332      *                         represent pixel values.
 333      *
 334      * @throws IllegalArgumentException If transferType is not one of
 335      *         <CODE>DataBuffer.TYPE_BYTE</CODE>,
 336      *         <CODE>DataBuffer.TYPE_USHORT</CODE>,
 337      *         <CODE>DataBuffer.TYPE_INT</CODE>,
 338      *         <CODE>DataBuffer.TYPE_SHORT</CODE>,
 339      *         <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
 340      *         <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 341      *
 342      * @see ColorSpace
 343      * @see java.awt.Transparency
 344      * @since 1.4
 345      */
 346     public ComponentColorModel (ColorSpace colorSpace,
 347                                 boolean hasAlpha,
 348                                 boolean isAlphaPremultiplied,
 349                                 int transparency,
 350                                 int transferType) {
 351         this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
 352              transparency, transferType);
 353     }
 354 
 355     private static int bitsHelper(int transferType,
 356                                   ColorSpace colorSpace,
 357                                   boolean hasAlpha) {
 358         int numBits = DataBuffer.getDataTypeSize(transferType);
 359         int numComponents = colorSpace.getNumComponents();
 360         if (hasAlpha) {


 645         float[] norm = getNormalizedComponents(opixel, null, 0);
 646         float[] rgb = colorSpace.toRGB(norm);
 647 
 648         return (int) (rgb[idx] * 255.0f + 0.5f);
 649     }
 650 
 651     /**
 652      * Returns the red color component for the specified pixel, scaled
 653      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
 654      * is done if necessary.  The pixel value is specified as an int.
 655      * The returned value will be a non pre-multiplied value.
 656      * If the alpha is premultiplied, this method divides
 657      * it out before returning the value (if the alpha value is 0,
 658      * the red value will be 0).
 659      *
 660      * @param pixel The pixel from which you want to get the red color component.
 661      *
 662      * @return The red color component for the specified pixel, as an int.
 663      *
 664      * @throws IllegalArgumentException If there is more than
 665      * one component in this <CODE>ColorModel</CODE>.
 666      * @throws IllegalArgumentException If the component value for this
 667      * <CODE>ColorModel</CODE> is signed
 668      */
 669     public int getRed(int pixel) {
 670         return getRGBComponent(pixel, 0);
 671     }
 672 
 673     /**
 674      * Returns the green color component for the specified pixel, scaled
 675      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
 676      * is done if necessary.  The pixel value is specified as an int.
 677      * The returned value will be a non
 678      * pre-multiplied value. If the alpha is premultiplied, this method
 679      * divides it out before returning the value (if the alpha value is 0,
 680      * the green value will be 0).
 681      *
 682      * @param pixel The pixel from which you want to get the green color component.
 683      *
 684      * @return The green color component for the specified pixel, as an int.
 685      *
 686      * @throws IllegalArgumentException If there is more than
 687      * one component in this <CODE>ColorModel</CODE>.
 688      * @throws IllegalArgumentException If the component value for this
 689      * <CODE>ColorModel</CODE> is signed
 690      */
 691     public int getGreen(int pixel) {
 692         return getRGBComponent(pixel, 1);
 693     }
 694 
 695     /**
 696      * Returns the blue color component for the specified pixel, scaled
 697      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
 698      * is done if necessary.  The pixel value is specified as an int.
 699      * The returned value will be a non
 700      * pre-multiplied value. If the alpha is premultiplied, this method
 701      * divides it out before returning the value (if the alpha value is 0,
 702      * the blue value will be 0).
 703      *
 704      * @param pixel The pixel from which you want to get the blue color component.
 705      *
 706      * @return The blue color component for the specified pixel, as an int.
 707      *
 708      * @throws IllegalArgumentException If there is more than
 709      * one component in this <CODE>ColorModel</CODE>.
 710      * @throws IllegalArgumentException If the component value for this
 711      * <CODE>ColorModel</CODE> is signed
 712      */
 713     public int getBlue(int pixel) {
 714         return getRGBComponent(pixel, 2);
 715     }
 716 
 717     /**
 718      * Returns the alpha component for the specified pixel, scaled
 719      * from 0 to 255.   The pixel value is specified as an int.
 720      *
 721      * @param pixel The pixel from which you want to get the alpha component.
 722      *
 723      * @return The alpha component for the specified pixel, as an int.
 724      *
 725      * @throws IllegalArgumentException If there is more than
 726      * one component in this <CODE>ColorModel</CODE>.
 727      * @throws IllegalArgumentException If the component value for this
 728      * <CODE>ColorModel</CODE> is signed
 729      */
 730     public int getAlpha(int pixel) {
 731         if (supportsAlpha == false) {
 732             return 255;
 733         }
 734         if (numComponents > 1) {
 735             throw new
 736                 IllegalArgumentException("More than one component per pixel");
 737         }
 738         if (signed) {
 739             throw new
 740                 IllegalArgumentException("Component value is signed");
 741         }
 742 
 743         return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f);
 744     }
 745 
 746     /**
 747      * Returns the color/alpha components of the pixel in the default
 748      * RGB color model format.  A color conversion is done if necessary.
 749      * The returned value will be in a non pre-multiplied format. If
 750      * the alpha is premultiplied, this method divides it out of the
 751      * color components (if the alpha value is 0, the color values will be 0).
 752      *
 753      * @param pixel The pixel from which you want to get the color/alpha components.
 754      *
 755      * @return The color/alpha components for the specified pixel, as an int.
 756      *
 757      * @throws IllegalArgumentException If there is more than
 758      * one component in this <CODE>ColorModel</CODE>.
 759      * @throws IllegalArgumentException If the component value for this
 760      * <CODE>ColorModel</CODE> is signed
 761      */
 762     public int getRGB(int pixel) {
 763         if (numComponents > 1) {
 764             throw new
 765                 IllegalArgumentException("More than one component per pixel");
 766         }
 767         if (signed) {
 768             throw new
 769                 IllegalArgumentException("Component value is signed");
 770         }
 771 
 772         return (getAlpha(pixel) << 24)
 773             | (getRed(pixel) << 16)
 774             | (getGreen(pixel) << 8)
 775             | (getBlue(pixel) << 0);
 776     }
 777 
 778     private int extractComponent(Object inData, int idx, int precision) {
 779         // Extract component idx from inData.  The precision argument
 780         // should be either 8 or 16.  If it's 8, this method will return


 896         if (is_sRGB_stdScale) {
 897             return extractComponent(inData, idx, 8);
 898         } else if (is_LinearRGB_stdScale) {
 899             int lutidx = extractComponent(inData, idx, 16);
 900             return tosRGB8LUT[lutidx] & 0xff;
 901         } else if (is_ICCGray_stdScale) {
 902             int lutidx = extractComponent(inData, 0, 16);
 903             return tosRGB8LUT[lutidx] & 0xff;
 904         }
 905 
 906         // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace
 907         float[] norm = getNormalizedComponents(inData, null, 0);
 908         // Note that getNormalizedComponents returns non-premultiplied values
 909         float[] rgb = colorSpace.toRGB(norm);
 910         return (int) (rgb[idx] * 255.0f + 0.5f);
 911     }
 912 
 913     /**
 914      * Returns the red color component for the specified pixel, scaled
 915      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
 916      * is done if necessary.  The <CODE>pixel</CODE> value is specified by an array
 917      * of data elements of type <CODE>transferType</CODE> passed in as an object
 918      * reference. The returned value will be a non pre-multiplied value. If the
 919      * alpha is premultiplied, this method divides it out before returning
 920      * the value (if the alpha value is 0, the red value will be 0). Since
 921      * <code>ComponentColorModel</code> can be subclassed, subclasses
 922      * inherit the implementation of this method and if they don't override
 923      * it then they throw an exception if they use an unsupported
 924      * <code>transferType</code>.
 925      *
 926      * @param inData The pixel from which you want to get the red color component,
 927      * specified by an array of data elements of type <CODE>transferType</CODE>.
 928      *
 929      * @return The red color component for the specified pixel, as an int.
 930      *
 931      * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
 932      * of type <CODE>transferType</CODE>.
 933      * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
 934      * large enough to hold a pixel value for this
 935      * <CODE>ColorModel</CODE>.
 936      * @throws UnsupportedOperationException If the transfer type of
 937      * this <CODE>ComponentColorModel</CODE>
 938      * is not one of the supported transfer types:
 939      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 940      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
 941      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 942      */
 943     public int getRed(Object inData) {
 944         return getRGBComponent(inData, 0);
 945     }
 946 
 947 
 948     /**
 949      * Returns the green color component for the specified pixel, scaled
 950      * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
 951      * A color conversion is done if necessary.  The <CODE>pixel</CODE> value
 952      * is specified by an array of data elements of type <CODE>transferType</CODE>
 953      * passed in as an object reference. The returned value is a non pre-multiplied
 954      * value. If the alpha is premultiplied, this method divides it out before
 955      * returning the value (if the alpha value is 0, the green value will be 0).
 956      * Since <code>ComponentColorModel</code> can be subclassed,
 957      * subclasses inherit the implementation of this method and if they
 958      * don't override it then they throw an exception if they use an
 959      * unsupported <code>transferType</code>.
 960      *
 961      * @param inData The pixel from which you want to get the green color component,
 962      * specified by an array of data elements of type <CODE>transferType</CODE>.
 963      *
 964      * @return The green color component for the specified pixel, as an int.
 965      *
 966      * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
 967      * of type <CODE>transferType</CODE>.
 968      * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
 969      * large enough to hold a pixel value for this
 970      * <CODE>ColorModel</CODE>.
 971      * @throws UnsupportedOperationException If the transfer type of
 972      * this <CODE>ComponentColorModel</CODE>
 973      * is not one of the supported transfer types:
 974      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
 975      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
 976      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
 977      */
 978     public int getGreen(Object inData) {
 979         return getRGBComponent(inData, 1);
 980     }
 981 
 982 
 983     /**
 984      * Returns the blue color component for the specified pixel, scaled
 985      * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
 986      * A color conversion is done if necessary.  The <CODE>pixel</CODE> value is
 987      * specified by an array of data elements of type <CODE>transferType</CODE>
 988      * passed in as an object reference. The returned value is a non pre-multiplied
 989      * value. If the alpha is premultiplied, this method divides it out before
 990      * returning the value (if the alpha value is 0, the blue value will be 0).
 991      * Since <code>ComponentColorModel</code> can be subclassed,
 992      * subclasses inherit the implementation of this method and if they
 993      * don't override it then they throw an exception if they use an
 994      * unsupported <code>transferType</code>.
 995      *
 996      * @param inData The pixel from which you want to get the blue color component,
 997      * specified by an array of data elements of type <CODE>transferType</CODE>.
 998      *
 999      * @return The blue color component for the specified pixel, as an int.
1000      *
1001      * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1002      * of type <CODE>transferType</CODE>.
1003      * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1004      * large enough to hold a pixel value for this
1005      * <CODE>ColorModel</CODE>.
1006      * @throws UnsupportedOperationException If the transfer type of
1007      * this <CODE>ComponentColorModel</CODE>
1008      * is not one of the supported transfer types:
1009      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1010      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1011      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1012      */
1013     public int getBlue(Object inData) {
1014         return getRGBComponent(inData, 2);
1015     }
1016 
1017     /**
1018      * Returns the alpha component for the specified pixel, scaled from
1019      * 0 to 255.  The pixel value is specified by an array of data
1020      * elements of type <CODE>transferType</CODE> passed in as an
1021      * object reference.  Since <code>ComponentColorModel</code> can be
1022      * subclassed, subclasses inherit the
1023      * implementation of this method and if they don't override it then
1024      * they throw an exception if they use an unsupported
1025      * <code>transferType</code>.
1026      *
1027      * @param inData The pixel from which you want to get the alpha component,
1028      * specified by an array of data elements of type <CODE>transferType</CODE>.
1029      *
1030      * @return The alpha component for the specified pixel, as an int.
1031      *
1032      * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1033      * of type <CODE>transferType</CODE>.
1034      * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1035      * large enough to hold a pixel value for this
1036      * <CODE>ColorModel</CODE>.
1037      * @throws UnsupportedOperationException If the transfer type of
1038      * this <CODE>ComponentColorModel</CODE>
1039      * is not one of the supported transfer types:
1040      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1041      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1042      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1043      */
1044     public int getAlpha(Object inData) {
1045         if (supportsAlpha == false) {
1046             return 255;
1047         }
1048 
1049         int alpha = 0;
1050         int aIdx = numColorComponents;
1051         int mask = (1 << nBits[aIdx]) - 1;
1052 
1053         switch (transferType) {
1054             case DataBuffer.TYPE_SHORT:
1055                 short sdata[] = (short[])inData;
1056                 alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f);
1057                 return alpha;
1058             case DataBuffer.TYPE_FLOAT:
1059                 float fdata[] = (float[])inData;
1060                 alpha = (int) (fdata[aIdx] * 255.0f + 0.5f);
1061                 return alpha;
1062             case DataBuffer.TYPE_DOUBLE:


1077             break;
1078             default:
1079                throw new
1080                    UnsupportedOperationException("This method has not "+
1081                    "been implemented for transferType " + transferType);
1082         }
1083 
1084         if (nBits[aIdx] == 8) {
1085             return alpha;
1086         } else {
1087             return (int)
1088                 ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) *
1089                  255.0f + 0.5f);
1090         }
1091     }
1092 
1093     /**
1094      * Returns the color/alpha components for the specified pixel in the
1095      * default RGB color model format.  A color conversion is done if
1096      * necessary.  The pixel value is specified by an
1097      * array of data elements of type <CODE>transferType</CODE> passed
1098      * in as an object reference.
1099      * The returned value is in a non pre-multiplied format. If
1100      * the alpha is premultiplied, this method divides it out of the
1101      * color components (if the alpha value is 0, the color values will be 0).
1102      * Since <code>ComponentColorModel</code> can be subclassed,
1103      * subclasses inherit the implementation of this method and if they
1104      * don't override it then they throw an exception if they use an
1105      * unsupported <code>transferType</code>.
1106      *
1107      * @param inData The pixel from which you want to get the color/alpha components,
1108      * specified by an array of data elements of type <CODE>transferType</CODE>.
1109      *
1110      * @return The color/alpha components for the specified pixel, as an int.
1111      *
1112      * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1113      * of type <CODE>transferType</CODE>.
1114      * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1115      * large enough to hold a pixel value for this
1116      * <CODE>ColorModel</CODE>.
1117      * @throws UnsupportedOperationException If the transfer type of
1118      * this <CODE>ComponentColorModel</CODE>
1119      * is not one of the supported transfer types:
1120      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1121      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1122      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1123      * @see ColorModel#getRGBdefault
1124      */
1125     public int getRGB(Object inData) {
1126         if (needScaleInit) {
1127             initScale();
1128         }
1129         if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1130             return (getAlpha(inData) << 24)
1131                 | (getRed(inData) << 16)
1132                 | (getGreen(inData) << 8)
1133                 | (getBlue(inData));
1134         } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
1135             int gray = getRed(inData); // Red sRGB component should equal
1136                                        // green and blue components
1137             return (getAlpha(inData) << 24)
1138                 | (gray << 16)
1139                 | (gray <<  8)
1140                 | gray;
1141         }
1142         float[] norm = getNormalizedComponents(inData, null, 0);
1143         // Note that getNormalizedComponents returns non-premult values
1144         float[] rgb = colorSpace.toRGB(norm);
1145         return (getAlpha(inData) << 24)
1146             | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
1147             | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
1148             | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
1149     }
1150 
1151     /**
1152      * Returns a data element array representation of a pixel in this
1153      * <CODE>ColorModel</CODE>, given an integer pixel representation
1154      * in the default RGB color model.
1155      * This array can then be passed to the <CODE>setDataElements</CODE>
1156      * method of a <CODE>WritableRaster</CODE> object.  If the
1157      * <CODE>pixel</CODE>
1158      * parameter is null, a new array is allocated.  Since
1159      * <code>ComponentColorModel</code> can be subclassed, subclasses
1160      * inherit the implementation of this method and if they don't
1161      * override it then
1162      * they throw an exception if they use an unsupported
1163      * <code>transferType</code>.
1164      *
1165      * @param rgb the integer representation of the pixel in the RGB
1166      *            color model
1167      * @param pixel the specified pixel
1168      * @return The data element array representation of a pixel
1169      * in this <CODE>ColorModel</CODE>.
1170      * @throws ClassCastException If <CODE>pixel</CODE> is not null and
1171      * is not a primitive array of type <CODE>transferType</CODE>.
1172      * @throws ArrayIndexOutOfBoundsException If <CODE>pixel</CODE> is
1173      * not large enough to hold a pixel value for this
1174      * <CODE>ColorModel</CODE>.
1175      * @throws UnsupportedOperationException If the transfer type of
1176      * this <CODE>ComponentColorModel</CODE>
1177      * is not one of the supported transfer types:
1178      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1179      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1180      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1181      *
1182      * @see WritableRaster#setDataElements
1183      * @see SampleModel#setDataElements
1184      */
1185     public Object getDataElements(int rgb, Object pixel) {
1186         // REMIND: Use rendering hints?
1187 
1188         int red, grn, blu, alp;
1189         red = (rgb>>16) & 0xff;
1190         grn = (rgb>>8) & 0xff;
1191         blu = rgb & 0xff;
1192 
1193         if (needScaleInit) {
1194             initScale();
1195         }
1196         if (signed) {
1197             // Handle SHORT, FLOAT, & DOUBLE here
1198 
1199             switch(transferType) {
1200             case DataBuffer.TYPE_SHORT:


1638             }
1639             case DataBuffer.TYPE_INT:
1640                 if (maxBits > 23) {
1641                     // fix 4412670 - for components of 24 or more bits
1642                     // some calculations done above with float precision
1643                     // may lose enough precision that the integer result
1644                     // overflows nBits, so we need to clamp.
1645                     for (int i = 0; i < numComponents; i++) {
1646                         if (intpixel[i] > ((1<<nBits[i]) - 1)) {
1647                             intpixel[i] = (1<<nBits[i]) - 1;
1648                         }
1649                     }
1650                 }
1651                 return intpixel;
1652         }
1653         throw new IllegalArgumentException("This method has not been "+
1654                  "implemented for transferType " + transferType);
1655     }
1656 
1657    /** Returns an array of unnormalized color/alpha components given a pixel
1658      * in this <CODE>ColorModel</CODE>.
1659      * An IllegalArgumentException is thrown if the component value for this
1660      * <CODE>ColorModel</CODE> is not conveniently representable in the
1661      * unnormalized form.  Color/alpha components are stored
1662      * in the <CODE>components</CODE> array starting at <CODE>offset</CODE>
1663      * (even if the array is allocated by this method).
1664      *
1665      * @param pixel The pixel value specified as an integer.
1666      * @param components An integer array in which to store the unnormalized
1667      * color/alpha components. If the <CODE>components</CODE> array is null,
1668      * a new array is allocated.
1669      * @param offset An offset into the <CODE>components</CODE> array.
1670      *
1671      * @return The components array.
1672      *
1673      * @throws IllegalArgumentException If there is more than one
1674      * component in this <CODE>ColorModel</CODE>.
1675      * @throws IllegalArgumentException If this
1676      * <CODE>ColorModel</CODE> does not support the unnormalized form
1677      * @throws ArrayIndexOutOfBoundsException If the <CODE>components</CODE>
1678      * array is not null and is not large enough to hold all the color and
1679      * alpha components (starting at offset).
1680      */
1681     public int[] getComponents(int pixel, int[] components, int offset) {
1682         if (numComponents > 1) {
1683             throw new
1684                 IllegalArgumentException("More than one component per pixel");
1685         }
1686         if (needScaleInit) {
1687             initScale();
1688         }
1689         if (noUnnorm) {
1690             throw new
1691                 IllegalArgumentException(
1692                     "This ColorModel does not support the unnormalized form");
1693         }
1694         if (components == null) {
1695             components = new int[offset+1];
1696         }
1697 
1698         components[offset+0] = (pixel & ((1<<nBits[0]) - 1));
1699         return components;
1700     }
1701 
1702     /**
1703      * Returns an array of unnormalized color/alpha components given a pixel
1704      * in this <CODE>ColorModel</CODE>.  The pixel value is specified by an
1705      * array of data elements of type <CODE>transferType</CODE> passed in as
1706      * an object reference.
1707      * An IllegalArgumentException is thrown if the component values for this
1708      * <CODE>ColorModel</CODE> are not conveniently representable in the
1709      * unnormalized form.
1710      * Color/alpha components are stored in the <CODE>components</CODE> array
1711      * starting at  <CODE>offset</CODE> (even if the array is allocated by
1712      * this method).  Since <code>ComponentColorModel</code> can be
1713      * subclassed, subclasses inherit the
1714      * implementation of this method and if they don't override it then
1715      * this method might throw an exception if they use an unsupported
1716      * <code>transferType</code>.
1717      *
1718      * @param pixel A pixel value specified by an array of data elements of
1719      * type <CODE>transferType</CODE>.
1720      * @param components An integer array in which to store the unnormalized
1721      * color/alpha components. If the <CODE>components</CODE> array is null,
1722      * a new array is allocated.
1723      * @param offset An offset into the <CODE>components</CODE> array.
1724      *
1725      * @return The <CODE>components</CODE> array.
1726      *
1727      * @throws IllegalArgumentException If this
1728      * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1729      * @throws UnsupportedOperationException in some cases iff the
1730      * transfer type of this <CODE>ComponentColorModel</CODE>
1731      * is not one of the following transfer types:
1732      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1733      * or <CODE>DataBuffer.TYPE_INT</CODE>.
1734      * @throws ClassCastException If <CODE>pixel</CODE> is not a primitive
1735      * array of type <CODE>transferType</CODE>.
1736      * @throws IllegalArgumentException If the <CODE>components</CODE> array is
1737      * not null and is not large enough to hold all the color and alpha
1738      * components (starting at offset), or if <CODE>pixel</CODE> is not large
1739      * enough to hold a pixel value for this ColorModel.
1740      */
1741     public int[] getComponents(Object pixel, int[] components, int offset) {
1742         int intpixel[];
1743         if (needScaleInit) {
1744             initScale();
1745         }
1746         if (noUnnorm) {
1747             throw new
1748                 IllegalArgumentException(
1749                     "This ColorModel does not support the unnormalized form");
1750         }
1751         if (pixel instanceof int[]) {
1752             intpixel = (int[])pixel;
1753         } else {
1754             intpixel = DataBuffer.toIntArray(pixel);
1755             if (intpixel == null) {
1756                throw new UnsupportedOperationException("This method has not been "+
1757                    "implemented for transferType " + transferType);
1758             }


1762                 ("Length of pixel array < number of components in model");
1763         }
1764         if (components == null) {
1765             components = new int[offset+numComponents];
1766         }
1767         else if ((components.length-offset) < numComponents) {
1768             throw new IllegalArgumentException
1769                 ("Length of components array < number of components in model");
1770         }
1771         System.arraycopy(intpixel, 0, components, offset, numComponents);
1772 
1773         return components;
1774     }
1775 
1776     /**
1777      * Returns an array of all of the color/alpha components in unnormalized
1778      * form, given a normalized component array.  Unnormalized components
1779      * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1780      * n is the number of bits for a particular component.  Normalized
1781      * components are float values between a per component minimum and
1782      * maximum specified by the <code>ColorSpace</code> object for this
1783      * <code>ColorModel</code>.  An <code>IllegalArgumentException</code>
1784      * will be thrown if color component values for this
1785      * <code>ColorModel</code> are not conveniently representable in the
1786      * unnormalized form.  If the
1787      * <code>components</code> array is <code>null</code>, a new array
1788      * will be allocated.  The <code>components</code> array will
1789      * be returned.  Color/alpha components are stored in the
1790      * <code>components</code> array starting at <code>offset</code> (even
1791      * if the array is allocated by this method). An
1792      * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1793      * <code>components</code> array is not <code>null</code> and is not
1794      * large enough to hold all the color and alpha
1795      * components (starting at <code>offset</code>).  An
1796      * <code>IllegalArgumentException</code> is thrown if the
1797      * <code>normComponents</code> array is not large enough to hold
1798      * all the color and alpha components starting at
1799      * <code>normOffset</code>.
1800      * @param normComponents an array containing normalized components
1801      * @param normOffset the offset into the <code>normComponents</code>
1802      * array at which to start retrieving normalized components
1803      * @param components an array that receives the components from
1804      * <code>normComponents</code>
1805      * @param offset the index into <code>components</code> at which to
1806      * begin storing normalized components from
1807      * <code>normComponents</code>
1808      * @return an array containing unnormalized color and alpha
1809      * components.
1810      * @throws IllegalArgumentException If this
1811      * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1812      * @throws IllegalArgumentException if the length of
1813      *          <code>normComponents</code> minus <code>normOffset</code>
1814      *          is less than <code>numComponents</code>
1815      */
1816     public int[] getUnnormalizedComponents(float[] normComponents,
1817                                            int normOffset,
1818                                            int[] components, int offset) {
1819         if (needScaleInit) {
1820             initScale();
1821         }
1822         if (noUnnorm) {
1823             throw new
1824                 IllegalArgumentException(
1825                     "This ColorModel does not support the unnormalized form");
1826         }
1827         return super.getUnnormalizedComponents(normComponents, normOffset,
1828                                                components, offset);
1829     }
1830 
1831     /**
1832      * Returns an array of all of the color/alpha components in normalized
1833      * form, given an unnormalized component array.  Unnormalized components
1834      * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1835      * n is the number of bits for a particular component.  Normalized
1836      * components are float values between a per component minimum and
1837      * maximum specified by the <code>ColorSpace</code> object for this
1838      * <code>ColorModel</code>.  An <code>IllegalArgumentException</code>
1839      * will be thrown if color component values for this
1840      * <code>ColorModel</code> are not conveniently representable in the
1841      * unnormalized form.  If the
1842      * <code>normComponents</code> array is <code>null</code>, a new array
1843      * will be allocated.  The <code>normComponents</code> array
1844      * will be returned.  Color/alpha components are stored in the
1845      * <code>normComponents</code> array starting at
1846      * <code>normOffset</code> (even if the array is allocated by this
1847      * method).  An <code>ArrayIndexOutOfBoundsException</code> is thrown
1848      * if the <code>normComponents</code> array is not <code>null</code>
1849      * and is not large enough to hold all the color and alpha components
1850      * (starting at <code>normOffset</code>).  An
1851      * <code>IllegalArgumentException</code> is thrown if the
1852      * <code>components</code> array is not large enough to hold all the
1853      * color and alpha components starting at <code>offset</code>.
1854      * @param components an array containing unnormalized components
1855      * @param offset the offset into the <code>components</code> array at
1856      * which to start retrieving unnormalized components
1857      * @param normComponents an array that receives the normalized components
1858      * @param normOffset the index into <code>normComponents</code> at
1859      * which to begin storing normalized components
1860      * @return an array containing normalized color and alpha
1861      * components.
1862      * @throws IllegalArgumentException If this
1863      * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1864      */
1865     public float[] getNormalizedComponents(int[] components, int offset,
1866                                            float[] normComponents,
1867                                            int normOffset) {
1868         if (needScaleInit) {
1869             initScale();
1870         }
1871         if (noUnnorm) {
1872             throw new
1873                 IllegalArgumentException(
1874                     "This ColorModel does not support the unnormalized form");
1875         }
1876         return super.getNormalizedComponents(components, offset,
1877                                              normComponents, normOffset);
1878     }
1879 
1880     /**
1881      * Returns a pixel value represented as an int in this <CODE>ColorModel</CODE>,
1882      * given an array of unnormalized color/alpha components.
1883      *
1884      * @param components An array of unnormalized color/alpha components.
1885      * @param offset An offset into the <CODE>components</CODE> array.
1886      *
1887      * @return A pixel value represented as an int.
1888      *
1889      * @throws IllegalArgumentException If there is more than one component
1890      * in this <CODE>ColorModel</CODE>.
1891      * @throws IllegalArgumentException If this
1892      * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1893      */
1894     public int getDataElement(int[] components, int offset) {
1895         if (needScaleInit) {
1896             initScale();
1897         }
1898         if (numComponents == 1) {
1899             if (noUnnorm) {
1900                 throw new
1901                     IllegalArgumentException(
1902                     "This ColorModel does not support the unnormalized form");
1903             }
1904             return components[offset+0];
1905         }
1906         throw new IllegalArgumentException("This model returns "+
1907                                            numComponents+
1908                                            " elements in the pixel array.");
1909     }
1910 
1911     /**
1912      * Returns a data element array representation of a pixel in this
1913      * <CODE>ColorModel</CODE>, given an array of unnormalized color/alpha
1914      * components. This array can then be passed to the <CODE>setDataElements</CODE>
1915      * method of a <CODE>WritableRaster</CODE> object.
1916      *
1917      * @param components An array of unnormalized color/alpha components.
1918      * @param offset The integer offset into the <CODE>components</CODE> array.
1919      * @param obj The object in which to store the data element array
1920      * representation of the pixel. If <CODE>obj</CODE> variable is null,
1921      * a new array is allocated.  If <CODE>obj</CODE> is not null, it must
1922      * be a primitive array of type <CODE>transferType</CODE>. An
1923      * <CODE>ArrayIndexOutOfBoundsException</CODE> is thrown if
1924      * <CODE>obj</CODE> is not large enough to hold a pixel value
1925      * for this <CODE>ColorModel</CODE>.  Since
1926      * <code>ComponentColorModel</code> can be subclassed, subclasses
1927      * inherit the implementation of this method and if they don't
1928      * override it then they throw an exception if they use an
1929      * unsupported <code>transferType</code>.
1930      *
1931      * @return The data element array representation of a pixel
1932      * in this <CODE>ColorModel</CODE>.
1933      *
1934      * @throws IllegalArgumentException If the components array
1935      * is not large enough to hold all the color and alpha components
1936      * (starting at offset).
1937      * @throws ClassCastException If <CODE>obj</CODE> is not null and is not a
1938      * primitive  array of type <CODE>transferType</CODE>.
1939      * @throws ArrayIndexOutOfBoundsException If <CODE>obj</CODE> is not large
1940      * enough to hold a pixel value for this <CODE>ColorModel</CODE>.
1941      * @throws IllegalArgumentException If this
1942      * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1943      * @throws UnsupportedOperationException If the transfer type of
1944      * this <CODE>ComponentColorModel</CODE>
1945      * is not one of the following transfer types:
1946      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1947      * or <CODE>DataBuffer.TYPE_INT</CODE>.
1948      *
1949      * @see WritableRaster#setDataElements
1950      * @see SampleModel#setDataElements
1951      */
1952     public Object getDataElements(int[] components, int offset, Object obj) {
1953         if (needScaleInit) {
1954             initScale();
1955         }
1956         if (noUnnorm) {
1957             throw new
1958                 IllegalArgumentException(
1959                     "This ColorModel does not support the unnormalized form");
1960         }
1961         if ((components.length-offset) < numComponents) {
1962             throw new IllegalArgumentException("Component array too small"+
1963                                                " (should be "+numComponents);
1964         }
1965         switch(transferType) {
1966         case DataBuffer.TYPE_INT:
1967             {


1998                 if (obj == null) {
1999                     pixel = new short[numComponents];
2000                 }
2001                 else {
2002                     pixel = (short[]) obj;
2003                 }
2004                 for (int i=0; i < numComponents; i++) {
2005                     pixel[i] = (short) (components[offset+i]&0xffff);
2006                 }
2007                 return pixel;
2008             }
2009 
2010         default:
2011             throw new UnsupportedOperationException("This method has not been "+
2012                                         "implemented for transferType " +
2013                                         transferType);
2014         }
2015     }
2016 
2017     /**
2018      * Returns a pixel value represented as an <code>int</code> in this
2019      * <code>ColorModel</code>, given an array of normalized color/alpha
2020      * components.  This method will throw an
2021      * <code>IllegalArgumentException</code> if pixel values for this
2022      * <code>ColorModel</code> are not conveniently representable as a
2023      * single <code>int</code>.  An
2024      * <code>ArrayIndexOutOfBoundsException</code> is thrown if  the
2025      * <code>normComponents</code> array is not large enough to hold all the
2026      * color and alpha components (starting at <code>normOffset</code>).
2027      * @param normComponents an array of normalized color and alpha
2028      * components
2029      * @param normOffset the index into <code>normComponents</code> at which to
2030      * begin retrieving the color and alpha components
2031      * @return an <code>int</code> pixel value in this
2032      * <code>ColorModel</code> corresponding to the specified components.
2033      * @throws IllegalArgumentException if
2034      *  pixel values for this <code>ColorModel</code> are not
2035      *  conveniently representable as a single <code>int</code>
2036      * @throws ArrayIndexOutOfBoundsException if
2037      *  the <code>normComponents</code> array is not large enough to
2038      *  hold all of the color and alpha components starting at
2039      *  <code>normOffset</code>
2040      * @since 1.4
2041      */
2042     public int getDataElement(float[] normComponents, int normOffset) {
2043         if (numComponents > 1) {
2044             throw new
2045                 IllegalArgumentException("More than one component per pixel");
2046         }
2047         if (signed) {
2048             throw new
2049                 IllegalArgumentException("Component value is signed");
2050         }
2051         if (needScaleInit) {
2052             initScale();
2053         }
2054         Object pixel = getDataElements(normComponents, normOffset, null);
2055         switch (transferType) {
2056         case DataBuffer.TYPE_BYTE:
2057             {
2058                 byte bpixel[] = (byte[]) pixel;
2059                 return bpixel[0] & 0xff;
2060             }
2061         case DataBuffer.TYPE_USHORT:
2062             {
2063                 short[] uspixel = (short[]) pixel;
2064                 return uspixel[0] & 0xffff;
2065             }
2066         case DataBuffer.TYPE_INT:
2067             {
2068                 int[] ipixel = (int[]) pixel;
2069                 return ipixel[0];
2070             }
2071         default:
2072             throw new UnsupportedOperationException("This method has not been "
2073                 + "implemented for transferType " + transferType);
2074         }
2075     }
2076 
2077     /**
2078      * Returns a data element array representation of a pixel in this
2079      * <code>ColorModel</code>, given an array of normalized color/alpha
2080      * components.  This array can then be passed to the
2081      * <code>setDataElements</code> method of a <code>WritableRaster</code>
2082      * object.  An <code>ArrayIndexOutOfBoundsException</code> is thrown
2083      * if the <code>normComponents</code> array is not large enough to hold
2084      * all the color and alpha components (starting at
2085      * <code>normOffset</code>).  If the <code>obj</code> variable is
2086      * <code>null</code>, a new array will be allocated.  If
2087      * <code>obj</code> is not <code>null</code>, it must be a primitive
2088      * array of type transferType; otherwise, a
2089      * <code>ClassCastException</code> is thrown.  An
2090      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
2091      * <code>obj</code> is not large enough to hold a pixel value for this
2092      * <code>ColorModel</code>.
2093      * @param normComponents an array of normalized color and alpha
2094      * components
2095      * @param normOffset the index into <code>normComponents</code> at which to
2096      * begin retrieving color and alpha components
2097      * @param obj a primitive data array to hold the returned pixel
2098      * @return an <code>Object</code> which is a primitive data array
2099      * representation of a pixel
2100      * @throws ClassCastException if <code>obj</code>
2101      *  is not a primitive array of type <code>transferType</code>
2102      * @throws ArrayIndexOutOfBoundsException if
2103      *  <code>obj</code> is not large enough to hold a pixel value
2104      *  for this <code>ColorModel</code> or the <code>normComponents</code>
2105      *  array is not large enough to hold all of the color and alpha
2106      *  components starting at <code>normOffset</code>
2107      * @see WritableRaster#setDataElements
2108      * @see SampleModel#setDataElements
2109      * @since 1.4
2110      */
2111     public Object getDataElements(float[] normComponents, int normOffset,
2112                                   Object obj) {
2113         boolean needAlpha = supportsAlpha && isAlphaPremultiplied;
2114         float[] stdNormComponents;
2115         if (needScaleInit) {
2116             initScale();
2117         }
2118         if (nonStdScale) {
2119             stdNormComponents = new float[numComponents];
2120             for (int c = 0, nc = normOffset; c < numColorComponents;
2121                  c++, nc++) {
2122                 stdNormComponents[c] = (normComponents[nc] - compOffset[c]) *
2123                                        compScale[c];
2124                 // REMIND: need to analyze whether this
2125                 // clamping is necessary
2126                 if (stdNormComponents[c] < 0.0f) {


2281                      c++, nc++) {
2282                     dpixel[c] = normComponents[nc] * alpha;
2283                 }
2284                 dpixel[numColorComponents] = alpha;
2285             } else {
2286                 for (int c = 0, nc = normOffset; c < numComponents;
2287                      c++, nc++) {
2288                     dpixel[c] = (double) normComponents[nc];
2289                 }
2290             }
2291             return dpixel;
2292         default:
2293             throw new UnsupportedOperationException("This method has not been "+
2294                                         "implemented for transferType " +
2295                                         transferType);
2296         }
2297     }
2298 
2299     /**
2300      * Returns an array of all of the color/alpha components in normalized
2301      * form, given a pixel in this <code>ColorModel</code>.  The pixel
2302      * value is specified by an array of data elements of type transferType
2303      * passed in as an object reference.  If pixel is not a primitive array
2304      * of type transferType, a <code>ClassCastException</code> is thrown.
2305      * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
2306      * <code>pixel</code> is not large enough to hold a pixel value for this
2307      * <code>ColorModel</code>.
2308      * Normalized components are float values between a per component minimum
2309      * and maximum specified by the <code>ColorSpace</code> object for this
2310      * <code>ColorModel</code>.  If the
2311      * <code>normComponents</code> array is <code>null</code>, a new array
2312      * will be allocated.  The <code>normComponents</code> array
2313      * will be returned.  Color/alpha components are stored in the
2314      * <code>normComponents</code> array starting at
2315      * <code>normOffset</code> (even if the array is allocated by this
2316      * method).  An <code>ArrayIndexOutOfBoundsException</code> is thrown
2317      * if the <code>normComponents</code> array is not <code>null</code>
2318      * and is not large enough to hold all the color and alpha components
2319      * (starting at <code>normOffset</code>).
2320      * <p>
2321      * This method must be overridden by a subclass if that subclass
2322      * is designed to translate pixel sample values to color component values
2323      * in a non-default way.  The default translations implemented by this
2324      * class is described in the class comments.  Any subclass implementing
2325      * a non-default translation must follow the constraints on allowable
2326      * translations defined there.
2327      * @param pixel the specified pixel
2328      * @param normComponents an array to receive the normalized components
2329      * @param normOffset the offset into the <code>normComponents</code>
2330      * array at which to start storing normalized components
2331      * @return an array containing normalized color and alpha
2332      * components.
2333      * @throws ClassCastException if <code>pixel</code> is not a primitive
2334      *          array of type transferType
2335      * @throws ArrayIndexOutOfBoundsException if
2336      *          <code>normComponents</code> is not large enough to hold all
2337      *          color and alpha components starting at <code>normOffset</code>
2338      * @throws ArrayIndexOutOfBoundsException if
2339      *          <code>pixel</code> is not large enough to hold a pixel
2340      *          value for this <code>ColorModel</code>.
2341      * @since 1.4
2342      */
2343     public float[] getNormalizedComponents(Object pixel,
2344                                            float[] normComponents,
2345                                            int normOffset) {
2346         if (normComponents == null) {
2347             normComponents = new float[numComponents+normOffset];
2348         }
2349         switch (transferType) {
2350         case DataBuffer.TYPE_BYTE:
2351             byte[] bpixel = (byte[]) pixel;
2352             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2353                 normComponents[nc] = ((float) (bpixel[c] & 0xff)) /
2354                                      ((float) ((1 << nBits[c]) - 1));
2355             }
2356             break;
2357         case DataBuffer.TYPE_USHORT:
2358             short[] uspixel = (short[]) pixel;
2359             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2360                 normComponents[nc] = ((float) (uspixel[c] & 0xffff)) /


2409             // possible case, in which this method is overridden, nonStdScale
2410             // is set true by initScale(), the subclass method for some
2411             // reason calls this superclass method, but the min and
2412             // diffMinMax arrays were never initialized by setupLUTs().  In
2413             // that case, the right thing to do is follow the intended
2414             // semantics of this method, and rescale the color components
2415             // only if the ColorSpace min/max were detected to be other
2416             // than 0.0/1.0 by setupLUTs().  Note that this implies the
2417             // transferType is byte, ushort, int, or short - i.e. components
2418             // derived from float and double pixel data are never rescaled.
2419             for (int c = 0; c < numColorComponents; c++) {
2420                 normComponents[c + normOffset] = min[c] +
2421                     diffMinMax[c] * normComponents[c + normOffset];
2422             }
2423         }
2424         return normComponents;
2425     }
2426 
2427     /**
2428      * Forces the raster data to match the state specified in the
2429      * <CODE>isAlphaPremultiplied</CODE> variable, assuming the data
2430      * is currently correctly described by this <CODE>ColorModel</CODE>.
2431      * It may multiply or divide the color raster data by alpha, or
2432      * do nothing if the data is in the correct state.  If the data needs
2433      * to be coerced, this method also returns an instance of
2434      * this <CODE>ColorModel</CODE> with
2435      * the <CODE>isAlphaPremultiplied</CODE> flag set appropriately.
2436      * Since <code>ColorModel</code> can be subclassed, subclasses inherit
2437      * the implementation of this method and if they don't override it
2438      * then they throw an exception if they use an unsupported
2439      * <code>transferType</code>.
2440      *
2441      * @throws NullPointerException if <code>raster</code> is
2442      * <code>null</code> and data coercion is required.
2443      * @throws UnsupportedOperationException if the transfer type of
2444      * this <CODE>ComponentColorModel</CODE>
2445      * is not one of the supported transfer types:
2446      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
2447      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
2448      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
2449      */
2450     public ColorModel coerceData (WritableRaster raster,
2451                                   boolean isAlphaPremultiplied) {
2452         if ((supportsAlpha == false) ||
2453             (this.isAlphaPremultiplied == isAlphaPremultiplied))
2454         {
2455             // Nothing to do
2456             return this;
2457         }
2458 
2459         int w = raster.getWidth();
2460         int h = raster.getHeight();
2461         int aIdx = raster.getNumBands() - 1;
2462         float normAlpha;
2463         int rminX = raster.getMinX();
2464         int rY = raster.getMinY();
2465         int rX;
2466         if (isAlphaPremultiplied) {
2467             switch (transferType) {
2468                 case DataBuffer.TYPE_BYTE: {


2757                 default:
2758                     throw new UnsupportedOperationException("This method has not been "+
2759                          "implemented for transferType " + transferType);
2760             }
2761         }
2762 
2763         // Return a new color model
2764         if (!signed) {
2765             return new ComponentColorModel(colorSpace, nBits, supportsAlpha,
2766                                            isAlphaPremultiplied, transparency,
2767                                            transferType);
2768         } else {
2769             return new ComponentColorModel(colorSpace, supportsAlpha,
2770                                            isAlphaPremultiplied, transparency,
2771                                            transferType);
2772         }
2773 
2774     }
2775 
2776     /**
2777       * Returns true if <CODE>raster</CODE> is compatible with this
2778       * <CODE>ColorModel</CODE>; false if it is not.
2779       *
2780       * @param raster The <CODE>Raster</CODE> object to test for compatibility.
2781       *
2782       * @return <CODE>true</CODE> if <CODE>raster</CODE> is compatible with this
2783       * <CODE>ColorModel</CODE>, <CODE>false</CODE> if it is not.
2784       */
2785     public boolean isCompatibleRaster(Raster raster) {
2786 
2787         SampleModel sm = raster.getSampleModel();
2788 
2789         if (sm instanceof ComponentSampleModel) {
2790             if (sm.getNumBands() != getNumComponents()) {
2791                 return false;
2792             }
2793             for (int i=0; i<nBits.length; i++) {
2794                 if (sm.getSampleSize(i) < nBits[i]) {
2795                     return false;
2796                 }
2797             }
2798             return (raster.getTransferType() == transferType);
2799         }
2800         else {
2801             return false;
2802         }
2803     }
2804 
2805     /**
2806      * Creates a <CODE>WritableRaster</CODE> with the specified width and height,
2807      * that  has a data layout (<CODE>SampleModel</CODE>) compatible with
2808      * this <CODE>ColorModel</CODE>.
2809      *
2810      * @param w The width of the <CODE>WritableRaster</CODE> you want to create.
2811      * @param h The height of the <CODE>WritableRaster</CODE> you want to create.
2812      *
2813      * @return A <CODE>WritableRaster</CODE> that is compatible with
2814      * this <CODE>ColorModel</CODE>.
2815      * @see WritableRaster
2816      * @see SampleModel
2817      */
2818     public WritableRaster createCompatibleWritableRaster (int w, int h) {
2819         int dataSize = w*h*numComponents;
2820         WritableRaster raster = null;
2821 
2822         switch (transferType) {
2823         case DataBuffer.TYPE_BYTE:
2824         case DataBuffer.TYPE_USHORT:
2825             raster = Raster.createInterleavedRaster(transferType,
2826                                                     w, h,
2827                                                     numComponents, null);
2828             break;
2829         default:
2830             SampleModel sm = createCompatibleSampleModel(w, h);
2831             DataBuffer db = sm.createDataBuffer();
2832             raster = Raster.createWritableRaster(sm, db, null);
2833         }
2834 
2835         return raster;
2836     }
2837 
2838     /**
2839      * Creates a <CODE>SampleModel</CODE> with the specified width and height,
2840      * that  has a data layout compatible with this <CODE>ColorModel</CODE>.
2841      *
2842      * @param w The width of the <CODE>SampleModel</CODE> you want to create.
2843      * @param h The height of the <CODE>SampleModel</CODE> you want to create.
2844      *
2845      * @return A <CODE>SampleModel</CODE> that is compatible with this
2846      * <CODE>ColorModel</CODE>.
2847      *
2848      * @see SampleModel
2849      */
2850     public SampleModel createCompatibleSampleModel(int w, int h) {
2851         int[] bandOffsets = new int[numComponents];
2852         for (int i=0; i < numComponents; i++) {
2853             bandOffsets[i] = i;
2854         }
2855         switch (transferType) {
2856         case DataBuffer.TYPE_BYTE:
2857         case DataBuffer.TYPE_USHORT:
2858             return new PixelInterleavedSampleModel(transferType, w, h,
2859                                                    numComponents,
2860                                                    w*numComponents,
2861                                                    bandOffsets);
2862         default:
2863             return new ComponentSampleModel(transferType, w, h,
2864                                             numComponents,
2865                                             w*numComponents,
2866                                             bandOffsets);
2867         }
2868     }
2869 
2870     /**
2871      * Checks whether or not the specified <CODE>SampleModel</CODE>
2872      * is compatible with this <CODE>ColorModel</CODE>.
2873      *
2874      * @param sm The <CODE>SampleModel</CODE> to test for compatibility.
2875      *
2876      * @return <CODE>true</CODE> if the <CODE>SampleModel</CODE> is
2877      * compatible with this <CODE>ColorModel</CODE>, <CODE>false</CODE>
2878      * if it is not.
2879      *
2880      * @see SampleModel
2881      */
2882     public boolean isCompatibleSampleModel(SampleModel sm) {
2883         if (!(sm instanceof ComponentSampleModel)) {
2884             return false;
2885         }
2886 
2887         // Must have the same number of components
2888         if (numComponents != sm.getNumBands()) {
2889             return false;
2890         }
2891 
2892         if (sm.getTransferType() != transferType) {
2893             return false;
2894         }
2895 
2896         return true;
2897     }
2898 
2899     /**
2900      * Returns a <CODE>Raster</CODE> representing the alpha channel of an image,
2901      * extracted from the input <CODE>Raster</CODE>.
2902      * This method assumes that <CODE>Raster</CODE> objects associated with
2903      * this <CODE>ColorModel</CODE> store the alpha band, if present, as
2904      * the last band of image data. Returns null if there is no separate spatial
2905      * alpha channel associated with this <CODE>ColorModel</CODE>.
2906      * This method creates a new <CODE>Raster</CODE>, but will share the data
2907      * array.
2908      *
2909      * @param raster The <CODE>WritableRaster</CODE> from which to extract the
2910      * alpha  channel.
2911      *
2912      * @return A <CODE>WritableRaster</CODE> containing the image's alpha channel.
2913      *
2914      */
2915     public WritableRaster getAlphaRaster(WritableRaster raster) {
2916         if (hasAlpha() == false) {
2917             return null;
2918         }
2919 
2920         int x = raster.getMinX();
2921         int y = raster.getMinY();
2922         int[] band = new int[1];
2923         band[0] = raster.getNumBands() - 1;
2924         return raster.createWritableChild(x, y, raster.getWidth(),
2925                                           raster.getHeight(), x, y,
2926                                           band);
2927     }
2928 
2929     /**
2930      * Compares this color model with another for equality.
2931      *
2932      * @param obj The object to compare with this color model.
2933      * @return <CODE>true</CODE> if the color model objects are equal,
2934      * <CODE>false</CODE> if they are not.
2935      */
2936     public boolean equals(Object obj) {
2937         if (!super.equals(obj)) {
2938             return false;
2939         }
2940 
2941         if (obj.getClass() !=  getClass()) {
2942             return false;
2943         }
2944 
2945         return true;
2946     }
2947 
2948 }


  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.image;
  27 
  28 import java.awt.color.ColorSpace;
  29 import java.awt.color.ICC_ColorSpace;
  30 
  31 /**
  32  * A {@code ColorModel} class that works with pixel values that
  33  * represent color and alpha information as separate samples and that
  34  * store each sample in a separate data element.  This class can be
  35  * used with an arbitrary {@code ColorSpace}.  The number of
  36  * color samples in the pixel values must be same as the number of
  37  * color components in the {@code ColorSpace}. There may be a
  38  * single alpha sample.
  39  * <p>
  40  * For those methods that use
  41  * a primitive array pixel representation of type {@code transferType},
  42  * the array length is the same as the number of color and alpha samples.
  43  * Color samples are stored first in the array followed by the alpha
  44  * sample, if present.  The order of the color samples is specified
  45  * by the {@code ColorSpace}.  Typically, this order reflects the
  46  * name of the color space type. For example, for {@code TYPE_RGB},
  47  * index 0 corresponds to red, index 1 to green, and index 2 to blue.
  48  * <p>
  49  * The translation from pixel sample values to color/alpha components for
  50  * display or processing purposes is based on a one-to-one correspondence of
  51  * samples to components.
  52  * Depending on the transfer type used to create an instance of
  53  * {@code ComponentColorModel}, the pixel sample values
  54  * represented by that instance may be signed or unsigned and may
  55  * be of integral type or float or double (see below for details).
  56  * The translation from sample values to normalized color/alpha components
  57  * must follow certain rules.  For float and double samples, the translation
  58  * is an identity, i.e. normalized component values are equal to the
  59  * corresponding sample values.  For integral samples, the translation
  60  * should be only a simple scale and offset, where the scale and offset
  61  * constants may be different for each component.  The result of
  62  * applying the scale and offset constants is a set of color/alpha
  63  * component values, which are guaranteed to fall within a certain
  64  * range.  Typically, the range for a color component will be the range
  65  * defined by the {@code getMinValue} and {@code getMaxValue}
  66  * methods of the {@code ColorSpace} class.  The range for an
  67  * alpha component should be 0.0 to 1.0.
  68  * <p>
  69  * Instances of {@code ComponentColorModel} created with transfer types
  70  * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
  71  * and {@code DataBuffer.TYPE_INT} have pixel sample values which
  72  * are treated as unsigned integral values.
  73  * The number of bits in a color or alpha sample of a pixel value might not
  74  * be the same as the number of bits for the corresponding color or alpha
  75  * sample passed to the
  76  * {@code ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)}
  77  * constructor.  In
  78  * that case, this class assumes that the least significant n bits of a sample
  79  * value hold the component value, where n is the number of significant bits
  80  * for the component passed to the constructor.  It also assumes that
  81  * any higher-order bits in a sample value are zero.  Thus, sample values
  82  * range from 0 to 2<sup>n</sup> - 1.  This class maps these sample values
  83  * to normalized color component values such that 0 maps to the value
  84  * obtained from the {@code ColorSpace's getMinValue}
  85  * method for each component and 2<sup>n</sup> - 1 maps to the value
  86  * obtained from {@code getMaxValue}.  To create a
  87  * {@code ComponentColorModel} with a different color sample mapping
  88  * requires subclassing this class and overriding the
  89  * {@code getNormalizedComponents(Object, float[], int)} method.
  90  * The mapping for an alpha sample always maps 0 to 0.0 and
  91  * 2<sup>n</sup> - 1 to 1.0.
  92  * <p>
  93  * For instances with unsigned sample values,
  94  * the unnormalized color/alpha component representation is only
  95  * supported if two conditions hold.  First, sample value 0 must
  96  * map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1
  97  * to 1.0.  Second the min/max range of all color components of the
  98  * {@code ColorSpace} must be 0.0 to 1.0.  In this case, the
  99  * component representation is the n least
 100  * significant bits of the corresponding sample.  Thus each component is
 101  * an unsigned integral value between 0 and 2<sup>n</sup> - 1, where
 102  * n is the number of significant bits for a particular component.
 103  * If these conditions are not met, any method taking an unnormalized
 104  * component argument will throw an {@code IllegalArgumentException}.
 105  * <p>
 106  * Instances of {@code ComponentColorModel} created with transfer types
 107  * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, and
 108  * {@code DataBuffer.TYPE_DOUBLE} have pixel sample values which
 109  * are treated as signed short, float, or double values.
 110  * Such instances do not support the unnormalized color/alpha component
 111  * representation, so any methods taking such a representation as an argument
 112  * will throw an {@code IllegalArgumentException} when called on one
 113  * of these instances.  The normalized component values of instances
 114  * of this class have a range which depends on the transfer
 115  * type as follows: for float samples, the full range of the float data
 116  * type; for double samples, the full range of the float data type
 117  * (resulting from casting double to float); for short samples,
 118  * from approximately -maxVal to +maxVal, where maxVal is the per
 119  * component maximum value for the {@code ColorSpace}
 120  * (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps
 121  * to +maxVal).  A subclass may override the scaling for short sample
 122  * values to normalized component values by overriding the
 123  * {@code getNormalizedComponents(Object, float[], int)} method.
 124  * For float and double samples, the normalized component values are
 125  * taken to be equal to the corresponding sample values, and subclasses
 126  * should not attempt to add any non-identity scaling for these transfer
 127  * types.
 128  * <p>
 129  * Instances of {@code ComponentColorModel} created with transfer types
 130  * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, and
 131  * {@code DataBuffer.TYPE_DOUBLE}
 132  * use all the bits of all sample values.  Thus all color/alpha components
 133  * have 16 bits when using {@code DataBuffer.TYPE_SHORT}, 32 bits when
 134  * using {@code DataBuffer.TYPE_FLOAT}, and 64 bits when using
 135  * {@code DataBuffer.TYPE_DOUBLE}.  When the
 136  * {@code ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)}
 137  * form of constructor is used with one of these transfer types, the
 138  * bits array argument is ignored.
 139  * <p>
 140  * It is possible to have color/alpha sample values
 141  * which cannot be reasonably interpreted as component values for rendering.
 142  * This can happen when {@code ComponentColorModel} is subclassed to
 143  * override the mapping of unsigned sample values to normalized color
 144  * component values or when signed sample values outside a certain range
 145  * are used.  (As an example, specifying an alpha component as a signed
 146  * short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can
 147  * lead to unexpected results.) It is the
 148  * responsibility of applications to appropriately scale pixel data before
 149  * rendering such that color components fall within the normalized range
 150  * of the {@code ColorSpace} (obtained using the {@code getMinValue}
 151  * and {@code getMaxValue} methods of the {@code ColorSpace} class)
 152  * and the alpha component is between 0.0 and 1.0.  If color or alpha
 153  * component values fall outside these ranges, rendering results are
 154  * indeterminate.
 155  * <p>
 156  * Methods that use a single int pixel representation throw
 157  * an {@code IllegalArgumentException}, unless the number of components
 158  * for the {@code ComponentColorModel} is one and the component
 159  * value is unsigned -- in other words,  a single color component using
 160  * a transfer type of {@code DataBuffer.TYPE_BYTE},
 161  * {@code DataBuffer.TYPE_USHORT}, or {@code DataBuffer.TYPE_INT}
 162  * and no alpha.
 163  * <p>
 164  * A {@code ComponentColorModel} can be used in conjunction with a
 165  * {@code ComponentSampleModel}, a {@code BandedSampleModel},
 166  * or a {@code PixelInterleavedSampleModel} to construct a
 167  * {@code BufferedImage}.
 168  *
 169  * @see ColorModel
 170  * @see ColorSpace
 171  * @see ComponentSampleModel
 172  * @see BandedSampleModel
 173  * @see PixelInterleavedSampleModel
 174  * @see BufferedImage
 175  *
 176  */
 177 public class ComponentColorModel extends ColorModel {
 178 
 179     /**
 180      * {@code signed}  is {@code true} for {@code short},
 181      * {@code float}, and {@code double} transfer types; it
 182      * is {@code false} for {@code byte}, {@code ushort},
 183      * and {@code int} transfer types.
 184      */
 185     private boolean signed; // true for transfer types short, float, double
 186                             // false for byte, ushort, int
 187     private boolean is_sRGB_stdScale;
 188     private boolean is_LinearRGB_stdScale;
 189     private boolean is_LinearGray_stdScale;
 190     private boolean is_ICCGray_stdScale;
 191     private byte[] tosRGB8LUT;
 192     private byte[] fromsRGB8LUT8;
 193     private short[] fromsRGB8LUT16;
 194     private byte[] fromLinearGray16ToOtherGray8LUT;
 195     private short[] fromLinearGray16ToOtherGray16LUT;
 196     private boolean needScaleInit;
 197     private boolean noUnnorm;
 198     private boolean nonStdScale;
 199     private float[] min;
 200     private float[] diffMinMax;
 201     private float[] compOffset;
 202     private float[] compScale;
 203 
 204     /**
 205      * Constructs a {@code ComponentColorModel} from the specified
 206      * parameters. Color components will be in the specified
 207      * {@code ColorSpace}.  The supported transfer types are
 208      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
 209      * {@code DataBuffer.TYPE_INT},
 210      * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT},
 211      * and {@code DataBuffer.TYPE_DOUBLE}.
 212      * If not null, the {@code bits} array specifies the
 213      * number of significant bits per color and alpha component and its
 214      * length should be at least the number of components in the
 215      * {@code ColorSpace} if there is no alpha
 216      * information in the pixel values, or one more than this number if
 217      * there is alpha information.  When the {@code transferType} is
 218      * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT},
 219      * or {@code DataBuffer.TYPE_DOUBLE} the {@code bits} array
 220      * argument is ignored.  {@code hasAlpha} indicates whether alpha
 221      * information is present.  If {@code hasAlpha} is true, then
 222      * the boolean {@code isAlphaPremultiplied}
 223      * specifies how to interpret color and alpha samples in pixel values.
 224      * If the boolean is true, color samples are assumed to have been
 225      * multiplied by the alpha sample. The {@code transparency}
 226      * specifies what alpha values can be represented by this color model.
 227      * The acceptable {@code transparency} values are
 228      * {@code OPAQUE}, {@code BITMASK} or {@code TRANSLUCENT}.
 229      * The {@code transferType} is the type of primitive array used
 230      * to represent pixel values.
 231      *
 232      * @param colorSpace       The {@code ColorSpace} associated
 233      *                         with this color model.
 234      * @param bits             The number of significant bits per component.
 235      *                         May be null, in which case all bits of all
 236      *                         component samples will be significant.
 237      *                         Ignored if transferType is one of
 238      *                         {@code DataBuffer.TYPE_SHORT},
 239      *                         {@code DataBuffer.TYPE_FLOAT}, or
 240      *                         {@code DataBuffer.TYPE_DOUBLE},
 241      *                         in which case all bits of all component
 242      *                         samples will be significant.
 243      * @param hasAlpha         If true, this color model supports alpha.
 244      * @param isAlphaPremultiplied If true, alpha is premultiplied.
 245      * @param transparency     Specifies what alpha values can be represented
 246      *                         by this color model.
 247      * @param transferType     Specifies the type of primitive array used to
 248      *                         represent pixel values.
 249      *
 250      * @throws IllegalArgumentException If the {@code bits} array
 251      *         argument is not null, its length is less than the number of
 252      *         color and alpha components, and transferType is one of
 253      *         {@code DataBuffer.TYPE_BYTE},
 254      *         {@code DataBuffer.TYPE_USHORT}, or
 255      *         {@code DataBuffer.TYPE_INT}.
 256      * @throws IllegalArgumentException If transferType is not one of
 257      *         {@code DataBuffer.TYPE_BYTE},
 258      *         {@code DataBuffer.TYPE_USHORT},
 259      *         {@code DataBuffer.TYPE_INT},
 260      *         {@code DataBuffer.TYPE_SHORT},
 261      *         {@code DataBuffer.TYPE_FLOAT}, or
 262      *         {@code DataBuffer.TYPE_DOUBLE}.
 263      *
 264      * @see ColorSpace
 265      * @see java.awt.Transparency
 266      */
 267     public ComponentColorModel (ColorSpace colorSpace,
 268                                 int[] bits,
 269                                 boolean hasAlpha,
 270                                 boolean isAlphaPremultiplied,
 271                                 int transparency,
 272                                 int transferType) {
 273         super (bitsHelper(transferType, colorSpace, hasAlpha),
 274                bitsArrayHelper(bits, transferType, colorSpace, hasAlpha),
 275                colorSpace, hasAlpha, isAlphaPremultiplied, transparency,
 276                transferType);
 277         switch(transferType) {
 278             case DataBuffer.TYPE_BYTE:
 279             case DataBuffer.TYPE_USHORT:
 280             case DataBuffer.TYPE_INT:
 281                 signed = false;
 282                 needScaleInit = true;
 283                 break;
 284             case DataBuffer.TYPE_SHORT:
 285                 signed = true;
 286                 needScaleInit = true;
 287                 break;
 288             case DataBuffer.TYPE_FLOAT:
 289             case DataBuffer.TYPE_DOUBLE:
 290                 signed = true;
 291                 needScaleInit = false;
 292                 noUnnorm = true;
 293                 nonStdScale = false;
 294                 break;
 295             default:
 296                 throw new IllegalArgumentException("This constructor is not "+
 297                          "compatible with transferType " + transferType);
 298         }
 299         setupLUTs();
 300     }
 301 
 302     /**
 303      * Constructs a {@code ComponentColorModel} from the specified
 304      * parameters. Color components will be in the specified
 305      * {@code ColorSpace}.  The supported transfer types are
 306      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
 307      * {@code DataBuffer.TYPE_INT},
 308      * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT},
 309      * and {@code DataBuffer.TYPE_DOUBLE}.  The number of significant
 310      * bits per color and alpha component will be 8, 16, 32, 16, 32,  or 64,
 311      * respectively.  The number of color components will be the
 312      * number of components in the {@code ColorSpace}.  There will be
 313      * an alpha component if {@code hasAlpha} is {@code true}.
 314      * If {@code hasAlpha} is true, then
 315      * the boolean {@code isAlphaPremultiplied}
 316      * specifies how to interpret color and alpha samples in pixel values.
 317      * If the boolean is true, color samples are assumed to have been
 318      * multiplied by the alpha sample. The {@code transparency}
 319      * specifies what alpha values can be represented by this color model.
 320      * The acceptable {@code transparency} values are
 321      * {@code OPAQUE}, {@code BITMASK} or {@code TRANSLUCENT}.
 322      * The {@code transferType} is the type of primitive array used
 323      * to represent pixel values.
 324      *
 325      * @param colorSpace       The {@code ColorSpace} associated
 326      *                         with this color model.
 327      * @param hasAlpha         If true, this color model supports alpha.
 328      * @param isAlphaPremultiplied If true, alpha is premultiplied.
 329      * @param transparency     Specifies what alpha values can be represented
 330      *                         by this color model.
 331      * @param transferType     Specifies the type of primitive array used to
 332      *                         represent pixel values.
 333      *
 334      * @throws IllegalArgumentException If transferType is not one of
 335      *         {@code DataBuffer.TYPE_BYTE},
 336      *         {@code DataBuffer.TYPE_USHORT},
 337      *         {@code DataBuffer.TYPE_INT},
 338      *         {@code DataBuffer.TYPE_SHORT},
 339      *         {@code DataBuffer.TYPE_FLOAT}, or
 340      *         {@code DataBuffer.TYPE_DOUBLE}.
 341      *
 342      * @see ColorSpace
 343      * @see java.awt.Transparency
 344      * @since 1.4
 345      */
 346     public ComponentColorModel (ColorSpace colorSpace,
 347                                 boolean hasAlpha,
 348                                 boolean isAlphaPremultiplied,
 349                                 int transparency,
 350                                 int transferType) {
 351         this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
 352              transparency, transferType);
 353     }
 354 
 355     private static int bitsHelper(int transferType,
 356                                   ColorSpace colorSpace,
 357                                   boolean hasAlpha) {
 358         int numBits = DataBuffer.getDataTypeSize(transferType);
 359         int numComponents = colorSpace.getNumComponents();
 360         if (hasAlpha) {


 645         float[] norm = getNormalizedComponents(opixel, null, 0);
 646         float[] rgb = colorSpace.toRGB(norm);
 647 
 648         return (int) (rgb[idx] * 255.0f + 0.5f);
 649     }
 650 
 651     /**
 652      * Returns the red color component for the specified pixel, scaled
 653      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
 654      * is done if necessary.  The pixel value is specified as an int.
 655      * The returned value will be a non pre-multiplied value.
 656      * If the alpha is premultiplied, this method divides
 657      * it out before returning the value (if the alpha value is 0,
 658      * the red value will be 0).
 659      *
 660      * @param pixel The pixel from which you want to get the red color component.
 661      *
 662      * @return The red color component for the specified pixel, as an int.
 663      *
 664      * @throws IllegalArgumentException If there is more than
 665      * one component in this {@code ColorModel}.
 666      * @throws IllegalArgumentException If the component value for this
 667      * {@code ColorModel} is signed
 668      */
 669     public int getRed(int pixel) {
 670         return getRGBComponent(pixel, 0);
 671     }
 672 
 673     /**
 674      * Returns the green color component for the specified pixel, scaled
 675      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
 676      * is done if necessary.  The pixel value is specified as an int.
 677      * The returned value will be a non
 678      * pre-multiplied value. If the alpha is premultiplied, this method
 679      * divides it out before returning the value (if the alpha value is 0,
 680      * the green value will be 0).
 681      *
 682      * @param pixel The pixel from which you want to get the green color component.
 683      *
 684      * @return The green color component for the specified pixel, as an int.
 685      *
 686      * @throws IllegalArgumentException If there is more than
 687      * one component in this {@code ColorModel}.
 688      * @throws IllegalArgumentException If the component value for this
 689      * {@code ColorModel} is signed
 690      */
 691     public int getGreen(int pixel) {
 692         return getRGBComponent(pixel, 1);
 693     }
 694 
 695     /**
 696      * Returns the blue color component for the specified pixel, scaled
 697      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
 698      * is done if necessary.  The pixel value is specified as an int.
 699      * The returned value will be a non
 700      * pre-multiplied value. If the alpha is premultiplied, this method
 701      * divides it out before returning the value (if the alpha value is 0,
 702      * the blue value will be 0).
 703      *
 704      * @param pixel The pixel from which you want to get the blue color component.
 705      *
 706      * @return The blue color component for the specified pixel, as an int.
 707      *
 708      * @throws IllegalArgumentException If there is more than
 709      * one component in this {@code ColorModel}.
 710      * @throws IllegalArgumentException If the component value for this
 711      * {@code ColorModel} is signed
 712      */
 713     public int getBlue(int pixel) {
 714         return getRGBComponent(pixel, 2);
 715     }
 716 
 717     /**
 718      * Returns the alpha component for the specified pixel, scaled
 719      * from 0 to 255.   The pixel value is specified as an int.
 720      *
 721      * @param pixel The pixel from which you want to get the alpha component.
 722      *
 723      * @return The alpha component for the specified pixel, as an int.
 724      *
 725      * @throws IllegalArgumentException If there is more than
 726      * one component in this {@code ColorModel}.
 727      * @throws IllegalArgumentException If the component value for this
 728      * {@code ColorModel} is signed
 729      */
 730     public int getAlpha(int pixel) {
 731         if (supportsAlpha == false) {
 732             return 255;
 733         }
 734         if (numComponents > 1) {
 735             throw new
 736                 IllegalArgumentException("More than one component per pixel");
 737         }
 738         if (signed) {
 739             throw new
 740                 IllegalArgumentException("Component value is signed");
 741         }
 742 
 743         return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f);
 744     }
 745 
 746     /**
 747      * Returns the color/alpha components of the pixel in the default
 748      * RGB color model format.  A color conversion is done if necessary.
 749      * The returned value will be in a non pre-multiplied format. If
 750      * the alpha is premultiplied, this method divides it out of the
 751      * color components (if the alpha value is 0, the color values will be 0).
 752      *
 753      * @param pixel The pixel from which you want to get the color/alpha components.
 754      *
 755      * @return The color/alpha components for the specified pixel, as an int.
 756      *
 757      * @throws IllegalArgumentException If there is more than
 758      * one component in this {@code ColorModel}.
 759      * @throws IllegalArgumentException If the component value for this
 760      * {@code ColorModel} is signed
 761      */
 762     public int getRGB(int pixel) {
 763         if (numComponents > 1) {
 764             throw new
 765                 IllegalArgumentException("More than one component per pixel");
 766         }
 767         if (signed) {
 768             throw new
 769                 IllegalArgumentException("Component value is signed");
 770         }
 771 
 772         return (getAlpha(pixel) << 24)
 773             | (getRed(pixel) << 16)
 774             | (getGreen(pixel) << 8)
 775             | (getBlue(pixel) << 0);
 776     }
 777 
 778     private int extractComponent(Object inData, int idx, int precision) {
 779         // Extract component idx from inData.  The precision argument
 780         // should be either 8 or 16.  If it's 8, this method will return


 896         if (is_sRGB_stdScale) {
 897             return extractComponent(inData, idx, 8);
 898         } else if (is_LinearRGB_stdScale) {
 899             int lutidx = extractComponent(inData, idx, 16);
 900             return tosRGB8LUT[lutidx] & 0xff;
 901         } else if (is_ICCGray_stdScale) {
 902             int lutidx = extractComponent(inData, 0, 16);
 903             return tosRGB8LUT[lutidx] & 0xff;
 904         }
 905 
 906         // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace
 907         float[] norm = getNormalizedComponents(inData, null, 0);
 908         // Note that getNormalizedComponents returns non-premultiplied values
 909         float[] rgb = colorSpace.toRGB(norm);
 910         return (int) (rgb[idx] * 255.0f + 0.5f);
 911     }
 912 
 913     /**
 914      * Returns the red color component for the specified pixel, scaled
 915      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
 916      * is done if necessary.  The {@code pixel} value is specified by an array
 917      * of data elements of type {@code transferType} passed in as an object
 918      * reference. The returned value will be a non pre-multiplied value. If the
 919      * alpha is premultiplied, this method divides it out before returning
 920      * the value (if the alpha value is 0, the red value will be 0). Since
 921      * {@code ComponentColorModel} can be subclassed, subclasses
 922      * inherit the implementation of this method and if they don't override
 923      * it then they throw an exception if they use an unsupported
 924      * {@code transferType}.
 925      *
 926      * @param inData The pixel from which you want to get the red color component,
 927      * specified by an array of data elements of type {@code transferType}.
 928      *
 929      * @return The red color component for the specified pixel, as an int.
 930      *
 931      * @throws ClassCastException If {@code inData} is not a primitive array
 932      * of type {@code transferType}.
 933      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
 934      * large enough to hold a pixel value for this
 935      * {@code ColorModel}.
 936      * @throws UnsupportedOperationException If the transfer type of
 937      * this {@code ComponentColorModel}
 938      * is not one of the supported transfer types:
 939      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
 940      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
 941      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
 942      */
 943     public int getRed(Object inData) {
 944         return getRGBComponent(inData, 0);
 945     }
 946 
 947 
 948     /**
 949      * Returns the green color component for the specified pixel, scaled
 950      * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB.
 951      * A color conversion is done if necessary.  The {@code pixel} value
 952      * is specified by an array of data elements of type {@code transferType}
 953      * passed in as an object reference. The returned value is a non pre-multiplied
 954      * value. If the alpha is premultiplied, this method divides it out before
 955      * returning the value (if the alpha value is 0, the green value will be 0).
 956      * Since {@code ComponentColorModel} can be subclassed,
 957      * subclasses inherit the implementation of this method and if they
 958      * don't override it then they throw an exception if they use an
 959      * unsupported {@code transferType}.
 960      *
 961      * @param inData The pixel from which you want to get the green color component,
 962      * specified by an array of data elements of type {@code transferType}.
 963      *
 964      * @return The green color component for the specified pixel, as an int.
 965      *
 966      * @throws ClassCastException If {@code inData} is not a primitive array
 967      * of type {@code transferType}.
 968      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
 969      * large enough to hold a pixel value for this
 970      * {@code ColorModel}.
 971      * @throws UnsupportedOperationException If the transfer type of
 972      * this {@code ComponentColorModel}
 973      * is not one of the supported transfer types:
 974      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
 975      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
 976      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
 977      */
 978     public int getGreen(Object inData) {
 979         return getRGBComponent(inData, 1);
 980     }
 981 
 982 
 983     /**
 984      * Returns the blue color component for the specified pixel, scaled
 985      * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB.
 986      * A color conversion is done if necessary.  The {@code pixel} value is
 987      * specified by an array of data elements of type {@code transferType}
 988      * passed in as an object reference. The returned value is a non pre-multiplied
 989      * value. If the alpha is premultiplied, this method divides it out before
 990      * returning the value (if the alpha value is 0, the blue value will be 0).
 991      * Since {@code ComponentColorModel} can be subclassed,
 992      * subclasses inherit the implementation of this method and if they
 993      * don't override it then they throw an exception if they use an
 994      * unsupported {@code transferType}.
 995      *
 996      * @param inData The pixel from which you want to get the blue color component,
 997      * specified by an array of data elements of type {@code transferType}.
 998      *
 999      * @return The blue color component for the specified pixel, as an int.
1000      *
1001      * @throws ClassCastException If {@code inData} is not a primitive array
1002      * of type {@code transferType}.
1003      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
1004      * large enough to hold a pixel value for this
1005      * {@code ColorModel}.
1006      * @throws UnsupportedOperationException If the transfer type of
1007      * this {@code ComponentColorModel}
1008      * is not one of the supported transfer types:
1009      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
1010      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
1011      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
1012      */
1013     public int getBlue(Object inData) {
1014         return getRGBComponent(inData, 2);
1015     }
1016 
1017     /**
1018      * Returns the alpha component for the specified pixel, scaled from
1019      * 0 to 255.  The pixel value is specified by an array of data
1020      * elements of type {@code transferType} passed in as an
1021      * object reference.  Since {@code ComponentColorModel} can be
1022      * subclassed, subclasses inherit the
1023      * implementation of this method and if they don't override it then
1024      * they throw an exception if they use an unsupported
1025      * {@code transferType}.
1026      *
1027      * @param inData The pixel from which you want to get the alpha component,
1028      * specified by an array of data elements of type {@code transferType}.
1029      *
1030      * @return The alpha component for the specified pixel, as an int.
1031      *
1032      * @throws ClassCastException If {@code inData} is not a primitive array
1033      * of type {@code transferType}.
1034      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
1035      * large enough to hold a pixel value for this
1036      * {@code ColorModel}.
1037      * @throws UnsupportedOperationException If the transfer type of
1038      * this {@code ComponentColorModel}
1039      * is not one of the supported transfer types:
1040      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
1041      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
1042      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
1043      */
1044     public int getAlpha(Object inData) {
1045         if (supportsAlpha == false) {
1046             return 255;
1047         }
1048 
1049         int alpha = 0;
1050         int aIdx = numColorComponents;
1051         int mask = (1 << nBits[aIdx]) - 1;
1052 
1053         switch (transferType) {
1054             case DataBuffer.TYPE_SHORT:
1055                 short sdata[] = (short[])inData;
1056                 alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f);
1057                 return alpha;
1058             case DataBuffer.TYPE_FLOAT:
1059                 float fdata[] = (float[])inData;
1060                 alpha = (int) (fdata[aIdx] * 255.0f + 0.5f);
1061                 return alpha;
1062             case DataBuffer.TYPE_DOUBLE:


1077             break;
1078             default:
1079                throw new
1080                    UnsupportedOperationException("This method has not "+
1081                    "been implemented for transferType " + transferType);
1082         }
1083 
1084         if (nBits[aIdx] == 8) {
1085             return alpha;
1086         } else {
1087             return (int)
1088                 ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) *
1089                  255.0f + 0.5f);
1090         }
1091     }
1092 
1093     /**
1094      * Returns the color/alpha components for the specified pixel in the
1095      * default RGB color model format.  A color conversion is done if
1096      * necessary.  The pixel value is specified by an
1097      * array of data elements of type {@code transferType} passed
1098      * in as an object reference.
1099      * The returned value is in a non pre-multiplied format. If
1100      * the alpha is premultiplied, this method divides it out of the
1101      * color components (if the alpha value is 0, the color values will be 0).
1102      * Since {@code ComponentColorModel} can be subclassed,
1103      * subclasses inherit the implementation of this method and if they
1104      * don't override it then they throw an exception if they use an
1105      * unsupported {@code transferType}.
1106      *
1107      * @param inData The pixel from which you want to get the color/alpha components,
1108      * specified by an array of data elements of type {@code transferType}.
1109      *
1110      * @return The color/alpha components for the specified pixel, as an int.
1111      *
1112      * @throws ClassCastException If {@code inData} is not a primitive array
1113      * of type {@code transferType}.
1114      * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
1115      * large enough to hold a pixel value for this
1116      * {@code ColorModel}.
1117      * @throws UnsupportedOperationException If the transfer type of
1118      * this {@code ComponentColorModel}
1119      * is not one of the supported transfer types:
1120      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
1121      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
1122      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
1123      * @see ColorModel#getRGBdefault
1124      */
1125     public int getRGB(Object inData) {
1126         if (needScaleInit) {
1127             initScale();
1128         }
1129         if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1130             return (getAlpha(inData) << 24)
1131                 | (getRed(inData) << 16)
1132                 | (getGreen(inData) << 8)
1133                 | (getBlue(inData));
1134         } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
1135             int gray = getRed(inData); // Red sRGB component should equal
1136                                        // green and blue components
1137             return (getAlpha(inData) << 24)
1138                 | (gray << 16)
1139                 | (gray <<  8)
1140                 | gray;
1141         }
1142         float[] norm = getNormalizedComponents(inData, null, 0);
1143         // Note that getNormalizedComponents returns non-premult values
1144         float[] rgb = colorSpace.toRGB(norm);
1145         return (getAlpha(inData) << 24)
1146             | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
1147             | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
1148             | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
1149     }
1150 
1151     /**
1152      * Returns a data element array representation of a pixel in this
1153      * {@code ColorModel}, given an integer pixel representation
1154      * in the default RGB color model.
1155      * This array can then be passed to the {@code setDataElements}
1156      * method of a {@code WritableRaster} object.  If the
1157      * {@code pixel}
1158      * parameter is null, a new array is allocated.  Since
1159      * {@code ComponentColorModel} can be subclassed, subclasses
1160      * inherit the implementation of this method and if they don't
1161      * override it then
1162      * they throw an exception if they use an unsupported
1163      * {@code transferType}.
1164      *
1165      * @param rgb the integer representation of the pixel in the RGB
1166      *            color model
1167      * @param pixel the specified pixel
1168      * @return The data element array representation of a pixel
1169      * in this {@code ColorModel}.
1170      * @throws ClassCastException If {@code pixel} is not null and
1171      * is not a primitive array of type {@code transferType}.
1172      * @throws ArrayIndexOutOfBoundsException If {@code pixel} is
1173      * not large enough to hold a pixel value for this
1174      * {@code ColorModel}.
1175      * @throws UnsupportedOperationException If the transfer type of
1176      * this {@code ComponentColorModel}
1177      * is not one of the supported transfer types:
1178      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
1179      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
1180      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
1181      *
1182      * @see WritableRaster#setDataElements
1183      * @see SampleModel#setDataElements
1184      */
1185     public Object getDataElements(int rgb, Object pixel) {
1186         // REMIND: Use rendering hints?
1187 
1188         int red, grn, blu, alp;
1189         red = (rgb>>16) & 0xff;
1190         grn = (rgb>>8) & 0xff;
1191         blu = rgb & 0xff;
1192 
1193         if (needScaleInit) {
1194             initScale();
1195         }
1196         if (signed) {
1197             // Handle SHORT, FLOAT, & DOUBLE here
1198 
1199             switch(transferType) {
1200             case DataBuffer.TYPE_SHORT:


1638             }
1639             case DataBuffer.TYPE_INT:
1640                 if (maxBits > 23) {
1641                     // fix 4412670 - for components of 24 or more bits
1642                     // some calculations done above with float precision
1643                     // may lose enough precision that the integer result
1644                     // overflows nBits, so we need to clamp.
1645                     for (int i = 0; i < numComponents; i++) {
1646                         if (intpixel[i] > ((1<<nBits[i]) - 1)) {
1647                             intpixel[i] = (1<<nBits[i]) - 1;
1648                         }
1649                     }
1650                 }
1651                 return intpixel;
1652         }
1653         throw new IllegalArgumentException("This method has not been "+
1654                  "implemented for transferType " + transferType);
1655     }
1656 
1657    /** Returns an array of unnormalized color/alpha components given a pixel
1658      * in this {@code ColorModel}.
1659      * An IllegalArgumentException is thrown if the component value for this
1660      * {@code ColorModel} is not conveniently representable in the
1661      * unnormalized form.  Color/alpha components are stored
1662      * in the {@code components} array starting at {@code offset}
1663      * (even if the array is allocated by this method).
1664      *
1665      * @param pixel The pixel value specified as an integer.
1666      * @param components An integer array in which to store the unnormalized
1667      * color/alpha components. If the {@code components} array is null,
1668      * a new array is allocated.
1669      * @param offset An offset into the {@code components} array.
1670      *
1671      * @return The components array.
1672      *
1673      * @throws IllegalArgumentException If there is more than one
1674      * component in this {@code ColorModel}.
1675      * @throws IllegalArgumentException If this
1676      * {@code ColorModel} does not support the unnormalized form
1677      * @throws ArrayIndexOutOfBoundsException If the {@code components}
1678      * array is not null and is not large enough to hold all the color and
1679      * alpha components (starting at offset).
1680      */
1681     public int[] getComponents(int pixel, int[] components, int offset) {
1682         if (numComponents > 1) {
1683             throw new
1684                 IllegalArgumentException("More than one component per pixel");
1685         }
1686         if (needScaleInit) {
1687             initScale();
1688         }
1689         if (noUnnorm) {
1690             throw new
1691                 IllegalArgumentException(
1692                     "This ColorModel does not support the unnormalized form");
1693         }
1694         if (components == null) {
1695             components = new int[offset+1];
1696         }
1697 
1698         components[offset+0] = (pixel & ((1<<nBits[0]) - 1));
1699         return components;
1700     }
1701 
1702     /**
1703      * Returns an array of unnormalized color/alpha components given a pixel
1704      * in this {@code ColorModel}.  The pixel value is specified by an
1705      * array of data elements of type {@code transferType} passed in as
1706      * an object reference.
1707      * An IllegalArgumentException is thrown if the component values for this
1708      * {@code ColorModel} are not conveniently representable in the
1709      * unnormalized form.
1710      * Color/alpha components are stored in the {@code components} array
1711      * starting at  {@code offset} (even if the array is allocated by
1712      * this method).  Since {@code ComponentColorModel} can be
1713      * subclassed, subclasses inherit the
1714      * implementation of this method and if they don't override it then
1715      * this method might throw an exception if they use an unsupported
1716      * {@code transferType}.
1717      *
1718      * @param pixel A pixel value specified by an array of data elements of
1719      * type {@code transferType}.
1720      * @param components An integer array in which to store the unnormalized
1721      * color/alpha components. If the {@code components} array is null,
1722      * a new array is allocated.
1723      * @param offset An offset into the {@code components} array.
1724      *
1725      * @return The {@code components} array.
1726      *
1727      * @throws IllegalArgumentException If this
1728      * {@code ComponentColorModel} does not support the unnormalized form
1729      * @throws UnsupportedOperationException in some cases iff the
1730      * transfer type of this {@code ComponentColorModel}
1731      * is not one of the following transfer types:
1732      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
1733      * or {@code DataBuffer.TYPE_INT}.
1734      * @throws ClassCastException If {@code pixel} is not a primitive
1735      * array of type {@code transferType}.
1736      * @throws IllegalArgumentException If the {@code components} array is
1737      * not null and is not large enough to hold all the color and alpha
1738      * components (starting at offset), or if {@code pixel} is not large
1739      * enough to hold a pixel value for this ColorModel.
1740      */
1741     public int[] getComponents(Object pixel, int[] components, int offset) {
1742         int intpixel[];
1743         if (needScaleInit) {
1744             initScale();
1745         }
1746         if (noUnnorm) {
1747             throw new
1748                 IllegalArgumentException(
1749                     "This ColorModel does not support the unnormalized form");
1750         }
1751         if (pixel instanceof int[]) {
1752             intpixel = (int[])pixel;
1753         } else {
1754             intpixel = DataBuffer.toIntArray(pixel);
1755             if (intpixel == null) {
1756                throw new UnsupportedOperationException("This method has not been "+
1757                    "implemented for transferType " + transferType);
1758             }


1762                 ("Length of pixel array < number of components in model");
1763         }
1764         if (components == null) {
1765             components = new int[offset+numComponents];
1766         }
1767         else if ((components.length-offset) < numComponents) {
1768             throw new IllegalArgumentException
1769                 ("Length of components array < number of components in model");
1770         }
1771         System.arraycopy(intpixel, 0, components, offset, numComponents);
1772 
1773         return components;
1774     }
1775 
1776     /**
1777      * Returns an array of all of the color/alpha components in unnormalized
1778      * form, given a normalized component array.  Unnormalized components
1779      * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1780      * n is the number of bits for a particular component.  Normalized
1781      * components are float values between a per component minimum and
1782      * maximum specified by the {@code ColorSpace} object for this
1783      * {@code ColorModel}.  An {@code IllegalArgumentException}
1784      * will be thrown if color component values for this
1785      * {@code ColorModel} are not conveniently representable in the
1786      * unnormalized form.  If the
1787      * {@code components} array is {@code null}, a new array
1788      * will be allocated.  The {@code components} array will
1789      * be returned.  Color/alpha components are stored in the
1790      * {@code components} array starting at {@code offset} (even
1791      * if the array is allocated by this method). An
1792      * {@code ArrayIndexOutOfBoundsException} is thrown if the
1793      * {@code components} array is not {@code null} and is not
1794      * large enough to hold all the color and alpha
1795      * components (starting at {@code offset}).  An
1796      * {@code IllegalArgumentException} is thrown if the
1797      * {@code normComponents} array is not large enough to hold
1798      * all the color and alpha components starting at
1799      * {@code normOffset}.
1800      * @param normComponents an array containing normalized components
1801      * @param normOffset the offset into the {@code normComponents}
1802      * array at which to start retrieving normalized components
1803      * @param components an array that receives the components from
1804      * {@code normComponents}
1805      * @param offset the index into {@code components} at which to
1806      * begin storing normalized components from
1807      * {@code normComponents}
1808      * @return an array containing unnormalized color and alpha
1809      * components.
1810      * @throws IllegalArgumentException If this
1811      * {@code ComponentColorModel} does not support the unnormalized form
1812      * @throws IllegalArgumentException if the length of
1813      *          {@code normComponents} minus {@code normOffset}
1814      *          is less than {@code numComponents}
1815      */
1816     public int[] getUnnormalizedComponents(float[] normComponents,
1817                                            int normOffset,
1818                                            int[] components, int offset) {
1819         if (needScaleInit) {
1820             initScale();
1821         }
1822         if (noUnnorm) {
1823             throw new
1824                 IllegalArgumentException(
1825                     "This ColorModel does not support the unnormalized form");
1826         }
1827         return super.getUnnormalizedComponents(normComponents, normOffset,
1828                                                components, offset);
1829     }
1830 
1831     /**
1832      * Returns an array of all of the color/alpha components in normalized
1833      * form, given an unnormalized component array.  Unnormalized components
1834      * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1835      * n is the number of bits for a particular component.  Normalized
1836      * components are float values between a per component minimum and
1837      * maximum specified by the {@code ColorSpace} object for this
1838      * {@code ColorModel}.  An {@code IllegalArgumentException}
1839      * will be thrown if color component values for this
1840      * {@code ColorModel} are not conveniently representable in the
1841      * unnormalized form.  If the
1842      * {@code normComponents} array is {@code null}, a new array
1843      * will be allocated.  The {@code normComponents} array
1844      * will be returned.  Color/alpha components are stored in the
1845      * {@code normComponents} array starting at
1846      * {@code normOffset} (even if the array is allocated by this
1847      * method).  An {@code ArrayIndexOutOfBoundsException} is thrown
1848      * if the {@code normComponents} array is not {@code null}
1849      * and is not large enough to hold all the color and alpha components
1850      * (starting at {@code normOffset}).  An
1851      * {@code IllegalArgumentException} is thrown if the
1852      * {@code components} array is not large enough to hold all the
1853      * color and alpha components starting at {@code offset}.
1854      * @param components an array containing unnormalized components
1855      * @param offset the offset into the {@code components} array at
1856      * which to start retrieving unnormalized components
1857      * @param normComponents an array that receives the normalized components
1858      * @param normOffset the index into {@code normComponents} at
1859      * which to begin storing normalized components
1860      * @return an array containing normalized color and alpha
1861      * components.
1862      * @throws IllegalArgumentException If this
1863      * {@code ComponentColorModel} does not support the unnormalized form
1864      */
1865     public float[] getNormalizedComponents(int[] components, int offset,
1866                                            float[] normComponents,
1867                                            int normOffset) {
1868         if (needScaleInit) {
1869             initScale();
1870         }
1871         if (noUnnorm) {
1872             throw new
1873                 IllegalArgumentException(
1874                     "This ColorModel does not support the unnormalized form");
1875         }
1876         return super.getNormalizedComponents(components, offset,
1877                                              normComponents, normOffset);
1878     }
1879 
1880     /**
1881      * Returns a pixel value represented as an int in this {@code ColorModel},
1882      * given an array of unnormalized color/alpha components.
1883      *
1884      * @param components An array of unnormalized color/alpha components.
1885      * @param offset An offset into the {@code components} array.
1886      *
1887      * @return A pixel value represented as an int.
1888      *
1889      * @throws IllegalArgumentException If there is more than one component
1890      * in this {@code ColorModel}.
1891      * @throws IllegalArgumentException If this
1892      * {@code ComponentColorModel} does not support the unnormalized form
1893      */
1894     public int getDataElement(int[] components, int offset) {
1895         if (needScaleInit) {
1896             initScale();
1897         }
1898         if (numComponents == 1) {
1899             if (noUnnorm) {
1900                 throw new
1901                     IllegalArgumentException(
1902                     "This ColorModel does not support the unnormalized form");
1903             }
1904             return components[offset+0];
1905         }
1906         throw new IllegalArgumentException("This model returns "+
1907                                            numComponents+
1908                                            " elements in the pixel array.");
1909     }
1910 
1911     /**
1912      * Returns a data element array representation of a pixel in this
1913      * {@code ColorModel}, given an array of unnormalized color/alpha
1914      * components. This array can then be passed to the {@code setDataElements}
1915      * method of a {@code WritableRaster} object.
1916      *
1917      * @param components An array of unnormalized color/alpha components.
1918      * @param offset The integer offset into the {@code components} array.
1919      * @param obj The object in which to store the data element array
1920      * representation of the pixel. If {@code obj} variable is null,
1921      * a new array is allocated.  If {@code obj} is not null, it must
1922      * be a primitive array of type {@code transferType}. An
1923      * {@code ArrayIndexOutOfBoundsException} is thrown if
1924      * {@code obj} is not large enough to hold a pixel value
1925      * for this {@code ColorModel}.  Since
1926      * {@code ComponentColorModel} can be subclassed, subclasses
1927      * inherit the implementation of this method and if they don't
1928      * override it then they throw an exception if they use an
1929      * unsupported {@code transferType}.
1930      *
1931      * @return The data element array representation of a pixel
1932      * in this {@code ColorModel}.
1933      *
1934      * @throws IllegalArgumentException If the components array
1935      * is not large enough to hold all the color and alpha components
1936      * (starting at offset).
1937      * @throws ClassCastException If {@code obj} is not null and is not a
1938      * primitive  array of type {@code transferType}.
1939      * @throws ArrayIndexOutOfBoundsException If {@code obj} is not large
1940      * enough to hold a pixel value for this {@code ColorModel}.
1941      * @throws IllegalArgumentException If this
1942      * {@code ComponentColorModel} does not support the unnormalized form
1943      * @throws UnsupportedOperationException If the transfer type of
1944      * this {@code ComponentColorModel}
1945      * is not one of the following transfer types:
1946      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
1947      * or {@code DataBuffer.TYPE_INT}.
1948      *
1949      * @see WritableRaster#setDataElements
1950      * @see SampleModel#setDataElements
1951      */
1952     public Object getDataElements(int[] components, int offset, Object obj) {
1953         if (needScaleInit) {
1954             initScale();
1955         }
1956         if (noUnnorm) {
1957             throw new
1958                 IllegalArgumentException(
1959                     "This ColorModel does not support the unnormalized form");
1960         }
1961         if ((components.length-offset) < numComponents) {
1962             throw new IllegalArgumentException("Component array too small"+
1963                                                " (should be "+numComponents);
1964         }
1965         switch(transferType) {
1966         case DataBuffer.TYPE_INT:
1967             {


1998                 if (obj == null) {
1999                     pixel = new short[numComponents];
2000                 }
2001                 else {
2002                     pixel = (short[]) obj;
2003                 }
2004                 for (int i=0; i < numComponents; i++) {
2005                     pixel[i] = (short) (components[offset+i]&0xffff);
2006                 }
2007                 return pixel;
2008             }
2009 
2010         default:
2011             throw new UnsupportedOperationException("This method has not been "+
2012                                         "implemented for transferType " +
2013                                         transferType);
2014         }
2015     }
2016 
2017     /**
2018      * Returns a pixel value represented as an {@code int} in this
2019      * {@code ColorModel}, given an array of normalized color/alpha
2020      * components.  This method will throw an
2021      * {@code IllegalArgumentException} if pixel values for this
2022      * {@code ColorModel} are not conveniently representable as a
2023      * single {@code int}.  An
2024      * {@code ArrayIndexOutOfBoundsException} is thrown if  the
2025      * {@code normComponents} array is not large enough to hold all the
2026      * color and alpha components (starting at {@code normOffset}).
2027      * @param normComponents an array of normalized color and alpha
2028      * components
2029      * @param normOffset the index into {@code normComponents} at which to
2030      * begin retrieving the color and alpha components
2031      * @return an {@code int} pixel value in this
2032      * {@code ColorModel} corresponding to the specified components.
2033      * @throws IllegalArgumentException if
2034      *  pixel values for this {@code ColorModel} are not
2035      *  conveniently representable as a single {@code int}
2036      * @throws ArrayIndexOutOfBoundsException if
2037      *  the {@code normComponents} array is not large enough to
2038      *  hold all of the color and alpha components starting at
2039      *  {@code normOffset}
2040      * @since 1.4
2041      */
2042     public int getDataElement(float[] normComponents, int normOffset) {
2043         if (numComponents > 1) {
2044             throw new
2045                 IllegalArgumentException("More than one component per pixel");
2046         }
2047         if (signed) {
2048             throw new
2049                 IllegalArgumentException("Component value is signed");
2050         }
2051         if (needScaleInit) {
2052             initScale();
2053         }
2054         Object pixel = getDataElements(normComponents, normOffset, null);
2055         switch (transferType) {
2056         case DataBuffer.TYPE_BYTE:
2057             {
2058                 byte bpixel[] = (byte[]) pixel;
2059                 return bpixel[0] & 0xff;
2060             }
2061         case DataBuffer.TYPE_USHORT:
2062             {
2063                 short[] uspixel = (short[]) pixel;
2064                 return uspixel[0] & 0xffff;
2065             }
2066         case DataBuffer.TYPE_INT:
2067             {
2068                 int[] ipixel = (int[]) pixel;
2069                 return ipixel[0];
2070             }
2071         default:
2072             throw new UnsupportedOperationException("This method has not been "
2073                 + "implemented for transferType " + transferType);
2074         }
2075     }
2076 
2077     /**
2078      * Returns a data element array representation of a pixel in this
2079      * {@code ColorModel}, given an array of normalized color/alpha
2080      * components.  This array can then be passed to the
2081      * {@code setDataElements} method of a {@code WritableRaster}
2082      * object.  An {@code ArrayIndexOutOfBoundsException} is thrown
2083      * if the {@code normComponents} array is not large enough to hold
2084      * all the color and alpha components (starting at
2085      * {@code normOffset}).  If the {@code obj} variable is
2086      * {@code null}, a new array will be allocated.  If
2087      * {@code obj} is not {@code null}, it must be a primitive
2088      * array of type transferType; otherwise, a
2089      * {@code ClassCastException} is thrown.  An
2090      * {@code ArrayIndexOutOfBoundsException} is thrown if
2091      * {@code obj} is not large enough to hold a pixel value for this
2092      * {@code ColorModel}.
2093      * @param normComponents an array of normalized color and alpha
2094      * components
2095      * @param normOffset the index into {@code normComponents} at which to
2096      * begin retrieving color and alpha components
2097      * @param obj a primitive data array to hold the returned pixel
2098      * @return an {@code Object} which is a primitive data array
2099      * representation of a pixel
2100      * @throws ClassCastException if {@code obj}
2101      *  is not a primitive array of type {@code transferType}
2102      * @throws ArrayIndexOutOfBoundsException if
2103      *  {@code obj} is not large enough to hold a pixel value
2104      *  for this {@code ColorModel} or the {@code normComponents}
2105      *  array is not large enough to hold all of the color and alpha
2106      *  components starting at {@code normOffset}
2107      * @see WritableRaster#setDataElements
2108      * @see SampleModel#setDataElements
2109      * @since 1.4
2110      */
2111     public Object getDataElements(float[] normComponents, int normOffset,
2112                                   Object obj) {
2113         boolean needAlpha = supportsAlpha && isAlphaPremultiplied;
2114         float[] stdNormComponents;
2115         if (needScaleInit) {
2116             initScale();
2117         }
2118         if (nonStdScale) {
2119             stdNormComponents = new float[numComponents];
2120             for (int c = 0, nc = normOffset; c < numColorComponents;
2121                  c++, nc++) {
2122                 stdNormComponents[c] = (normComponents[nc] - compOffset[c]) *
2123                                        compScale[c];
2124                 // REMIND: need to analyze whether this
2125                 // clamping is necessary
2126                 if (stdNormComponents[c] < 0.0f) {


2281                      c++, nc++) {
2282                     dpixel[c] = normComponents[nc] * alpha;
2283                 }
2284                 dpixel[numColorComponents] = alpha;
2285             } else {
2286                 for (int c = 0, nc = normOffset; c < numComponents;
2287                      c++, nc++) {
2288                     dpixel[c] = (double) normComponents[nc];
2289                 }
2290             }
2291             return dpixel;
2292         default:
2293             throw new UnsupportedOperationException("This method has not been "+
2294                                         "implemented for transferType " +
2295                                         transferType);
2296         }
2297     }
2298 
2299     /**
2300      * Returns an array of all of the color/alpha components in normalized
2301      * form, given a pixel in this {@code ColorModel}.  The pixel
2302      * value is specified by an array of data elements of type transferType
2303      * passed in as an object reference.  If pixel is not a primitive array
2304      * of type transferType, a {@code ClassCastException} is thrown.
2305      * An {@code ArrayIndexOutOfBoundsException} is thrown if
2306      * {@code pixel} is not large enough to hold a pixel value for this
2307      * {@code ColorModel}.
2308      * Normalized components are float values between a per component minimum
2309      * and maximum specified by the {@code ColorSpace} object for this
2310      * {@code ColorModel}.  If the
2311      * {@code normComponents} array is {@code null}, a new array
2312      * will be allocated.  The {@code normComponents} array
2313      * will be returned.  Color/alpha components are stored in the
2314      * {@code normComponents} array starting at
2315      * {@code normOffset} (even if the array is allocated by this
2316      * method).  An {@code ArrayIndexOutOfBoundsException} is thrown
2317      * if the {@code normComponents} array is not {@code null}
2318      * and is not large enough to hold all the color and alpha components
2319      * (starting at {@code normOffset}).
2320      * <p>
2321      * This method must be overridden by a subclass if that subclass
2322      * is designed to translate pixel sample values to color component values
2323      * in a non-default way.  The default translations implemented by this
2324      * class is described in the class comments.  Any subclass implementing
2325      * a non-default translation must follow the constraints on allowable
2326      * translations defined there.
2327      * @param pixel the specified pixel
2328      * @param normComponents an array to receive the normalized components
2329      * @param normOffset the offset into the {@code normComponents}
2330      * array at which to start storing normalized components
2331      * @return an array containing normalized color and alpha
2332      * components.
2333      * @throws ClassCastException if {@code pixel} is not a primitive
2334      *          array of type transferType
2335      * @throws ArrayIndexOutOfBoundsException if
2336      *          {@code normComponents} is not large enough to hold all
2337      *          color and alpha components starting at {@code normOffset}
2338      * @throws ArrayIndexOutOfBoundsException if
2339      *          {@code pixel} is not large enough to hold a pixel
2340      *          value for this {@code ColorModel}.
2341      * @since 1.4
2342      */
2343     public float[] getNormalizedComponents(Object pixel,
2344                                            float[] normComponents,
2345                                            int normOffset) {
2346         if (normComponents == null) {
2347             normComponents = new float[numComponents+normOffset];
2348         }
2349         switch (transferType) {
2350         case DataBuffer.TYPE_BYTE:
2351             byte[] bpixel = (byte[]) pixel;
2352             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2353                 normComponents[nc] = ((float) (bpixel[c] & 0xff)) /
2354                                      ((float) ((1 << nBits[c]) - 1));
2355             }
2356             break;
2357         case DataBuffer.TYPE_USHORT:
2358             short[] uspixel = (short[]) pixel;
2359             for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2360                 normComponents[nc] = ((float) (uspixel[c] & 0xffff)) /


2409             // possible case, in which this method is overridden, nonStdScale
2410             // is set true by initScale(), the subclass method for some
2411             // reason calls this superclass method, but the min and
2412             // diffMinMax arrays were never initialized by setupLUTs().  In
2413             // that case, the right thing to do is follow the intended
2414             // semantics of this method, and rescale the color components
2415             // only if the ColorSpace min/max were detected to be other
2416             // than 0.0/1.0 by setupLUTs().  Note that this implies the
2417             // transferType is byte, ushort, int, or short - i.e. components
2418             // derived from float and double pixel data are never rescaled.
2419             for (int c = 0; c < numColorComponents; c++) {
2420                 normComponents[c + normOffset] = min[c] +
2421                     diffMinMax[c] * normComponents[c + normOffset];
2422             }
2423         }
2424         return normComponents;
2425     }
2426 
2427     /**
2428      * Forces the raster data to match the state specified in the
2429      * {@code isAlphaPremultiplied} variable, assuming the data
2430      * is currently correctly described by this {@code ColorModel}.
2431      * It may multiply or divide the color raster data by alpha, or
2432      * do nothing if the data is in the correct state.  If the data needs
2433      * to be coerced, this method also returns an instance of
2434      * this {@code ColorModel} with
2435      * the {@code isAlphaPremultiplied} flag set appropriately.
2436      * Since {@code ColorModel} can be subclassed, subclasses inherit
2437      * the implementation of this method and if they don't override it
2438      * then they throw an exception if they use an unsupported
2439      * {@code transferType}.
2440      *
2441      * @throws NullPointerException if {@code raster} is
2442      * {@code null} and data coercion is required.
2443      * @throws UnsupportedOperationException if the transfer type of
2444      * this {@code ComponentColorModel}
2445      * is not one of the supported transfer types:
2446      * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT},
2447      * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT},
2448      * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}.
2449      */
2450     public ColorModel coerceData (WritableRaster raster,
2451                                   boolean isAlphaPremultiplied) {
2452         if ((supportsAlpha == false) ||
2453             (this.isAlphaPremultiplied == isAlphaPremultiplied))
2454         {
2455             // Nothing to do
2456             return this;
2457         }
2458 
2459         int w = raster.getWidth();
2460         int h = raster.getHeight();
2461         int aIdx = raster.getNumBands() - 1;
2462         float normAlpha;
2463         int rminX = raster.getMinX();
2464         int rY = raster.getMinY();
2465         int rX;
2466         if (isAlphaPremultiplied) {
2467             switch (transferType) {
2468                 case DataBuffer.TYPE_BYTE: {


2757                 default:
2758                     throw new UnsupportedOperationException("This method has not been "+
2759                          "implemented for transferType " + transferType);
2760             }
2761         }
2762 
2763         // Return a new color model
2764         if (!signed) {
2765             return new ComponentColorModel(colorSpace, nBits, supportsAlpha,
2766                                            isAlphaPremultiplied, transparency,
2767                                            transferType);
2768         } else {
2769             return new ComponentColorModel(colorSpace, supportsAlpha,
2770                                            isAlphaPremultiplied, transparency,
2771                                            transferType);
2772         }
2773 
2774     }
2775 
2776     /**
2777       * Returns true if {@code raster} is compatible with this
2778       * {@code ColorModel}; false if it is not.
2779       *
2780       * @param raster The {@code Raster} object to test for compatibility.
2781       *
2782       * @return {@code true} if {@code raster} is compatible with this
2783       * {@code ColorModel}, {@code false} if it is not.
2784       */
2785     public boolean isCompatibleRaster(Raster raster) {
2786 
2787         SampleModel sm = raster.getSampleModel();
2788 
2789         if (sm instanceof ComponentSampleModel) {
2790             if (sm.getNumBands() != getNumComponents()) {
2791                 return false;
2792             }
2793             for (int i=0; i<nBits.length; i++) {
2794                 if (sm.getSampleSize(i) < nBits[i]) {
2795                     return false;
2796                 }
2797             }
2798             return (raster.getTransferType() == transferType);
2799         }
2800         else {
2801             return false;
2802         }
2803     }
2804 
2805     /**
2806      * Creates a {@code WritableRaster} with the specified width and height,
2807      * that  has a data layout ({@code SampleModel}) compatible with
2808      * this {@code ColorModel}.
2809      *
2810      * @param w The width of the {@code WritableRaster} you want to create.
2811      * @param h The height of the {@code WritableRaster} you want to create.
2812      *
2813      * @return A {@code WritableRaster} that is compatible with
2814      * this {@code ColorModel}.
2815      * @see WritableRaster
2816      * @see SampleModel
2817      */
2818     public WritableRaster createCompatibleWritableRaster (int w, int h) {
2819         int dataSize = w*h*numComponents;
2820         WritableRaster raster = null;
2821 
2822         switch (transferType) {
2823         case DataBuffer.TYPE_BYTE:
2824         case DataBuffer.TYPE_USHORT:
2825             raster = Raster.createInterleavedRaster(transferType,
2826                                                     w, h,
2827                                                     numComponents, null);
2828             break;
2829         default:
2830             SampleModel sm = createCompatibleSampleModel(w, h);
2831             DataBuffer db = sm.createDataBuffer();
2832             raster = Raster.createWritableRaster(sm, db, null);
2833         }
2834 
2835         return raster;
2836     }
2837 
2838     /**
2839      * Creates a {@code SampleModel} with the specified width and height,
2840      * that  has a data layout compatible with this {@code ColorModel}.
2841      *
2842      * @param w The width of the {@code SampleModel} you want to create.
2843      * @param h The height of the {@code SampleModel} you want to create.
2844      *
2845      * @return A {@code SampleModel} that is compatible with this
2846      * {@code ColorModel}.
2847      *
2848      * @see SampleModel
2849      */
2850     public SampleModel createCompatibleSampleModel(int w, int h) {
2851         int[] bandOffsets = new int[numComponents];
2852         for (int i=0; i < numComponents; i++) {
2853             bandOffsets[i] = i;
2854         }
2855         switch (transferType) {
2856         case DataBuffer.TYPE_BYTE:
2857         case DataBuffer.TYPE_USHORT:
2858             return new PixelInterleavedSampleModel(transferType, w, h,
2859                                                    numComponents,
2860                                                    w*numComponents,
2861                                                    bandOffsets);
2862         default:
2863             return new ComponentSampleModel(transferType, w, h,
2864                                             numComponents,
2865                                             w*numComponents,
2866                                             bandOffsets);
2867         }
2868     }
2869 
2870     /**
2871      * Checks whether or not the specified {@code SampleModel}
2872      * is compatible with this {@code ColorModel}.
2873      *
2874      * @param sm The {@code SampleModel} to test for compatibility.
2875      *
2876      * @return {@code true} if the {@code SampleModel} is
2877      * compatible with this {@code ColorModel}, {@code false}
2878      * if it is not.
2879      *
2880      * @see SampleModel
2881      */
2882     public boolean isCompatibleSampleModel(SampleModel sm) {
2883         if (!(sm instanceof ComponentSampleModel)) {
2884             return false;
2885         }
2886 
2887         // Must have the same number of components
2888         if (numComponents != sm.getNumBands()) {
2889             return false;
2890         }
2891 
2892         if (sm.getTransferType() != transferType) {
2893             return false;
2894         }
2895 
2896         return true;
2897     }
2898 
2899     /**
2900      * Returns a {@code Raster} representing the alpha channel of an image,
2901      * extracted from the input {@code Raster}.
2902      * This method assumes that {@code Raster} objects associated with
2903      * this {@code ColorModel} store the alpha band, if present, as
2904      * the last band of image data. Returns null if there is no separate spatial
2905      * alpha channel associated with this {@code ColorModel}.
2906      * This method creates a new {@code Raster}, but will share the data
2907      * array.
2908      *
2909      * @param raster The {@code WritableRaster} from which to extract the
2910      * alpha  channel.
2911      *
2912      * @return A {@code WritableRaster} containing the image's alpha channel.
2913      *
2914      */
2915     public WritableRaster getAlphaRaster(WritableRaster raster) {
2916         if (hasAlpha() == false) {
2917             return null;
2918         }
2919 
2920         int x = raster.getMinX();
2921         int y = raster.getMinY();
2922         int[] band = new int[1];
2923         band[0] = raster.getNumBands() - 1;
2924         return raster.createWritableChild(x, y, raster.getWidth(),
2925                                           raster.getHeight(), x, y,
2926                                           band);
2927     }
2928 
2929     /**
2930      * Compares this color model with another for equality.
2931      *
2932      * @param obj The object to compare with this color model.
2933      * @return {@code true} if the color model objects are equal,
2934      * {@code false} if they are not.
2935      */
2936     public boolean equals(Object obj) {
2937         if (!super.equals(obj)) {
2938             return false;
2939         }
2940 
2941         if (obj.getClass() !=  getClass()) {
2942             return false;
2943         }
2944 
2945         return true;
2946     }
2947 
2948 }
< prev index next >