src/java.desktop/share/classes/java/awt/image/IndexColorModel.java
changeset 47216 71c04702a3d5
parent 45025 9ad3afa82b5e
child 47971 75686e8da573
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1995, 2017, 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 
       
    33 /**
       
    34  * The {@code IndexColorModel} class is a {@code ColorModel}
       
    35  * class that works with pixel values consisting of a
       
    36  * single sample that is an index into a fixed colormap in the default
       
    37  * sRGB color space.  The colormap specifies red, green, blue, and
       
    38  * optional alpha components corresponding to each index.  All components
       
    39  * are represented in the colormap as 8-bit unsigned integral values.
       
    40  * Some constructors allow the caller to specify "holes" in the colormap
       
    41  * by indicating which colormap entries are valid and which represent
       
    42  * unusable colors via the bits set in a {@code BigInteger} object.
       
    43  * This color model is similar to an X11 PseudoColor visual.
       
    44  * <p>
       
    45  * Some constructors provide a means to specify an alpha component
       
    46  * for each pixel in the colormap, while others either provide no
       
    47  * such means or, in some cases, a flag to indicate whether the
       
    48  * colormap data contains alpha values.  If no alpha is supplied to
       
    49  * the constructor, an opaque alpha component (alpha = 1.0) is
       
    50  * assumed for each entry.
       
    51  * An optional transparent pixel value can be supplied that indicates a
       
    52  * pixel to be made completely transparent, regardless of any alpha
       
    53  * component supplied or assumed for that pixel value.
       
    54  * Note that the color components in the colormap of an
       
    55  * {@code IndexColorModel} objects are never pre-multiplied with
       
    56  * the alpha components.
       
    57  * <p>
       
    58  * <a id="transparency">
       
    59  * The transparency of an {@code IndexColorModel} object is
       
    60  * determined by examining the alpha components of the colors in the
       
    61  * colormap and choosing the most specific value after considering
       
    62  * the optional alpha values and any transparent index specified.
       
    63  * The transparency value is {@code Transparency.OPAQUE}
       
    64  * only if all valid colors in
       
    65  * the colormap are opaque and there is no valid transparent pixel.
       
    66  * If all valid colors
       
    67  * in the colormap are either completely opaque (alpha = 1.0) or
       
    68  * completely transparent (alpha = 0.0), which typically occurs when
       
    69  * a valid transparent pixel is specified,
       
    70  * the value is {@code Transparency.BITMASK}.
       
    71  * Otherwise, the value is {@code Transparency.TRANSLUCENT}, indicating
       
    72  * that some valid color has an alpha component that is
       
    73  * neither completely transparent nor completely opaque
       
    74  * (0.0 &lt; alpha &lt; 1.0).
       
    75  * </a>
       
    76  *
       
    77  * <p>
       
    78  * If an {@code IndexColorModel} object has
       
    79  * a transparency value of {@code Transparency.OPAQUE},
       
    80  * then the {@code hasAlpha}
       
    81  * and {@code getNumComponents} methods
       
    82  * (both inherited from {@code ColorModel})
       
    83  * return false and 3, respectively.
       
    84  * For any other transparency value,
       
    85  * {@code hasAlpha} returns true
       
    86  * and {@code getNumComponents} returns 4.
       
    87  *
       
    88  * <p>
       
    89  * <a id="index_values">
       
    90  * The values used to index into the colormap are taken from the least
       
    91  * significant <em>n</em> bits of pixel representations where
       
    92  * <em>n</em> is based on the pixel size specified in the constructor.
       
    93  * For pixel sizes smaller than 8 bits, <em>n</em> is rounded up to a
       
    94  * power of two (3 becomes 4 and 5,6,7 become 8).
       
    95  * For pixel sizes between 8 and 16 bits, <em>n</em> is equal to the
       
    96  * pixel size.
       
    97  * Pixel sizes larger than 16 bits are not supported by this class.
       
    98  * Higher order bits beyond <em>n</em> are ignored in pixel representations.
       
    99  * Index values greater than or equal to the map size, but less than
       
   100  * 2<sup><em>n</em></sup>, are undefined and return 0 for all color and
       
   101  * alpha components.
       
   102  * </a>
       
   103  * <p>
       
   104  * For those methods that use a primitive array pixel representation of
       
   105  * type {@code transferType}, the array length is always one.
       
   106  * The transfer types supported are {@code DataBuffer.TYPE_BYTE} and
       
   107  * {@code DataBuffer.TYPE_USHORT}.  A single int pixel
       
   108  * representation is valid for all objects of this class, since it is
       
   109  * always possible to represent pixel values used with this class in a
       
   110  * single int.  Therefore, methods that use this representation do
       
   111  * not throw an {@code IllegalArgumentException} due to an invalid
       
   112  * pixel value.
       
   113  * <p>
       
   114  * Many of the methods in this class are final.  The reason for
       
   115  * this is that the underlying native graphics code makes assumptions
       
   116  * about the layout and operation of this class and those assumptions
       
   117  * are reflected in the implementations of the methods here that are
       
   118  * marked final.  You can subclass this class for other reasons, but
       
   119  * you cannot override or modify the behaviour of those methods.
       
   120  *
       
   121  * @see ColorModel
       
   122  * @see ColorSpace
       
   123  * @see DataBuffer
       
   124  *
       
   125  */
       
   126 public class IndexColorModel extends ColorModel {
       
   127     private int rgb[];
       
   128     private int map_size;
       
   129     private int pixel_mask;
       
   130     private int transparent_index = -1;
       
   131     private boolean allgrayopaque;
       
   132     private BigInteger validBits;
       
   133     private volatile int hashCode;
       
   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      * @deprecated The {@code finalize} method has been deprecated.
       
  1519      *     Subclasses that override {@code finalize} in order to perform cleanup
       
  1520      *     should be modified to use alternative cleanup mechanisms and
       
  1521      *     to remove the overriding {@code finalize} method.
       
  1522      *     When overriding the {@code finalize} method, its implementation must explicitly
       
  1523      *     ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
       
  1524      *     See the specification for {@link Object#finalize()} for further
       
  1525      *     information about migration options.
       
  1526      */
       
  1527     @Deprecated(since="9")
       
  1528     public void finalize() {
       
  1529     }
       
  1530 
       
  1531     /**
       
  1532      * Returns the {@code String} representation of the contents of
       
  1533      * this {@code ColorModel} object.
       
  1534      * @return a {@code String} representing the contents of this
       
  1535      * {@code ColorModel} object.
       
  1536      */
       
  1537     public String toString() {
       
  1538        return new String("IndexColorModel: #pixelBits = "+pixel_bits
       
  1539                          + " numComponents = "+numComponents
       
  1540                          + " color space = "+colorSpace
       
  1541                          + " transparency = "+transparency
       
  1542                          + " transIndex   = "+transparent_index
       
  1543                          + " has alpha = "+supportsAlpha
       
  1544                          + " isAlphaPre = "+isAlphaPremultiplied
       
  1545                          );
       
  1546     }
       
  1547 
       
  1548     /**
       
  1549      * Tests if the specified {@code Object} is an
       
  1550      * instance of {@code IndexColorModel}
       
  1551      * and if it equals this {@code IndexColorModel}
       
  1552      * @param obj the {@code Object} to test for equality
       
  1553      * @return {@code true} if the specified {@code Object}
       
  1554      * equals this {@code IndexColorModel}; {@code false} otherwise.
       
  1555      */
       
  1556     @Override
       
  1557     public boolean equals(Object obj) {
       
  1558 
       
  1559         if (!(obj instanceof IndexColorModel)) {
       
  1560             return false;
       
  1561         }
       
  1562 
       
  1563         IndexColorModel cm = (IndexColorModel) obj;
       
  1564         if (supportsAlpha != cm.hasAlpha() ||
       
  1565             isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
       
  1566             pixel_bits != cm.getPixelSize() ||
       
  1567             transparency != cm.getTransparency() ||
       
  1568             numComponents != cm.getNumComponents() ||
       
  1569             (!(colorSpace.equals(cm.colorSpace))) ||
       
  1570             transferType != cm.transferType ||
       
  1571             map_size != cm.map_size ||
       
  1572             transparent_index != cm.transparent_index)
       
  1573         {
       
  1574             return false;
       
  1575         }
       
  1576 
       
  1577         if (!(Arrays.equals(nBits, cm.getComponentSize()))) {
       
  1578             return false;
       
  1579         }
       
  1580 
       
  1581         // verify whether we have to check equality of all bits in validBits
       
  1582         boolean testValidBits;
       
  1583         if (validBits == cm.validBits) {
       
  1584             testValidBits = false;
       
  1585         } else if (validBits == null || cm.validBits == null) {
       
  1586             return false;
       
  1587         } else if (validBits.equals(cm.validBits)) {
       
  1588             testValidBits = false;
       
  1589         } else {
       
  1590             testValidBits = true;
       
  1591         }
       
  1592 
       
  1593         if (testValidBits) {
       
  1594             for (int i = 0; i < map_size; i++) {
       
  1595                 if (rgb[i] != cm.rgb[i] ||
       
  1596                     validBits.testBit(i) != cm.validBits.testBit(i))
       
  1597                 {
       
  1598                     return false;
       
  1599                 }
       
  1600             }
       
  1601         } else {
       
  1602             for (int i = 0; i < map_size; i++) {
       
  1603                 if (rgb[i] != cm.rgb[i]) {
       
  1604                     return false;
       
  1605                 }
       
  1606             }
       
  1607         }
       
  1608         return true;
       
  1609     }
       
  1610 
       
  1611     /**
       
  1612      * Returns the hash code for IndexColorModel.
       
  1613      *
       
  1614      * @return    a hash code for IndexColorModel
       
  1615      */
       
  1616     @Override
       
  1617     public int hashCode() {
       
  1618         int result = hashCode;
       
  1619         if (result == 0) {
       
  1620             /*
       
  1621              * We are intentionally not calculating hashCode for validBits,
       
  1622              * because it is only used for 8-bit indexed screens and they
       
  1623              * are very rare. It is very unlikely for 2 IndexColorModels
       
  1624              * to have different valiBits and have same value for all
       
  1625              * other properties.
       
  1626              */
       
  1627             result = 7;
       
  1628             result = 89 * result + this.pixel_bits;
       
  1629             result = 89 * result + Arrays.hashCode(this.nBits);
       
  1630             result = 89 * result + this.transparency;
       
  1631             result = 89 * result + (this.supportsAlpha ? 1 : 0);
       
  1632             result = 89 * result + (this.isAlphaPremultiplied ? 1 : 0);
       
  1633             result = 89 * result + this.numComponents;
       
  1634             result = 89 * result + this.colorSpace.hashCode();
       
  1635             result = 89 * result + this.transferType;
       
  1636             result = 89 * result + Arrays.hashCode(this.rgb);
       
  1637             result = 89 * result + this.map_size;
       
  1638             result = 89 * result + this.transparent_index;
       
  1639             hashCode = result;
       
  1640         }
       
  1641         return result;
       
  1642     }
       
  1643 }