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