Frames | No Frames |
1: /* IndexColorModel.java -- Java class for interpreting Pixel objects 2: Copyright (C) 1999, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package java.awt.image; 39: 40: import gnu.java.awt.Buffers; 41: 42: import java.awt.color.ColorSpace; 43: import java.math.BigInteger; 44: 45: /** 46: * Color model similar to pseudo visual in X11. 47: * <br><br> 48: * This color model maps linear pixel values to actual RGB and alpha colors. 49: * Thus, pixel values are indexes into the color map. Each color component is 50: * an 8-bit unsigned value. 51: * <br><br> 52: * The <code>IndexColorModel</code> supports a map of valid pixels, allowing 53: * the representation of holes in the the color map. The valid map is 54: * represented as a {@link BigInteger} where each bit indicates the validity 55: * of the map entry with the same index. 56: * <br><br> 57: * Colors can have alpha components for transparency support. If alpha 58: * component values aren't given, color values are opaque. The model also 59: * supports a reserved pixel value to represent completely transparent colors, 60: * no matter what the actual color component values are. 61: * <br><br> 62: * <code>IndexColorModel</code> supports anywhere from 1 to 16 bit index 63: * values. The allowed transfer types are {@link DataBuffer#TYPE_BYTE} and 64: * {@link DataBuffer#TYPE_USHORT}. 65: * 66: * @author C. Brian Jones (cbj@gnu.org) 67: */ 68: public class IndexColorModel extends ColorModel 69: { 70: private int map_size; 71: private boolean opaque; // no alpha, but doesn't account for trans 72: private int trans = -1; 73: private int[] rgb; 74: private BigInteger validBits = BigInteger.ZERO; 75: 76: /** 77: * Creates a new indexed color model for <code>size</code> color elements 78: * with no alpha component. Each array must contain at least 79: * <code>size</code> elements. For each array, the i-th color is described 80: * by reds[i], greens[i] and blues[i]. 81: * 82: * @param bits the number of bits needed to represent <code>size</code> 83: * colors. 84: * @param size the number of colors in the color map. 85: * @param reds the red component of all colors. 86: * @param greens the green component of all colors. 87: * @param blues the blue component of all colors. 88: * 89: * @throws IllegalArgumentException if <code>bits</code> < 1 or 90: * <code>bits</code> > 16. 91: * @throws NullPointerException if any of the arrays is <code>null</code>. 92: * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater 93: * than the length of the component arrays. 94: */ 95: public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, 96: byte[] blues) 97: { 98: this(bits, size, reds, greens, blues, (byte[]) null); 99: } 100: 101: /** 102: * Creates a new indexed color model for <code>size</code> color elements. 103: * Each array must contain at least <code>size</code> elements. For each 104: * array, the i-th color is described by reds[i], greens[i] and blues[i]. 105: * All the colors are opaque except for the transparent color. 106: * 107: * @param bits the number of bits needed to represent <code>size</code> 108: * colors 109: * @param size the number of colors in the color map 110: * @param reds the red component of all colors 111: * @param greens the green component of all colors 112: * @param blues the blue component of all colors 113: * @param trans the index of the transparent color (use -1 for no 114: * transparent color). 115: * 116: * @throws IllegalArgumentException if <code>bits</code> < 1 or 117: * <code>bits</code> > 16. 118: * @throws NullPointerException if any of the arrays is <code>null</code>. 119: * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater 120: * than the length of the component arrays. 121: */ 122: public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, 123: byte[] blues, int trans) 124: { 125: super(bits, nArray(8, (0 <= trans && trans < size) ? 4 : 3), 126: ColorSpace.getInstance(ColorSpace.CS_sRGB), 127: (0 <= trans && trans < size), // hasAlpha 128: false, OPAQUE, 129: Buffers.smallestAppropriateTransferType(bits)); 130: if (bits < 1) 131: throw new IllegalArgumentException("bits < 1"); 132: if (bits > 16) 133: throw new IllegalArgumentException("bits > 16"); 134: if (size < 1) 135: throw new IllegalArgumentException("size < 1"); 136: map_size = size; 137: rgb = createColorMap(bits, size); 138: for (int i = 0; i < size; i++) 139: { 140: rgb[i] = (0xff000000 141: | ((reds[i] & 0xff) << 16) 142: | ((greens[i] & 0xff) << 8) 143: | (blues[i] & 0xff)); 144: } 145: 146: setTransparentPixel(trans); 147: 148: // Generate a bigint with 1's for every pixel 149: validBits = validBits.setBit(size).subtract(BigInteger.ONE); 150: } 151: 152: /** 153: * Creates a new indexed color model for <code>size</code> color elements 154: * including alpha. Each array must contain at least <code>size</code> 155: * elements. For each array, the i-th color is described 156: * by reds[i], greens[i], blues[i] and alphas[i]. 157: * 158: * @param bits the number of bits needed to represent <code>size</code> 159: * colors. 160: * @param size the number of colors in the color map. 161: * @param reds the red component of all colors. 162: * @param greens the green component of all colors. 163: * @param blues the blue component of all colors. 164: * @param alphas the alpha component of all colors (<code>null</code> 165: * permitted). 166: * 167: * @throws IllegalArgumentException if <code>bits</code> < 1 or 168: * <code>bits</code> > 16. 169: * @throws NullPointerException if <code>reds</code>, <code>greens</code> or 170: * <code>blues</code> is <code>null</code>. 171: * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater 172: * than the length of the component arrays. 173: */ 174: public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, 175: byte[] blues, byte[] alphas) 176: { 177: super(bits, nArray(8, (alphas == null ? 3 : 4)), 178: ColorSpace.getInstance(ColorSpace.CS_sRGB), 179: (alphas != null), false, TRANSLUCENT, 180: Buffers.smallestAppropriateTransferType(bits)); 181: if (bits < 1) 182: throw new IllegalArgumentException("bits < 1"); 183: if (bits > 16) 184: throw new IllegalArgumentException("bits > 16"); 185: if (size < 1) 186: throw new IllegalArgumentException("size < 1"); 187: map_size = size; 188: opaque = (alphas == null); 189: 190: rgb = createColorMap(bits, size); 191: if (alphas == null) 192: { 193: for (int i = 0; i < size; i++) 194: { 195: rgb[i] = (0xff000000 196: | ((reds[i] & 0xff) << 16) 197: | ((greens[i] & 0xff) << 8) 198: | (blues[i] & 0xff)); 199: } 200: transparency = OPAQUE; 201: } 202: else 203: { 204: byte alphaZero = (byte) 0x00; 205: byte alphaOne = (byte) 0xFF; 206: for (int i = 0; i < size; i++) 207: { 208: alphaZero = (byte) (alphaZero | alphas[i]); 209: alphaOne = (byte) (alphaOne & alphas[i]); 210: rgb[i] = ((alphas[i] & 0xff) << 24 211: | ((reds[i] & 0xff) << 16) 212: | ((greens[i] & 0xff) << 8) 213: | (blues[i] & 0xff)); 214: } 215: if ((alphaZero == (byte) 0x00) || (alphaOne == (byte) 0xFF)) 216: transparency = BITMASK; 217: else 218: transparency = TRANSLUCENT; 219: } 220: 221: // Generate a bigint with 1's for every pixel 222: validBits = validBits.setBit(size).subtract(BigInteger.ONE); 223: } 224: 225: /** 226: * Creates a new indexed color model using the color components in 227: * <code>cmap</code>. If <code>hasAlpha</code> is <code>true</code> then 228: * <code>cmap</code> contains an alpha component after each of the red, green 229: * and blue components. 230: * 231: * @param bits the number of bits needed to represent <code>size</code> 232: * colors 233: * @param size the number of colors in the color map 234: * @param cmap packed color components 235: * @param start the offset of the first color component in <code>cmap</code> 236: * @param hasAlpha <code>cmap</code> has alpha values 237: * @throws IllegalArgumentException if bits < 1, bits > 16, or size 238: * < 1. 239: * @throws NullPointerException if <code>cmap</code> is <code>null</code>. 240: */ 241: public IndexColorModel(int bits, int size, byte[] cmap, int start, 242: boolean hasAlpha) 243: { 244: this(bits, size, cmap, start, hasAlpha, -1); 245: } 246: 247: /** 248: * Construct an IndexColorModel from an array of red, green, blue, and 249: * optional alpha components. The component values are interleaved as RGB(A). 250: * 251: * @param bits the number of bits needed to represent <code>size</code> 252: * colors 253: * @param size the number of colors in the color map 254: * @param cmap interleaved color components 255: * @param start the offset of the first color component in <code>cmap</code> 256: * @param hasAlpha <code>cmap</code> has alpha values 257: * @param trans the index of the transparent color 258: * @throws IllegalArgumentException if bits < 1, bits > 16, or size 259: * < 1. 260: * @throws NullPointerException if <code>cmap</code> is <code>null</code>. 261: */ 262: public IndexColorModel(int bits, int size, byte[] cmap, int start, 263: boolean hasAlpha, int trans) 264: { 265: super(bits, nArray(8, hasAlpha || (0 <= trans && trans < size) ? 4 : 3), 266: ColorSpace.getInstance(ColorSpace.CS_sRGB), 267: hasAlpha || (0 <= trans && trans < size), false, OPAQUE, 268: Buffers.smallestAppropriateTransferType(bits)); 269: if (bits < 1) 270: throw new IllegalArgumentException("bits < 1"); 271: if (bits > 16) 272: throw new IllegalArgumentException("bits > 16"); 273: if (size < 1) 274: throw new IllegalArgumentException("size < 1"); 275: map_size = size; 276: opaque = !hasAlpha; 277: 278: rgb = createColorMap(bits, size); 279: if (hasAlpha) 280: { 281: int alpha; 282: int alphaZero = 0x00; // use to detect all zeros 283: int alphaOne = 0xff; // use to detect all ones 284: for (int i = 0; i < size; i++) { 285: alpha = cmap[4 * i + 3 + start] & 0xff; 286: alphaZero = alphaZero | alpha; 287: alphaOne = alphaOne & alpha; 288: rgb[i] = 289: ( alpha << 24 290: // red 291: | ((cmap[4 * i + start] & 0xff) << 16) 292: // green 293: | ((cmap[4 * i + 1 + start] & 0xff) << 8) 294: // blue 295: | (cmap[4 * i + 2 + start] & 0xff)); 296: } 297: if (alphaZero == 0) 298: transparency = BITMASK; 299: else if (alphaOne == 255) 300: transparency = (trans != -1 ? BITMASK : OPAQUE); 301: else 302: transparency = TRANSLUCENT; 303: } 304: else 305: { 306: for (int i = 0; i < size; i++) 307: rgb[i] = (0xff000000 308: // red 309: | ((cmap[3 * i + start] & 0xff) << 16) 310: // green 311: | ((cmap[3 * i + 1 + start] & 0xff) << 8) 312: // blue 313: | (cmap[3 * i + 2 + start] & 0xff)); 314: if (trans != -1) 315: transparency = BITMASK; 316: } 317: 318: setTransparentPixel(trans); 319: 320: // Generate a bigint with 1's for every pixel 321: validBits = validBits.setBit(size).subtract(BigInteger.ONE); 322: } 323: 324: /** 325: * Construct an IndexColorModel from an array of <code>size</code> packed 326: * colors. Each int element contains 8-bit red, green, blue, and optional 327: * alpha values packed in order. If hasAlpha is false, then all the colors 328: * are opaque except for the transparent color. 329: * 330: * @param bits the number of bits needed to represent <code>size</code> 331: * colors 332: * @param size the number of colors in the color map 333: * @param cmap packed color components 334: * @param start the offset of the first color component in <code>cmap</code> 335: * @param hasAlpha <code>cmap</code> has alpha values 336: * @param trans the index of the transparent color 337: * @param transferType {@link DataBuffer#TYPE_BYTE} or 338: {@link DataBuffer#TYPE_USHORT}. 339: * @throws IllegalArgumentException if bits < 1, bits > 16, or size 340: * < 1. 341: * @throws IllegalArgumentException if <code>transferType</code> is something 342: * other than {@link DataBuffer#TYPE_BYTE} or 343: * {@link DataBuffer#TYPE_USHORT}. 344: */ 345: public IndexColorModel(int bits, int size, int[] cmap, int start, 346: boolean hasAlpha, int trans, int transferType) 347: { 348: super(bits, 349: nArray(8, 4), // bits for each channel 350: ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB 351: true, // has alpha 352: false, // not premultiplied 353: TRANSLUCENT, transferType); 354: if (transferType != DataBuffer.TYPE_BYTE 355: && transferType != DataBuffer.TYPE_USHORT) 356: throw new IllegalArgumentException(); 357: if (bits > 16) 358: throw new IllegalArgumentException("bits > 16"); 359: if (size < 1) 360: throw new IllegalArgumentException("size < 1"); 361: map_size = size; 362: opaque = !hasAlpha; 363: rgb = createColorMap(bits, size); 364: if (!hasAlpha) 365: for (int i = 0; i < size; i++) 366: rgb[i] = cmap[i + start] | 0xff000000; 367: else 368: System.arraycopy(cmap, start, rgb, 0, size); 369: 370: setTransparentPixel(trans); 371: 372: // Generate a bigint with 1's for every pixel 373: validBits = validBits.setBit(size).subtract(BigInteger.ONE); 374: } 375: 376: /** 377: * Construct an IndexColorModel using a colormap with holes. 378: * <br><br> 379: * The IndexColorModel is built from the array of ints defining the 380: * colormap. Each element contains red, green, blue, and alpha 381: * components. The ColorSpace is sRGB. The transparency value is 382: * automatically determined. 383: * <br><br> 384: * This constructor permits indicating which colormap entries are valid, 385: * using the validBits argument. Each entry in cmap is valid if the 386: * corresponding bit in validBits is set. 387: * 388: * @param bits the number of bits needed to represent <code>size</code> 389: * colors. 390: * @param size the number of colors in the color map. 391: * @param cmap packed color components. 392: * @param start the offset of the first color component in <code>cmap</code>. 393: * @param transferType {@link DataBuffer#TYPE_BYTE} or 394: * {@link DataBuffer#TYPE_USHORT}. 395: * @param validBits a map of the valid entries in <code>cmap</code>. 396: * @throws IllegalArgumentException if bits < 1, bits > 16, or size 397: * < 1. 398: * @throws IllegalArgumentException if transferType is something other than 399: * {@link DataBuffer#TYPE_BYTE} or {@link DataBuffer#TYPE_USHORT}. 400: */ 401: public IndexColorModel(int bits, int size, int[] cmap, int start, 402: int transferType, BigInteger validBits) 403: { 404: super(bits, // total bits, sRGB, four channels 405: nArray(8, 4), // bits for each channel 406: ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB 407: true, // has alpha 408: false, // not premultiplied 409: TRANSLUCENT, transferType); 410: if (transferType != DataBuffer.TYPE_BYTE 411: && transferType != DataBuffer.TYPE_USHORT) 412: throw new IllegalArgumentException(); 413: if (bits > 16) 414: throw new IllegalArgumentException("bits > 16"); 415: if (size < 1) 416: throw new IllegalArgumentException("size < 1"); 417: map_size = size; 418: opaque = false; 419: this.trans = -1; 420: this.validBits = validBits; 421: 422: rgb = createColorMap(bits, size); 423: if (!hasAlpha) 424: for (int i = 0; i < size; i++) 425: rgb[i] = cmap[i + start] | 0xff000000; 426: else 427: System.arraycopy(cmap, start, rgb, 0, size); 428: } 429: 430: /** 431: * Returns the size of the color lookup table. 432: * 433: * @return The size of the color lookup table. 434: */ 435: public final int getMapSize() 436: { 437: return map_size; 438: } 439: 440: /** 441: * Get the index of the transparent color in this color model. 442: * 443: * @return The index of the color that is considered transparent, or -1 if 444: * there is no transparent color. 445: */ 446: public final int getTransparentPixel() 447: { 448: return trans; 449: } 450: 451: /** 452: * Fills the supplied array with the red component of each color in the 453: * lookup table. 454: * 455: * @param r an array that is at least as large as {@link #getMapSize()}. 456: * @throws NullPointerException if <code>r</code> is <code>null</code>. 457: * @throws ArrayIndexOutOfBoundsException if <code>r</code> has less 458: * than {@link #getMapSize()} elements. 459: */ 460: public final void getReds(byte[] r) 461: { 462: int i; 463: for (i = 0; i < map_size; i++) 464: r[i] = (byte) ((0x00FF0000 & rgb[i]) >> 16); 465: } 466: 467: /** 468: * Fills the supplied array with the green component of each color in the 469: * lookup table. 470: * 471: * @param g an array that is at least as large as {@link #getMapSize()}. 472: * @throws NullPointerException if <code>g</code> is <code>null</code>. 473: * @throws ArrayIndexOutOfBoundsException if <code>g</code> has less 474: * than {@link #getMapSize()} elements. 475: */ 476: public final void getGreens(byte[] g) 477: { 478: int i; 479: for (i = 0; i < map_size; i++) 480: g[i] = (byte) ((0x0000FF00 & rgb[i]) >> 8); 481: } 482: 483: /** 484: * Fills the supplied array with the blue component of each color in the 485: * lookup table. 486: * 487: * @param b an array that is at least as large as {@link #getMapSize()}. 488: * @throws NullPointerException if <code>b</code> is <code>null</code>. 489: * @throws ArrayIndexOutOfBoundsException if <code>b</code> has less 490: * than {@link #getMapSize()} elements. 491: */ 492: public final void getBlues(byte[] b) 493: { 494: int i; 495: for (i = 0; i < map_size; i++) 496: b[i] = (byte) (0x000000FF & rgb[i]); 497: } 498: 499: /** 500: * Fills the supplied array with the alpha component of each color in the 501: * lookup table. If the model has a transparent pixel specified, the alpha 502: * for that pixel will be 0. 503: * 504: * @param a an array that is at least as large as {@link #getMapSize()}. 505: * @throws NullPointerException if <code>a</code> is <code>null</code>. 506: * @throws ArrayIndexOutOfBoundsException if <code>a</code> has less 507: * than {@link #getMapSize()} elements. 508: */ 509: public final void getAlphas(byte[] a) 510: { 511: int i; 512: for (i = 0; i < map_size; i++) 513: if (i == trans) 514: a[i] = (byte) 0; 515: else 516: a[i] = (byte) ((0xFF000000 & rgb[i]) >> 24); 517: } 518: 519: /** 520: * Returns the red component of the color in the lookup table for the 521: * given pixel value. 522: * 523: * @param pixel the pixel lookup value. 524: * 525: * @return The red component of the color in the lookup table. 526: * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. 527: */ 528: public final int getRed(int pixel) 529: { 530: if (pixel < map_size) 531: return (0x00FF0000 & rgb[pixel]) >> 16; 532: 533: return 0; 534: } 535: 536: /** 537: * Returns the green component of the color in the lookup table for the 538: * given pixel value. 539: * 540: * @param pixel the pixel lookup value. 541: * 542: * @return The green component of the color in the lookup table. 543: * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. 544: */ 545: public final int getGreen(int pixel) 546: { 547: if (pixel < map_size) 548: return (0x0000FF00 & rgb[pixel]) >> 8; 549: 550: return 0; 551: } 552: 553: /** 554: * Returns the blue component of the color in the lookup table for the 555: * given pixel value. 556: * 557: * @param pixel the pixel lookup value. 558: * 559: * @return The blue component of the color in the lookup table. 560: * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. 561: */ 562: public final int getBlue(int pixel) 563: { 564: if (pixel < map_size) 565: return 0x000000FF & rgb[pixel]; 566: 567: return 0; 568: } 569: 570: /** 571: * Returns the alpha component of the color in the lookup table for the 572: * given pixel value. If no alpha channel was specified when the color model 573: * was created, then 255 is returned for all pixels except the transparent 574: * pixel (if one is defined - see {@link #getTransparentPixel()}) which 575: * returns an alpha of 0. 576: * 577: * @param pixel the pixel lookup value. 578: * 579: * @return The alpha component of the color in the lookup table (in the 580: * range 0 to 255). 581: * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. 582: */ 583: public final int getAlpha(int pixel) 584: { 585: return (rgb[pixel] >> 24) & 0xFF; 586: } 587: 588: /** 589: * Get the RGB color value of the given pixel using the default 590: * RGB color model. 591: * 592: * @param pixel the pixel lookup value. 593: * @return The RGB color value. 594: * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. 595: */ 596: public final int getRGB(int pixel) 597: { 598: if (pixel >= 0 && pixel < map_size) 599: return rgb[pixel]; 600: 601: return 0; 602: } 603: 604: /** 605: * Get the RGB color values of all pixels in the map using the default 606: * RGB color model. 607: * 608: * @param rgb The destination array. 609: */ 610: public final void getRGBs(int[] rgb) 611: { 612: System.arraycopy(this.rgb, 0, rgb, 0, map_size); 613: } 614: 615: /** 616: * Return <code>true</code> if the lookup table contains valid data for 617: * <code>pixel</code>, and <code>false</code> otherwise. 618: * 619: * @param pixel the pixel value used to index the color lookup table. 620: * @return <code>true</code> if <code>pixel</code> is valid, 621: * <code>false</code> otherwise. 622: */ 623: public boolean isValid(int pixel) 624: { 625: if (pixel >= 0) 626: return validBits.testBit(pixel); 627: return false; 628: } 629: 630: /** 631: * Return <code>true</code> if all pixels are valid, <code>false</code> 632: * otherwise. 633: * 634: * @return <code>true</code> if all pixels are valid, <code>false</code> 635: * otherwise. 636: */ 637: public boolean isValid() 638: { 639: // Generate a bigint with 1's for every pixel 640: BigInteger allbits = new BigInteger("0"); 641: allbits = allbits.setBit(map_size); 642: allbits = allbits.subtract(new BigInteger("1")); 643: return allbits.equals(validBits); 644: } 645: 646: /** 647: * Returns a binary value ({@link BigInteger}) where each bit represents an 648: * entry in the color lookup table. If the bit is on, the entry is valid. 649: * 650: * @return The binary value. 651: */ 652: public BigInteger getValidPixels() 653: { 654: return validBits; 655: } 656: 657: /** 658: * Construct a {@link BufferedImage} with rgb pixel values from a 659: * {@link Raster}. 660: * 661: * Constructs a new BufferedImage in which each pixel is an RGBA int from 662: * a Raster with index-valued pixels. If this model has no alpha component 663: * or transparent pixel, the type of the new BufferedImage is TYPE_INT_RGB. 664: * Otherwise the type is TYPE_INT_ARGB. If forceARGB is true, the type is 665: * forced to be TYPE_INT_ARGB no matter what. 666: * 667: * @param raster The source of pixel values. 668: * @param forceARGB True if type must be TYPE_INT_ARGB. 669: * @return New BufferedImage with RBGA int pixel values. 670: */ 671: public BufferedImage convertToIntDiscrete(Raster raster, boolean forceARGB) 672: { 673: int type = forceARGB ? BufferedImage.TYPE_INT_ARGB 674: : ((opaque && trans == -1) ? BufferedImage.TYPE_INT_RGB : 675: BufferedImage.TYPE_INT_ARGB); 676: 677: // FIXME: assuming that raster has only 1 band since pixels are supposed 678: // to be int indexes. 679: // FIXME: it would likely be more efficient to fetch a complete array, 680: // but it would take much more memory. 681: // FIXME: I'm not sure if transparent pixels or alpha values need special 682: // handling here. 683: BufferedImage im = new BufferedImage(raster.width, raster.height, type); 684: for (int x = raster.minX; x < raster.width + raster.minX; x++) 685: for (int y = raster.minY; y < raster.height + raster.minY; y++) 686: im.setRGB(x, y, rgb[raster.getSample(x, y, 0)]); 687: 688: return im; 689: } 690: 691: /** 692: * Creates a {@link SampleModel} that is compatible to this color model. 693: * This will be a {@link MultiPixelPackedSampleModel} for bits/pixel of 694: * 1, 2 or 4, or a {@link ComponentColorModel} for the other cases. 695: * 696: * @param w the width of the sample model to create 697: * @param h the height of the sample model to create 698: * 699: * @return a compatible sample model 700: */ 701: public SampleModel createCompatibleSampleModel(int w, int h) 702: { 703: SampleModel sm; 704: if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) 705: sm = new MultiPixelPackedSampleModel(transferType, w, h, pixel_bits); 706: else 707: sm = new ComponentSampleModel(transferType, w, h, 1, w, new int[]{0}); 708: return sm; 709: } 710: 711: /** 712: * Sets the transparent pixel. This is called by the various constructors. 713: * 714: * @param t the transparent pixel 715: */ 716: private void setTransparentPixel(int t) 717: { 718: if (t >= 0 && t < map_size) 719: { 720: rgb[t] &= 0xffffff; // Make the value transparent. 721: trans = t; 722: if (transparency == OPAQUE) 723: { 724: transparency = BITMASK; 725: hasAlpha = true; 726: } 727: } 728: } 729: 730: private int[] createColorMap(int bits, int size) 731: { 732: // According to a Mauve test, the RI allocates at least 256 entries here. 733: int realSize = Math.max(256, Math.max(1 << bits, size)); 734: return new int[realSize]; 735: } 736: }