< prev index next >

src/java.desktop/share/classes/java/awt/image/IndexColorModel.java

Print this page


   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


 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


 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;


 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         }


 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) {


 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;


 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      *


 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) {


 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;


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.


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},


   1 /*
   2  * Copyright (c) 1995, 2018, 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


 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


 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;


 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         }


 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) {


 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;


 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      *


 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) {


 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;


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.


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},


< prev index next >