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