0001 /*
0002 * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.awt.image;
0027
0028 import java.awt.Transparency;
0029 import java.awt.color.ColorSpace;
0030 import java.math.BigInteger;
0031
0032 /**
0033 * The <code>IndexColorModel</code> class is a <code>ColorModel</code>
0034 * class that works with pixel values consisting of a
0035 * single sample that is an index into a fixed colormap in the default
0036 * sRGB color space. The colormap specifies red, green, blue, and
0037 * optional alpha components corresponding to each index. All components
0038 * are represented in the colormap as 8-bit unsigned integral values.
0039 * Some constructors allow the caller to specify "holes" in the colormap
0040 * by indicating which colormap entries are valid and which represent
0041 * unusable colors via the bits set in a <code>BigInteger</code> object.
0042 * This color model is similar to an X11 PseudoColor visual.
0043 * <p>
0044 * Some constructors provide a means to specify an alpha component
0045 * for each pixel in the colormap, while others either provide no
0046 * such means or, in some cases, a flag to indicate whether the
0047 * colormap data contains alpha values. If no alpha is supplied to
0048 * the constructor, an opaque alpha component (alpha = 1.0) is
0049 * assumed for each entry.
0050 * An optional transparent pixel value can be supplied that indicates a
0051 * pixel to be made completely transparent, regardless of any alpha
0052 * component supplied or assumed for that pixel value.
0053 * Note that the color components in the colormap of an
0054 * <code>IndexColorModel</code> objects are never pre-multiplied with
0055 * the alpha components.
0056 * <p>
0057 * <a name="transparency">
0058 * The transparency of an <code>IndexColorModel</code> object is
0059 * determined by examining the alpha components of the colors in the
0060 * colormap and choosing the most specific value after considering
0061 * the optional alpha values and any transparent index specified.
0062 * The transparency value is <code>Transparency.OPAQUE</code>
0063 * only if all valid colors in
0064 * the colormap are opaque and there is no valid transparent pixel.
0065 * If all valid colors
0066 * in the colormap are either completely opaque (alpha = 1.0) or
0067 * completely transparent (alpha = 0.0), which typically occurs when
0068 * a valid transparent pixel is specified,
0069 * the value is <code>Transparency.BITMASK</code>.
0070 * Otherwise, the value is <code>Transparency.TRANSLUCENT</code>, indicating
0071 * that some valid color has an alpha component that is
0072 * neither completely transparent nor completely opaque
0073 * (0.0 < alpha < 1.0).
0074 * </a>
0075 *
0076 * <p>
0077 * If an <code>IndexColorModel</code> object has
0078 * a transparency value of <code>Transparency.OPAQUE</code>,
0079 * then the <code>hasAlpha</code>
0080 * and <code>getNumComponents</code> methods
0081 * (both inherited from <code>ColorModel</code>)
0082 * return false and 3, respectively.
0083 * For any other transparency value,
0084 * <code>hasAlpha</code> returns true
0085 * and <code>getNumComponents</code> returns 4.
0086 *
0087 * <p>
0088 * <a name="index_values">
0089 * The values used to index into the colormap are taken from the least
0090 * significant <em>n</em> bits of pixel representations where
0091 * <em>n</em> is based on the pixel size specified in the constructor.
0092 * For pixel sizes smaller than 8 bits, <em>n</em> is rounded up to a
0093 * power of two (3 becomes 4 and 5,6,7 become 8).
0094 * For pixel sizes between 8 and 16 bits, <em>n</em> is equal to the
0095 * pixel size.
0096 * Pixel sizes larger than 16 bits are not supported by this class.
0097 * Higher order bits beyond <em>n</em> are ignored in pixel representations.
0098 * Index values greater than or equal to the map size, but less than
0099 * 2<sup><em>n</em></sup>, are undefined and return 0 for all color and
0100 * alpha components.
0101 * <p>
0102 * For those methods that use a primitive array pixel representation of
0103 * type <code>transferType</code>, the array length is always one.
0104 * The transfer types supported are <code>DataBuffer.TYPE_BYTE</code> and
0105 * <code>DataBuffer.TYPE_USHORT</code>. A single int pixel
0106 * representation is valid for all objects of this class, since it is
0107 * always possible to represent pixel values used with this class in a
0108 * single int. Therefore, methods that use this representation do
0109 * not throw an <code>IllegalArgumentException</code> due to an invalid
0110 * pixel value.
0111 * <p>
0112 * Many of the methods in this class are final. The reason for
0113 * this is that the underlying native graphics code makes assumptions
0114 * about the layout and operation of this class and those assumptions
0115 * are reflected in the implementations of the methods here that are
0116 * marked final. You can subclass this class for other reasons, but
0117 * you cannot override or modify the behaviour of those methods.
0118 *
0119 * @see ColorModel
0120 * @see ColorSpace
0121 * @see DataBuffer
0122 *
0123 * @version 10 Feb 1997
0124 */
0125 public class IndexColorModel extends ColorModel {
0126 private int rgb[];
0127 private int map_size;
0128 private int pixel_mask;
0129 private int transparent_index = -1;
0130 private boolean allgrayopaque;
0131 private BigInteger validBits;
0132
0133 private static int[] opaqueBits = { 8, 8, 8 };
0134 private static int[] alphaBits = { 8, 8, 8, 8 };
0135
0136 static private native void initIDs();
0137
0138 static {
0139 ColorModel.loadLibraries();
0140 initIDs();
0141 }
0142
0143 /**
0144 * Constructs an <code>IndexColorModel</code> from the specified
0145 * arrays of red, green, and blue components. Pixels described
0146 * by this color model all have alpha components of 255
0147 * unnormalized (1.0 normalized), which means they
0148 * are fully opaque. All of the arrays specifying the color
0149 * components must have at least the specified number of entries.
0150 * The <code>ColorSpace</code> is the default sRGB space.
0151 * Since there is no alpha information in any of the arguments
0152 * to this constructor, the transparency value is always
0153 * <code>Transparency.OPAQUE</code>.
0154 * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
0155 * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel.
0156 * @param bits the number of bits each pixel occupies
0157 * @param size the size of the color component arrays
0158 * @param r the array of red color components
0159 * @param g the array of green color components
0160 * @param b the array of blue color components
0161 * @throws IllegalArgumentException if <code>bits</code> is less
0162 * than 1 or greater than 16
0163 * @throws IllegalArgumentException if <code>size</code> is less
0164 * than 1
0165 */
0166 public IndexColorModel(int bits, int size, byte r[], byte g[],
0167 byte b[]) {
0168 super (bits, opaqueBits, ColorSpace
0169 .getInstance(ColorSpace.CS_sRGB), false, false, OPAQUE,
0170 ColorModel.getDefaultTransferType(bits));
0171 if (bits < 1 || bits > 16) {
0172 throw new IllegalArgumentException(
0173 "Number of bits must be between" + " 1 and 16.");
0174 }
0175 setRGBs(size, r, g, b, null);
0176 calculatePixelMask();
0177 }
0178
0179 /**
0180 * Constructs an <code>IndexColorModel</code> from the given arrays
0181 * of red, green, and blue components. Pixels described by this color
0182 * model all have alpha components of 255 unnormalized
0183 * (1.0 normalized), which means they are fully opaque, except
0184 * for the indicated pixel to be made transparent. All of the arrays
0185 * specifying the color components must have at least the specified
0186 * number of entries.
0187 * The <code>ColorSpace</code> is the default sRGB space.
0188 * The transparency value may be <code>Transparency.OPAQUE</code> or
0189 * <code>Transparency.BITMASK</code> depending on the arguments, as
0190 * specified in the <a href="#transparency">class description</a> above.
0191 * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
0192 * or <code>DataBuffer.TYPE_USHORT</code> that can hold a
0193 * single pixel.
0194 * @param bits the number of bits each pixel occupies
0195 * @param size the size of the color component arrays
0196 * @param r the array of red color components
0197 * @param g the array of green color components
0198 * @param b the array of blue color components
0199 * @param trans the index of the transparent pixel
0200 * @throws IllegalArgumentException if <code>bits</code> is less than
0201 * 1 or greater than 16
0202 * @throws IllegalArgumentException if <code>size</code> is less than
0203 * 1
0204 */
0205 public IndexColorModel(int bits, int size, byte r[], byte g[],
0206 byte b[], int trans) {
0207 super (bits, opaqueBits, ColorSpace
0208 .getInstance(ColorSpace.CS_sRGB), false, false, OPAQUE,
0209 ColorModel.getDefaultTransferType(bits));
0210 if (bits < 1 || bits > 16) {
0211 throw new IllegalArgumentException(
0212 "Number of bits must be between" + " 1 and 16.");
0213 }
0214 setRGBs(size, r, g, b, null);
0215 setTransparentPixel(trans);
0216 calculatePixelMask();
0217 }
0218
0219 /**
0220 * Constructs an <code>IndexColorModel</code> from the given
0221 * arrays of red, green, blue and alpha components. All of the
0222 * arrays specifying the components must have at least the specified
0223 * number of entries.
0224 * The <code>ColorSpace</code> is the default sRGB space.
0225 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
0226 * <code>Transparency.BITMASK</code>,
0227 * or <code>Transparency.TRANSLUCENT</code>
0228 * depending on the arguments, as specified
0229 * in the <a href="#transparency">class description</a> above.
0230 * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
0231 * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel.
0232 * @param bits the number of bits each pixel occupies
0233 * @param size the size of the color component arrays
0234 * @param r the array of red color components
0235 * @param g the array of green color components
0236 * @param b the array of blue color components
0237 * @param a the array of alpha value components
0238 * @throws IllegalArgumentException if <code>bits</code> is less
0239 * than 1 or greater than 16
0240 * @throws IllegalArgumentException if <code>size</code> is less
0241 * than 1
0242 */
0243 public IndexColorModel(int bits, int size, byte r[], byte g[],
0244 byte b[], byte a[]) {
0245 super (bits, alphaBits, ColorSpace
0246 .getInstance(ColorSpace.CS_sRGB), true, false,
0247 TRANSLUCENT, ColorModel.getDefaultTransferType(bits));
0248 if (bits < 1 || bits > 16) {
0249 throw new IllegalArgumentException(
0250 "Number of bits must be between" + " 1 and 16.");
0251 }
0252 setRGBs(size, r, g, b, a);
0253 calculatePixelMask();
0254 }
0255
0256 /**
0257 * Constructs an <code>IndexColorModel</code> from a single
0258 * array of interleaved red, green, blue and optional alpha
0259 * components. The array must have enough values in it to
0260 * fill all of the needed component arrays of the specified
0261 * size. The <code>ColorSpace</code> is the default sRGB space.
0262 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
0263 * <code>Transparency.BITMASK</code>,
0264 * or <code>Transparency.TRANSLUCENT</code>
0265 * depending on the arguments, as specified
0266 * in the <a href="#transparency">class description</a> above.
0267 * The transfer type is the smallest of
0268 * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code>
0269 * that can hold a single pixel.
0270 *
0271 * @param bits the number of bits each pixel occupies
0272 * @param size the size of the color component arrays
0273 * @param cmap the array of color components
0274 * @param start the starting offset of the first color component
0275 * @param hasalpha indicates whether alpha values are contained in
0276 * the <code>cmap</code> array
0277 * @throws IllegalArgumentException if <code>bits</code> is less
0278 * than 1 or greater than 16
0279 * @throws IllegalArgumentException if <code>size</code> is less
0280 * than 1
0281 */
0282 public IndexColorModel(int bits, int size, byte cmap[], int start,
0283 boolean hasalpha) {
0284 this (bits, size, cmap, start, hasalpha, -1);
0285 if (bits < 1 || bits > 16) {
0286 throw new IllegalArgumentException(
0287 "Number of bits must be between" + " 1 and 16.");
0288 }
0289 }
0290
0291 /**
0292 * Constructs an <code>IndexColorModel</code> from a single array of
0293 * interleaved red, green, blue and optional alpha components. The
0294 * specified transparent index represents a pixel that is made
0295 * entirely transparent regardless of any alpha value specified
0296 * for it. The array must have enough values in it to fill all
0297 * of the needed component arrays of the specified size.
0298 * The <code>ColorSpace</code> is the default sRGB space.
0299 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
0300 * <code>Transparency.BITMASK</code>,
0301 * or <code>Transparency.TRANSLUCENT</code>
0302 * depending on the arguments, as specified
0303 * in the <a href="#transparency">class description</a> above.
0304 * The transfer type is the smallest of
0305 * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code>
0306 * that can hold a single pixel.
0307 * @param bits the number of bits each pixel occupies
0308 * @param size the size of the color component arrays
0309 * @param cmap the array of color components
0310 * @param start the starting offset of the first color component
0311 * @param hasalpha indicates whether alpha values are contained in
0312 * the <code>cmap</code> array
0313 * @param trans the index of the fully transparent pixel
0314 * @throws IllegalArgumentException if <code>bits</code> is less than
0315 * 1 or greater than 16
0316 * @throws IllegalArgumentException if <code>size</code> is less than
0317 * 1
0318 */
0319 public IndexColorModel(int bits, int size, byte cmap[], int start,
0320 boolean hasalpha, int trans) {
0321 // REMIND: This assumes the ordering: RGB[A]
0322 super (bits, opaqueBits, ColorSpace
0323 .getInstance(ColorSpace.CS_sRGB), false, false, OPAQUE,
0324 ColorModel.getDefaultTransferType(bits));
0325
0326 if (bits < 1 || bits > 16) {
0327 throw new IllegalArgumentException(
0328 "Number of bits must be between" + " 1 and 16.");
0329 }
0330 if (size < 1) {
0331 throw new IllegalArgumentException("Map size (" + size
0332 + ") must be >= 1");
0333 }
0334 map_size = size;
0335 rgb = new int[calcRealMapSize(bits, size)];
0336 int j = start;
0337 int alpha = 0xff;
0338 boolean allgray = true;
0339 int transparency = OPAQUE;
0340 for (int i = 0; i < size; i++) {
0341 int r = cmap[j++] & 0xff;
0342 int g = cmap[j++] & 0xff;
0343 int b = cmap[j++] & 0xff;
0344 allgray = allgray && (r == g) && (g == b);
0345 if (hasalpha) {
0346 alpha = cmap[j++] & 0xff;
0347 if (alpha != 0xff) {
0348 if (alpha == 0x00) {
0349 if (transparency == OPAQUE) {
0350 transparency = BITMASK;
0351 }
0352 if (transparent_index < 0) {
0353 transparent_index = i;
0354 }
0355 } else {
0356 transparency = TRANSLUCENT;
0357 }
0358 allgray = false;
0359 }
0360 }
0361 rgb[i] = (alpha << 24) | (r << 16) | (g << 8) | b;
0362 }
0363 this .allgrayopaque = allgray;
0364 setTransparency(transparency);
0365 setTransparentPixel(trans);
0366 calculatePixelMask();
0367 }
0368
0369 /**
0370 * Constructs an <code>IndexColorModel</code> from an array of
0371 * ints where each int is comprised of red, green, blue, and
0372 * optional alpha components in the default RGB color model format.
0373 * The specified transparent index represents a pixel that is made
0374 * entirely transparent regardless of any alpha value specified
0375 * for it. The array must have enough values in it to fill all
0376 * of the needed component arrays of the specified size.
0377 * The <code>ColorSpace</code> is the default sRGB space.
0378 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
0379 * <code>Transparency.BITMASK</code>,
0380 * or <code>Transparency.TRANSLUCENT</code>
0381 * depending on the arguments, as specified
0382 * in the <a href="#transparency">class description</a> above.
0383 * @param bits the number of bits each pixel occupies
0384 * @param size the size of the color component arrays
0385 * @param cmap the array of color components
0386 * @param start the starting offset of the first color component
0387 * @param hasalpha indicates whether alpha values are contained in
0388 * the <code>cmap</code> array
0389 * @param trans the index of the fully transparent pixel
0390 * @param transferType the data type of the array used to represent
0391 * pixel values. The data type must be either
0392 * <code>DataBuffer.TYPE_BYTE</code> or
0393 * <code>DataBuffer.TYPE_USHORT</code>.
0394 * @throws IllegalArgumentException if <code>bits</code> is less
0395 * than 1 or greater than 16
0396 * @throws IllegalArgumentException if <code>size</code> is less
0397 * than 1
0398 * @throws IllegalArgumentException if <code>transferType</code> is not
0399 * one of <code>DataBuffer.TYPE_BYTE</code> or
0400 * <code>DataBuffer.TYPE_USHORT</code>
0401 */
0402 public IndexColorModel(int bits, int size, int cmap[], int start,
0403 boolean hasalpha, int trans, int transferType) {
0404 // REMIND: This assumes the ordering: RGB[A]
0405 super (bits, opaqueBits, ColorSpace
0406 .getInstance(ColorSpace.CS_sRGB), false, false, OPAQUE,
0407 transferType);
0408
0409 if (bits < 1 || bits > 16) {
0410 throw new IllegalArgumentException(
0411 "Number of bits must be between" + " 1 and 16.");
0412 }
0413 if (size < 1) {
0414 throw new IllegalArgumentException("Map size (" + size
0415 + ") must be >= 1");
0416 }
0417 if ((transferType != DataBuffer.TYPE_BYTE)
0418 && (transferType != DataBuffer.TYPE_USHORT)) {
0419 throw new IllegalArgumentException(
0420 "transferType must be either"
0421 + "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT");
0422 }
0423
0424 setRGBs(size, cmap, start, hasalpha);
0425 setTransparentPixel(trans);
0426 calculatePixelMask();
0427 }
0428
0429 /**
0430 * Constructs an <code>IndexColorModel</code> from an
0431 * <code>int</code> array where each <code>int</code> is
0432 * comprised of red, green, blue, and alpha
0433 * components in the default RGB color model format.
0434 * The array must have enough values in it to fill all
0435 * of the needed component arrays of the specified size.
0436 * The <code>ColorSpace</code> is the default sRGB space.
0437 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
0438 * <code>Transparency.BITMASK</code>,
0439 * or <code>Transparency.TRANSLUCENT</code>
0440 * depending on the arguments, as specified
0441 * in the <a href="#transparency">class description</a> above.
0442 * The transfer type must be one of <code>DataBuffer.TYPE_BYTE</code>
0443 * <code>DataBuffer.TYPE_USHORT</code>.
0444 * The <code>BigInteger</code> object specifies the valid/invalid pixels
0445 * in the <code>cmap</code> array. A pixel is valid if the
0446 * <code>BigInteger</code> value at that index is set, and is invalid
0447 * if the <code>BigInteger</code> bit at that index is not set.
0448 * @param bits the number of bits each pixel occupies
0449 * @param size the size of the color component array
0450 * @param cmap the array of color components
0451 * @param start the starting offset of the first color component
0452 * @param transferType the specified data type
0453 * @param validBits a <code>BigInteger</code> object. If a bit is
0454 * set in the BigInteger, the pixel at that index is valid.
0455 * If a bit is not set, the pixel at that index
0456 * is considered invalid. If null, all pixels are valid.
0457 * Only bits from 0 to the map size are considered.
0458 * @throws IllegalArgumentException if <code>bits</code> is less
0459 * than 1 or greater than 16
0460 * @throws IllegalArgumentException if <code>size</code> is less
0461 * than 1
0462 * @throws IllegalArgumentException if <code>transferType</code> is not
0463 * one of <code>DataBuffer.TYPE_BYTE</code> or
0464 * <code>DataBuffer.TYPE_USHORT</code>
0465 *
0466 * @since 1.3
0467 */
0468 public IndexColorModel(int bits, int size, int cmap[], int start,
0469 int transferType, BigInteger validBits) {
0470 super (bits, alphaBits, ColorSpace
0471 .getInstance(ColorSpace.CS_sRGB), true, false,
0472 TRANSLUCENT, transferType);
0473
0474 if (bits < 1 || bits > 16) {
0475 throw new IllegalArgumentException(
0476 "Number of bits must be between" + " 1 and 16.");
0477 }
0478 if (size < 1) {
0479 throw new IllegalArgumentException("Map size (" + size
0480 + ") must be >= 1");
0481 }
0482 if ((transferType != DataBuffer.TYPE_BYTE)
0483 && (transferType != DataBuffer.TYPE_USHORT)) {
0484 throw new IllegalArgumentException(
0485 "transferType must be either"
0486 + "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT");
0487 }
0488
0489 if (validBits != null) {
0490 // Check to see if it is all valid
0491 for (int i = 0; i < size; i++) {
0492 if (!validBits.testBit(i)) {
0493 this .validBits = validBits;
0494 break;
0495 }
0496 }
0497 }
0498
0499 setRGBs(size, cmap, start, true);
0500 calculatePixelMask();
0501 }
0502
0503 private void setRGBs(int size, byte r[], byte g[], byte b[],
0504 byte a[]) {
0505 if (size < 1) {
0506 throw new IllegalArgumentException("Map size (" + size
0507 + ") must be >= 1");
0508 }
0509 map_size = size;
0510 rgb = new int[calcRealMapSize(pixel_bits, size)];
0511 int alpha = 0xff;
0512 int transparency = OPAQUE;
0513 boolean allgray = true;
0514 for (int i = 0; i < size; i++) {
0515 int rc = r[i] & 0xff;
0516 int gc = g[i] & 0xff;
0517 int bc = b[i] & 0xff;
0518 allgray = allgray && (rc == gc) && (gc == bc);
0519 if (a != null) {
0520 alpha = a[i] & 0xff;
0521 if (alpha != 0xff) {
0522 if (alpha == 0x00) {
0523 if (transparency == OPAQUE) {
0524 transparency = BITMASK;
0525 }
0526 if (transparent_index < 0) {
0527 transparent_index = i;
0528 }
0529 } else {
0530 transparency = TRANSLUCENT;
0531 }
0532 allgray = false;
0533 }
0534 }
0535 rgb[i] = (alpha << 24) | (rc << 16) | (gc << 8) | bc;
0536 }
0537 this .allgrayopaque = allgray;
0538 setTransparency(transparency);
0539 }
0540
0541 private void setRGBs(int size, int cmap[], int start,
0542 boolean hasalpha) {
0543 map_size = size;
0544 rgb = new int[calcRealMapSize(pixel_bits, size)];
0545 int j = start;
0546 int transparency = OPAQUE;
0547 boolean allgray = true;
0548 BigInteger validBits = this .validBits;
0549 for (int i = 0; i < size; i++, j++) {
0550 if (validBits != null && !validBits.testBit(i)) {
0551 continue;
0552 }
0553 int cmaprgb = cmap[j];
0554 int r = (cmaprgb >> 16) & 0xff;
0555 int g = (cmaprgb >> 8) & 0xff;
0556 int b = (cmaprgb) & 0xff;
0557 allgray = allgray && (r == g) && (g == b);
0558 if (hasalpha) {
0559 int alpha = cmaprgb >>> 24;
0560 if (alpha != 0xff) {
0561 if (alpha == 0x00) {
0562 if (transparency == OPAQUE) {
0563 transparency = BITMASK;
0564 }
0565 if (transparent_index < 0) {
0566 transparent_index = i;
0567 }
0568 } else {
0569 transparency = TRANSLUCENT;
0570 }
0571 allgray = false;
0572 }
0573 } else {
0574 cmaprgb |= 0xff000000;
0575 }
0576 rgb[i] = cmaprgb;
0577 }
0578 this .allgrayopaque = allgray;
0579 setTransparency(transparency);
0580 }
0581
0582 private int calcRealMapSize(int bits, int size) {
0583 int newSize = Math.max(1 << bits, size);
0584 return Math.max(newSize, 256);
0585 }
0586
0587 private BigInteger getAllValid() {
0588 int numbytes = (map_size + 7) / 8;
0589 byte[] valid = new byte[numbytes];
0590 java.util.Arrays.fill(valid, (byte) 0xff);
0591 valid[0] = (byte) (0xff >>> (numbytes * 8 - map_size));
0592
0593 return new BigInteger(1, valid);
0594 }
0595
0596 /**
0597 * Returns the transparency. Returns either OPAQUE, BITMASK,
0598 * or TRANSLUCENT
0599 * @return the transparency of this <code>IndexColorModel</code>
0600 * @see Transparency#OPAQUE
0601 * @see Transparency#BITMASK
0602 * @see Transparency#TRANSLUCENT
0603 */
0604 public int getTransparency() {
0605 return transparency;
0606 }
0607
0608 /**
0609 * Returns an array of the number of bits for each color/alpha component.
0610 * The array contains the color components in the order red, green,
0611 * blue, followed by the alpha component, if present.
0612 * @return an array containing the number of bits of each color
0613 * and alpha component of this <code>IndexColorModel</code>
0614 */
0615 public int[] getComponentSize() {
0616 if (nBits == null) {
0617 if (supportsAlpha) {
0618 nBits = new int[4];
0619 nBits[3] = 8;
0620 } else {
0621 nBits = new int[3];
0622 }
0623 nBits[0] = nBits[1] = nBits[2] = 8;
0624 }
0625 return nBits;
0626 }
0627
0628 /**
0629 * Returns the size of the color/alpha component arrays in this
0630 * <code>IndexColorModel</code>.
0631 * @return the size of the color and alpha component arrays.
0632 */
0633 final public int getMapSize() {
0634 return map_size;
0635 }
0636
0637 /**
0638 * Returns the index of a transparent pixel in this
0639 * <code>IndexColorModel</code> or -1 if there is no pixel
0640 * with an alpha value of 0. If a transparent pixel was
0641 * explicitly specified in one of the constructors by its
0642 * index, then that index will be preferred, otherwise,
0643 * the index of any pixel which happens to be fully transparent
0644 * may be returned.
0645 * @return the index of a transparent pixel in this
0646 * <code>IndexColorModel</code> object, or -1 if there
0647 * is no such pixel
0648 */
0649 final public int getTransparentPixel() {
0650 return transparent_index;
0651 }
0652
0653 /**
0654 * Copies the array of red color components into the specified array.
0655 * Only the initial entries of the array as specified by
0656 * {@link #getMapSize() getMapSize} are written.
0657 * @param r the specified array into which the elements of the
0658 * array of red color components are copied
0659 */
0660 final public void getReds(byte r[]) {
0661 for (int i = 0; i < map_size; i++) {
0662 r[i] = (byte) (rgb[i] >> 16);
0663 }
0664 }
0665
0666 /**
0667 * Copies the array of green color components into the specified array.
0668 * Only the initial entries of the array as specified by
0669 * <code>getMapSize</code> are written.
0670 * @param g the specified array into which the elements of the
0671 * array of green color components are copied
0672 */
0673 final public void getGreens(byte g[]) {
0674 for (int i = 0; i < map_size; i++) {
0675 g[i] = (byte) (rgb[i] >> 8);
0676 }
0677 }
0678
0679 /**
0680 * Copies the array of blue color components into the specified array.
0681 * Only the initial entries of the array as specified by
0682 * <code>getMapSize</code> are written.
0683 * @param b the specified array into which the elements of the
0684 * array of blue color components are copied
0685 */
0686 final public void getBlues(byte b[]) {
0687 for (int i = 0; i < map_size; i++) {
0688 b[i] = (byte) rgb[i];
0689 }
0690 }
0691
0692 /**
0693 * Copies the array of alpha transparency components into the
0694 * specified array. Only the initial entries of the array as specified
0695 * by <code>getMapSize</code> are written.
0696 * @param a the specified array into which the elements of the
0697 * array of alpha components are copied
0698 */
0699 final public void getAlphas(byte a[]) {
0700 for (int i = 0; i < map_size; i++) {
0701 a[i] = (byte) (rgb[i] >> 24);
0702 }
0703 }
0704
0705 /**
0706 * Converts data for each index from the color and alpha component
0707 * arrays to an int in the default RGB ColorModel format and copies
0708 * the resulting 32-bit ARGB values into the specified array. Only
0709 * the initial entries of the array as specified by
0710 * <code>getMapSize</code> are
0711 * written.
0712 * @param rgb the specified array into which the converted ARGB
0713 * values from this array of color and alpha components
0714 * are copied.
0715 */
0716 final public void getRGBs(int rgb[]) {
0717 System.arraycopy(this .rgb, 0, rgb, 0, map_size);
0718 }
0719
0720 private void setTransparentPixel(int trans) {
0721 if (trans >= 0 && trans < map_size) {
0722 rgb[trans] &= 0x00ffffff;
0723 transparent_index = trans;
0724 allgrayopaque = false;
0725 if (this .transparency == OPAQUE) {
0726 setTransparency(BITMASK);
0727 }
0728 }
0729 }
0730
0731 private void setTransparency(int transparency) {
0732 if (this .transparency != transparency) {
0733 this .transparency = transparency;
0734 if (transparency == OPAQUE) {
0735 supportsAlpha = false;
0736 numComponents = 3;
0737 nBits = opaqueBits;
0738 } else {
0739 supportsAlpha = true;
0740 numComponents = 4;
0741 nBits = alphaBits;
0742 }
0743 }
0744 }
0745
0746 /**
0747 * This method is called from the constructors to set the pixel_mask
0748 * value, which is based on the value of pixel_bits. The pixel_mask
0749 * value is used to mask off the pixel parameters for methods such
0750 * as getRed(), getGreen(), getBlue(), getAlpha(), and getRGB().
0751 */
0752 private final void calculatePixelMask() {
0753 // Note that we adjust the mask so that our masking behavior here
0754 // is consistent with that of our native rendering loops.
0755 int maskbits = pixel_bits;
0756 if (maskbits == 3) {
0757 maskbits = 4;
0758 } else if (maskbits > 4 && maskbits < 8) {
0759 maskbits = 8;
0760 }
0761 pixel_mask = (1 << maskbits) - 1;
0762 }
0763
0764 /**
0765 * Returns the red color component for the specified pixel, scaled
0766 * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
0767 * is specified as an int.
0768 * Only the lower <em>n</em> bits of the pixel value, as specified in the
0769 * <a href="#index_values">class description</a> above, are used to
0770 * calculate the returned value.
0771 * The returned value is a non pre-multiplied value.
0772 * @param pixel the specified pixel
0773 * @return the value of the red color component for the specified pixel
0774 */
0775 final public int getRed(int pixel) {
0776 return (rgb[pixel & pixel_mask] >> 16) & 0xff;
0777 }
0778
0779 /**
0780 * Returns the green color component for the specified pixel, scaled
0781 * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
0782 * is specified as an int.
0783 * Only the lower <em>n</em> bits of the pixel value, as specified in the
0784 * <a href="#index_values">class description</a> above, are used to
0785 * calculate the returned value.
0786 * The returned value is a non pre-multiplied value.
0787 * @param pixel the specified pixel
0788 * @return the value of the green color component for the specified pixel
0789 */
0790 final public int getGreen(int pixel) {
0791 return (rgb[pixel & pixel_mask] >> 8) & 0xff;
0792 }
0793
0794 /**
0795 * Returns the blue color component for the specified pixel, scaled
0796 * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
0797 * is specified as an int.
0798 * Only the lower <em>n</em> bits of the pixel value, as specified in the
0799 * <a href="#index_values">class description</a> above, are used to
0800 * calculate the returned value.
0801 * The returned value is a non pre-multiplied value.
0802 * @param pixel the specified pixel
0803 * @return the value of the blue color component for the specified pixel
0804 */
0805 final public int getBlue(int pixel) {
0806 return rgb[pixel & pixel_mask] & 0xff;
0807 }
0808
0809 /**
0810 * Returns the alpha component for the specified pixel, scaled
0811 * from 0 to 255. The pixel value is specified as an int.
0812 * Only the lower <em>n</em> bits of the pixel value, as specified in the
0813 * <a href="#index_values">class description</a> above, are used to
0814 * calculate the returned value.
0815 * @param pixel the specified pixel
0816 * @return the value of the alpha component for the specified pixel
0817 */
0818 final public int getAlpha(int pixel) {
0819 return (rgb[pixel & pixel_mask] >> 24) & 0xff;
0820 }
0821
0822 /**
0823 * Returns the color/alpha components of the pixel in the default
0824 * RGB color model format. The pixel value is specified as an int.
0825 * Only the lower <em>n</em> bits of the pixel value, as specified in the
0826 * <a href="#index_values">class description</a> above, are used to
0827 * calculate the returned value.
0828 * The returned value is in a non pre-multiplied format.
0829 * @param pixel the specified pixel
0830 * @return the color and alpha components of the specified pixel
0831 * @see ColorModel#getRGBdefault
0832 */
0833 final public int getRGB(int pixel) {
0834 return rgb[pixel & pixel_mask];
0835 }
0836
0837 private static final int CACHESIZE = 40;
0838 private int lookupcache[] = new int[CACHESIZE];
0839
0840 /**
0841 * Returns a data element array representation of a pixel in this
0842 * ColorModel, given an integer pixel representation in the
0843 * default RGB color model. This array can then be passed to the
0844 * {@link WritableRaster#setDataElements(int, int, java.lang.Object) setDataElements}
0845 * method of a {@link WritableRaster} object. If the pixel variable is
0846 * <code>null</code>, a new array is allocated. If <code>pixel</code>
0847 * is not <code>null</code>, it must be
0848 * a primitive array of type <code>transferType</code>; otherwise, a
0849 * <code>ClassCastException</code> is thrown. An
0850 * <code>ArrayIndexOutOfBoundsException</code> is
0851 * thrown if <code>pixel</code> is not large enough to hold a pixel
0852 * value for this <code>ColorModel</code>. The pixel array is returned.
0853 * <p>
0854 * Since <code>IndexColorModel</code> can be subclassed, subclasses
0855 * inherit the implementation of this method and if they don't
0856 * override it then they throw an exception if they use an
0857 * unsupported <code>transferType</code>.
0858 *
0859 * @param rgb the integer pixel representation in the default RGB
0860 * color model
0861 * @param pixel the specified pixel
0862 * @return an array representation of the specified pixel in this
0863 * <code>IndexColorModel</code>.
0864 * @throws ClassCastException if <code>pixel</code>
0865 * is not a primitive array of type <code>transferType</code>
0866 * @throws ArrayIndexOutOfBoundsException if
0867 * <code>pixel</code> is not large enough to hold a pixel value
0868 * for this <code>ColorModel</code>
0869 * @throws UnsupportedOperationException if <code>transferType</code>
0870 * is invalid
0871 * @see WritableRaster#setDataElements
0872 * @see SampleModel#setDataElements
0873 */
0874 public synchronized Object getDataElements(int rgb, Object pixel) {
0875 int red = (rgb >> 16) & 0xff;
0876 int green = (rgb >> 8) & 0xff;
0877 int blue = rgb & 0xff;
0878 int alpha = (rgb >>> 24);
0879 int pix = 0;
0880
0881 // Note that pixels are stored at lookupcache[2*i]
0882 // and the rgb that was searched is stored at
0883 // lookupcache[2*i+1]. Also, the pixel is first
0884 // inverted using the unary complement operator
0885 // before storing in the cache so it can never be 0.
0886 for (int i = CACHESIZE - 2; i >= 0; i -= 2) {
0887 if ((pix = lookupcache[i]) == 0) {
0888 break;
0889 }
0890 if (rgb == lookupcache[i + 1]) {
0891 return installpixel(pixel, ~pix);
0892 }
0893 }
0894
0895 if (allgrayopaque) {
0896 // IndexColorModel objects are all tagged as
0897 // non-premultiplied so ignore the alpha value
0898 // of the incoming color, convert the
0899 // non-premultiplied color components to a
0900 // grayscale value and search for the closest
0901 // gray value in the palette. Since all colors
0902 // in the palette are gray, we only need compare
0903 // to one of the color components for a match
0904 // using a simple linear distance formula.
0905
0906 int minDist = 256;
0907 int d;
0908 int gray = (int) (red * 77 + green * 150 + blue * 29 + 128) / 256;
0909
0910 for (int i = 0; i < map_size; i++) {
0911 if (this .rgb[i] == 0x0) {
0912 // For allgrayopaque colormaps, entries are 0
0913 // iff they are an invalid color and should be
0914 // ignored during color searches.
0915 continue;
0916 }
0917 d = (this .rgb[i] & 0xff) - gray;
0918 if (d < 0)
0919 d = -d;
0920 if (d < minDist) {
0921 pix = i;
0922 if (d == 0) {
0923 break;
0924 }
0925 minDist = d;
0926 }
0927 }
0928 } else if (transparency == OPAQUE) {
0929 // IndexColorModel objects are all tagged as
0930 // non-premultiplied so ignore the alpha value
0931 // of the incoming color and search for closest
0932 // color match independently using a 3 component
0933 // Euclidean distance formula.
0934 // For opaque colormaps, palette entries are 0
0935 // iff they are an invalid color and should be
0936 // ignored during color searches.
0937 // As an optimization, exact color searches are
0938 // likely to be fairly common in opaque colormaps
0939 // so first we will do a quick search for an
0940 // exact match.
0941
0942 int smallestError = Integer.MAX_VALUE;
0943 int lut[] = this .rgb;
0944 int lutrgb;
0945 for (int i = 0; i < map_size; i++) {
0946 lutrgb = lut[i];
0947 if (lutrgb == rgb && lutrgb != 0) {
0948 pix = i;
0949 smallestError = 0;
0950 break;
0951 }
0952 }
0953
0954 if (smallestError != 0) {
0955 for (int i = 0; i < map_size; i++) {
0956 lutrgb = lut[i];
0957 if (lutrgb == 0) {
0958 continue;
0959 }
0960
0961 int tmp = ((lutrgb >> 16) & 0xff) - red;
0962 int currentError = tmp * tmp;
0963 if (currentError < smallestError) {
0964 tmp = ((lutrgb >> 8) & 0xff) - green;
0965 currentError += tmp * tmp;
0966 if (currentError < smallestError) {
0967 tmp = (lutrgb & 0xff) - blue;
0968 currentError += tmp * tmp;
0969 if (currentError < smallestError) {
0970 pix = i;
0971 smallestError = currentError;
0972 }
0973 }
0974 }
0975 }
0976 }
0977 } else if (alpha == 0 && transparent_index >= 0) {
0978 // Special case - transparent color maps to the
0979 // specified transparent pixel, if there is one
0980
0981 pix = transparent_index;
0982 } else {
0983 // IndexColorModel objects are all tagged as
0984 // non-premultiplied so use non-premultiplied
0985 // color components in the distance calculations.
0986 // Look for closest match using a 4 component
0987 // Euclidean distance formula.
0988
0989 int smallestError = Integer.MAX_VALUE;
0990 int lut[] = this .rgb;
0991 for (int i = 0; i < map_size; i++) {
0992 int lutrgb = lut[i];
0993 if (lutrgb == rgb) {
0994 if (validBits != null && !validBits.testBit(i)) {
0995 continue;
0996 }
0997 pix = i;
0998 break;
0999 }
1000
1001 int tmp = ((lutrgb >> 16) & 0xff) - red;
1002 int currentError = tmp * tmp;
1003 if (currentError < smallestError) {
1004 tmp = ((lutrgb >> 8) & 0xff) - green;
1005 currentError += tmp * tmp;
1006 if (currentError < smallestError) {
1007 tmp = (lutrgb & 0xff) - blue;
1008 currentError += tmp * tmp;
1009 if (currentError < smallestError) {
1010 tmp = (lutrgb >>> 24) - alpha;
1011 currentError += tmp * tmp;
1012 if (currentError < smallestError
1013 && (validBits == null || validBits
1014 .testBit(i))) {
1015 pix = i;
1016 smallestError = currentError;
1017 }
1018 }
1019 }
1020 }
1021 }
1022 }
1023 System.arraycopy(lookupcache, 2, lookupcache, 0, CACHESIZE - 2);
1024 lookupcache[CACHESIZE - 1] = rgb;
1025 lookupcache[CACHESIZE - 2] = ~pix;
1026 return installpixel(pixel, pix);
1027 }
1028
1029 private Object installpixel(Object pixel, int pix) {
1030 switch (transferType) {
1031 case DataBuffer.TYPE_INT:
1032 int[] intObj;
1033 if (pixel == null) {
1034 pixel = intObj = new int[1];
1035 } else {
1036 intObj = (int[]) pixel;
1037 }
1038 intObj[0] = pix;
1039 break;
1040 case DataBuffer.TYPE_BYTE:
1041 byte[] byteObj;
1042 if (pixel == null) {
1043 pixel = byteObj = new byte[1];
1044 } else {
1045 byteObj = (byte[]) pixel;
1046 }
1047 byteObj[0] = (byte) pix;
1048 break;
1049 case DataBuffer.TYPE_USHORT:
1050 short[] shortObj;
1051 if (pixel == null) {
1052 pixel = shortObj = new short[1];
1053 } else {
1054 shortObj = (short[]) pixel;
1055 }
1056 shortObj[0] = (short) pix;
1057 break;
1058 default:
1059 throw new UnsupportedOperationException(
1060 "This method has not been "
1061 + "implemented for transferType "
1062 + 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,
1159 int offset) {
1160 int intpixel;
1161 switch (transferType) {
1162 case DataBuffer.TYPE_BYTE:
1163 byte bdata[] = (byte[]) pixel;
1164 intpixel = bdata[0] & 0xff;
1165 break;
1166 case DataBuffer.TYPE_USHORT:
1167 short sdata[] = (short[]) pixel;
1168 intpixel = sdata[0] & 0xffff;
1169 break;
1170 case DataBuffer.TYPE_INT:
1171 int idata[] = (int[]) pixel;
1172 intpixel = idata[0];
1173 break;
1174 default:
1175 throw new UnsupportedOperationException(
1176 "This method has not been "
1177 + "implemented for transferType "
1178 + 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</code> given an array of unnormalized
1186 * color/alpha components. An
1187 * <code>ArrayIndexOutOfBoundsException</code>
1188 * is thrown if the <code>components</code> array is not large
1189 * enough to hold all of the color and alpha components starting
1190 * at <code>offset</code>. Since
1191 * <code>ColorModel</code> can be subclassed, subclasses inherit the
1192 * implementation of this method and if they don't override it then
1193 * they throw an exception if they use an unsupported transferType.
1194 * @param components an array of unnormalized color and alpha
1195 * components
1196 * @param offset the index into <code>components</code> at which to
1197 * begin retrieving the color and alpha components
1198 * @return an <code>int</code> pixel value in this
1199 * <code>ColorModel</code> corresponding to the specified components.
1200 * @throws ArrayIndexOutOfBoundsException if
1201 * the <code>components</code> array is not large enough to
1202 * hold all of the color and alpha components starting at
1203 * <code>offset</code>
1204 * @throws UnsupportedOperationException if <code>transferType</code>
1205 * is invalid
1206 */
1207 public int getDataElement(int[] components, int offset) {
1208 int rgb = (components[offset + 0] << 16)
1209 | (components[offset + 1] << 8)
1210 | (components[offset + 2]);
1211 if (supportsAlpha) {
1212 rgb |= (components[offset + 3] << 24);
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(
1233 "This method has not been "
1234 + "implemented for transferType "
1235 + transferType);
1236 }
1237 return pixel;
1238 }
1239
1240 /**
1241 * Returns a data element array representation of a pixel in this
1242 * <code>ColorModel</code> given an array of unnormalized color/alpha
1243 * components. This array can then be passed to the
1244 * <code>setDataElements</code> method of a <code>WritableRaster</code>
1245 * object. An <code>ArrayIndexOutOfBoundsException</code> is
1246 * thrown if the
1247 * <code>components</code> array is not large enough to hold all of the
1248 * color and alpha components starting at <code>offset</code>.
1249 * If the pixel variable is <code>null</code>, a new array
1250 * is allocated. If <code>pixel</code> is not <code>null</code>,
1251 * it must be a primitive array of type <code>transferType</code>;
1252 * otherwise, a <code>ClassCastException</code> is thrown.
1253 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if pixel
1254 * is not large enough to hold a pixel value for this
1255 * <code>ColorModel</code>.
1256 * <p>
1257 * Since <code>IndexColorModel</code> can be subclassed, subclasses
1258 * inherit the implementation of this method and if they don't
1259 * override it then they throw an exception if they use an
1260 * unsupported <code>transferType</code>
1261 *
1262 * @param components an array of unnormalized color and alpha
1263 * components
1264 * @param offset the index into <code>components</code> at which to
1265 * begin retrieving color and alpha components
1266 * @param pixel the <code>Object</code> representing an array of color
1267 * and alpha components
1268 * @return an <code>Object</code> representing an array of color and
1269 * alpha components.
1270 * @throws ClassCastException if <code>pixel</code>
1271 * is not a primitive array of type <code>transferType</code>
1272 * @throws ArrayIndexOutOfBoundsException if
1273 * <code>pixel</code> is not large enough to hold a pixel value
1274 * for this <code>ColorModel</code> or the <code>components</code>
1275 * array is not large enough to hold all of the color and alpha
1276 * components starting at <code>offset</code>
1277 * @throws UnsupportedOperationException if <code>transferType</code>
1278 * is not one of the supported transer types
1279 * @see WritableRaster#setDataElements
1280 * @see SampleModel#setDataElements
1281 */
1282 public Object getDataElements(int[] components, int offset,
1283 Object pixel) {
1284 int rgb = (components[offset + 0] << 16)
1285 | (components[offset + 1] << 8)
1286 | (components[offset + 2]);
1287 if (supportsAlpha) {
1288 rgb |= (components[offset + 3] << 24);
1289 } else {
1290 rgb &= 0xff000000;
1291 }
1292 return getDataElements(rgb, pixel);
1293 }
1294
1295 /**
1296 * Creates a <code>WritableRaster</code> with the specified width
1297 * and height that has a data layout (<code>SampleModel</code>)
1298 * compatible with this <code>ColorModel</code>. This method
1299 * only works for color models with 16 or fewer bits per pixel.
1300 * <p>
1301 * Since <code>IndexColorModel</code> can be subclassed, any
1302 * subclass that supports greater than 16 bits per pixel must
1303 * override this method.
1304 *
1305 * @param w the width to apply to the new <code>WritableRaster</code>
1306 * @param h the height to apply to the new <code>WritableRaster</code>
1307 * @return a <code>WritableRaster</code> object with the specified
1308 * width and height.
1309 * @throws UnsupportedOperationException if the number of bits in a
1310 * pixel is greater than 16
1311 * @see WritableRaster
1312 * @see SampleModel
1313 */
1314 public WritableRaster createCompatibleWritableRaster(int w, int h) {
1315 WritableRaster raster;
1316
1317 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
1318 // TYPE_BINARY
1319 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, w,
1320 h, 1, pixel_bits, null);
1321 } else if (pixel_bits <= 8) {
1322 raster = Raster.createInterleavedRaster(
1323 DataBuffer.TYPE_BYTE, w, h, 1, null);
1324 } else if (pixel_bits <= 16) {
1325 raster = Raster.createInterleavedRaster(
1326 DataBuffer.TYPE_USHORT, w, h, 1, null);
1327 } else {
1328 throw new UnsupportedOperationException(
1329 "This method is not supported "
1330 + " for pixel bits > 16.");
1331 }
1332 return raster;
1333 }
1334
1335 /**
1336 * Returns <code>true</code> if <code>raster</code> is compatible
1337 * with this <code>ColorModel</code> or <code>false</code> if it
1338 * is not compatible with this <code>ColorModel</code>.
1339 * @param raster the {@link Raster} object to test for compatibility
1340 * @return <code>true</code> if <code>raster</code> is compatible
1341 * with this <code>ColorModel</code>; <code>false</code> otherwise.
1342 *
1343 */
1344 public boolean isCompatibleRaster(Raster raster) {
1345
1346 int size = raster.getSampleModel().getSampleSize(0);
1347 return ((raster.getTransferType() == transferType)
1348 && (raster.getNumBands() == 1) && ((1 << size) >= map_size));
1349 }
1350
1351 /**
1352 * Creates a <code>SampleModel</code> with the specified
1353 * width and height that has a data layout compatible with
1354 * this <code>ColorModel</code>.
1355 * @param w the width to apply to the new <code>SampleModel</code>
1356 * @param h the height to apply to the new <code>SampleModel</code>
1357 * @return a <code>SampleModel</code> object with the specified
1358 * width and height.
1359 * @throws IllegalArgumentException if <code>w</code> or
1360 * <code>h</code> is not greater than 0
1361 * @see SampleModel
1362 */
1363 public SampleModel createCompatibleSampleModel(int w, int h) {
1364 int[] off = new int[1];
1365 off[0] = 0;
1366 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
1367 return new MultiPixelPackedSampleModel(transferType, w, h,
1368 pixel_bits);
1369 } else {
1370 return new ComponentSampleModel(transferType, w, h, 1, w,
1371 off);
1372 }
1373 }
1374
1375 /**
1376 * Checks if the specified <code>SampleModel</code> is compatible
1377 * with this <code>ColorModel</code>. If <code>sm</code> is
1378 * <code>null</code>, this method returns <code>false</code>.
1379 * @param sm the specified <code>SampleModel</code>,
1380 * or <code>null</code>
1381 * @return <code>true</code> if the specified <code>SampleModel</code>
1382 * is compatible with this <code>ColorModel</code>; <code>false</code>
1383 * otherwise.
1384 * @see SampleModel
1385 */
1386 public boolean isCompatibleSampleModel(SampleModel sm) {
1387 // fix 4238629
1388 if (!(sm instanceof ComponentSampleModel)
1389 && !(sm instanceof MultiPixelPackedSampleModel)) {
1390 return false;
1391 }
1392
1393 // Transfer type must be the same
1394 if (sm.getTransferType() != transferType) {
1395 return false;
1396 }
1397
1398 if (sm.getNumBands() != 1) {
1399 return false;
1400 }
1401
1402 return true;
1403 }
1404
1405 /**
1406 * Returns a new <code>BufferedImage</code> of TYPE_INT_ARGB or
1407 * TYPE_INT_RGB that has a <code>Raster</code> with pixel data
1408 * computed by expanding the indices in the source <code>Raster</code>
1409 * using the color/alpha component arrays of this <code>ColorModel</code>.
1410 * Only the lower <em>n</em> bits of each index value in the source
1411 * <code>Raster</code>, as specified in the
1412 * <a href="#index_values">class description</a> above, are used to
1413 * compute the color/alpha values in the returned image.
1414 * If <code>forceARGB</code> is <code>true</code>, a TYPE_INT_ARGB image is
1415 * returned regardless of whether or not this <code>ColorModel</code>
1416 * has an alpha component array or a transparent pixel.
1417 * @param raster the specified <code>Raster</code>
1418 * @param forceARGB if <code>true</code>, the returned
1419 * <code>BufferedImage</code> is TYPE_INT_ARGB; otherwise it is
1420 * TYPE_INT_RGB
1421 * @return a <code>BufferedImage</code> created with the specified
1422 * <code>Raster</code>
1423 * @throws IllegalArgumentException if the raster argument is not
1424 * compatible with this IndexColorModel
1425 */
1426 public BufferedImage convertToIntDiscrete(Raster raster,
1427 boolean forceARGB) {
1428 ColorModel cm;
1429
1430 if (!isCompatibleRaster(raster)) {
1431 throw new IllegalArgumentException(
1432 "This raster is not compatible"
1433 + "with this IndexColorModel.");
1434 }
1435 if (forceARGB || transparency == TRANSLUCENT) {
1436 cm = ColorModel.getRGBdefault();
1437 } else if (transparency == BITMASK) {
1438 cm = new DirectColorModel(25, 0xff0000, 0x00ff00, 0x0000ff,
1439 0x1000000);
1440 } else {
1441 cm = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff);
1442 }
1443
1444 int w = raster.getWidth();
1445 int h = raster.getHeight();
1446 WritableRaster discreteRaster = cm
1447 .createCompatibleWritableRaster(w, h);
1448 Object obj = null;
1449 int[] data = null;
1450
1451 int rX = raster.getMinX();
1452 int rY = raster.getMinY();
1453
1454 for (int y = 0; y < h; y++, rY++) {
1455 obj = raster.getDataElements(rX, rY, w, 1, obj);
1456 if (obj instanceof int[]) {
1457 data = (int[]) obj;
1458 } else {
1459 data = DataBuffer.toIntArray(obj);
1460 }
1461 for (int x = 0; x < w; x++) {
1462 data[x] = rgb[data[x] & pixel_mask];
1463 }
1464 discreteRaster.setDataElements(0, y, w, 1, data);
1465 }
1466
1467 return new BufferedImage(cm, discreteRaster, false, null);
1468 }
1469
1470 /**
1471 * Returns whether or not the pixel is valid.
1472 * @param pixel the specified pixel value
1473 * @return <code>true</code> if <code>pixel</code>
1474 * is valid; <code>false</code> otherwise.
1475 * @since 1.3
1476 */
1477 public boolean isValid(int pixel) {
1478 return ((pixel >= 0 && pixel < map_size) && (validBits == null || validBits
1479 .testBit(pixel)));
1480 }
1481
1482 /**
1483 * Returns whether or not all of the pixels are valid.
1484 * @return <code>true</code> if all pixels are valid;
1485 * <code>false</code> otherwise.
1486 * @since 1.3
1487 */
1488 public boolean isValid() {
1489 return (validBits == null);
1490 }
1491
1492 /**
1493 * Returns a <code>BigInteger</code> that indicates the valid/invalid
1494 * pixels in the colormap. A bit is valid if the
1495 * <code>BigInteger</code> value at that index is set, and is invalid
1496 * if the <code>BigInteger</code> value at that index is not set.
1497 * The only valid ranges to query in the <code>BigInteger</code> are
1498 * between 0 and the map size.
1499 * @return a <code>BigInteger</code> indicating the valid/invalid pixels.
1500 * @since 1.3
1501 */
1502 public BigInteger getValidPixels() {
1503 if (validBits == null) {
1504 return getAllValid();
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 sun.awt.image.BufImgSurfaceData.freeNativeICMData(this );
1517 }
1518
1519 /**
1520 * Returns the <code>String</code> representation of the contents of
1521 * this <code>ColorModel</code>object.
1522 * @return a <code>String</code> representing the contents of this
1523 * <code>ColorModel</code> object.
1524 */
1525 public String toString() {
1526 return new String("IndexColorModel: #pixelBits = " + pixel_bits
1527 + " numComponents = " + numComponents
1528 + " color space = " + colorSpace + " transparency = "
1529 + transparency + " transIndex = " + transparent_index
1530 + " has alpha = " + supportsAlpha + " isAlphaPre = "
1531 + isAlphaPremultiplied);
1532 }
1533 }
|