Source for java.awt.image.IndexColorModel

   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> &lt; 1 or 
  90:    *         <code>bits</code> &gt; 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> &lt; 1 or 
 117:    *         <code>bits</code> &gt; 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:     if (0 <= trans && trans < size) {
 138:       this.trans = trans;
 139:       transparency = BITMASK;
 140:     }
 141:     rgb = new int[size];
 142:     for (int i = 0; i < size; i++)
 143:       {
 144:         rgb[i] = (0xff000000
 145:                   | ((reds[i] & 0xff) << 16)
 146:                   | ((greens[i] & 0xff) << 8)
 147:                   | (blues[i] & 0xff));
 148:       }
 149:     // Generate a bigint with 1's for every pixel
 150:     validBits = validBits.setBit(size).subtract(BigInteger.ONE);
 151:   }
 152: 
 153:   /**
 154:    * Creates a new indexed color model for <code>size</code> color elements 
 155:    * including alpha.  Each array must contain at least <code>size</code> 
 156:    * elements.  For each array, the i-th color is described 
 157:    * by reds[i], greens[i], blues[i] and alphas[i]. 
 158:    *
 159:    * @param bits the number of bits needed to represent <code>size</code> 
 160:    *             colors.
 161:    * @param size the number of colors in the color map.
 162:    * @param reds the red component of all colors.
 163:    * @param greens the green component of all colors.
 164:    * @param blues the blue component of all colors.
 165:    * @param alphas the alpha component of all colors (<code>null</code> 
 166:    *               permitted).
 167:    *
 168:    * @throws IllegalArgumentException if <code>bits</code> &lt; 1 or 
 169:    *           <code>bits</code> &gt; 16.
 170:    * @throws NullPointerException if <code>reds</code>, <code>greens</code> or
 171:    *         <code>blues</code> is <code>null</code>.
 172:    * @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater 
 173:    *         than the length of the component arrays.
 174:    */
 175:   public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
 176:                          byte[] blues, byte[] alphas)
 177:   {
 178:     super(bits, nArray(8, (alphas == null ? 3 : 4)), 
 179:         ColorSpace.getInstance(ColorSpace.CS_sRGB), 
 180:         (alphas != null), false, TRANSLUCENT, 
 181:         Buffers.smallestAppropriateTransferType(bits)); 
 182:     if (bits < 1) 
 183:       throw new IllegalArgumentException("bits < 1");
 184:     if (bits > 16)
 185:       throw new IllegalArgumentException("bits > 16");
 186:     if (size < 1)
 187:       throw new IllegalArgumentException("size < 1");
 188:     map_size = size;
 189:     opaque = (alphas == null);
 190: 
 191:     rgb = new int[size];
 192:     if (alphas == null)
 193:       {
 194:         for (int i = 0; i < size; i++)
 195:           {
 196:             rgb[i] = (0xff000000
 197:                       | ((reds[i] & 0xff) << 16)
 198:                       | ((greens[i] & 0xff) << 8)
 199:                       | (blues[i] & 0xff));
 200:           }
 201:         transparency = OPAQUE;
 202:       }
 203:     else
 204:       {
 205:     byte alphaZero = (byte) 0x00;
 206:         byte alphaOne = (byte) 0xFF;
 207:         for (int i = 0; i < size; i++)
 208:           {
 209:         alphaZero = (byte) (alphaZero | alphas[i]);
 210:             alphaOne = (byte) (alphaOne & alphas[i]);
 211:             rgb[i] = ((alphas[i] & 0xff) << 24
 212:                       | ((reds[i] & 0xff) << 16)
 213:                       | ((greens[i] & 0xff) << 8)
 214:                       | (blues[i] & 0xff));
 215:           }
 216:         if ((alphaZero == (byte) 0x00) || (alphaOne == (byte) 0xFF))
 217:       transparency = BITMASK;
 218:     else
 219:       transparency = TRANSLUCENT;
 220:       }
 221: 
 222:     // Generate a bigint with 1's for every pixel
 223:     validBits = validBits.setBit(size).subtract(BigInteger.ONE);
 224:   }
 225: 
 226:   /**
 227:    * Creates a new indexed color model using the color components in 
 228:    * <code>cmap</code>. If <code>hasAlpha</code> is <code>true</code> then
 229:    * <code>cmap</code> contains an alpha component after each of the red, green
 230:    * and blue components.
 231:    *
 232:    * @param bits the number of bits needed to represent <code>size</code> 
 233:    *             colors
 234:    * @param size the number of colors in the color map
 235:    * @param cmap packed color components
 236:    * @param start the offset of the first color component in <code>cmap</code>
 237:    * @param hasAlpha <code>cmap</code> has alpha values
 238:    * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size 
 239:    *         &lt; 1.
 240:    * @throws NullPointerException if <code>cmap</code> is <code>null</code>.
 241:    */
 242:   public IndexColorModel(int bits, int size, byte[] cmap, int start, 
 243:                          boolean hasAlpha)
 244:   {
 245:     this(bits, size, cmap, start, hasAlpha, -1);
 246:   }
 247: 
 248:   /**
 249:    * Construct an IndexColorModel from an array of red, green, blue, and
 250:    * optional alpha components. The component values are interleaved as RGB(A).
 251:    * 
 252:    * @param bits the number of bits needed to represent <code>size</code> 
 253:    *             colors
 254:    * @param size the number of colors in the color map
 255:    * @param cmap interleaved color components
 256:    * @param start the offset of the first color component in <code>cmap</code>
 257:    * @param hasAlpha <code>cmap</code> has alpha values
 258:    * @param trans the index of the transparent color
 259:    * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
 260:    *         &lt; 1.
 261:    * @throws NullPointerException if <code>cmap</code> is <code>null</code>.
 262:    */
 263:   public IndexColorModel(int bits, int size, byte[] cmap, int start, 
 264:                          boolean hasAlpha, int trans)
 265:   {
 266:     super(bits, nArray(8, hasAlpha || (0 <= trans && trans < size) ? 4 : 3), 
 267:         ColorSpace.getInstance(ColorSpace.CS_sRGB),
 268:         hasAlpha || (0 <= trans && trans < size), false, OPAQUE, 
 269:         Buffers.smallestAppropriateTransferType(bits));
 270:     if (bits < 1)
 271:       throw new IllegalArgumentException("bits < 1");
 272:     if (bits > 16)
 273:       throw new IllegalArgumentException("bits > 16");
 274:     if (size < 1)
 275:       throw new IllegalArgumentException("size < 1");
 276:     map_size = size;
 277:     opaque = !hasAlpha;
 278:     if (0 <= trans && trans < size)
 279:       this.trans = trans;
 280: 
 281:     rgb = new int[size];
 282:     if (hasAlpha)
 283:     {
 284:       int alpha;
 285:       int alphaZero = 0x00;  // use to detect all zeros
 286:       int alphaOne = 0xff;   // use to detect all ones
 287:       for (int i = 0; i < size; i++) {
 288:     alpha = cmap[4 * i + 3 + start] & 0xff;  
 289:         alphaZero = alphaZero | alpha;
 290:         alphaOne = alphaOne & alpha;
 291:         rgb[i] =
 292:       ( alpha << 24
 293:        // red
 294:        | ((cmap[4 * i + start] & 0xff) << 16)
 295:        // green
 296:        | ((cmap[4 * i + 1 + start] & 0xff) << 8)
 297:        // blue
 298:        | (cmap[4 * i + 2 + start] & 0xff));
 299:       }
 300:       if (alphaZero == 0) 
 301:     transparency = BITMASK;
 302:       else if (alphaOne == 255) 
 303:         transparency = (trans != -1 ? BITMASK : OPAQUE);
 304:       else
 305:     transparency = TRANSLUCENT;
 306:     }
 307:     else
 308:     {
 309:       for (int i = 0; i < size; i++)
 310:     rgb[i] = (0xff000000
 311:           // red
 312:           | ((cmap[3 * i + start] & 0xff) << 16)
 313:           // green
 314:           | ((cmap[3 * i + 1 + start] & 0xff) << 8)
 315:           // blue
 316:           | (cmap[3 * i + 2 + start] & 0xff));
 317:       if (trans != -1)
 318:     transparency = BITMASK;
 319:     }
 320: 
 321:     // Generate a bigint with 1's for every pixel
 322:     validBits = validBits.setBit(size).subtract(BigInteger.ONE);
 323:   }
 324: 
 325:   /**
 326:    * Construct an IndexColorModel from an array of <code>size</code> packed
 327:    * colors.  Each int element contains 8-bit red, green, blue, and optional
 328:    * alpha values packed in order.  If hasAlpha is false, then all the colors
 329:    * are opaque except for the transparent color.
 330:    *
 331:    * @param bits the number of bits needed to represent <code>size</code> 
 332:    *             colors
 333:    * @param size the number of colors in the color map
 334:    * @param cmap packed color components
 335:    * @param start the offset of the first color component in <code>cmap</code>
 336:    * @param hasAlpha <code>cmap</code> has alpha values
 337:    * @param trans the index of the transparent color
 338:    * @param transferType {@link DataBuffer#TYPE_BYTE} or 
 339:             {@link DataBuffer#TYPE_USHORT}.
 340:    * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
 341:    *         &lt; 1.
 342:    * @throws IllegalArgumentException if <code>transferType</code> is something
 343:    *         other than {@link DataBuffer#TYPE_BYTE} or 
 344:    *         {@link DataBuffer#TYPE_USHORT}.
 345:    */
 346:   public IndexColorModel(int bits, int size, int[] cmap, int start, 
 347:                          boolean hasAlpha, int trans, int transferType)
 348:   {
 349:     super(bits, 
 350:       nArray(8, 4), // bits for each channel
 351:       ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
 352:       true, // has alpha
 353:       false, // not premultiplied
 354:       TRANSLUCENT, transferType);
 355:     if (transferType != DataBuffer.TYPE_BYTE
 356:         && transferType != DataBuffer.TYPE_USHORT)
 357:       throw new IllegalArgumentException();
 358:     if (bits > 16)
 359:       throw new IllegalArgumentException("bits > 16");
 360:     if (size < 1)
 361:       throw new IllegalArgumentException("size < 1");
 362:     map_size = size;
 363:     opaque = !hasAlpha;
 364:     if (0 <= trans && trans < size)
 365:       this.trans = trans;
 366: 
 367:     rgb = new int[size];
 368:     if (!hasAlpha)
 369:       for (int i = 0; i < size; i++)
 370:     rgb[i] = cmap[i + start] | 0xff000000;
 371:     else
 372:       System.arraycopy(cmap, start, rgb, 0, size);
 373: 
 374:     // Generate a bigint with 1's for every pixel
 375:     validBits = validBits.setBit(size).subtract(BigInteger.ONE);
 376:   }
 377: 
 378:   /**
 379:    * Construct an IndexColorModel using a colormap with holes.
 380:    * <br><br>
 381:    * The IndexColorModel is built from the array of ints defining the
 382:    * colormap.  Each element contains red, green, blue, and alpha
 383:    * components.    The ColorSpace is sRGB.  The transparency value is
 384:    * automatically determined.
 385:    * <br><br>
 386:    * This constructor permits indicating which colormap entries are valid,
 387:    * using the validBits argument.  Each entry in cmap is valid if the
 388:    * corresponding bit in validBits is set.  
 389:    * 
 390:    * @param bits the number of bits needed to represent <code>size</code> 
 391:    *             colors.
 392:    * @param size the number of colors in the color map.
 393:    * @param cmap packed color components.
 394:    * @param start the offset of the first color component in <code>cmap</code>.
 395:    * @param transferType {@link DataBuffer#TYPE_BYTE} or 
 396:    *                     {@link DataBuffer#TYPE_USHORT}.
 397:    * @param validBits a map of the valid entries in <code>cmap</code>.
 398:    * @throws IllegalArgumentException if bits &lt; 1, bits &gt; 16, or size
 399:    *         &lt; 1.
 400:    * @throws IllegalArgumentException if transferType is something other than
 401:    *         {@link DataBuffer#TYPE_BYTE} or {@link DataBuffer#TYPE_USHORT}.
 402:    */
 403:   public IndexColorModel(int bits, int size, int[] cmap, int start, 
 404:                          int transferType, BigInteger validBits)
 405:   {
 406:     super(bits, // total bits, sRGB, four channels
 407:       nArray(8, 4), // bits for each channel
 408:       ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
 409:       true, // has alpha
 410:       false, // not premultiplied
 411:       TRANSLUCENT, transferType);
 412:     if (transferType != DataBuffer.TYPE_BYTE
 413:         && transferType != DataBuffer.TYPE_USHORT)
 414:       throw new IllegalArgumentException();
 415:     if (bits > 16)
 416:       throw new IllegalArgumentException("bits > 16");
 417:     if (size < 1)
 418:       throw new IllegalArgumentException("size < 1");
 419:     map_size = size;
 420:     opaque = false;
 421:     this.trans = -1;
 422:     this.validBits = validBits;
 423: 
 424:     rgb = new int[size];
 425:     if (!hasAlpha)
 426:       for (int i = 0; i < size; i++)
 427:     rgb[i] = cmap[i + start] | 0xff000000;
 428:     else
 429:       System.arraycopy(cmap, start, rgb, 0, size);
 430:   }
 431: 
 432:   /**
 433:    * Returns the size of the color lookup table.
 434:    *
 435:    * @return The size of the color lookup table.
 436:    */
 437:   public final int getMapSize()
 438:   {
 439:     return map_size;
 440:   }
 441: 
 442:   /**
 443:    * Get the index of the transparent color in this color model.
 444:    *
 445:    * @return The index of the color that is considered transparent, or -1 if 
 446:    *         there is no transparent color.
 447:    */
 448:   public final int getTransparentPixel()
 449:   {
 450:     return trans;
 451:   }
 452: 
 453:   /**
 454:    * Fills the supplied array with the red component of each color in the 
 455:    * lookup table.
 456:    *
 457:    * @param r an array that is at least as large as {@link #getMapSize()}.
 458:    * @throws NullPointerException if <code>r</code> is <code>null</code>.
 459:    * @throws ArrayIndexOutOfBoundsException if <code>r</code> has less 
 460:    *         than {@link #getMapSize()} elements. 
 461:    */
 462:   public final void getReds(byte[] r)
 463:   {
 464:     int i;
 465:     for (i = 0; i < map_size; i++)
 466:       r[i] = (byte) ((0x00FF0000  & rgb[i]) >> 16);
 467:   }
 468: 
 469:   /**
 470:    * Fills the supplied array with the green component of each color in the 
 471:    * lookup table.
 472:    *
 473:    * @param g an array that is at least as large as {@link #getMapSize()}.
 474:    * @throws NullPointerException if <code>g</code> is <code>null</code>.
 475:    * @throws ArrayIndexOutOfBoundsException if <code>g</code> has less 
 476:    *         than {@link #getMapSize()} elements. 
 477:    */
 478:   public final void getGreens(byte[] g)
 479:   {
 480:     int i;
 481:     for (i = 0; i < map_size; i++)
 482:       g[i] = (byte) ((0x0000FF00  & rgb[i]) >> 8);
 483:   }
 484: 
 485:   /**
 486:    * Fills the supplied array with the blue component of each color in the 
 487:    * lookup table.
 488:    *
 489:    * @param b an array that is at least as large as {@link #getMapSize()}.
 490:    * @throws NullPointerException if <code>b</code> is <code>null</code>.
 491:    * @throws ArrayIndexOutOfBoundsException if <code>b</code> has less 
 492:    *         than {@link #getMapSize()} elements. 
 493:    */
 494:   public final void getBlues(byte[] b)
 495:   {
 496:     int i;
 497:     for (i = 0; i < map_size; i++)
 498:       b[i] = (byte) (0x000000FF & rgb[i]);
 499:   }
 500: 
 501:   /**
 502:    * Fills the supplied array with the alpha component of each color in the 
 503:    * lookup table.  If the model has a transparent pixel specified, the alpha
 504:    * for that pixel will be 0.
 505:    *
 506:    * @param a an array that is at least as large as {@link #getMapSize()}.
 507:    * @throws NullPointerException if <code>a</code> is <code>null</code>.
 508:    * @throws ArrayIndexOutOfBoundsException if <code>a</code> has less 
 509:    *         than {@link #getMapSize()} elements. 
 510:    */
 511:   public final void getAlphas(byte[] a)
 512:   {
 513:     int i;
 514:     for (i = 0; i < map_size; i++)
 515:       if (i == trans) 
 516:     a[i] = (byte) 0;
 517:       else 
 518:         a[i] = (byte) ((0xFF000000  & rgb[i]) >> 24);
 519:   }
 520: 
 521:   /**
 522:    * Returns the red component of the color in the lookup table for the 
 523:    * given pixel value.
 524:    *
 525:    * @param pixel  the pixel lookup value.
 526:    *
 527:    * @return The red component of the color in the lookup table.
 528:    * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
 529:    */
 530:   public final int getRed(int pixel)
 531:   {
 532:     if (pixel < map_size)
 533:       return (0x00FF0000 & rgb[pixel]) >> 16;
 534:     
 535:     return 0;
 536:   }
 537: 
 538:   /**
 539:    * Returns the green component of the color in the lookup table for the 
 540:    * given pixel value.
 541:    *
 542:    * @param pixel  the pixel lookup value.
 543:    *
 544:    * @return The green component of the color in the lookup table.
 545:    * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
 546:    */
 547:   public final int getGreen(int pixel)
 548:   {
 549:     if (pixel < map_size)
 550:       return (0x0000FF00 & rgb[pixel]) >> 8;
 551:     
 552:     return 0;
 553:   }
 554: 
 555:   /**
 556:    * Returns the blue component of the color in the lookup table for the 
 557:    * given pixel value.
 558:    *
 559:    * @param pixel  the pixel lookup value.
 560:    *
 561:    * @return The blue component of the color in the lookup table.
 562:    * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
 563:    */
 564:   public final int getBlue(int pixel)
 565:   {
 566:     if (pixel < map_size)
 567:       return 0x000000FF & rgb[pixel];
 568:     
 569:     return 0;
 570:   }
 571: 
 572:   /**
 573:    * Returns the alpha component of the color in the lookup table for the 
 574:    * given pixel value. If no alpha channel was specified when the color model
 575:    * was created, then 255 is returned for all pixels except the transparent
 576:    * pixel (if one is defined - see {@link #getTransparentPixel()}) which
 577:    * returns an alpha of 0.
 578:    *
 579:    * @param pixel  the pixel lookup value.
 580:    *
 581:    * @return The alpha component of the color in the lookup table (in the 
 582:    *         range 0 to 255).
 583:    * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
 584:    */
 585:   public final int getAlpha(int pixel)
 586:   {
 587:     if (opaque && pixel != trans) 
 588:       return 255;
 589:     if ((pixel == trans && trans != -1) || pixel >= map_size)
 590:       return 0;
 591: 
 592:     return (0xFF000000 & rgb[pixel]) >> 24;
 593:   }
 594: 
 595:   /**
 596:    * Get the RGB color value of the given pixel using the default
 597:    * RGB color model. 
 598:    *
 599:    * @param pixel the pixel lookup value.
 600:    * @return The RGB color value.
 601:    * @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative.
 602:    */
 603:   public final int getRGB(int pixel)
 604:   {
 605:     if (pixel >= 0 && pixel < map_size)
 606:       return rgb[pixel];
 607:     
 608:     return 0;
 609:   }
 610:     
 611:   /**
 612:    * Get the RGB color values of all pixels in the map using the default
 613:    * RGB color model. 
 614:    *
 615:    * @param rgb The destination array.
 616:    */
 617:   public final void getRGBs(int[] rgb)
 618:   {
 619:     System.arraycopy(this.rgb, 0, rgb, 0, map_size);
 620:   }
 621:     
 622:   /** 
 623:    * Return <code>true</code> if the lookup table contains valid data for 
 624:    * <code>pixel</code>, and <code>false</code> otherwise.
 625:    *
 626:    * @param pixel  the pixel value used to index the color lookup table.
 627:    * @return <code>true</code> if <code>pixel</code> is valid, 
 628:    *         <code>false</code> otherwise.
 629:    */
 630:   public boolean isValid(int pixel)
 631:   {
 632:     if (pixel >= 0)
 633:       return validBits.testBit(pixel);
 634:     return false;
 635:   }
 636:   
 637:   /** 
 638:    * Return <code>true</code> if all pixels are valid, <code>false</code> 
 639:    * otherwise.
 640:    *
 641:    * @return <code>true</code> if all pixels are valid, <code>false</code> 
 642:    * otherwise.
 643:    */
 644:   public boolean isValid()
 645:   {
 646:     // Generate a bigint with 1's for every pixel
 647:     BigInteger allbits = new BigInteger("0");
 648:     allbits = allbits.setBit(map_size);
 649:     allbits = allbits.subtract(new BigInteger("1"));
 650:     return allbits.equals(validBits);
 651:   }
 652:   
 653:   /** 
 654:    * Returns a binary value ({@link BigInteger}) where each bit represents an 
 655:    * entry in the color lookup table.  If the bit is on, the entry is valid.
 656:    * 
 657:    * @return The binary value.
 658:    */
 659:   public BigInteger getValidPixels()
 660:   {
 661:     return validBits;
 662:   }
 663:   
 664:   /**
 665:    * Construct a {@link BufferedImage} with rgb pixel values from a 
 666:    * {@link Raster}.
 667:    * 
 668:    * Constructs a new BufferedImage in which each pixel is an RGBA int from
 669:    * a Raster with index-valued pixels.  If this model has no alpha component
 670:    * or transparent pixel, the type of the new BufferedImage is TYPE_INT_RGB.
 671:    * Otherwise the type is TYPE_INT_ARGB.  If forceARGB is true, the type is
 672:    * forced to be TYPE_INT_ARGB no matter what.
 673:    * 
 674:    * @param raster The source of pixel values.
 675:    * @param forceARGB True if type must be TYPE_INT_ARGB.
 676:    * @return New BufferedImage with RBGA int pixel values.
 677:    */
 678:   public BufferedImage convertToIntDiscrete(Raster raster, boolean forceARGB)
 679:   {
 680:     int type = forceARGB ? BufferedImage.TYPE_INT_ARGB
 681:       : ((opaque && trans == -1) ? BufferedImage.TYPE_INT_RGB :
 682:      BufferedImage.TYPE_INT_ARGB); 
 683: 
 684:     // FIXME: assuming that raster has only 1 band since pixels are supposed
 685:     // to be int indexes.
 686:     // FIXME: it would likely be more efficient to fetch a complete array,
 687:     // but it would take much more memory.
 688:     // FIXME: I'm not sure if transparent pixels or alpha values need special
 689:     // handling here.
 690:     BufferedImage im = new BufferedImage(raster.width, raster.height, type);
 691:     for (int x = raster.minX; x < raster.width + raster.minX; x++)
 692:       for (int y = raster.minY; y < raster.height + raster.minY; y++)
 693:         im.setRGB(x, y, rgb[raster.getSample(x, y, 0)]);
 694: 
 695:     return im;
 696:   }
 697: }