Home » openjdk-7 » java » awt » image » [javadoc | source]

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

Home » openjdk-7 » java » awt » image » [javadoc | source]