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