1 /*
   2  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.image;
  27 
  28 import java.awt.Transparency;
  29 import java.awt.color.ColorSpace;
  30 import java.math.BigInteger;
  31 
  32 /**
  33  * The <code>IndexColorModel</code> class is a <code>ColorModel</code>
  34  * class that works with pixel values consisting of a
  35  * single sample that is an index into a fixed colormap in the default
  36  * sRGB color space.  The colormap specifies red, green, blue, and
  37  * optional alpha components corresponding to each index.  All components
  38  * are represented in the colormap as 8-bit unsigned integral values.
  39  * Some constructors allow the caller to specify "holes" in the colormap
  40  * by indicating which colormap entries are valid and which represent
  41  * unusable colors via the bits set in a <code>BigInteger</code> object.
  42  * This color model is similar to an X11 PseudoColor visual.
  43  * <p>
  44  * Some constructors provide a means to specify an alpha component
  45  * for each pixel in the colormap, while others either provide no
  46  * such means or, in some cases, a flag to indicate whether the
  47  * colormap data contains alpha values.  If no alpha is supplied to
  48  * the constructor, an opaque alpha component (alpha = 1.0) is
  49  * assumed for each entry.
  50  * An optional transparent pixel value can be supplied that indicates a
  51  * pixel to be made completely transparent, regardless of any alpha
  52  * component supplied or assumed for that pixel value.
  53  * Note that the color components in the colormap of an
  54  * <code>IndexColorModel</code> objects are never pre-multiplied with
  55  * the alpha components.
  56  * <p>
  57  * <a name="transparency">
  58  * The transparency of an <code>IndexColorModel</code> object is
  59  * determined by examining the alpha components of the colors in the
  60  * colormap and choosing the most specific value after considering
  61  * the optional alpha values and any transparent index specified.
  62  * The transparency value is <code>Transparency.OPAQUE</code>
  63  * only if all valid colors in
  64  * the colormap are opaque and there is no valid transparent pixel.
  65  * If all valid colors
  66  * in the colormap are either completely opaque (alpha = 1.0) or
  67  * completely transparent (alpha = 0.0), which typically occurs when
  68  * a valid transparent pixel is specified,
  69  * the value is <code>Transparency.BITMASK</code>.
  70  * Otherwise, the value is <code>Transparency.TRANSLUCENT</code>, indicating
  71  * that some valid color has an alpha component that is
  72  * neither completely transparent nor completely opaque
  73  * (0.0 &lt; alpha &lt; 1.0).
  74  * </a>
  75  *
  76  * <p>
  77  * If an <code>IndexColorModel</code> object has
  78  * a transparency value of <code>Transparency.OPAQUE</code>,
  79  * then the <code>hasAlpha</code>
  80  * and <code>getNumComponents</code> methods
  81  * (both inherited from <code>ColorModel</code>)
  82  * return false and 3, respectively.
  83  * For any other transparency value,
  84  * <code>hasAlpha</code> returns true
  85  * and <code>getNumComponents</code> returns 4.
  86  *
  87  * <p>
  88  * <a name="index_values">
  89  * The values used to index into the colormap are taken from the least
  90  * significant <em>n</em> bits of pixel representations where
  91  * <em>n</em> is based on the pixel size specified in the constructor.
  92  * For pixel sizes smaller than 8 bits, <em>n</em> is rounded up to a
  93  * power of two (3 becomes 4 and 5,6,7 become 8).
  94  * For pixel sizes between 8 and 16 bits, <em>n</em> is equal to the
  95  * pixel size.
  96  * Pixel sizes larger than 16 bits are not supported by this class.
  97  * Higher order bits beyond <em>n</em> are ignored in pixel representations.
  98  * Index values greater than or equal to the map size, but less than
  99  * 2<sup><em>n</em></sup>, are undefined and return 0 for all color and
 100  * alpha components.
 101  * <p>
 102  * For those methods that use a primitive array pixel representation of
 103  * type <code>transferType</code>, the array length is always one.
 104  * The transfer types supported are <code>DataBuffer.TYPE_BYTE</code> and
 105  * <code>DataBuffer.TYPE_USHORT</code>.  A single int pixel
 106  * representation is valid for all objects of this class, since it is
 107  * always possible to represent pixel values used with this class in a
 108  * single int.  Therefore, methods that use this representation do
 109  * not throw an <code>IllegalArgumentException</code> due to an invalid
 110  * pixel value.
 111  * <p>
 112  * Many of the methods in this class are final.  The reason for
 113  * this is that the underlying native graphics code makes assumptions
 114  * about the layout and operation of this class and those assumptions
 115  * are reflected in the implementations of the methods here that are
 116  * marked final.  You can subclass this class for other reasons, but
 117  * you cannot override or modify the behaviour of those methods.
 118  *
 119  * @see ColorModel
 120  * @see ColorSpace
 121  * @see DataBuffer
 122  *
 123  */
 124 public class IndexColorModel extends ColorModel {
 125     private int rgb[];
 126     private int map_size;
 127     private int pixel_mask;
 128     private int transparent_index = -1;
 129     private boolean allgrayopaque;
 130     private BigInteger validBits;
 131 
 132     private sun.awt.image.BufImgSurfaceData.ICMColorData colorData = null;
 133 
 134     private static int[] opaqueBits = {8, 8, 8};
 135     private static int[] alphaBits = {8, 8, 8, 8};
 136 
 137     static private native void initIDs();
 138     static {
 139         ColorModel.loadLibraries();
 140         initIDs();
 141     }
 142     /**
 143      * Constructs an <code>IndexColorModel</code> from the specified
 144      * arrays of red, green, and blue components.  Pixels described
 145      * by this color model all have alpha components of 255
 146      * unnormalized (1.0&nbsp;normalized), which means they
 147      * are fully opaque.  All of the arrays specifying the color
 148      * components must have at least the specified number of entries.
 149      * The <code>ColorSpace</code> is the default sRGB space.
 150      * Since there is no alpha information in any of the arguments
 151      * to this constructor, the transparency value is always
 152      * <code>Transparency.OPAQUE</code>.
 153      * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
 154      * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel.
 155      * @param bits      the number of bits each pixel occupies
 156      * @param size      the size of the color component arrays
 157      * @param r         the array of red color components
 158      * @param g         the array of green color components
 159      * @param b         the array of blue color components
 160      * @throws IllegalArgumentException if <code>bits</code> is less
 161      *         than 1 or greater than 16
 162      * @throws IllegalArgumentException if <code>size</code> is less
 163      *         than 1
 164      */
 165     public IndexColorModel(int bits, int size,
 166                            byte r[], byte g[], byte b[]) {
 167         super(bits, opaqueBits,
 168               ColorSpace.getInstance(ColorSpace.CS_sRGB),
 169               false, false, OPAQUE,
 170               ColorModel.getDefaultTransferType(bits));
 171         if (bits < 1 || bits > 16) {
 172             throw new IllegalArgumentException("Number of bits must be between"
 173                                                +" 1 and 16.");
 174         }
 175         setRGBs(size, r, g, b, null);
 176         calculatePixelMask();
 177     }
 178 
 179     /**
 180      * Constructs an <code>IndexColorModel</code> from the given arrays
 181      * of red, green, and blue components.  Pixels described by this color
 182      * model all have alpha components of 255 unnormalized
 183      * (1.0&nbsp;normalized), which means they are fully opaque, except
 184      * for the indicated pixel to be made transparent.  All of the arrays
 185      * specifying the color components must have at least the specified
 186      * number of entries.
 187      * The <code>ColorSpace</code> is the default sRGB space.
 188      * The transparency value may be <code>Transparency.OPAQUE</code> or
 189      * <code>Transparency.BITMASK</code> depending on the arguments, as
 190      * specified in the <a href="#transparency">class description</a> above.
 191      * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
 192      * or <code>DataBuffer.TYPE_USHORT</code> that can hold a
 193      * single pixel.
 194      * @param bits      the number of bits each pixel occupies
 195      * @param size      the size of the color component arrays
 196      * @param r         the array of red color components
 197      * @param g         the array of green color components
 198      * @param b         the array of blue color components
 199      * @param trans     the index of the transparent pixel
 200      * @throws IllegalArgumentException if <code>bits</code> is less than
 201      *          1 or greater than 16
 202      * @throws IllegalArgumentException if <code>size</code> is less than
 203      *          1
 204      */
 205     public IndexColorModel(int bits, int size,
 206                            byte r[], byte g[], byte b[], int trans) {
 207         super(bits, opaqueBits,
 208               ColorSpace.getInstance(ColorSpace.CS_sRGB),
 209               false, false, OPAQUE,
 210               ColorModel.getDefaultTransferType(bits));
 211         if (bits < 1 || bits > 16) {
 212             throw new IllegalArgumentException("Number of bits must be between"
 213                                                +" 1 and 16.");
 214         }
 215         setRGBs(size, r, g, b, null);
 216         setTransparentPixel(trans);
 217         calculatePixelMask();
 218     }
 219 
 220     /**
 221      * Constructs an <code>IndexColorModel</code> from the given
 222      * arrays of red, green, blue and alpha components.  All of the
 223      * arrays specifying the components must have at least the specified
 224      * number of entries.
 225      * The <code>ColorSpace</code> is the default sRGB space.
 226      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
 227      * <code>Transparency.BITMASK</code>,
 228      * or <code>Transparency.TRANSLUCENT</code>
 229      * depending on the arguments, as specified
 230      * in the <a href="#transparency">class description</a> above.
 231      * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
 232      * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel.
 233      * @param bits      the number of bits each pixel occupies
 234      * @param size      the size of the color component arrays
 235      * @param r         the array of red color components
 236      * @param g         the array of green color components
 237      * @param b         the array of blue color components
 238      * @param a         the array of alpha value components
 239      * @throws IllegalArgumentException if <code>bits</code> is less
 240      *           than 1 or greater than 16
 241      * @throws IllegalArgumentException if <code>size</code> is less
 242      *           than 1
 243      */
 244     public IndexColorModel(int bits, int size,
 245                            byte r[], byte g[], byte b[], byte a[]) {
 246         super (bits, alphaBits,
 247                ColorSpace.getInstance(ColorSpace.CS_sRGB),
 248                true, false, TRANSLUCENT,
 249                ColorModel.getDefaultTransferType(bits));
 250         if (bits < 1 || bits > 16) {
 251             throw new IllegalArgumentException("Number of bits must be between"
 252                                                +" 1 and 16.");
 253         }
 254         setRGBs (size, r, g, b, a);
 255         calculatePixelMask();
 256     }
 257 
 258     /**
 259      * Constructs an <code>IndexColorModel</code> from a single
 260      * array of interleaved red, green, blue and optional alpha
 261      * components.  The array must have enough values in it to
 262      * fill all of the needed component arrays of the specified
 263      * size.  The <code>ColorSpace</code> is the default sRGB space.
 264      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
 265      * <code>Transparency.BITMASK</code>,
 266      * or <code>Transparency.TRANSLUCENT</code>
 267      * depending on the arguments, as specified
 268      * in the <a href="#transparency">class description</a> above.
 269      * The transfer type is the smallest of
 270      * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code>
 271      * that can hold a single pixel.
 272      *
 273      * @param bits      the number of bits each pixel occupies
 274      * @param size      the size of the color component arrays
 275      * @param cmap      the array of color components
 276      * @param start     the starting offset of the first color component
 277      * @param hasalpha  indicates whether alpha values are contained in
 278      *                  the <code>cmap</code> array
 279      * @throws IllegalArgumentException if <code>bits</code> is less
 280      *           than 1 or greater than 16
 281      * @throws IllegalArgumentException if <code>size</code> is less
 282      *           than 1
 283      */
 284     public IndexColorModel(int bits, int size, byte cmap[], int start,
 285                            boolean hasalpha) {
 286         this(bits, size, cmap, start, hasalpha, -1);
 287         if (bits < 1 || bits > 16) {
 288             throw new IllegalArgumentException("Number of bits must be between"
 289                                                +" 1 and 16.");
 290         }
 291     }
 292 
 293     /**
 294      * Constructs an <code>IndexColorModel</code> from a single array of
 295      * interleaved red, green, blue and optional alpha components.  The
 296      * specified transparent index represents a pixel that is made
 297      * entirely transparent regardless of any alpha value specified
 298      * for it.  The array must have enough values in it to fill all
 299      * of the needed component arrays of the specified size.
 300      * The <code>ColorSpace</code> is the default sRGB space.
 301      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
 302      * <code>Transparency.BITMASK</code>,
 303      * or <code>Transparency.TRANSLUCENT</code>
 304      * depending on the arguments, as specified
 305      * in the <a href="#transparency">class description</a> above.
 306      * The transfer type is the smallest of
 307      * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code>
 308      * that can hold a single pixel.
 309      * @param bits      the number of bits each pixel occupies
 310      * @param size      the size of the color component arrays
 311      * @param cmap      the array of color components
 312      * @param start     the starting offset of the first color component
 313      * @param hasalpha  indicates whether alpha values are contained in
 314      *                  the <code>cmap</code> array
 315      * @param trans     the index of the fully transparent pixel
 316      * @throws IllegalArgumentException if <code>bits</code> is less than
 317      *               1 or greater than 16
 318      * @throws IllegalArgumentException if <code>size</code> is less than
 319      *               1
 320      */
 321     public IndexColorModel(int bits, int size, byte cmap[], int start,
 322                            boolean hasalpha, int trans) {
 323         // REMIND: This assumes the ordering: RGB[A]
 324         super(bits, opaqueBits,
 325               ColorSpace.getInstance(ColorSpace.CS_sRGB),
 326               false, false, OPAQUE,
 327               ColorModel.getDefaultTransferType(bits));
 328 
 329         if (bits < 1 || bits > 16) {
 330             throw new IllegalArgumentException("Number of bits must be between"
 331                                                +" 1 and 16.");
 332         }
 333         if (size < 1) {
 334             throw new IllegalArgumentException("Map size ("+size+
 335                                                ") must be >= 1");
 336         }
 337         map_size = size;
 338         rgb = new int[calcRealMapSize(bits, size)];
 339         int j = start;
 340         int alpha = 0xff;
 341         boolean allgray = true;
 342         int transparency = OPAQUE;
 343         for (int i = 0; i < size; i++) {
 344             int r = cmap[j++] & 0xff;
 345             int g = cmap[j++] & 0xff;
 346             int b = cmap[j++] & 0xff;
 347             allgray = allgray && (r == g) && (g == b);
 348             if (hasalpha) {
 349                 alpha = cmap[j++] & 0xff;
 350                 if (alpha != 0xff) {
 351                     if (alpha == 0x00) {
 352                         if (transparency == OPAQUE) {
 353                             transparency = BITMASK;
 354                         }
 355                         if (transparent_index < 0) {
 356                             transparent_index = i;
 357                         }
 358                     } else {
 359                         transparency = TRANSLUCENT;
 360                     }
 361                     allgray = false;
 362                 }
 363             }
 364             rgb[i] = (alpha << 24) | (r << 16) | (g << 8) | b;
 365         }
 366         this.allgrayopaque = allgray;
 367         setTransparency(transparency);
 368         setTransparentPixel(trans);
 369         calculatePixelMask();
 370     }
 371 
 372     /**
 373      * Constructs an <code>IndexColorModel</code> from an array of
 374      * ints where each int is comprised of red, green, blue, and
 375      * optional alpha components in the default RGB color model format.
 376      * The specified transparent index represents a pixel that is made
 377      * entirely transparent regardless of any alpha value specified
 378      * for it.  The array must have enough values in it to fill all
 379      * of the needed component arrays of the specified size.
 380      * The <code>ColorSpace</code> is the default sRGB space.
 381      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
 382      * <code>Transparency.BITMASK</code>,
 383      * or <code>Transparency.TRANSLUCENT</code>
 384      * depending on the arguments, as specified
 385      * in the <a href="#transparency">class description</a> above.
 386      * @param bits      the number of bits each pixel occupies
 387      * @param size      the size of the color component arrays
 388      * @param cmap      the array of color components
 389      * @param start     the starting offset of the first color component
 390      * @param hasalpha  indicates whether alpha values are contained in
 391      *                  the <code>cmap</code> array
 392      * @param trans     the index of the fully transparent pixel
 393      * @param transferType the data type of the array used to represent
 394      *           pixel values.  The data type must be either
 395      *           <code>DataBuffer.TYPE_BYTE</code> or
 396      *           <code>DataBuffer.TYPE_USHORT</code>.
 397      * @throws IllegalArgumentException if <code>bits</code> is less
 398      *           than 1 or greater than 16
 399      * @throws IllegalArgumentException if <code>size</code> is less
 400      *           than 1
 401      * @throws IllegalArgumentException if <code>transferType</code> is not
 402      *           one of <code>DataBuffer.TYPE_BYTE</code> or
 403      *           <code>DataBuffer.TYPE_USHORT</code>
 404      */
 405     public IndexColorModel(int bits, int size,
 406                            int cmap[], int start,
 407                            boolean hasalpha, int trans, int transferType) {
 408         // REMIND: This assumes the ordering: RGB[A]
 409         super(bits, opaqueBits,
 410               ColorSpace.getInstance(ColorSpace.CS_sRGB),
 411               false, false, OPAQUE,
 412               transferType);
 413 
 414         if (bits < 1 || bits > 16) {
 415             throw new IllegalArgumentException("Number of bits must be between"
 416                                                +" 1 and 16.");
 417         }
 418         if (size < 1) {
 419             throw new IllegalArgumentException("Map size ("+size+
 420                                                ") must be >= 1");
 421         }
 422         if ((transferType != DataBuffer.TYPE_BYTE) &&
 423             (transferType != DataBuffer.TYPE_USHORT)) {
 424             throw new IllegalArgumentException("transferType must be either" +
 425                 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT");
 426         }
 427 
 428         setRGBs(size, cmap, start, hasalpha);
 429         setTransparentPixel(trans);
 430         calculatePixelMask();
 431     }
 432 
 433     /**
 434      * Constructs an <code>IndexColorModel</code> from an
 435      * <code>int</code> array where each <code>int</code> is
 436      * comprised of red, green, blue, and alpha
 437      * components in the default RGB color model format.
 438      * The array must have enough values in it to fill all
 439      * of the needed component arrays of the specified size.
 440      * The <code>ColorSpace</code> is the default sRGB space.
 441      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
 442      * <code>Transparency.BITMASK</code>,
 443      * or <code>Transparency.TRANSLUCENT</code>
 444      * depending on the arguments, as specified
 445      * in the <a href="#transparency">class description</a> above.
 446      * The transfer type must be one of <code>DataBuffer.TYPE_BYTE</code>
 447      * <code>DataBuffer.TYPE_USHORT</code>.
 448      * The <code>BigInteger</code> object specifies the valid/invalid pixels
 449      * in the <code>cmap</code> array.  A pixel is valid if the
 450      * <code>BigInteger</code> value at that index is set, and is invalid
 451      * if the <code>BigInteger</code> bit  at that index is not set.
 452      * @param bits the number of bits each pixel occupies
 453      * @param size the size of the color component array
 454      * @param cmap the array of color components
 455      * @param start the starting offset of the first color component
 456      * @param transferType the specified data type
 457      * @param validBits a <code>BigInteger</code> object.  If a bit is
 458      *    set in the BigInteger, the pixel at that index is valid.
 459      *    If a bit is not set, the pixel at that index
 460      *    is considered invalid.  If null, all pixels are valid.
 461      *    Only bits from 0 to the map size are considered.
 462      * @throws IllegalArgumentException if <code>bits</code> is less
 463      *           than 1 or greater than 16
 464      * @throws IllegalArgumentException if <code>size</code> is less
 465      *           than 1
 466      * @throws IllegalArgumentException if <code>transferType</code> is not
 467      *           one of <code>DataBuffer.TYPE_BYTE</code> or
 468      *           <code>DataBuffer.TYPE_USHORT</code>
 469      *
 470      * @since 1.3
 471      */
 472     public IndexColorModel(int bits, int size, int cmap[], int start,
 473                            int transferType, BigInteger validBits) {
 474         super (bits, alphaBits,
 475                ColorSpace.getInstance(ColorSpace.CS_sRGB),
 476                true, false, TRANSLUCENT,
 477                transferType);
 478 
 479         if (bits < 1 || bits > 16) {
 480             throw new IllegalArgumentException("Number of bits must be between"
 481                                                +" 1 and 16.");
 482         }
 483         if (size < 1) {
 484             throw new IllegalArgumentException("Map size ("+size+
 485                                                ") must be >= 1");
 486         }
 487         if ((transferType != DataBuffer.TYPE_BYTE) &&
 488             (transferType != DataBuffer.TYPE_USHORT)) {
 489             throw new IllegalArgumentException("transferType must be either" +
 490                 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT");
 491         }
 492 
 493         if (validBits != null) {
 494             // Check to see if it is all valid
 495             for (int i=0; i < size; i++) {
 496                 if (!validBits.testBit(i)) {
 497                     this.validBits = validBits;
 498                     break;
 499                 }
 500             }
 501         }
 502 
 503         setRGBs(size, cmap, start, true);
 504         calculatePixelMask();
 505     }
 506 
 507     private void setRGBs(int size, byte r[], byte g[], byte b[], byte a[]) {
 508         if (size < 1) {
 509             throw new IllegalArgumentException("Map size ("+size+
 510                                                ") must be >= 1");
 511         }
 512         map_size = size;
 513         rgb = new int[calcRealMapSize(pixel_bits, size)];
 514         int alpha = 0xff;
 515         int transparency = OPAQUE;
 516         boolean allgray = true;
 517         for (int i = 0; i < size; i++) {
 518             int rc = r[i] & 0xff;
 519             int gc = g[i] & 0xff;
 520             int bc = b[i] & 0xff;
 521             allgray = allgray && (rc == gc) && (gc == bc);
 522             if (a != null) {
 523                 alpha = a[i] & 0xff;
 524                 if (alpha != 0xff) {
 525                     if (alpha == 0x00) {
 526                         if (transparency == OPAQUE) {
 527                             transparency = BITMASK;
 528                         }
 529                         if (transparent_index < 0) {
 530                             transparent_index = i;
 531                         }
 532                     } else {
 533                         transparency = TRANSLUCENT;
 534                     }
 535                     allgray = false;
 536                 }
 537             }
 538             rgb[i] = (alpha << 24) | (rc << 16) | (gc << 8) | bc;
 539         }
 540         this.allgrayopaque = allgray;
 541         setTransparency(transparency);
 542     }
 543 
 544     private void setRGBs(int size, int cmap[], int start, boolean hasalpha) {
 545         map_size = size;
 546         rgb = new int[calcRealMapSize(pixel_bits, size)];
 547         int j = start;
 548         int transparency = OPAQUE;
 549         boolean allgray = true;
 550         BigInteger validBits = this.validBits;
 551         for (int i = 0; i < size; i++, j++) {
 552             if (validBits != null && !validBits.testBit(i)) {
 553                 continue;
 554             }
 555             int cmaprgb = cmap[j];
 556             int r = (cmaprgb >> 16) & 0xff;
 557             int g = (cmaprgb >>  8) & 0xff;
 558             int b = (cmaprgb      ) & 0xff;
 559             allgray = allgray && (r == g) && (g == b);
 560             if (hasalpha) {
 561                 int alpha = cmaprgb >>> 24;
 562                 if (alpha != 0xff) {
 563                     if (alpha == 0x00) {
 564                         if (transparency == OPAQUE) {
 565                             transparency = BITMASK;
 566                         }
 567                         if (transparent_index < 0) {
 568                             transparent_index = i;
 569                         }
 570                     } else {
 571                         transparency = TRANSLUCENT;
 572                     }
 573                     allgray = false;
 574                 }
 575             } else {
 576                 cmaprgb |= 0xff000000;
 577             }
 578             rgb[i] = cmaprgb;
 579         }
 580         this.allgrayopaque = allgray;
 581         setTransparency(transparency);
 582     }
 583 
 584     private int calcRealMapSize(int bits, int size) {
 585         int newSize = Math.max(1 << bits, size);
 586         return Math.max(newSize, 256);
 587     }
 588 
 589     private BigInteger getAllValid() {
 590         int numbytes = (map_size+7)/8;
 591         byte[] valid = new byte[numbytes];
 592         java.util.Arrays.fill(valid, (byte)0xff);
 593         valid[0] = (byte)(0xff >>> (numbytes*8 - map_size));
 594 
 595         return new BigInteger(1, valid);
 596     }
 597 
 598     /**
 599      * Returns the transparency.  Returns either OPAQUE, BITMASK,
 600      * or TRANSLUCENT
 601      * @return the transparency of this <code>IndexColorModel</code>
 602      * @see Transparency#OPAQUE
 603      * @see Transparency#BITMASK
 604      * @see Transparency#TRANSLUCENT
 605      */
 606     public int getTransparency() {
 607         return transparency;
 608     }
 609 
 610     /**
 611      * Returns an array of the number of bits for each color/alpha component.
 612      * The array contains the color components in the order red, green,
 613      * blue, followed by the alpha component, if present.
 614      * @return an array containing the number of bits of each color
 615      *         and alpha component of this <code>IndexColorModel</code>
 616      */
 617     public int[] getComponentSize() {
 618         if (nBits == null) {
 619             if (supportsAlpha) {
 620                 nBits = new int[4];
 621                 nBits[3] = 8;
 622             }
 623             else {
 624                 nBits = new int[3];
 625             }
 626             nBits[0] = nBits[1] = nBits[2] = 8;
 627         }
 628         return nBits.clone();
 629     }
 630 
 631     /**
 632      * Returns the size of the color/alpha component arrays in this
 633      * <code>IndexColorModel</code>.
 634      * @return the size of the color and alpha component arrays.
 635      */
 636     final public int getMapSize() {
 637         return map_size;
 638     }
 639 
 640     /**
 641      * Returns the index of a transparent pixel in this
 642      * <code>IndexColorModel</code> or -1 if there is no pixel
 643      * with an alpha value of 0.  If a transparent pixel was
 644      * explicitly specified in one of the constructors by its
 645      * index, then that index will be preferred, otherwise,
 646      * the index of any pixel which happens to be fully transparent
 647      * may be returned.
 648      * @return the index of a transparent pixel in this
 649      *         <code>IndexColorModel</code> object, or -1 if there
 650      *         is no such pixel
 651      */
 652     final public int getTransparentPixel() {
 653         return transparent_index;
 654     }
 655 
 656     /**
 657      * Copies the array of red color components into the specified array.
 658      * Only the initial entries of the array as specified by
 659      * {@link #getMapSize() getMapSize} are written.
 660      * @param r the specified array into which the elements of the
 661      *      array of red color components are copied
 662      */
 663     final public void getReds(byte r[]) {
 664         for (int i = 0; i < map_size; i++) {
 665             r[i] = (byte) (rgb[i] >> 16);
 666         }
 667     }
 668 
 669     /**
 670      * Copies the array of green color components into the specified array.
 671      * Only the initial entries of the array as specified by
 672      * <code>getMapSize</code> are written.
 673      * @param g the specified array into which the elements of the
 674      *      array of green color components are copied
 675      */
 676     final public void getGreens(byte g[]) {
 677         for (int i = 0; i < map_size; i++) {
 678             g[i] = (byte) (rgb[i] >> 8);
 679         }
 680     }
 681 
 682     /**
 683      * Copies the array of blue color components into the specified array.
 684      * Only the initial entries of the array as specified by
 685      * <code>getMapSize</code> are written.
 686      * @param b the specified array into which the elements of the
 687      *      array of blue color components are copied
 688      */
 689     final public void getBlues(byte b[]) {
 690         for (int i = 0; i < map_size; i++) {
 691             b[i] = (byte) rgb[i];
 692         }
 693     }
 694 
 695     /**
 696      * Copies the array of alpha transparency components into the
 697      * specified array.  Only the initial entries of the array as specified
 698      * by <code>getMapSize</code> are written.
 699      * @param a the specified array into which the elements of the
 700      *      array of alpha components are copied
 701      */
 702     final public void getAlphas(byte a[]) {
 703         for (int i = 0; i < map_size; i++) {
 704             a[i] = (byte) (rgb[i] >> 24);
 705         }
 706     }
 707 
 708     /**
 709      * Converts data for each index from the color and alpha component
 710      * arrays to an int in the default RGB ColorModel format and copies
 711      * the resulting 32-bit ARGB values into the specified array.  Only
 712      * the initial entries of the array as specified by
 713      * <code>getMapSize</code> are
 714      * written.
 715      * @param rgb the specified array into which the converted ARGB
 716      *        values from this array of color and alpha components
 717      *        are copied.
 718      */
 719     final public void getRGBs(int rgb[]) {
 720         System.arraycopy(this.rgb, 0, rgb, 0, map_size);
 721     }
 722 
 723     private void setTransparentPixel(int trans) {
 724         if (trans >= 0 && trans < map_size) {
 725             rgb[trans] &= 0x00ffffff;
 726             transparent_index = trans;
 727             allgrayopaque = false;
 728             if (this.transparency == OPAQUE) {
 729                 setTransparency(BITMASK);
 730             }
 731         }
 732     }
 733 
 734     private void setTransparency(int transparency) {
 735         if (this.transparency != transparency) {
 736             this.transparency = transparency;
 737             if (transparency == OPAQUE) {
 738                 supportsAlpha = false;
 739                 numComponents = 3;
 740                 nBits = opaqueBits;
 741             } else {
 742                 supportsAlpha = true;
 743                 numComponents = 4;
 744                 nBits = alphaBits;
 745             }
 746         }
 747     }
 748 
 749     /**
 750      * This method is called from the constructors to set the pixel_mask
 751      * value, which is based on the value of pixel_bits.  The pixel_mask
 752      * value is used to mask off the pixel parameters for methods such
 753      * as getRed(), getGreen(), getBlue(), getAlpha(), and getRGB().
 754      */
 755     private final void calculatePixelMask() {
 756         // Note that we adjust the mask so that our masking behavior here
 757         // is consistent with that of our native rendering loops.
 758         int maskbits = pixel_bits;
 759         if (maskbits == 3) {
 760             maskbits = 4;
 761         } else if (maskbits > 4 && maskbits < 8) {
 762             maskbits = 8;
 763         }
 764         pixel_mask = (1 << maskbits) - 1;
 765     }
 766 
 767     /**
 768      * Returns the red color component for the specified pixel, scaled
 769      * from 0 to 255 in the default RGB ColorSpace, sRGB.  The pixel value
 770      * is specified as an int.
 771      * Only the lower <em>n</em> bits of the pixel value, as specified in the
 772      * <a href="#index_values">class description</a> above, are used to
 773      * calculate the returned value.
 774      * The returned value is a non pre-multiplied value.
 775      * @param pixel the specified pixel
 776      * @return the value of the red color component for the specified pixel
 777      */
 778     final public int getRed(int pixel) {
 779         return (rgb[pixel & pixel_mask] >> 16) & 0xff;
 780     }
 781 
 782     /**
 783      * Returns the green color component for the specified pixel, scaled
 784      * from 0 to 255 in the default RGB ColorSpace, sRGB.  The pixel value
 785      * is specified as an int.
 786      * Only the lower <em>n</em> bits of the pixel value, as specified in the
 787      * <a href="#index_values">class description</a> above, are used to
 788      * calculate the returned value.
 789      * The returned value is a non pre-multiplied value.
 790      * @param pixel the specified pixel
 791      * @return the value of the green color component for the specified pixel
 792      */
 793     final public int getGreen(int pixel) {
 794         return (rgb[pixel & pixel_mask] >> 8) & 0xff;
 795     }
 796 
 797     /**
 798      * Returns the blue color component for the specified pixel, scaled
 799      * from 0 to 255 in the default RGB ColorSpace, sRGB.  The pixel value
 800      * is specified as an int.
 801      * Only the lower <em>n</em> bits of the pixel value, as specified in the
 802      * <a href="#index_values">class description</a> above, are used to
 803      * calculate the returned value.
 804      * The returned value is a non pre-multiplied value.
 805      * @param pixel the specified pixel
 806      * @return the value of the blue color component for the specified pixel
 807      */
 808     final public int getBlue(int pixel) {
 809         return rgb[pixel & pixel_mask] & 0xff;
 810     }
 811 
 812     /**
 813      * Returns the alpha component for the specified pixel, scaled
 814      * from 0 to 255.  The pixel value is specified as an int.
 815      * Only the lower <em>n</em> bits of the pixel value, as specified in the
 816      * <a href="#index_values">class description</a> above, are used to
 817      * calculate the returned value.
 818      * @param pixel the specified pixel
 819      * @return the value of the alpha component for the specified pixel
 820      */
 821     final public int getAlpha(int pixel) {
 822         return (rgb[pixel & pixel_mask] >> 24) & 0xff;
 823     }
 824 
 825     /**
 826      * Returns the color/alpha components of the pixel in the default
 827      * RGB color model format.  The pixel value is specified as an int.
 828      * Only the lower <em>n</em> bits of the pixel value, as specified in the
 829      * <a href="#index_values">class description</a> above, are used to
 830      * calculate the returned value.
 831      * The returned value is in a non pre-multiplied format.
 832      * @param pixel the specified pixel
 833      * @return the color and alpha components of the specified pixel
 834      * @see ColorModel#getRGBdefault
 835      */
 836     final public int getRGB(int pixel) {
 837         return rgb[pixel & pixel_mask];
 838     }
 839 
 840     private static final int CACHESIZE = 40;
 841     private int lookupcache[] = new int[CACHESIZE];
 842 
 843     /**
 844      * Returns a data element array representation of a pixel in this
 845      * ColorModel, given an integer pixel representation in the
 846      * default RGB color model.  This array can then be passed to the
 847      * {@link WritableRaster#setDataElements(int, int, java.lang.Object) setDataElements}
 848      * method of a {@link WritableRaster} object.  If the pixel variable is
 849      * <code>null</code>, a new array is allocated.  If <code>pixel</code>
 850      * is not <code>null</code>, it must be
 851      * a primitive array of type <code>transferType</code>; otherwise, a
 852      * <code>ClassCastException</code> is thrown.  An
 853      * <code>ArrayIndexOutOfBoundsException</code> is
 854      * thrown if <code>pixel</code> is not large enough to hold a pixel
 855      * value for this <code>ColorModel</code>.  The pixel array is returned.
 856      * <p>
 857      * Since <code>IndexColorModel</code> can be subclassed, subclasses
 858      * inherit the implementation of this method and if they don't
 859      * override it then they throw an exception if they use an
 860      * unsupported <code>transferType</code>.
 861      *
 862      * @param rgb the integer pixel representation in the default RGB
 863      * color model
 864      * @param pixel the specified pixel
 865      * @return an array representation of the specified pixel in this
 866      *  <code>IndexColorModel</code>.
 867      * @throws ClassCastException if <code>pixel</code>
 868      *  is not a primitive array of type <code>transferType</code>
 869      * @throws ArrayIndexOutOfBoundsException if
 870      *  <code>pixel</code> is not large enough to hold a pixel value
 871      *  for this <code>ColorModel</code>
 872      * @throws UnsupportedOperationException if <code>transferType</code>
 873      *         is invalid
 874      * @see WritableRaster#setDataElements
 875      * @see SampleModel#setDataElements
 876      */
 877     public synchronized Object getDataElements(int rgb, Object pixel) {
 878         int red = (rgb>>16) & 0xff;
 879         int green = (rgb>>8) & 0xff;
 880         int blue  = rgb & 0xff;
 881         int alpha = (rgb>>>24);
 882         int pix = 0;
 883 
 884         // Note that pixels are stored at lookupcache[2*i]
 885         // and the rgb that was searched is stored at
 886         // lookupcache[2*i+1].  Also, the pixel is first
 887         // inverted using the unary complement operator
 888         // before storing in the cache so it can never be 0.
 889         for (int i = CACHESIZE - 2; i >= 0; i -= 2) {
 890             if ((pix = lookupcache[i]) == 0) {
 891                 break;
 892             }
 893             if (rgb == lookupcache[i+1]) {
 894                 return installpixel(pixel, ~pix);
 895             }
 896         }
 897 
 898         if (allgrayopaque) {
 899             // IndexColorModel objects are all tagged as
 900             // non-premultiplied so ignore the alpha value
 901             // of the incoming color, convert the
 902             // non-premultiplied color components to a
 903             // grayscale value and search for the closest
 904             // gray value in the palette.  Since all colors
 905             // in the palette are gray, we only need compare
 906             // to one of the color components for a match
 907             // using a simple linear distance formula.
 908 
 909             int minDist = 256;
 910             int d;
 911             int gray = (red*77 + green*150 + blue*29 + 128)/256;
 912 
 913             for (int i = 0; i < map_size; i++) {
 914                 if (this.rgb[i] == 0x0) {
 915                     // For allgrayopaque colormaps, entries are 0
 916                     // iff they are an invalid color and should be
 917                     // ignored during color searches.
 918                     continue;
 919                 }
 920                 d = (this.rgb[i] & 0xff) - gray;
 921                 if (d < 0) d = -d;
 922                 if (d < minDist) {
 923                     pix = i;
 924                     if (d == 0) {
 925                         break;
 926                     }
 927                     minDist = d;
 928                 }
 929             }
 930         } else if (transparency == OPAQUE) {
 931             // IndexColorModel objects are all tagged as
 932             // non-premultiplied so ignore the alpha value
 933             // of the incoming color and search for closest
 934             // color match independently using a 3 component
 935             // Euclidean distance formula.
 936             // For opaque colormaps, palette entries are 0
 937             // iff they are an invalid color and should be
 938             // ignored during color searches.
 939             // As an optimization, exact color searches are
 940             // likely to be fairly common in opaque colormaps
 941             // so first we will do a quick search for an
 942             // exact match.
 943 
 944             int smallestError = Integer.MAX_VALUE;
 945             int lut[] = this.rgb;
 946             int lutrgb;
 947             for (int i=0; i < map_size; i++) {
 948                 lutrgb = lut[i];
 949                 if (lutrgb == rgb && lutrgb != 0) {
 950                     pix = i;
 951                     smallestError = 0;
 952                     break;
 953                 }
 954             }
 955 
 956             if (smallestError != 0) {
 957                 for (int i=0; i < map_size; i++) {
 958                     lutrgb = lut[i];
 959                     if (lutrgb == 0) {
 960                         continue;
 961                     }
 962 
 963                     int tmp = ((lutrgb >> 16) & 0xff) - red;
 964                     int currentError = tmp*tmp;
 965                     if (currentError < smallestError) {
 966                         tmp = ((lutrgb >> 8) & 0xff) - green;
 967                         currentError += tmp * tmp;
 968                         if (currentError < smallestError) {
 969                             tmp = (lutrgb & 0xff) - blue;
 970                             currentError += tmp * tmp;
 971                             if (currentError < smallestError) {
 972                                 pix = i;
 973                                 smallestError = currentError;
 974                             }
 975                         }
 976                     }
 977                 }
 978             }
 979         } else if (alpha == 0 && transparent_index >= 0) {
 980             // Special case - transparent color maps to the
 981             // specified transparent pixel, if there is one
 982 
 983             pix = transparent_index;
 984         } else {
 985             // IndexColorModel objects are all tagged as
 986             // non-premultiplied so use non-premultiplied
 987             // color components in the distance calculations.
 988             // Look for closest match using a 4 component
 989             // Euclidean distance formula.
 990 
 991             int smallestError = Integer.MAX_VALUE;
 992             int lut[] = this.rgb;
 993             for (int i=0; i < map_size; i++) {
 994                 int lutrgb = lut[i];
 995                 if (lutrgb == rgb) {
 996                     if (validBits != null && !validBits.testBit(i)) {
 997                         continue;
 998                     }
 999                     pix = i;
1000                     break;
1001                 }
1002 
1003                 int tmp = ((lutrgb >> 16) & 0xff) - red;
1004                 int currentError = tmp*tmp;
1005                 if (currentError < smallestError) {
1006                     tmp = ((lutrgb >> 8) & 0xff) - green;
1007                     currentError += tmp * tmp;
1008                     if (currentError < smallestError) {
1009                         tmp = (lutrgb & 0xff) - blue;
1010                         currentError += tmp * tmp;
1011                         if (currentError < smallestError) {
1012                             tmp = (lutrgb >>> 24) - alpha;
1013                             currentError += tmp * tmp;
1014                             if (currentError < smallestError &&
1015                                 (validBits == null || validBits.testBit(i)))
1016                             {
1017                                 pix = i;
1018                                 smallestError = currentError;
1019                             }
1020                         }
1021                     }
1022                 }
1023             }
1024         }
1025         System.arraycopy(lookupcache, 2, lookupcache, 0, CACHESIZE - 2);
1026         lookupcache[CACHESIZE - 1] = rgb;
1027         lookupcache[CACHESIZE - 2] = ~pix;
1028         return installpixel(pixel, pix);
1029     }
1030 
1031     private Object installpixel(Object pixel, int pix) {
1032         switch (transferType) {
1033         case DataBuffer.TYPE_INT:
1034             int[] intObj;
1035             if (pixel == null) {
1036                 pixel = intObj = new int[1];
1037             } else {
1038                 intObj = (int[]) pixel;
1039             }
1040             intObj[0] = pix;
1041             break;
1042         case DataBuffer.TYPE_BYTE:
1043             byte[] byteObj;
1044             if (pixel == null) {
1045                 pixel = byteObj = new byte[1];
1046             } else {
1047                 byteObj = (byte[]) pixel;
1048             }
1049             byteObj[0] = (byte) pix;
1050             break;
1051         case DataBuffer.TYPE_USHORT:
1052             short[] shortObj;
1053             if (pixel == null) {
1054                 pixel = shortObj = new short[1];
1055             } else {
1056                 shortObj = (short[]) pixel;
1057             }
1058             shortObj[0] = (short) pix;
1059             break;
1060         default:
1061             throw new UnsupportedOperationException("This method has not been "+
1062                              "implemented for transferType " + transferType);
1063         }
1064         return pixel;
1065     }
1066 
1067     /**
1068      * Returns an array of unnormalized color/alpha components for a
1069      * specified pixel in this <code>ColorModel</code>.  The pixel value
1070      * is specified as an int.  If the <code>components</code> array is <code>null</code>,
1071      * a new array is allocated that contains
1072      * <code>offset + getNumComponents()</code> elements.
1073      * The <code>components</code> array is returned,
1074      * with the alpha component included
1075      * only if <code>hasAlpha</code> returns true.
1076      * Color/alpha components are stored in the <code>components</code> array starting
1077      * at <code>offset</code> even if the array is allocated by this method.
1078      * An <code>ArrayIndexOutOfBoundsException</code>
1079      * is thrown if  the <code>components</code> array is not <code>null</code> and is
1080      * not large enough to hold all the color and alpha components
1081      * starting at <code>offset</code>.
1082      * @param pixel the specified pixel
1083      * @param components the array to receive the color and alpha
1084      * components of the specified pixel
1085      * @param offset the offset into the <code>components</code> array at
1086      * which to start storing the color and alpha components
1087      * @return an array containing the color and alpha components of the
1088      * specified pixel starting at the specified offset.
1089      * @see ColorModel#hasAlpha
1090      * @see ColorModel#getNumComponents
1091      */
1092     public int[] getComponents(int pixel, int[] components, int offset) {
1093         if (components == null) {
1094             components = new int[offset+numComponents];
1095         }
1096 
1097         // REMIND: Needs to change if different color space
1098         components[offset+0] = getRed(pixel);
1099         components[offset+1] = getGreen(pixel);
1100         components[offset+2] = getBlue(pixel);
1101         if (supportsAlpha && (components.length-offset) > 3) {
1102             components[offset+3] = getAlpha(pixel);
1103         }
1104 
1105         return components;
1106     }
1107 
1108     /**
1109      * Returns an array of unnormalized color/alpha components for
1110      * a specified pixel in this <code>ColorModel</code>.  The pixel
1111      * value is specified by an array of data elements of type
1112      * <code>transferType</code> passed in as an object reference.
1113      * If <code>pixel</code> is not a primitive array of type
1114      * <code>transferType</code>, a <code>ClassCastException</code>
1115      * is thrown.  An <code>ArrayIndexOutOfBoundsException</code>
1116      * is thrown if <code>pixel</code> is not large enough to hold
1117      * a pixel value for this <code>ColorModel</code>.  If the
1118      * <code>components</code> array is <code>null</code>, a new array
1119      * is allocated that contains
1120      * <code>offset + getNumComponents()</code> elements.
1121      * The <code>components</code> array is returned,
1122      * with the alpha component included
1123      * only if <code>hasAlpha</code> returns true.
1124      * Color/alpha components are stored in the <code>components</code>
1125      * array starting at <code>offset</code> even if the array is
1126      * allocated by this method.  An
1127      * <code>ArrayIndexOutOfBoundsException</code> is also
1128      * thrown if  the <code>components</code> array is not
1129      * <code>null</code> and is not large enough to hold all the color
1130      * and alpha components starting at <code>offset</code>.
1131      * <p>
1132      * Since <code>IndexColorModel</code> can be subclassed, subclasses
1133      * inherit the implementation of this method and if they don't
1134      * override it then they throw an exception if they use an
1135      * unsupported <code>transferType</code>.
1136      *
1137      * @param pixel the specified pixel
1138      * @param components an array that receives the color and alpha
1139      * components of the specified pixel
1140      * @param offset the index into the <code>components</code> array at
1141      * which to begin storing the color and alpha components of the
1142      * specified pixel
1143      * @return an array containing the color and alpha components of the
1144      * specified pixel starting at the specified offset.
1145      * @throws ArrayIndexOutOfBoundsException if <code>pixel</code>
1146      *            is not large enough to hold a pixel value for this
1147      *            <code>ColorModel</code> or if the
1148      *            <code>components</code> array is not <code>null</code>
1149      *            and is not large enough to hold all the color
1150      *            and alpha components starting at <code>offset</code>
1151      * @throws ClassCastException if <code>pixel</code> is not a
1152      *            primitive array of type <code>transferType</code>
1153      * @throws UnsupportedOperationException if <code>transferType</code>
1154      *         is not one of the supported transer types
1155      * @see ColorModel#hasAlpha
1156      * @see ColorModel#getNumComponents
1157      */
1158     public int[] getComponents(Object pixel, int[] components, int offset) {
1159         int intpixel;
1160         switch (transferType) {
1161             case DataBuffer.TYPE_BYTE:
1162                byte bdata[] = (byte[])pixel;
1163                intpixel = bdata[0] & 0xff;
1164             break;
1165             case DataBuffer.TYPE_USHORT:
1166                short sdata[] = (short[])pixel;
1167                intpixel = sdata[0] & 0xffff;
1168             break;
1169             case DataBuffer.TYPE_INT:
1170                int idata[] = (int[])pixel;
1171                intpixel = idata[0];
1172             break;
1173             default:
1174                throw new UnsupportedOperationException("This method has not been "+
1175                    "implemented for transferType " + transferType);
1176         }
1177         return getComponents(intpixel, components, offset);
1178     }
1179 
1180     /**
1181      * Returns a pixel value represented as an int in this
1182      * <code>ColorModel</code> given an array of unnormalized
1183      * color/alpha components.  An
1184      * <code>ArrayIndexOutOfBoundsException</code>
1185      * is thrown if the <code>components</code> array is not large
1186      * enough to hold all of the color and alpha components starting
1187      * at <code>offset</code>.  Since
1188      * <code>ColorModel</code> can be subclassed, subclasses inherit the
1189      * implementation of this method and if they don't override it then
1190      * they throw an exception if they use an unsupported transferType.
1191      * @param components an array of unnormalized color and alpha
1192      * components
1193      * @param offset the index into <code>components</code> at which to
1194      * begin retrieving the color and alpha components
1195      * @return an <code>int</code> pixel value in this
1196      * <code>ColorModel</code> corresponding to the specified components.
1197      * @throws ArrayIndexOutOfBoundsException if
1198      *  the <code>components</code> array is not large enough to
1199      *  hold all of the color and alpha components starting at
1200      *  <code>offset</code>
1201      * @throws UnsupportedOperationException if <code>transferType</code>
1202      *         is invalid
1203      */
1204     public int getDataElement(int[] components, int offset) {
1205         int rgb = (components[offset+0]<<16)
1206             | (components[offset+1]<<8) | (components[offset+2]);
1207         if (supportsAlpha) {
1208             rgb |= (components[offset+3]<<24);
1209         }
1210         else {
1211             rgb |= 0xff000000;
1212         }
1213         Object inData = getDataElements(rgb, null);
1214         int pixel;
1215         switch (transferType) {
1216             case DataBuffer.TYPE_BYTE:
1217                byte bdata[] = (byte[])inData;
1218                pixel = bdata[0] & 0xff;
1219             break;
1220             case DataBuffer.TYPE_USHORT:
1221                short sdata[] = (short[])inData;
1222                pixel = sdata[0];
1223             break;
1224             case DataBuffer.TYPE_INT:
1225                int idata[] = (int[])inData;
1226                pixel = idata[0];
1227             break;
1228             default:
1229                throw new UnsupportedOperationException("This method has not been "+
1230                    "implemented for transferType " + transferType);
1231         }
1232         return pixel;
1233     }
1234 
1235     /**
1236      * Returns a data element array representation of a pixel in this
1237      * <code>ColorModel</code> given an array of unnormalized color/alpha
1238      * components.  This array can then be passed to the
1239      * <code>setDataElements</code> method of a <code>WritableRaster</code>
1240      * object.  An <code>ArrayIndexOutOfBoundsException</code> is
1241      * thrown if the
1242      * <code>components</code> array is not large enough to hold all of the
1243      * color and alpha components starting at <code>offset</code>.
1244      * If the pixel variable is <code>null</code>, a new array
1245      * is allocated.  If <code>pixel</code> is not <code>null</code>,
1246      * it must be a primitive array of type <code>transferType</code>;
1247      * otherwise, a <code>ClassCastException</code> is thrown.
1248      * An <code>ArrayIndexOutOfBoundsException</code> is thrown if pixel
1249      * is not large enough to hold a pixel value for this
1250      * <code>ColorModel</code>.
1251      * <p>
1252      * Since <code>IndexColorModel</code> can be subclassed, subclasses
1253      * inherit the implementation of this method and if they don't
1254      * override it then they throw an exception if they use an
1255      * unsupported <code>transferType</code>
1256      *
1257      * @param components an array of unnormalized color and alpha
1258      * components
1259      * @param offset the index into <code>components</code> at which to
1260      * begin retrieving color and alpha components
1261      * @param pixel the <code>Object</code> representing an array of color
1262      * and alpha components
1263      * @return an <code>Object</code> representing an array of color and
1264      * alpha components.
1265      * @throws ClassCastException if <code>pixel</code>
1266      *  is not a primitive array of type <code>transferType</code>
1267      * @throws ArrayIndexOutOfBoundsException if
1268      *  <code>pixel</code> is not large enough to hold a pixel value
1269      *  for this <code>ColorModel</code> or the <code>components</code>
1270      *  array is not large enough to hold all of the color and alpha
1271      *  components starting at <code>offset</code>
1272      * @throws UnsupportedOperationException if <code>transferType</code>
1273      *         is not one of the supported transer types
1274      * @see WritableRaster#setDataElements
1275      * @see SampleModel#setDataElements
1276      */
1277     public Object getDataElements(int[] components, int offset, Object pixel) {
1278         int rgb = (components[offset+0]<<16) | (components[offset+1]<<8)
1279             | (components[offset+2]);
1280         if (supportsAlpha) {
1281             rgb |= (components[offset+3]<<24);
1282         }
1283         else {
1284             rgb &= 0xff000000;
1285         }
1286         return getDataElements(rgb, pixel);
1287     }
1288 
1289     /**
1290      * Creates a <code>WritableRaster</code> with the specified width
1291      * and height that has a data layout (<code>SampleModel</code>)
1292      * compatible with this <code>ColorModel</code>.  This method
1293      * only works for color models with 16 or fewer bits per pixel.
1294      * <p>
1295      * Since <code>IndexColorModel</code> can be subclassed, any
1296      * subclass that supports greater than 16 bits per pixel must
1297      * override this method.
1298      *
1299      * @param w the width to apply to the new <code>WritableRaster</code>
1300      * @param h the height to apply to the new <code>WritableRaster</code>
1301      * @return a <code>WritableRaster</code> object with the specified
1302      * width and height.
1303      * @throws UnsupportedOperationException if the number of bits in a
1304      *         pixel is greater than 16
1305      * @see WritableRaster
1306      * @see SampleModel
1307      */
1308     public WritableRaster createCompatibleWritableRaster(int w, int h) {
1309         WritableRaster raster;
1310 
1311         if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
1312             // TYPE_BINARY
1313             raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
1314                                                w, h, 1, pixel_bits, null);
1315         }
1316         else if (pixel_bits <= 8) {
1317             raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
1318                                                   w,h,1,null);
1319         }
1320         else if (pixel_bits <= 16) {
1321             raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT,
1322                                                   w,h,1,null);
1323         }
1324         else {
1325             throw new
1326                 UnsupportedOperationException("This method is not supported "+
1327                                               " for pixel bits > 16.");
1328         }
1329         return raster;
1330     }
1331 
1332     /**
1333       * Returns <code>true</code> if <code>raster</code> is compatible
1334       * with this <code>ColorModel</code> or <code>false</code> if it
1335       * is not compatible with this <code>ColorModel</code>.
1336       * @param raster the {@link Raster} object to test for compatibility
1337       * @return <code>true</code> if <code>raster</code> is compatible
1338       * with this <code>ColorModel</code>; <code>false</code> otherwise.
1339       *
1340       */
1341     public boolean isCompatibleRaster(Raster raster) {
1342 
1343         int size = raster.getSampleModel().getSampleSize(0);
1344         return ((raster.getTransferType() == transferType) &&
1345                 (raster.getNumBands() == 1) && ((1 << size) >= map_size));
1346     }
1347 
1348     /**
1349      * Creates a <code>SampleModel</code> with the specified
1350      * width and height that has a data layout compatible with
1351      * this <code>ColorModel</code>.
1352      * @param w the width to apply to the new <code>SampleModel</code>
1353      * @param h the height to apply to the new <code>SampleModel</code>
1354      * @return a <code>SampleModel</code> object with the specified
1355      * width and height.
1356      * @throws IllegalArgumentException if <code>w</code> or
1357      *         <code>h</code> is not greater than 0
1358      * @see SampleModel
1359      */
1360     public SampleModel createCompatibleSampleModel(int w, int h) {
1361         int[] off = new int[1];
1362         off[0] = 0;
1363         if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
1364             return new MultiPixelPackedSampleModel(transferType, w, h,
1365                                                    pixel_bits);
1366         }
1367         else {
1368             return new ComponentSampleModel(transferType, w, h, 1, w,
1369                                             off);
1370         }
1371     }
1372 
1373     /**
1374      * Checks if the specified <code>SampleModel</code> is compatible
1375      * with this <code>ColorModel</code>.  If <code>sm</code> is
1376      * <code>null</code>, this method returns <code>false</code>.
1377      * @param sm the specified <code>SampleModel</code>,
1378      *           or <code>null</code>
1379      * @return <code>true</code> if the specified <code>SampleModel</code>
1380      * is compatible with this <code>ColorModel</code>; <code>false</code>
1381      * otherwise.
1382      * @see SampleModel
1383      */
1384     public boolean isCompatibleSampleModel(SampleModel sm) {
1385         // fix 4238629
1386         if (! (sm instanceof ComponentSampleModel) &&
1387             ! (sm instanceof MultiPixelPackedSampleModel)   ) {
1388             return false;
1389         }
1390 
1391         // Transfer type must be the same
1392         if (sm.getTransferType() != transferType) {
1393             return false;
1394         }
1395 
1396         if (sm.getNumBands() != 1) {
1397             return false;
1398         }
1399 
1400         return true;
1401     }
1402 
1403     /**
1404      * Returns a new <code>BufferedImage</code> of TYPE_INT_ARGB or
1405      * TYPE_INT_RGB that has a <code>Raster</code> with pixel data
1406      * computed by expanding the indices in the source <code>Raster</code>
1407      * using the color/alpha component arrays of this <code>ColorModel</code>.
1408      * Only the lower <em>n</em> bits of each index value in the source
1409      * <code>Raster</code>, as specified in the
1410      * <a href="#index_values">class description</a> above, are used to
1411      * compute the color/alpha values in the returned image.
1412      * If <code>forceARGB</code> is <code>true</code>, a TYPE_INT_ARGB image is
1413      * returned regardless of whether or not this <code>ColorModel</code>
1414      * has an alpha component array or a transparent pixel.
1415      * @param raster the specified <code>Raster</code>
1416      * @param forceARGB if <code>true</code>, the returned
1417      *     <code>BufferedImage</code> is TYPE_INT_ARGB; otherwise it is
1418      *     TYPE_INT_RGB
1419      * @return a <code>BufferedImage</code> created with the specified
1420      *     <code>Raster</code>
1421      * @throws IllegalArgumentException if the raster argument is not
1422      *           compatible with this IndexColorModel
1423      */
1424     public BufferedImage convertToIntDiscrete(Raster raster,
1425                                               boolean forceARGB) {
1426         ColorModel cm;
1427 
1428         if (!isCompatibleRaster(raster)) {
1429             throw new IllegalArgumentException("This raster is not compatible" +
1430                  "with this IndexColorModel.");
1431         }
1432         if (forceARGB || transparency == TRANSLUCENT) {
1433             cm = ColorModel.getRGBdefault();
1434         }
1435         else if (transparency == BITMASK) {
1436             cm = new DirectColorModel(25, 0xff0000, 0x00ff00, 0x0000ff,
1437                                       0x1000000);
1438         }
1439         else {
1440             cm = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff);
1441         }
1442 
1443         int w = raster.getWidth();
1444         int h = raster.getHeight();
1445         WritableRaster discreteRaster =
1446                   cm.createCompatibleWritableRaster(w, h);
1447         Object obj = null;
1448         int[] data = null;
1449 
1450         int rX = raster.getMinX();
1451         int rY = raster.getMinY();
1452 
1453         for (int y=0; y < h; y++, rY++) {
1454             obj = raster.getDataElements(rX, rY, w, 1, obj);
1455             if (obj instanceof int[]) {
1456                 data = (int[])obj;
1457             } else {
1458                 data = DataBuffer.toIntArray(obj);
1459             }
1460             for (int x=0; x < w; x++) {
1461                 data[x] = rgb[data[x] & pixel_mask];
1462             }
1463             discreteRaster.setDataElements(0, y, w, 1, data);
1464         }
1465 
1466         return new BufferedImage(cm, discreteRaster, false, null);
1467     }
1468 
1469     /**
1470      * Returns whether or not the pixel is valid.
1471      * @param pixel the specified pixel value
1472      * @return <code>true</code> if <code>pixel</code>
1473      * is valid; <code>false</code> otherwise.
1474      * @since 1.3
1475      */
1476     public boolean isValid(int pixel) {
1477         return ((pixel >= 0 && pixel < map_size) &&
1478                 (validBits == null || validBits.testBit(pixel)));
1479     }
1480 
1481     /**
1482      * Returns whether or not all of the pixels are valid.
1483      * @return <code>true</code> if all pixels are valid;
1484      * <code>false</code> otherwise.
1485      * @since 1.3
1486      */
1487     public boolean isValid() {
1488         return (validBits == null);
1489     }
1490 
1491     /**
1492      * Returns a <code>BigInteger</code> that indicates the valid/invalid
1493      * pixels in the colormap.  A bit is valid if the
1494      * <code>BigInteger</code> value at that index is set, and is invalid
1495      * if the <code>BigInteger</code> value at that index is not set.
1496      * The only valid ranges to query in the <code>BigInteger</code> are
1497      * between 0 and the map size.
1498      * @return a <code>BigInteger</code> indicating the valid/invalid pixels.
1499      * @since 1.3
1500      */
1501     public BigInteger getValidPixels() {
1502         if (validBits == null) {
1503             return getAllValid();
1504         }
1505         else {
1506             return validBits;
1507         }
1508     }
1509 
1510     /**
1511      * Disposes of system resources associated with this
1512      * <code>ColorModel</code> once this <code>ColorModel</code> is no
1513      * longer referenced.
1514      */
1515     public void finalize() {
1516     }
1517 
1518     /**
1519      * Returns the <code>String</code> representation of the contents of
1520      * this <code>ColorModel</code>object.
1521      * @return a <code>String</code> representing the contents of this
1522      * <code>ColorModel</code> object.
1523      */
1524     public String toString() {
1525        return new String("IndexColorModel: #pixelBits = "+pixel_bits
1526                          + " numComponents = "+numComponents
1527                          + " color space = "+colorSpace
1528                          + " transparency = "+transparency
1529                          + " transIndex   = "+transparent_index
1530                          + " has alpha = "+supportsAlpha
1531                          + " isAlphaPre = "+isAlphaPremultiplied
1532                          );
1533     }
1534 }