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 < alpha < 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 * </a> 102 * <p> 103 * For those methods that use a primitive array pixel representation of 104 * type <code>transferType</code>, the array length is always one. 105 * The transfer types supported are <code>DataBuffer.TYPE_BYTE</code> and 106 * <code>DataBuffer.TYPE_USHORT</code>. A single int pixel 107 * representation is valid for all objects of this class, since it is 108 * always possible to represent pixel values used with this class in a 109 * single int. Therefore, methods that use this representation do 110 * not throw an <code>IllegalArgumentException</code> due to an invalid 111 * pixel value. 112 * <p> 113 * Many of the methods in this class are final. The reason for 114 * this is that the underlying native graphics code makes assumptions 115 * about the layout and operation of this class and those assumptions 116 * are reflected in the implementations of the methods here that are 117 * marked final. You can subclass this class for other reasons, but 118 * you cannot override or modify the behaviour of those methods. 119 * 120 * @see ColorModel 121 * @see ColorSpace 122 * @see DataBuffer 123 * 124 */ 125 public class IndexColorModel extends ColorModel { 126 private int rgb[]; 127 private int map_size; 128 private int pixel_mask; 129 private int transparent_index = -1; 130 private boolean allgrayopaque; 131 private BigInteger validBits; 132 133 private sun.awt.image.BufImgSurfaceData.ICMColorData colorData = null; 134 135 private static int[] opaqueBits = {8, 8, 8}; 136 private static int[] alphaBits = {8, 8, 8, 8}; 137 138 private static native void initIDs(); 139 static { 140 ColorModel.loadLibraries(); 141 initIDs(); 142 } 143 /** 144 * Constructs an <code>IndexColorModel</code> from the specified 145 * arrays of red, green, and blue components. Pixels described 146 * by this color model all have alpha components of 255 147 * unnormalized (1.0 normalized), which means they 148 * are fully opaque. All of the arrays specifying the color 149 * components must have at least the specified number of entries. 150 * The <code>ColorSpace</code> is the default sRGB space. 151 * Since there is no alpha information in any of the arguments 152 * to this constructor, the transparency value is always 153 * <code>Transparency.OPAQUE</code>. 154 * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code> 155 * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel. 156 * @param bits the number of bits each pixel occupies 157 * @param size the size of the color component arrays 158 * @param r the array of red color components 159 * @param g the array of green color components 160 * @param b the array of blue color components 161 * @throws IllegalArgumentException if <code>bits</code> is less 162 * than 1 or greater than 16 163 * @throws IllegalArgumentException if <code>size</code> is less 164 * than 1 165 */ 166 public IndexColorModel(int bits, int size, 167 byte r[], byte g[], byte b[]) { 168 super(bits, opaqueBits, 169 ColorSpace.getInstance(ColorSpace.CS_sRGB), 170 false, false, OPAQUE, 171 ColorModel.getDefaultTransferType(bits)); 172 if (bits < 1 || bits > 16) { 173 throw new IllegalArgumentException("Number of bits must be between" 174 +" 1 and 16."); 175 } 176 setRGBs(size, r, g, b, null); 177 calculatePixelMask(); 178 } 179 180 /** 181 * Constructs an <code>IndexColorModel</code> from the given arrays 182 * of red, green, and blue components. Pixels described by this color 183 * model all have alpha components of 255 unnormalized 184 * (1.0 normalized), which means they are fully opaque, except 185 * for the indicated pixel to be made transparent. All of the arrays 186 * specifying the color components must have at least the specified 187 * number of entries. 188 * The <code>ColorSpace</code> is the default sRGB space. 189 * The transparency value may be <code>Transparency.OPAQUE</code> or 190 * <code>Transparency.BITMASK</code> depending on the arguments, as 191 * specified in the <a href="#transparency">class description</a> above. 192 * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code> 193 * or <code>DataBuffer.TYPE_USHORT</code> that can hold a 194 * single pixel. 195 * @param bits the number of bits each pixel occupies 196 * @param size the size of the color component arrays 197 * @param r the array of red color components 198 * @param g the array of green color components 199 * @param b the array of blue color components 200 * @param trans the index of the transparent pixel 201 * @throws IllegalArgumentException if <code>bits</code> is less than 202 * 1 or greater than 16 203 * @throws IllegalArgumentException if <code>size</code> is less than 204 * 1 205 */ 206 public IndexColorModel(int bits, int size, 207 byte r[], byte g[], byte b[], int trans) { 208 super(bits, opaqueBits, 209 ColorSpace.getInstance(ColorSpace.CS_sRGB), 210 false, false, OPAQUE, 211 ColorModel.getDefaultTransferType(bits)); 212 if (bits < 1 || bits > 16) { 213 throw new IllegalArgumentException("Number of bits must be between" 214 +" 1 and 16."); 215 } 216 setRGBs(size, r, g, b, null); 217 setTransparentPixel(trans); 218 calculatePixelMask(); 219 } 220 221 /** 222 * Constructs an <code>IndexColorModel</code> from the given 223 * arrays of red, green, blue and alpha components. All of the 224 * arrays specifying the components must have at least the specified 225 * number of entries. 226 * The <code>ColorSpace</code> is the default sRGB space. 227 * The transparency value may be any of <code>Transparency.OPAQUE</code>, 228 * <code>Transparency.BITMASK</code>, 229 * or <code>Transparency.TRANSLUCENT</code> 230 * depending on the arguments, as specified 231 * in the <a href="#transparency">class description</a> above. 232 * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code> 233 * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel. 234 * @param bits the number of bits each pixel occupies 235 * @param size the size of the color component arrays 236 * @param r the array of red color components 237 * @param g the array of green color components 238 * @param b the array of blue color components 239 * @param a the array of alpha value components 240 * @throws IllegalArgumentException if <code>bits</code> is less 241 * than 1 or greater than 16 242 * @throws IllegalArgumentException if <code>size</code> is less 243 * than 1 244 */ 245 public IndexColorModel(int bits, int size, 246 byte r[], byte g[], byte b[], byte a[]) { 247 super (bits, alphaBits, 248 ColorSpace.getInstance(ColorSpace.CS_sRGB), 249 true, false, TRANSLUCENT, 250 ColorModel.getDefaultTransferType(bits)); 251 if (bits < 1 || bits > 16) { 252 throw new IllegalArgumentException("Number of bits must be between" 253 +" 1 and 16."); 254 } 255 setRGBs (size, r, g, b, a); 256 calculatePixelMask(); 257 } 258 259 /** 260 * Constructs an <code>IndexColorModel</code> from a single 261 * array of interleaved red, green, blue and optional alpha 262 * components. The array must have enough values in it to 263 * fill all of the needed component arrays of the specified 264 * size. The <code>ColorSpace</code> is the default sRGB space. 265 * The transparency value may be any of <code>Transparency.OPAQUE</code>, 266 * <code>Transparency.BITMASK</code>, 267 * or <code>Transparency.TRANSLUCENT</code> 268 * depending on the arguments, as specified 269 * in the <a href="#transparency">class description</a> above. 270 * The transfer type is the smallest of 271 * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code> 272 * that can hold a single pixel. 273 * 274 * @param bits the number of bits each pixel occupies 275 * @param size the size of the color component arrays 276 * @param cmap the array of color components 277 * @param start the starting offset of the first color component 278 * @param hasalpha indicates whether alpha values are contained in 279 * the <code>cmap</code> array 280 * @throws IllegalArgumentException if <code>bits</code> is less 281 * than 1 or greater than 16 282 * @throws IllegalArgumentException if <code>size</code> is less 283 * than 1 284 */ 285 public IndexColorModel(int bits, int size, byte cmap[], int start, 286 boolean hasalpha) { 287 this(bits, size, cmap, start, hasalpha, -1); 288 if (bits < 1 || bits > 16) { 289 throw new IllegalArgumentException("Number of bits must be between" 290 +" 1 and 16."); 291 } 292 } 293 294 /** 295 * Constructs an <code>IndexColorModel</code> from a single array of 296 * interleaved red, green, blue and optional alpha components. The 297 * specified transparent index represents a pixel that is made 298 * entirely transparent regardless of any alpha value specified 299 * for it. The array must have enough values in it to fill all 300 * of the needed component arrays of the specified size. 301 * The <code>ColorSpace</code> is the default sRGB space. 302 * The transparency value may be any of <code>Transparency.OPAQUE</code>, 303 * <code>Transparency.BITMASK</code>, 304 * or <code>Transparency.TRANSLUCENT</code> 305 * depending on the arguments, as specified 306 * in the <a href="#transparency">class description</a> above. 307 * The transfer type is the smallest of 308 * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code> 309 * that can hold a single pixel. 310 * @param bits the number of bits each pixel occupies 311 * @param size the size of the color component arrays 312 * @param cmap the array of color components 313 * @param start the starting offset of the first color component 314 * @param hasalpha indicates whether alpha values are contained in 315 * the <code>cmap</code> array 316 * @param trans the index of the fully transparent pixel 317 * @throws IllegalArgumentException if <code>bits</code> is less than 318 * 1 or greater than 16 319 * @throws IllegalArgumentException if <code>size</code> is less than 320 * 1 321 */ 322 public IndexColorModel(int bits, int size, byte cmap[], int start, 323 boolean hasalpha, int trans) { 324 // REMIND: This assumes the ordering: RGB[A] 325 super(bits, opaqueBits, 326 ColorSpace.getInstance(ColorSpace.CS_sRGB), 327 false, false, OPAQUE, 328 ColorModel.getDefaultTransferType(bits)); 329 330 if (bits < 1 || bits > 16) { 331 throw new IllegalArgumentException("Number of bits must be between" 332 +" 1 and 16."); 333 } 334 if (size < 1) { 335 throw new IllegalArgumentException("Map size ("+size+ 336 ") must be >= 1"); 337 } 338 map_size = size; 339 rgb = new int[calcRealMapSize(bits, size)]; 354 transparency = BITMASK; 355 } 356 if (transparent_index < 0) { 357 transparent_index = i; 358 } 359 } else { 360 transparency = TRANSLUCENT; 361 } 362 allgray = false; 363 } 364 } 365 rgb[i] = (alpha << 24) | (r << 16) | (g << 8) | b; 366 } 367 this.allgrayopaque = allgray; 368 setTransparency(transparency); 369 setTransparentPixel(trans); 370 calculatePixelMask(); 371 } 372 373 /** 374 * Constructs an <code>IndexColorModel</code> from an array of 375 * ints where each int is comprised of red, green, blue, and 376 * optional alpha components in the default RGB color model format. 377 * The specified transparent index represents a pixel that is made 378 * entirely transparent regardless of any alpha value specified 379 * for it. The array must have enough values in it to fill all 380 * of the needed component arrays of the specified size. 381 * The <code>ColorSpace</code> is the default sRGB space. 382 * The transparency value may be any of <code>Transparency.OPAQUE</code>, 383 * <code>Transparency.BITMASK</code>, 384 * or <code>Transparency.TRANSLUCENT</code> 385 * depending on the arguments, as specified 386 * in the <a href="#transparency">class description</a> above. 387 * @param bits the number of bits each pixel occupies 388 * @param size the size of the color component arrays 389 * @param cmap the array of color components 390 * @param start the starting offset of the first color component 391 * @param hasalpha indicates whether alpha values are contained in 392 * the <code>cmap</code> array 393 * @param trans the index of the fully transparent pixel 394 * @param transferType the data type of the array used to represent 395 * pixel values. The data type must be either 396 * <code>DataBuffer.TYPE_BYTE</code> or 397 * <code>DataBuffer.TYPE_USHORT</code>. 398 * @throws IllegalArgumentException if <code>bits</code> is less 399 * than 1 or greater than 16 400 * @throws IllegalArgumentException if <code>size</code> is less 401 * than 1 402 * @throws IllegalArgumentException if <code>transferType</code> is not 403 * one of <code>DataBuffer.TYPE_BYTE</code> or 404 * <code>DataBuffer.TYPE_USHORT</code> 405 */ 406 public IndexColorModel(int bits, int size, 407 int cmap[], int start, 408 boolean hasalpha, int trans, int transferType) { 409 // REMIND: This assumes the ordering: RGB[A] 410 super(bits, opaqueBits, 411 ColorSpace.getInstance(ColorSpace.CS_sRGB), 412 false, false, OPAQUE, 413 transferType); 414 415 if (bits < 1 || bits > 16) { 416 throw new IllegalArgumentException("Number of bits must be between" 417 +" 1 and 16."); 418 } 419 if (size < 1) { 420 throw new IllegalArgumentException("Map size ("+size+ 421 ") must be >= 1"); 422 } 423 if ((transferType != DataBuffer.TYPE_BYTE) && 424 (transferType != DataBuffer.TYPE_USHORT)) { 425 throw new IllegalArgumentException("transferType must be either" + 426 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); 427 } 428 429 setRGBs(size, cmap, start, hasalpha); 430 setTransparentPixel(trans); 431 calculatePixelMask(); 432 } 433 434 /** 435 * Constructs an <code>IndexColorModel</code> from an 436 * <code>int</code> array where each <code>int</code> is 437 * comprised of red, green, blue, and alpha 438 * components in the default RGB color model format. 439 * The array must have enough values in it to fill all 440 * of the needed component arrays of the specified size. 441 * The <code>ColorSpace</code> is the default sRGB space. 442 * The transparency value may be any of <code>Transparency.OPAQUE</code>, 443 * <code>Transparency.BITMASK</code>, 444 * or <code>Transparency.TRANSLUCENT</code> 445 * depending on the arguments, as specified 446 * in the <a href="#transparency">class description</a> above. 447 * The transfer type must be one of <code>DataBuffer.TYPE_BYTE</code> 448 * <code>DataBuffer.TYPE_USHORT</code>. 449 * The <code>BigInteger</code> object specifies the valid/invalid pixels 450 * in the <code>cmap</code> array. A pixel is valid if the 451 * <code>BigInteger</code> value at that index is set, and is invalid 452 * if the <code>BigInteger</code> bit at that index is not set. 453 * @param bits the number of bits each pixel occupies 454 * @param size the size of the color component array 455 * @param cmap the array of color components 456 * @param start the starting offset of the first color component 457 * @param transferType the specified data type 458 * @param validBits a <code>BigInteger</code> object. If a bit is 459 * set in the BigInteger, the pixel at that index is valid. 460 * If a bit is not set, the pixel at that index 461 * is considered invalid. If null, all pixels are valid. 462 * Only bits from 0 to the map size are considered. 463 * @throws IllegalArgumentException if <code>bits</code> is less 464 * than 1 or greater than 16 465 * @throws IllegalArgumentException if <code>size</code> is less 466 * than 1 467 * @throws IllegalArgumentException if <code>transferType</code> is not 468 * one of <code>DataBuffer.TYPE_BYTE</code> or 469 * <code>DataBuffer.TYPE_USHORT</code> 470 * 471 * @since 1.3 472 */ 473 public IndexColorModel(int bits, int size, int cmap[], int start, 474 int transferType, BigInteger validBits) { 475 super (bits, alphaBits, 476 ColorSpace.getInstance(ColorSpace.CS_sRGB), 477 true, false, TRANSLUCENT, 478 transferType); 479 480 if (bits < 1 || bits > 16) { 481 throw new IllegalArgumentException("Number of bits must be between" 482 +" 1 and 16."); 483 } 484 if (size < 1) { 485 throw new IllegalArgumentException("Map size ("+size+ 486 ") must be >= 1"); 487 } 488 if ((transferType != DataBuffer.TYPE_BYTE) && 489 (transferType != DataBuffer.TYPE_USHORT)) { 582 setTransparency(transparency); 583 } 584 585 private int calcRealMapSize(int bits, int size) { 586 int newSize = Math.max(1 << bits, size); 587 return Math.max(newSize, 256); 588 } 589 590 private BigInteger getAllValid() { 591 int numbytes = (map_size+7)/8; 592 byte[] valid = new byte[numbytes]; 593 java.util.Arrays.fill(valid, (byte)0xff); 594 valid[0] = (byte)(0xff >>> (numbytes*8 - map_size)); 595 596 return new BigInteger(1, valid); 597 } 598 599 /** 600 * Returns the transparency. Returns either OPAQUE, BITMASK, 601 * or TRANSLUCENT 602 * @return the transparency of this <code>IndexColorModel</code> 603 * @see Transparency#OPAQUE 604 * @see Transparency#BITMASK 605 * @see Transparency#TRANSLUCENT 606 */ 607 public int getTransparency() { 608 return transparency; 609 } 610 611 /** 612 * Returns an array of the number of bits for each color/alpha component. 613 * The array contains the color components in the order red, green, 614 * blue, followed by the alpha component, if present. 615 * @return an array containing the number of bits of each color 616 * and alpha component of this <code>IndexColorModel</code> 617 */ 618 public int[] getComponentSize() { 619 if (nBits == null) { 620 if (supportsAlpha) { 621 nBits = new int[4]; 622 nBits[3] = 8; 623 } 624 else { 625 nBits = new int[3]; 626 } 627 nBits[0] = nBits[1] = nBits[2] = 8; 628 } 629 return nBits.clone(); 630 } 631 632 /** 633 * Returns the size of the color/alpha component arrays in this 634 * <code>IndexColorModel</code>. 635 * @return the size of the color and alpha component arrays. 636 */ 637 public final int getMapSize() { 638 return map_size; 639 } 640 641 /** 642 * Returns the index of a transparent pixel in this 643 * <code>IndexColorModel</code> or -1 if there is no pixel 644 * with an alpha value of 0. If a transparent pixel was 645 * explicitly specified in one of the constructors by its 646 * index, then that index will be preferred, otherwise, 647 * the index of any pixel which happens to be fully transparent 648 * may be returned. 649 * @return the index of a transparent pixel in this 650 * <code>IndexColorModel</code> object, or -1 if there 651 * is no such pixel 652 */ 653 public final int getTransparentPixel() { 654 return transparent_index; 655 } 656 657 /** 658 * Copies the array of red color components into the specified array. 659 * Only the initial entries of the array as specified by 660 * {@link #getMapSize() getMapSize} are written. 661 * @param r the specified array into which the elements of the 662 * array of red color components are copied 663 */ 664 public final void getReds(byte r[]) { 665 for (int i = 0; i < map_size; i++) { 666 r[i] = (byte) (rgb[i] >> 16); 667 } 668 } 669 670 /** 671 * Copies the array of green color components into the specified array. 672 * Only the initial entries of the array as specified by 673 * <code>getMapSize</code> are written. 674 * @param g the specified array into which the elements of the 675 * array of green color components are copied 676 */ 677 public final void getGreens(byte g[]) { 678 for (int i = 0; i < map_size; i++) { 679 g[i] = (byte) (rgb[i] >> 8); 680 } 681 } 682 683 /** 684 * Copies the array of blue color components into the specified array. 685 * Only the initial entries of the array as specified by 686 * <code>getMapSize</code> are written. 687 * @param b the specified array into which the elements of the 688 * array of blue color components are copied 689 */ 690 public final void getBlues(byte b[]) { 691 for (int i = 0; i < map_size; i++) { 692 b[i] = (byte) rgb[i]; 693 } 694 } 695 696 /** 697 * Copies the array of alpha transparency components into the 698 * specified array. Only the initial entries of the array as specified 699 * by <code>getMapSize</code> are written. 700 * @param a the specified array into which the elements of the 701 * array of alpha components are copied 702 */ 703 public final void getAlphas(byte a[]) { 704 for (int i = 0; i < map_size; i++) { 705 a[i] = (byte) (rgb[i] >> 24); 706 } 707 } 708 709 /** 710 * Converts data for each index from the color and alpha component 711 * arrays to an int in the default RGB ColorModel format and copies 712 * the resulting 32-bit ARGB values into the specified array. Only 713 * the initial entries of the array as specified by 714 * <code>getMapSize</code> are 715 * written. 716 * @param rgb the specified array into which the converted ARGB 717 * values from this array of color and alpha components 718 * are copied. 719 */ 720 public final void getRGBs(int rgb[]) { 721 System.arraycopy(this.rgb, 0, rgb, 0, map_size); 722 } 723 724 private void setTransparentPixel(int trans) { 725 if (trans >= 0 && trans < map_size) { 726 rgb[trans] &= 0x00ffffff; 727 transparent_index = trans; 728 allgrayopaque = false; 729 if (this.transparency == OPAQUE) { 730 setTransparency(BITMASK); 731 } 732 } 733 } 734 830 * <a href="#index_values">class description</a> above, are used to 831 * calculate the returned value. 832 * The returned value is in a non pre-multiplied format. 833 * @param pixel the specified pixel 834 * @return the color and alpha components of the specified pixel 835 * @see ColorModel#getRGBdefault 836 */ 837 public final int getRGB(int pixel) { 838 return rgb[pixel & pixel_mask]; 839 } 840 841 private static final int CACHESIZE = 40; 842 private int lookupcache[] = new int[CACHESIZE]; 843 844 /** 845 * Returns a data element array representation of a pixel in this 846 * ColorModel, given an integer pixel representation in the 847 * default RGB color model. This array can then be passed to the 848 * {@link WritableRaster#setDataElements(int, int, java.lang.Object) setDataElements} 849 * method of a {@link WritableRaster} object. If the pixel variable is 850 * <code>null</code>, a new array is allocated. If <code>pixel</code> 851 * is not <code>null</code>, it must be 852 * a primitive array of type <code>transferType</code>; otherwise, a 853 * <code>ClassCastException</code> is thrown. An 854 * <code>ArrayIndexOutOfBoundsException</code> is 855 * thrown if <code>pixel</code> is not large enough to hold a pixel 856 * value for this <code>ColorModel</code>. The pixel array is returned. 857 * <p> 858 * Since <code>IndexColorModel</code> can be subclassed, subclasses 859 * inherit the implementation of this method and if they don't 860 * override it then they throw an exception if they use an 861 * unsupported <code>transferType</code>. 862 * 863 * @param rgb the integer pixel representation in the default RGB 864 * color model 865 * @param pixel the specified pixel 866 * @return an array representation of the specified pixel in this 867 * <code>IndexColorModel</code>. 868 * @throws ClassCastException if <code>pixel</code> 869 * is not a primitive array of type <code>transferType</code> 870 * @throws ArrayIndexOutOfBoundsException if 871 * <code>pixel</code> is not large enough to hold a pixel value 872 * for this <code>ColorModel</code> 873 * @throws UnsupportedOperationException if <code>transferType</code> 874 * is invalid 875 * @see WritableRaster#setDataElements 876 * @see SampleModel#setDataElements 877 */ 878 public synchronized Object getDataElements(int rgb, Object pixel) { 879 int red = (rgb>>16) & 0xff; 880 int green = (rgb>>8) & 0xff; 881 int blue = rgb & 0xff; 882 int alpha = (rgb>>>24); 883 int pix = 0; 884 885 // Note that pixels are stored at lookupcache[2*i] 886 // and the rgb that was searched is stored at 887 // lookupcache[2*i+1]. Also, the pixel is first 888 // inverted using the unary complement operator 889 // before storing in the cache so it can never be 0. 890 for (int i = CACHESIZE - 2; i >= 0; i -= 2) { 891 if ((pix = lookupcache[i]) == 0) { 892 break; 893 } 1050 byteObj[0] = (byte) pix; 1051 break; 1052 case DataBuffer.TYPE_USHORT: 1053 short[] shortObj; 1054 if (pixel == null) { 1055 pixel = shortObj = new short[1]; 1056 } else { 1057 shortObj = (short[]) pixel; 1058 } 1059 shortObj[0] = (short) pix; 1060 break; 1061 default: 1062 throw new UnsupportedOperationException("This method has not been "+ 1063 "implemented for transferType " + transferType); 1064 } 1065 return pixel; 1066 } 1067 1068 /** 1069 * Returns an array of unnormalized color/alpha components for a 1070 * specified pixel in this <code>ColorModel</code>. The pixel value 1071 * is specified as an int. If the <code>components</code> array is <code>null</code>, 1072 * a new array is allocated that contains 1073 * <code>offset + getNumComponents()</code> elements. 1074 * The <code>components</code> array is returned, 1075 * with the alpha component included 1076 * only if <code>hasAlpha</code> returns true. 1077 * Color/alpha components are stored in the <code>components</code> array starting 1078 * at <code>offset</code> even if the array is allocated by this method. 1079 * An <code>ArrayIndexOutOfBoundsException</code> 1080 * is thrown if the <code>components</code> array is not <code>null</code> and is 1081 * not large enough to hold all the color and alpha components 1082 * starting at <code>offset</code>. 1083 * @param pixel the specified pixel 1084 * @param components the array to receive the color and alpha 1085 * components of the specified pixel 1086 * @param offset the offset into the <code>components</code> array at 1087 * which to start storing the color and alpha components 1088 * @return an array containing the color and alpha components of the 1089 * specified pixel starting at the specified offset. 1090 * @see ColorModel#hasAlpha 1091 * @see ColorModel#getNumComponents 1092 */ 1093 public int[] getComponents(int pixel, int[] components, int offset) { 1094 if (components == null) { 1095 components = new int[offset+numComponents]; 1096 } 1097 1098 // REMIND: Needs to change if different color space 1099 components[offset+0] = getRed(pixel); 1100 components[offset+1] = getGreen(pixel); 1101 components[offset+2] = getBlue(pixel); 1102 if (supportsAlpha && (components.length-offset) > 3) { 1103 components[offset+3] = getAlpha(pixel); 1104 } 1105 1106 return components; 1107 } 1108 1109 /** 1110 * Returns an array of unnormalized color/alpha components for 1111 * a specified pixel in this <code>ColorModel</code>. The pixel 1112 * value is specified by an array of data elements of type 1113 * <code>transferType</code> passed in as an object reference. 1114 * If <code>pixel</code> is not a primitive array of type 1115 * <code>transferType</code>, a <code>ClassCastException</code> 1116 * is thrown. An <code>ArrayIndexOutOfBoundsException</code> 1117 * is thrown if <code>pixel</code> is not large enough to hold 1118 * a pixel value for this <code>ColorModel</code>. If the 1119 * <code>components</code> array is <code>null</code>, a new array 1120 * is allocated that contains 1121 * <code>offset + getNumComponents()</code> elements. 1122 * The <code>components</code> array is returned, 1123 * with the alpha component included 1124 * only if <code>hasAlpha</code> returns true. 1125 * Color/alpha components are stored in the <code>components</code> 1126 * array starting at <code>offset</code> even if the array is 1127 * allocated by this method. An 1128 * <code>ArrayIndexOutOfBoundsException</code> is also 1129 * thrown if the <code>components</code> array is not 1130 * <code>null</code> and is not large enough to hold all the color 1131 * and alpha components starting at <code>offset</code>. 1132 * <p> 1133 * Since <code>IndexColorModel</code> can be subclassed, subclasses 1134 * inherit the implementation of this method and if they don't 1135 * override it then they throw an exception if they use an 1136 * unsupported <code>transferType</code>. 1137 * 1138 * @param pixel the specified pixel 1139 * @param components an array that receives the color and alpha 1140 * components of the specified pixel 1141 * @param offset the index into the <code>components</code> array at 1142 * which to begin storing the color and alpha components of the 1143 * specified pixel 1144 * @return an array containing the color and alpha components of the 1145 * specified pixel starting at the specified offset. 1146 * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> 1147 * is not large enough to hold a pixel value for this 1148 * <code>ColorModel</code> or if the 1149 * <code>components</code> array is not <code>null</code> 1150 * and is not large enough to hold all the color 1151 * and alpha components starting at <code>offset</code> 1152 * @throws ClassCastException if <code>pixel</code> is not a 1153 * primitive array of type <code>transferType</code> 1154 * @throws UnsupportedOperationException if <code>transferType</code> 1155 * is not one of the supported transfer types 1156 * @see ColorModel#hasAlpha 1157 * @see ColorModel#getNumComponents 1158 */ 1159 public int[] getComponents(Object pixel, int[] components, 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("This method has not been "+ 1176 "implemented for transferType " + transferType); 1177 } 1178 return getComponents(intpixel, components, offset); 1179 } 1180 1181 /** 1182 * Returns a pixel value represented as an int in this 1183 * <code>ColorModel</code> given an array of unnormalized 1184 * color/alpha components. An 1185 * <code>ArrayIndexOutOfBoundsException</code> 1186 * is thrown if the <code>components</code> array is not large 1187 * enough to hold all of the color and alpha components starting 1188 * at <code>offset</code>. Since 1189 * <code>ColorModel</code> can be subclassed, subclasses inherit the 1190 * implementation of this method and if they don't override it then 1191 * they throw an exception if they use an unsupported transferType. 1192 * @param components an array of unnormalized color and alpha 1193 * components 1194 * @param offset the index into <code>components</code> at which to 1195 * begin retrieving the color and alpha components 1196 * @return an <code>int</code> pixel value in this 1197 * <code>ColorModel</code> corresponding to the specified components. 1198 * @throws ArrayIndexOutOfBoundsException if 1199 * the <code>components</code> array is not large enough to 1200 * hold all of the color and alpha components starting at 1201 * <code>offset</code> 1202 * @throws UnsupportedOperationException if <code>transferType</code> 1203 * is invalid 1204 */ 1205 public int getDataElement(int[] components, int offset) { 1206 int rgb = (components[offset+0]<<16) 1207 | (components[offset+1]<<8) | (components[offset+2]); 1208 if (supportsAlpha) { 1209 rgb |= (components[offset+3]<<24); 1210 } 1211 else { 1212 rgb |= 0xff000000; 1213 } 1214 Object inData = getDataElements(rgb, null); 1215 int pixel; 1216 switch (transferType) { 1217 case DataBuffer.TYPE_BYTE: 1218 byte bdata[] = (byte[])inData; 1219 pixel = bdata[0] & 0xff; 1220 break; 1221 case DataBuffer.TYPE_USHORT: 1222 short sdata[] = (short[])inData; 1223 pixel = sdata[0]; 1224 break; 1225 case DataBuffer.TYPE_INT: 1226 int idata[] = (int[])inData; 1227 pixel = idata[0]; 1228 break; 1229 default: 1230 throw new UnsupportedOperationException("This method has not been "+ 1231 "implemented for transferType " + transferType); 1232 } 1233 return pixel; 1234 } 1235 1236 /** 1237 * Returns a data element array representation of a pixel in this 1238 * <code>ColorModel</code> given an array of unnormalized color/alpha 1239 * components. This array can then be passed to the 1240 * <code>setDataElements</code> method of a <code>WritableRaster</code> 1241 * object. An <code>ArrayIndexOutOfBoundsException</code> is 1242 * thrown if the 1243 * <code>components</code> array is not large enough to hold all of the 1244 * color and alpha components starting at <code>offset</code>. 1245 * If the pixel variable is <code>null</code>, a new array 1246 * is allocated. If <code>pixel</code> is not <code>null</code>, 1247 * it must be a primitive array of type <code>transferType</code>; 1248 * otherwise, a <code>ClassCastException</code> is thrown. 1249 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if pixel 1250 * is not large enough to hold a pixel value for this 1251 * <code>ColorModel</code>. 1252 * <p> 1253 * Since <code>IndexColorModel</code> can be subclassed, subclasses 1254 * inherit the implementation of this method and if they don't 1255 * override it then they throw an exception if they use an 1256 * unsupported <code>transferType</code> 1257 * 1258 * @param components an array of unnormalized color and alpha 1259 * components 1260 * @param offset the index into <code>components</code> at which to 1261 * begin retrieving color and alpha components 1262 * @param pixel the <code>Object</code> representing an array of color 1263 * and alpha components 1264 * @return an <code>Object</code> representing an array of color and 1265 * alpha components. 1266 * @throws ClassCastException if <code>pixel</code> 1267 * is not a primitive array of type <code>transferType</code> 1268 * @throws ArrayIndexOutOfBoundsException if 1269 * <code>pixel</code> is not large enough to hold a pixel value 1270 * for this <code>ColorModel</code> or the <code>components</code> 1271 * array is not large enough to hold all of the color and alpha 1272 * components starting at <code>offset</code> 1273 * @throws UnsupportedOperationException if <code>transferType</code> 1274 * is not one of the supported transfer types 1275 * @see WritableRaster#setDataElements 1276 * @see SampleModel#setDataElements 1277 */ 1278 public Object getDataElements(int[] components, int offset, Object pixel) { 1279 int rgb = (components[offset+0]<<16) | (components[offset+1]<<8) 1280 | (components[offset+2]); 1281 if (supportsAlpha) { 1282 rgb |= (components[offset+3]<<24); 1283 } 1284 else { 1285 rgb &= 0xff000000; 1286 } 1287 return getDataElements(rgb, pixel); 1288 } 1289 1290 /** 1291 * Creates a <code>WritableRaster</code> with the specified width 1292 * and height that has a data layout (<code>SampleModel</code>) 1293 * compatible with this <code>ColorModel</code>. This method 1294 * only works for color models with 16 or fewer bits per pixel. 1295 * <p> 1296 * Since <code>IndexColorModel</code> can be subclassed, any 1297 * subclass that supports greater than 16 bits per pixel must 1298 * override this method. 1299 * 1300 * @param w the width to apply to the new <code>WritableRaster</code> 1301 * @param h the height to apply to the new <code>WritableRaster</code> 1302 * @return a <code>WritableRaster</code> object with the specified 1303 * width and height. 1304 * @throws UnsupportedOperationException if the number of bits in a 1305 * pixel is greater than 16 1306 * @see WritableRaster 1307 * @see SampleModel 1308 */ 1309 public WritableRaster createCompatibleWritableRaster(int w, int h) { 1310 WritableRaster raster; 1311 1312 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) { 1313 // TYPE_BINARY 1314 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, 1315 w, h, 1, pixel_bits, null); 1316 } 1317 else if (pixel_bits <= 8) { 1318 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1319 w,h,1,null); 1320 } 1321 else if (pixel_bits <= 16) { 1322 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, 1323 w,h,1,null); 1324 } 1325 else { 1326 throw new 1327 UnsupportedOperationException("This method is not supported "+ 1328 " for pixel bits > 16."); 1329 } 1330 return raster; 1331 } 1332 1333 /** 1334 * Returns <code>true</code> if <code>raster</code> is compatible 1335 * with this <code>ColorModel</code> or <code>false</code> if it 1336 * is not compatible with this <code>ColorModel</code>. 1337 * @param raster the {@link Raster} object to test for compatibility 1338 * @return <code>true</code> if <code>raster</code> is compatible 1339 * with this <code>ColorModel</code>; <code>false</code> otherwise. 1340 * 1341 */ 1342 public boolean isCompatibleRaster(Raster raster) { 1343 1344 int size = raster.getSampleModel().getSampleSize(0); 1345 return ((raster.getTransferType() == transferType) && 1346 (raster.getNumBands() == 1) && ((1 << size) >= map_size)); 1347 } 1348 1349 /** 1350 * Creates a <code>SampleModel</code> with the specified 1351 * width and height that has a data layout compatible with 1352 * this <code>ColorModel</code>. 1353 * @param w the width to apply to the new <code>SampleModel</code> 1354 * @param h the height to apply to the new <code>SampleModel</code> 1355 * @return a <code>SampleModel</code> object with the specified 1356 * width and height. 1357 * @throws IllegalArgumentException if <code>w</code> or 1358 * <code>h</code> is not greater than 0 1359 * @see SampleModel 1360 */ 1361 public SampleModel createCompatibleSampleModel(int w, int h) { 1362 int[] off = new int[1]; 1363 off[0] = 0; 1364 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) { 1365 return new MultiPixelPackedSampleModel(transferType, w, h, 1366 pixel_bits); 1367 } 1368 else { 1369 return new ComponentSampleModel(transferType, w, h, 1, w, 1370 off); 1371 } 1372 } 1373 1374 /** 1375 * Checks if the specified <code>SampleModel</code> is compatible 1376 * with this <code>ColorModel</code>. If <code>sm</code> is 1377 * <code>null</code>, this method returns <code>false</code>. 1378 * @param sm the specified <code>SampleModel</code>, 1379 * or <code>null</code> 1380 * @return <code>true</code> if the specified <code>SampleModel</code> 1381 * is compatible with this <code>ColorModel</code>; <code>false</code> 1382 * otherwise. 1383 * @see SampleModel 1384 */ 1385 public boolean isCompatibleSampleModel(SampleModel sm) { 1386 // fix 4238629 1387 if (! (sm instanceof ComponentSampleModel) && 1388 ! (sm instanceof MultiPixelPackedSampleModel) ) { 1389 return false; 1390 } 1391 1392 // Transfer type must be the same 1393 if (sm.getTransferType() != transferType) { 1394 return false; 1395 } 1396 1397 if (sm.getNumBands() != 1) { 1398 return false; 1399 } 1400 1401 return true; 1402 } 1403 1404 /** 1405 * Returns a new <code>BufferedImage</code> of TYPE_INT_ARGB or 1406 * TYPE_INT_RGB that has a <code>Raster</code> with pixel data 1407 * computed by expanding the indices in the source <code>Raster</code> 1408 * using the color/alpha component arrays of this <code>ColorModel</code>. 1409 * Only the lower <em>n</em> bits of each index value in the source 1410 * <code>Raster</code>, as specified in the 1411 * <a href="#index_values">class description</a> above, are used to 1412 * compute the color/alpha values in the returned image. 1413 * If <code>forceARGB</code> is <code>true</code>, a TYPE_INT_ARGB image is 1414 * returned regardless of whether or not this <code>ColorModel</code> 1415 * has an alpha component array or a transparent pixel. 1416 * @param raster the specified <code>Raster</code> 1417 * @param forceARGB if <code>true</code>, the returned 1418 * <code>BufferedImage</code> is TYPE_INT_ARGB; otherwise it is 1419 * TYPE_INT_RGB 1420 * @return a <code>BufferedImage</code> created with the specified 1421 * <code>Raster</code> 1422 * @throws IllegalArgumentException if the raster argument is not 1423 * compatible with this IndexColorModel 1424 */ 1425 public BufferedImage convertToIntDiscrete(Raster raster, 1426 boolean forceARGB) { 1427 ColorModel cm; 1428 1429 if (!isCompatibleRaster(raster)) { 1430 throw new IllegalArgumentException("This raster is not compatible" + 1431 "with this IndexColorModel."); 1432 } 1433 if (forceARGB || transparency == TRANSLUCENT) { 1434 cm = ColorModel.getRGBdefault(); 1435 } 1436 else if (transparency == BITMASK) { 1437 cm = new DirectColorModel(25, 0xff0000, 0x00ff00, 0x0000ff, 1438 0x1000000); 1439 } 1440 else { 1441 cm = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff); 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) && 1479 (validBits == null || validBits.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 } 1506 else { 1507 return validBits; 1508 } 1509 } 1510 1511 /** 1512 * Disposes of system resources associated with this 1513 * <code>ColorModel</code> once this <code>ColorModel</code> is no 1514 * longer referenced. 1515 */ 1516 public void finalize() { 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 1529 + " transparency = "+transparency 1530 + " transIndex = "+transparent_index 1531 + " has alpha = "+supportsAlpha 1532 + " isAlphaPre = "+isAlphaPremultiplied 1533 ); 1534 } 1535 } | 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} class is a {@code ColorModel} 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} 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} objects are never pre-multiplied with 55 * the alpha components. 56 * <p> 57 * <a name="transparency"> 58 * The transparency of an {@code IndexColorModel} 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} 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}. 70 * Otherwise, the value is {@code Transparency.TRANSLUCENT}, indicating 71 * that some valid color has an alpha component that is 72 * neither completely transparent nor completely opaque 73 * (0.0 < alpha < 1.0). 74 * </a> 75 * 76 * <p> 77 * If an {@code IndexColorModel} object has 78 * a transparency value of {@code Transparency.OPAQUE}, 79 * then the {@code hasAlpha} 80 * and {@code getNumComponents} methods 81 * (both inherited from {@code ColorModel}) 82 * return false and 3, respectively. 83 * For any other transparency value, 84 * {@code hasAlpha} returns true 85 * and {@code getNumComponents} 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 * </a> 102 * <p> 103 * For those methods that use a primitive array pixel representation of 104 * type {@code transferType}, the array length is always one. 105 * The transfer types supported are {@code DataBuffer.TYPE_BYTE} and 106 * {@code DataBuffer.TYPE_USHORT}. A single int pixel 107 * representation is valid for all objects of this class, since it is 108 * always possible to represent pixel values used with this class in a 109 * single int. Therefore, methods that use this representation do 110 * not throw an {@code IllegalArgumentException} due to an invalid 111 * pixel value. 112 * <p> 113 * Many of the methods in this class are final. The reason for 114 * this is that the underlying native graphics code makes assumptions 115 * about the layout and operation of this class and those assumptions 116 * are reflected in the implementations of the methods here that are 117 * marked final. You can subclass this class for other reasons, but 118 * you cannot override or modify the behaviour of those methods. 119 * 120 * @see ColorModel 121 * @see ColorSpace 122 * @see DataBuffer 123 * 124 */ 125 public class IndexColorModel extends ColorModel { 126 private int rgb[]; 127 private int map_size; 128 private int pixel_mask; 129 private int transparent_index = -1; 130 private boolean allgrayopaque; 131 private BigInteger validBits; 132 133 private sun.awt.image.BufImgSurfaceData.ICMColorData colorData = null; 134 135 private static int[] opaqueBits = {8, 8, 8}; 136 private static int[] alphaBits = {8, 8, 8, 8}; 137 138 private static native void initIDs(); 139 static { 140 ColorModel.loadLibraries(); 141 initIDs(); 142 } 143 /** 144 * Constructs an {@code IndexColorModel} from the specified 145 * arrays of red, green, and blue components. Pixels described 146 * by this color model all have alpha components of 255 147 * unnormalized (1.0 normalized), which means they 148 * are fully opaque. All of the arrays specifying the color 149 * components must have at least the specified number of entries. 150 * The {@code ColorSpace} is the default sRGB space. 151 * Since there is no alpha information in any of the arguments 152 * to this constructor, the transparency value is always 153 * {@code Transparency.OPAQUE}. 154 * The transfer type is the smallest of {@code DataBuffer.TYPE_BYTE} 155 * or {@code DataBuffer.TYPE_USHORT} that can hold a single pixel. 156 * @param bits the number of bits each pixel occupies 157 * @param size the size of the color component arrays 158 * @param r the array of red color components 159 * @param g the array of green color components 160 * @param b the array of blue color components 161 * @throws IllegalArgumentException if {@code bits} is less 162 * than 1 or greater than 16 163 * @throws IllegalArgumentException if {@code size} is less 164 * than 1 165 */ 166 public IndexColorModel(int bits, int size, 167 byte r[], byte g[], byte b[]) { 168 super(bits, opaqueBits, 169 ColorSpace.getInstance(ColorSpace.CS_sRGB), 170 false, false, OPAQUE, 171 ColorModel.getDefaultTransferType(bits)); 172 if (bits < 1 || bits > 16) { 173 throw new IllegalArgumentException("Number of bits must be between" 174 +" 1 and 16."); 175 } 176 setRGBs(size, r, g, b, null); 177 calculatePixelMask(); 178 } 179 180 /** 181 * Constructs an {@code IndexColorModel} from the given arrays 182 * of red, green, and blue components. Pixels described by this color 183 * model all have alpha components of 255 unnormalized 184 * (1.0 normalized), which means they are fully opaque, except 185 * for the indicated pixel to be made transparent. All of the arrays 186 * specifying the color components must have at least the specified 187 * number of entries. 188 * The {@code ColorSpace} is the default sRGB space. 189 * The transparency value may be {@code Transparency.OPAQUE} or 190 * {@code Transparency.BITMASK} depending on the arguments, as 191 * specified in the <a href="#transparency">class description</a> above. 192 * The transfer type is the smallest of {@code DataBuffer.TYPE_BYTE} 193 * or {@code DataBuffer.TYPE_USHORT} that can hold a 194 * single pixel. 195 * @param bits the number of bits each pixel occupies 196 * @param size the size of the color component arrays 197 * @param r the array of red color components 198 * @param g the array of green color components 199 * @param b the array of blue color components 200 * @param trans the index of the transparent pixel 201 * @throws IllegalArgumentException if {@code bits} is less than 202 * 1 or greater than 16 203 * @throws IllegalArgumentException if {@code size} is less than 204 * 1 205 */ 206 public IndexColorModel(int bits, int size, 207 byte r[], byte g[], byte b[], int trans) { 208 super(bits, opaqueBits, 209 ColorSpace.getInstance(ColorSpace.CS_sRGB), 210 false, false, OPAQUE, 211 ColorModel.getDefaultTransferType(bits)); 212 if (bits < 1 || bits > 16) { 213 throw new IllegalArgumentException("Number of bits must be between" 214 +" 1 and 16."); 215 } 216 setRGBs(size, r, g, b, null); 217 setTransparentPixel(trans); 218 calculatePixelMask(); 219 } 220 221 /** 222 * Constructs an {@code IndexColorModel} from the given 223 * arrays of red, green, blue and alpha components. All of the 224 * arrays specifying the components must have at least the specified 225 * number of entries. 226 * The {@code ColorSpace} is the default sRGB space. 227 * The transparency value may be any of {@code Transparency.OPAQUE}, 228 * {@code Transparency.BITMASK}, 229 * or {@code Transparency.TRANSLUCENT} 230 * depending on the arguments, as specified 231 * in the <a href="#transparency">class description</a> above. 232 * The transfer type is the smallest of {@code DataBuffer.TYPE_BYTE} 233 * or {@code DataBuffer.TYPE_USHORT} that can hold a single pixel. 234 * @param bits the number of bits each pixel occupies 235 * @param size the size of the color component arrays 236 * @param r the array of red color components 237 * @param g the array of green color components 238 * @param b the array of blue color components 239 * @param a the array of alpha value components 240 * @throws IllegalArgumentException if {@code bits} is less 241 * than 1 or greater than 16 242 * @throws IllegalArgumentException if {@code size} is less 243 * than 1 244 */ 245 public IndexColorModel(int bits, int size, 246 byte r[], byte g[], byte b[], byte a[]) { 247 super (bits, alphaBits, 248 ColorSpace.getInstance(ColorSpace.CS_sRGB), 249 true, false, TRANSLUCENT, 250 ColorModel.getDefaultTransferType(bits)); 251 if (bits < 1 || bits > 16) { 252 throw new IllegalArgumentException("Number of bits must be between" 253 +" 1 and 16."); 254 } 255 setRGBs (size, r, g, b, a); 256 calculatePixelMask(); 257 } 258 259 /** 260 * Constructs an {@code IndexColorModel} from a single 261 * array of interleaved red, green, blue and optional alpha 262 * components. The array must have enough values in it to 263 * fill all of the needed component arrays of the specified 264 * size. The {@code ColorSpace} is the default sRGB space. 265 * The transparency value may be any of {@code Transparency.OPAQUE}, 266 * {@code Transparency.BITMASK}, 267 * or {@code Transparency.TRANSLUCENT} 268 * depending on the arguments, as specified 269 * in the <a href="#transparency">class description</a> above. 270 * The transfer type is the smallest of 271 * {@code DataBuffer.TYPE_BYTE} or {@code DataBuffer.TYPE_USHORT} 272 * that can hold a single pixel. 273 * 274 * @param bits the number of bits each pixel occupies 275 * @param size the size of the color component arrays 276 * @param cmap the array of color components 277 * @param start the starting offset of the first color component 278 * @param hasalpha indicates whether alpha values are contained in 279 * the {@code cmap} array 280 * @throws IllegalArgumentException if {@code bits} is less 281 * than 1 or greater than 16 282 * @throws IllegalArgumentException if {@code size} is less 283 * than 1 284 */ 285 public IndexColorModel(int bits, int size, byte cmap[], int start, 286 boolean hasalpha) { 287 this(bits, size, cmap, start, hasalpha, -1); 288 if (bits < 1 || bits > 16) { 289 throw new IllegalArgumentException("Number of bits must be between" 290 +" 1 and 16."); 291 } 292 } 293 294 /** 295 * Constructs an {@code IndexColorModel} from a single array of 296 * interleaved red, green, blue and optional alpha components. The 297 * specified transparent index represents a pixel that is made 298 * entirely transparent regardless of any alpha value specified 299 * for it. The array must have enough values in it to fill all 300 * of the needed component arrays of the specified size. 301 * The {@code ColorSpace} is the default sRGB space. 302 * The transparency value may be any of {@code Transparency.OPAQUE}, 303 * {@code Transparency.BITMASK}, 304 * or {@code Transparency.TRANSLUCENT} 305 * depending on the arguments, as specified 306 * in the <a href="#transparency">class description</a> above. 307 * The transfer type is the smallest of 308 * {@code DataBuffer.TYPE_BYTE} or {@code DataBuffer.TYPE_USHORT} 309 * that can hold a single pixel. 310 * @param bits the number of bits each pixel occupies 311 * @param size the size of the color component arrays 312 * @param cmap the array of color components 313 * @param start the starting offset of the first color component 314 * @param hasalpha indicates whether alpha values are contained in 315 * the {@code cmap} array 316 * @param trans the index of the fully transparent pixel 317 * @throws IllegalArgumentException if {@code bits} is less than 318 * 1 or greater than 16 319 * @throws IllegalArgumentException if {@code size} is less than 320 * 1 321 */ 322 public IndexColorModel(int bits, int size, byte cmap[], int start, 323 boolean hasalpha, int trans) { 324 // REMIND: This assumes the ordering: RGB[A] 325 super(bits, opaqueBits, 326 ColorSpace.getInstance(ColorSpace.CS_sRGB), 327 false, false, OPAQUE, 328 ColorModel.getDefaultTransferType(bits)); 329 330 if (bits < 1 || bits > 16) { 331 throw new IllegalArgumentException("Number of bits must be between" 332 +" 1 and 16."); 333 } 334 if (size < 1) { 335 throw new IllegalArgumentException("Map size ("+size+ 336 ") must be >= 1"); 337 } 338 map_size = size; 339 rgb = new int[calcRealMapSize(bits, size)]; 354 transparency = BITMASK; 355 } 356 if (transparent_index < 0) { 357 transparent_index = i; 358 } 359 } else { 360 transparency = TRANSLUCENT; 361 } 362 allgray = false; 363 } 364 } 365 rgb[i] = (alpha << 24) | (r << 16) | (g << 8) | b; 366 } 367 this.allgrayopaque = allgray; 368 setTransparency(transparency); 369 setTransparentPixel(trans); 370 calculatePixelMask(); 371 } 372 373 /** 374 * Constructs an {@code IndexColorModel} from an array of 375 * ints where each int is comprised of red, green, blue, and 376 * optional alpha components in the default RGB color model format. 377 * The specified transparent index represents a pixel that is made 378 * entirely transparent regardless of any alpha value specified 379 * for it. The array must have enough values in it to fill all 380 * of the needed component arrays of the specified size. 381 * The {@code ColorSpace} is the default sRGB space. 382 * The transparency value may be any of {@code Transparency.OPAQUE}, 383 * {@code Transparency.BITMASK}, 384 * or {@code Transparency.TRANSLUCENT} 385 * depending on the arguments, as specified 386 * in the <a href="#transparency">class description</a> above. 387 * @param bits the number of bits each pixel occupies 388 * @param size the size of the color component arrays 389 * @param cmap the array of color components 390 * @param start the starting offset of the first color component 391 * @param hasalpha indicates whether alpha values are contained in 392 * the {@code cmap} array 393 * @param trans the index of the fully transparent pixel 394 * @param transferType the data type of the array used to represent 395 * pixel values. The data type must be either 396 * {@code DataBuffer.TYPE_BYTE} or 397 * {@code DataBuffer.TYPE_USHORT}. 398 * @throws IllegalArgumentException if {@code bits} is less 399 * than 1 or greater than 16 400 * @throws IllegalArgumentException if {@code size} is less 401 * than 1 402 * @throws IllegalArgumentException if {@code transferType} is not 403 * one of {@code DataBuffer.TYPE_BYTE} or 404 * {@code DataBuffer.TYPE_USHORT} 405 */ 406 public IndexColorModel(int bits, int size, 407 int cmap[], int start, 408 boolean hasalpha, int trans, int transferType) { 409 // REMIND: This assumes the ordering: RGB[A] 410 super(bits, opaqueBits, 411 ColorSpace.getInstance(ColorSpace.CS_sRGB), 412 false, false, OPAQUE, 413 transferType); 414 415 if (bits < 1 || bits > 16) { 416 throw new IllegalArgumentException("Number of bits must be between" 417 +" 1 and 16."); 418 } 419 if (size < 1) { 420 throw new IllegalArgumentException("Map size ("+size+ 421 ") must be >= 1"); 422 } 423 if ((transferType != DataBuffer.TYPE_BYTE) && 424 (transferType != DataBuffer.TYPE_USHORT)) { 425 throw new IllegalArgumentException("transferType must be either" + 426 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); 427 } 428 429 setRGBs(size, cmap, start, hasalpha); 430 setTransparentPixel(trans); 431 calculatePixelMask(); 432 } 433 434 /** 435 * Constructs an {@code IndexColorModel} from an 436 * {@code int} array where each {@code int} is 437 * comprised of red, green, blue, and alpha 438 * components in the default RGB color model format. 439 * The array must have enough values in it to fill all 440 * of the needed component arrays of the specified size. 441 * The {@code ColorSpace} is the default sRGB space. 442 * The transparency value may be any of {@code Transparency.OPAQUE}, 443 * {@code Transparency.BITMASK}, 444 * or {@code Transparency.TRANSLUCENT} 445 * depending on the arguments, as specified 446 * in the <a href="#transparency">class description</a> above. 447 * The transfer type must be one of {@code DataBuffer.TYPE_BYTE} 448 * {@code DataBuffer.TYPE_USHORT}. 449 * The {@code BigInteger} object specifies the valid/invalid pixels 450 * in the {@code cmap} array. A pixel is valid if the 451 * {@code BigInteger} value at that index is set, and is invalid 452 * if the {@code BigInteger} bit at that index is not set. 453 * @param bits the number of bits each pixel occupies 454 * @param size the size of the color component array 455 * @param cmap the array of color components 456 * @param start the starting offset of the first color component 457 * @param transferType the specified data type 458 * @param validBits a {@code BigInteger} object. If a bit is 459 * set in the BigInteger, the pixel at that index is valid. 460 * If a bit is not set, the pixel at that index 461 * is considered invalid. If null, all pixels are valid. 462 * Only bits from 0 to the map size are considered. 463 * @throws IllegalArgumentException if {@code bits} is less 464 * than 1 or greater than 16 465 * @throws IllegalArgumentException if {@code size} is less 466 * than 1 467 * @throws IllegalArgumentException if {@code transferType} is not 468 * one of {@code DataBuffer.TYPE_BYTE} or 469 * {@code DataBuffer.TYPE_USHORT} 470 * 471 * @since 1.3 472 */ 473 public IndexColorModel(int bits, int size, int cmap[], int start, 474 int transferType, BigInteger validBits) { 475 super (bits, alphaBits, 476 ColorSpace.getInstance(ColorSpace.CS_sRGB), 477 true, false, TRANSLUCENT, 478 transferType); 479 480 if (bits < 1 || bits > 16) { 481 throw new IllegalArgumentException("Number of bits must be between" 482 +" 1 and 16."); 483 } 484 if (size < 1) { 485 throw new IllegalArgumentException("Map size ("+size+ 486 ") must be >= 1"); 487 } 488 if ((transferType != DataBuffer.TYPE_BYTE) && 489 (transferType != DataBuffer.TYPE_USHORT)) { 582 setTransparency(transparency); 583 } 584 585 private int calcRealMapSize(int bits, int size) { 586 int newSize = Math.max(1 << bits, size); 587 return Math.max(newSize, 256); 588 } 589 590 private BigInteger getAllValid() { 591 int numbytes = (map_size+7)/8; 592 byte[] valid = new byte[numbytes]; 593 java.util.Arrays.fill(valid, (byte)0xff); 594 valid[0] = (byte)(0xff >>> (numbytes*8 - map_size)); 595 596 return new BigInteger(1, valid); 597 } 598 599 /** 600 * Returns the transparency. Returns either OPAQUE, BITMASK, 601 * or TRANSLUCENT 602 * @return the transparency of this {@code IndexColorModel} 603 * @see Transparency#OPAQUE 604 * @see Transparency#BITMASK 605 * @see Transparency#TRANSLUCENT 606 */ 607 public int getTransparency() { 608 return transparency; 609 } 610 611 /** 612 * Returns an array of the number of bits for each color/alpha component. 613 * The array contains the color components in the order red, green, 614 * blue, followed by the alpha component, if present. 615 * @return an array containing the number of bits of each color 616 * and alpha component of this {@code IndexColorModel} 617 */ 618 public int[] getComponentSize() { 619 if (nBits == null) { 620 if (supportsAlpha) { 621 nBits = new int[4]; 622 nBits[3] = 8; 623 } 624 else { 625 nBits = new int[3]; 626 } 627 nBits[0] = nBits[1] = nBits[2] = 8; 628 } 629 return nBits.clone(); 630 } 631 632 /** 633 * Returns the size of the color/alpha component arrays in this 634 * {@code IndexColorModel}. 635 * @return the size of the color and alpha component arrays. 636 */ 637 public final int getMapSize() { 638 return map_size; 639 } 640 641 /** 642 * Returns the index of a transparent pixel in this 643 * {@code IndexColorModel} or -1 if there is no pixel 644 * with an alpha value of 0. If a transparent pixel was 645 * explicitly specified in one of the constructors by its 646 * index, then that index will be preferred, otherwise, 647 * the index of any pixel which happens to be fully transparent 648 * may be returned. 649 * @return the index of a transparent pixel in this 650 * {@code IndexColorModel} object, or -1 if there 651 * is no such pixel 652 */ 653 public final int getTransparentPixel() { 654 return transparent_index; 655 } 656 657 /** 658 * Copies the array of red color components into the specified array. 659 * Only the initial entries of the array as specified by 660 * {@link #getMapSize() getMapSize} are written. 661 * @param r the specified array into which the elements of the 662 * array of red color components are copied 663 */ 664 public final void getReds(byte r[]) { 665 for (int i = 0; i < map_size; i++) { 666 r[i] = (byte) (rgb[i] >> 16); 667 } 668 } 669 670 /** 671 * Copies the array of green color components into the specified array. 672 * Only the initial entries of the array as specified by 673 * {@code getMapSize} are written. 674 * @param g the specified array into which the elements of the 675 * array of green color components are copied 676 */ 677 public final void getGreens(byte g[]) { 678 for (int i = 0; i < map_size; i++) { 679 g[i] = (byte) (rgb[i] >> 8); 680 } 681 } 682 683 /** 684 * Copies the array of blue color components into the specified array. 685 * Only the initial entries of the array as specified by 686 * {@code getMapSize} are written. 687 * @param b the specified array into which the elements of the 688 * array of blue color components are copied 689 */ 690 public final void getBlues(byte b[]) { 691 for (int i = 0; i < map_size; i++) { 692 b[i] = (byte) rgb[i]; 693 } 694 } 695 696 /** 697 * Copies the array of alpha transparency components into the 698 * specified array. Only the initial entries of the array as specified 699 * by {@code getMapSize} are written. 700 * @param a the specified array into which the elements of the 701 * array of alpha components are copied 702 */ 703 public final void getAlphas(byte a[]) { 704 for (int i = 0; i < map_size; i++) { 705 a[i] = (byte) (rgb[i] >> 24); 706 } 707 } 708 709 /** 710 * Converts data for each index from the color and alpha component 711 * arrays to an int in the default RGB ColorModel format and copies 712 * the resulting 32-bit ARGB values into the specified array. Only 713 * the initial entries of the array as specified by 714 * {@code getMapSize} are 715 * written. 716 * @param rgb the specified array into which the converted ARGB 717 * values from this array of color and alpha components 718 * are copied. 719 */ 720 public final void getRGBs(int rgb[]) { 721 System.arraycopy(this.rgb, 0, rgb, 0, map_size); 722 } 723 724 private void setTransparentPixel(int trans) { 725 if (trans >= 0 && trans < map_size) { 726 rgb[trans] &= 0x00ffffff; 727 transparent_index = trans; 728 allgrayopaque = false; 729 if (this.transparency == OPAQUE) { 730 setTransparency(BITMASK); 731 } 732 } 733 } 734 830 * <a href="#index_values">class description</a> above, are used to 831 * calculate the returned value. 832 * The returned value is in a non pre-multiplied format. 833 * @param pixel the specified pixel 834 * @return the color and alpha components of the specified pixel 835 * @see ColorModel#getRGBdefault 836 */ 837 public final int getRGB(int pixel) { 838 return rgb[pixel & pixel_mask]; 839 } 840 841 private static final int CACHESIZE = 40; 842 private int lookupcache[] = new int[CACHESIZE]; 843 844 /** 845 * Returns a data element array representation of a pixel in this 846 * ColorModel, given an integer pixel representation in the 847 * default RGB color model. This array can then be passed to the 848 * {@link WritableRaster#setDataElements(int, int, java.lang.Object) setDataElements} 849 * method of a {@link WritableRaster} object. If the pixel variable is 850 * {@code null}, a new array is allocated. If {@code pixel} 851 * is not {@code null}, it must be 852 * a primitive array of type {@code transferType}; otherwise, a 853 * {@code ClassCastException} is thrown. An 854 * {@code ArrayIndexOutOfBoundsException} is 855 * thrown if {@code pixel} is not large enough to hold a pixel 856 * value for this {@code ColorModel}. The pixel array is returned. 857 * <p> 858 * Since {@code IndexColorModel} can be subclassed, subclasses 859 * inherit the implementation of this method and if they don't 860 * override it then they throw an exception if they use an 861 * unsupported {@code transferType}. 862 * 863 * @param rgb the integer pixel representation in the default RGB 864 * color model 865 * @param pixel the specified pixel 866 * @return an array representation of the specified pixel in this 867 * {@code IndexColorModel}. 868 * @throws ClassCastException if {@code pixel} 869 * is not a primitive array of type {@code transferType} 870 * @throws ArrayIndexOutOfBoundsException if 871 * {@code pixel} is not large enough to hold a pixel value 872 * for this {@code ColorModel} 873 * @throws UnsupportedOperationException if {@code transferType} 874 * is invalid 875 * @see WritableRaster#setDataElements 876 * @see SampleModel#setDataElements 877 */ 878 public synchronized Object getDataElements(int rgb, Object pixel) { 879 int red = (rgb>>16) & 0xff; 880 int green = (rgb>>8) & 0xff; 881 int blue = rgb & 0xff; 882 int alpha = (rgb>>>24); 883 int pix = 0; 884 885 // Note that pixels are stored at lookupcache[2*i] 886 // and the rgb that was searched is stored at 887 // lookupcache[2*i+1]. Also, the pixel is first 888 // inverted using the unary complement operator 889 // before storing in the cache so it can never be 0. 890 for (int i = CACHESIZE - 2; i >= 0; i -= 2) { 891 if ((pix = lookupcache[i]) == 0) { 892 break; 893 } 1050 byteObj[0] = (byte) pix; 1051 break; 1052 case DataBuffer.TYPE_USHORT: 1053 short[] shortObj; 1054 if (pixel == null) { 1055 pixel = shortObj = new short[1]; 1056 } else { 1057 shortObj = (short[]) pixel; 1058 } 1059 shortObj[0] = (short) pix; 1060 break; 1061 default: 1062 throw new UnsupportedOperationException("This method has not been "+ 1063 "implemented for transferType " + transferType); 1064 } 1065 return pixel; 1066 } 1067 1068 /** 1069 * Returns an array of unnormalized color/alpha components for a 1070 * specified pixel in this {@code ColorModel}. The pixel value 1071 * is specified as an int. If the {@code components} array is {@code null}, 1072 * a new array is allocated that contains 1073 * {@code offset + getNumComponents()} elements. 1074 * The {@code components} array is returned, 1075 * with the alpha component included 1076 * only if {@code hasAlpha} returns true. 1077 * Color/alpha components are stored in the {@code components} array starting 1078 * at {@code offset} even if the array is allocated by this method. 1079 * An {@code ArrayIndexOutOfBoundsException} 1080 * is thrown if the {@code components} array is not {@code null} and is 1081 * not large enough to hold all the color and alpha components 1082 * starting at {@code offset}. 1083 * @param pixel the specified pixel 1084 * @param components the array to receive the color and alpha 1085 * components of the specified pixel 1086 * @param offset the offset into the {@code components} array at 1087 * which to start storing the color and alpha components 1088 * @return an array containing the color and alpha components of the 1089 * specified pixel starting at the specified offset. 1090 * @see ColorModel#hasAlpha 1091 * @see ColorModel#getNumComponents 1092 */ 1093 public int[] getComponents(int pixel, int[] components, int offset) { 1094 if (components == null) { 1095 components = new int[offset+numComponents]; 1096 } 1097 1098 // REMIND: Needs to change if different color space 1099 components[offset+0] = getRed(pixel); 1100 components[offset+1] = getGreen(pixel); 1101 components[offset+2] = getBlue(pixel); 1102 if (supportsAlpha && (components.length-offset) > 3) { 1103 components[offset+3] = getAlpha(pixel); 1104 } 1105 1106 return components; 1107 } 1108 1109 /** 1110 * Returns an array of unnormalized color/alpha components for 1111 * a specified pixel in this {@code ColorModel}. The pixel 1112 * value is specified by an array of data elements of type 1113 * {@code transferType} passed in as an object reference. 1114 * If {@code pixel} is not a primitive array of type 1115 * {@code transferType}, a {@code ClassCastException} 1116 * is thrown. An {@code ArrayIndexOutOfBoundsException} 1117 * is thrown if {@code pixel} is not large enough to hold 1118 * a pixel value for this {@code ColorModel}. If the 1119 * {@code components} array is {@code null}, a new array 1120 * is allocated that contains 1121 * {@code offset + getNumComponents()} elements. 1122 * The {@code components} array is returned, 1123 * with the alpha component included 1124 * only if {@code hasAlpha} returns true. 1125 * Color/alpha components are stored in the {@code components} 1126 * array starting at {@code offset} even if the array is 1127 * allocated by this method. An 1128 * {@code ArrayIndexOutOfBoundsException} is also 1129 * thrown if the {@code components} array is not 1130 * {@code null} and is not large enough to hold all the color 1131 * and alpha components starting at {@code offset}. 1132 * <p> 1133 * Since {@code IndexColorModel} can be subclassed, subclasses 1134 * inherit the implementation of this method and if they don't 1135 * override it then they throw an exception if they use an 1136 * unsupported {@code transferType}. 1137 * 1138 * @param pixel the specified pixel 1139 * @param components an array that receives the color and alpha 1140 * components of the specified pixel 1141 * @param offset the index into the {@code components} array at 1142 * which to begin storing the color and alpha components of the 1143 * specified pixel 1144 * @return an array containing the color and alpha components of the 1145 * specified pixel starting at the specified offset. 1146 * @throws ArrayIndexOutOfBoundsException if {@code pixel} 1147 * is not large enough to hold a pixel value for this 1148 * {@code ColorModel} or if the 1149 * {@code components} array is not {@code null} 1150 * and is not large enough to hold all the color 1151 * and alpha components starting at {@code offset} 1152 * @throws ClassCastException if {@code pixel} is not a 1153 * primitive array of type {@code transferType} 1154 * @throws UnsupportedOperationException if {@code transferType} 1155 * is not one of the supported transfer types 1156 * @see ColorModel#hasAlpha 1157 * @see ColorModel#getNumComponents 1158 */ 1159 public int[] getComponents(Object pixel, int[] components, 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("This method has not been "+ 1176 "implemented for transferType " + transferType); 1177 } 1178 return getComponents(intpixel, components, offset); 1179 } 1180 1181 /** 1182 * Returns a pixel value represented as an int in this 1183 * {@code ColorModel} given an array of unnormalized 1184 * color/alpha components. An 1185 * {@code ArrayIndexOutOfBoundsException} 1186 * is thrown if the {@code components} array is not large 1187 * enough to hold all of the color and alpha components starting 1188 * at {@code offset}. Since 1189 * {@code ColorModel} can be subclassed, subclasses inherit the 1190 * implementation of this method and if they don't override it then 1191 * they throw an exception if they use an unsupported transferType. 1192 * @param components an array of unnormalized color and alpha 1193 * components 1194 * @param offset the index into {@code components} at which to 1195 * begin retrieving the color and alpha components 1196 * @return an {@code int} pixel value in this 1197 * {@code ColorModel} corresponding to the specified components. 1198 * @throws ArrayIndexOutOfBoundsException if 1199 * the {@code components} array is not large enough to 1200 * hold all of the color and alpha components starting at 1201 * {@code offset} 1202 * @throws UnsupportedOperationException if {@code transferType} 1203 * is invalid 1204 */ 1205 public int getDataElement(int[] components, int offset) { 1206 int rgb = (components[offset+0]<<16) 1207 | (components[offset+1]<<8) | (components[offset+2]); 1208 if (supportsAlpha) { 1209 rgb |= (components[offset+3]<<24); 1210 } 1211 else { 1212 rgb |= 0xff000000; 1213 } 1214 Object inData = getDataElements(rgb, null); 1215 int pixel; 1216 switch (transferType) { 1217 case DataBuffer.TYPE_BYTE: 1218 byte bdata[] = (byte[])inData; 1219 pixel = bdata[0] & 0xff; 1220 break; 1221 case DataBuffer.TYPE_USHORT: 1222 short sdata[] = (short[])inData; 1223 pixel = sdata[0]; 1224 break; 1225 case DataBuffer.TYPE_INT: 1226 int idata[] = (int[])inData; 1227 pixel = idata[0]; 1228 break; 1229 default: 1230 throw new UnsupportedOperationException("This method has not been "+ 1231 "implemented for transferType " + transferType); 1232 } 1233 return pixel; 1234 } 1235 1236 /** 1237 * Returns a data element array representation of a pixel in this 1238 * {@code ColorModel} given an array of unnormalized color/alpha 1239 * components. This array can then be passed to the 1240 * {@code setDataElements} method of a {@code WritableRaster} 1241 * object. An {@code ArrayIndexOutOfBoundsException} is 1242 * thrown if the 1243 * {@code components} array is not large enough to hold all of the 1244 * color and alpha components starting at {@code offset}. 1245 * If the pixel variable is {@code null}, a new array 1246 * is allocated. If {@code pixel} is not {@code null}, 1247 * it must be a primitive array of type {@code transferType}; 1248 * otherwise, a {@code ClassCastException} is thrown. 1249 * An {@code ArrayIndexOutOfBoundsException} is thrown if pixel 1250 * is not large enough to hold a pixel value for this 1251 * {@code ColorModel}. 1252 * <p> 1253 * Since {@code IndexColorModel} can be subclassed, subclasses 1254 * inherit the implementation of this method and if they don't 1255 * override it then they throw an exception if they use an 1256 * unsupported {@code transferType} 1257 * 1258 * @param components an array of unnormalized color and alpha 1259 * components 1260 * @param offset the index into {@code components} at which to 1261 * begin retrieving color and alpha components 1262 * @param pixel the {@code Object} representing an array of color 1263 * and alpha components 1264 * @return an {@code Object} representing an array of color and 1265 * alpha components. 1266 * @throws ClassCastException if {@code pixel} 1267 * is not a primitive array of type {@code transferType} 1268 * @throws ArrayIndexOutOfBoundsException if 1269 * {@code pixel} is not large enough to hold a pixel value 1270 * for this {@code ColorModel} or the {@code components} 1271 * array is not large enough to hold all of the color and alpha 1272 * components starting at {@code offset} 1273 * @throws UnsupportedOperationException if {@code transferType} 1274 * is not one of the supported transfer types 1275 * @see WritableRaster#setDataElements 1276 * @see SampleModel#setDataElements 1277 */ 1278 public Object getDataElements(int[] components, int offset, Object pixel) { 1279 int rgb = (components[offset+0]<<16) | (components[offset+1]<<8) 1280 | (components[offset+2]); 1281 if (supportsAlpha) { 1282 rgb |= (components[offset+3]<<24); 1283 } 1284 else { 1285 rgb &= 0xff000000; 1286 } 1287 return getDataElements(rgb, pixel); 1288 } 1289 1290 /** 1291 * Creates a {@code WritableRaster} with the specified width 1292 * and height that has a data layout ({@code SampleModel}) 1293 * compatible with this {@code ColorModel}. This method 1294 * only works for color models with 16 or fewer bits per pixel. 1295 * <p> 1296 * Since {@code IndexColorModel} can be subclassed, any 1297 * subclass that supports greater than 16 bits per pixel must 1298 * override this method. 1299 * 1300 * @param w the width to apply to the new {@code WritableRaster} 1301 * @param h the height to apply to the new {@code WritableRaster} 1302 * @return a {@code WritableRaster} object with the specified 1303 * width and height. 1304 * @throws UnsupportedOperationException if the number of bits in a 1305 * pixel is greater than 16 1306 * @see WritableRaster 1307 * @see SampleModel 1308 */ 1309 public WritableRaster createCompatibleWritableRaster(int w, int h) { 1310 WritableRaster raster; 1311 1312 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) { 1313 // TYPE_BINARY 1314 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, 1315 w, h, 1, pixel_bits, null); 1316 } 1317 else if (pixel_bits <= 8) { 1318 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1319 w,h,1,null); 1320 } 1321 else if (pixel_bits <= 16) { 1322 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, 1323 w,h,1,null); 1324 } 1325 else { 1326 throw new 1327 UnsupportedOperationException("This method is not supported "+ 1328 " for pixel bits > 16."); 1329 } 1330 return raster; 1331 } 1332 1333 /** 1334 * Returns {@code true} if {@code raster} is compatible 1335 * with this {@code ColorModel} or {@code false} if it 1336 * is not compatible with this {@code ColorModel}. 1337 * @param raster the {@link Raster} object to test for compatibility 1338 * @return {@code true} if {@code raster} is compatible 1339 * with this {@code ColorModel}; {@code false} otherwise. 1340 * 1341 */ 1342 public boolean isCompatibleRaster(Raster raster) { 1343 1344 int size = raster.getSampleModel().getSampleSize(0); 1345 return ((raster.getTransferType() == transferType) && 1346 (raster.getNumBands() == 1) && ((1 << size) >= map_size)); 1347 } 1348 1349 /** 1350 * Creates a {@code SampleModel} with the specified 1351 * width and height that has a data layout compatible with 1352 * this {@code ColorModel}. 1353 * @param w the width to apply to the new {@code SampleModel} 1354 * @param h the height to apply to the new {@code SampleModel} 1355 * @return a {@code SampleModel} object with the specified 1356 * width and height. 1357 * @throws IllegalArgumentException if {@code w} or 1358 * {@code h} is not greater than 0 1359 * @see SampleModel 1360 */ 1361 public SampleModel createCompatibleSampleModel(int w, int h) { 1362 int[] off = new int[1]; 1363 off[0] = 0; 1364 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) { 1365 return new MultiPixelPackedSampleModel(transferType, w, h, 1366 pixel_bits); 1367 } 1368 else { 1369 return new ComponentSampleModel(transferType, w, h, 1, w, 1370 off); 1371 } 1372 } 1373 1374 /** 1375 * Checks if the specified {@code SampleModel} is compatible 1376 * with this {@code ColorModel}. If {@code sm} is 1377 * {@code null}, this method returns {@code false}. 1378 * @param sm the specified {@code SampleModel}, 1379 * or {@code null} 1380 * @return {@code true} if the specified {@code SampleModel} 1381 * is compatible with this {@code ColorModel}; {@code false} 1382 * otherwise. 1383 * @see SampleModel 1384 */ 1385 public boolean isCompatibleSampleModel(SampleModel sm) { 1386 // fix 4238629 1387 if (! (sm instanceof ComponentSampleModel) && 1388 ! (sm instanceof MultiPixelPackedSampleModel) ) { 1389 return false; 1390 } 1391 1392 // Transfer type must be the same 1393 if (sm.getTransferType() != transferType) { 1394 return false; 1395 } 1396 1397 if (sm.getNumBands() != 1) { 1398 return false; 1399 } 1400 1401 return true; 1402 } 1403 1404 /** 1405 * Returns a new {@code BufferedImage} of TYPE_INT_ARGB or 1406 * TYPE_INT_RGB that has a {@code Raster} with pixel data 1407 * computed by expanding the indices in the source {@code Raster} 1408 * using the color/alpha component arrays of this {@code ColorModel}. 1409 * Only the lower <em>n</em> bits of each index value in the source 1410 * {@code Raster}, as specified in the 1411 * <a href="#index_values">class description</a> above, are used to 1412 * compute the color/alpha values in the returned image. 1413 * If {@code forceARGB} is {@code true}, a TYPE_INT_ARGB image is 1414 * returned regardless of whether or not this {@code ColorModel} 1415 * has an alpha component array or a transparent pixel. 1416 * @param raster the specified {@code Raster} 1417 * @param forceARGB if {@code true}, the returned 1418 * {@code BufferedImage} is TYPE_INT_ARGB; otherwise it is 1419 * TYPE_INT_RGB 1420 * @return a {@code BufferedImage} created with the specified 1421 * {@code Raster} 1422 * @throws IllegalArgumentException if the raster argument is not 1423 * compatible with this IndexColorModel 1424 */ 1425 public BufferedImage convertToIntDiscrete(Raster raster, 1426 boolean forceARGB) { 1427 ColorModel cm; 1428 1429 if (!isCompatibleRaster(raster)) { 1430 throw new IllegalArgumentException("This raster is not compatible" + 1431 "with this IndexColorModel."); 1432 } 1433 if (forceARGB || transparency == TRANSLUCENT) { 1434 cm = ColorModel.getRGBdefault(); 1435 } 1436 else if (transparency == BITMASK) { 1437 cm = new DirectColorModel(25, 0xff0000, 0x00ff00, 0x0000ff, 1438 0x1000000); 1439 } 1440 else { 1441 cm = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff); 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} if {@code pixel} 1474 * is valid; {@code false} otherwise. 1475 * @since 1.3 1476 */ 1477 public boolean isValid(int pixel) { 1478 return ((pixel >= 0 && pixel < map_size) && 1479 (validBits == null || validBits.testBit(pixel))); 1480 } 1481 1482 /** 1483 * Returns whether or not all of the pixels are valid. 1484 * @return {@code true} if all pixels are valid; 1485 * {@code false} otherwise. 1486 * @since 1.3 1487 */ 1488 public boolean isValid() { 1489 return (validBits == null); 1490 } 1491 1492 /** 1493 * Returns a {@code BigInteger} that indicates the valid/invalid 1494 * pixels in the colormap. A bit is valid if the 1495 * {@code BigInteger} value at that index is set, and is invalid 1496 * if the {@code BigInteger} value at that index is not set. 1497 * The only valid ranges to query in the {@code BigInteger} are 1498 * between 0 and the map size. 1499 * @return a {@code BigInteger} indicating the valid/invalid pixels. 1500 * @since 1.3 1501 */ 1502 public BigInteger getValidPixels() { 1503 if (validBits == null) { 1504 return getAllValid(); 1505 } 1506 else { 1507 return validBits; 1508 } 1509 } 1510 1511 /** 1512 * Disposes of system resources associated with this 1513 * {@code ColorModel} once this {@code ColorModel} is no 1514 * longer referenced. 1515 */ 1516 public void finalize() { 1517 } 1518 1519 /** 1520 * Returns the {@code String} representation of the contents of 1521 * this {@code ColorModel} object. 1522 * @return a {@code String} representing the contents of this 1523 * {@code ColorModel} object. 1524 */ 1525 public String toString() { 1526 return new String("IndexColorModel: #pixelBits = "+pixel_bits 1527 + " numComponents = "+numComponents 1528 + " color space = "+colorSpace 1529 + " transparency = "+transparency 1530 + " transIndex = "+transparent_index 1531 + " has alpha = "+supportsAlpha 1532 + " isAlphaPre = "+isAlphaPremultiplied 1533 ); 1534 } 1535 } |