Frames | No Frames |
1: /* ColorModel.java -- 2: Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation 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: 39: package java.awt.image; 40: 41: import gnu.java.awt.Buffers; 42: 43: import java.awt.Point; 44: import java.awt.Transparency; 45: import java.awt.color.ColorSpace; 46: import java.lang.reflect.Constructor; 47: import java.util.Arrays; 48: 49: /** 50: * A color model operates with colors in several formats: 51: * 52: * <ul> 53: * <li>normalized: component samples are in range [0.0, 1.0].</li> 54: * 55: * <li>color model pixel value: all the color component samples for a 56: * sigle pixel packed/encoded in a way natural for the color 57: * model.</li> 58: * 59: * <li>color model pixel int value: only makes sense if the natural 60: * encoding of a single pixel can fit in a single int value.</li> 61: * 62: * <li>array of transferType containing a single pixel: the pixel is 63: * encoded in the natural way of the color model, taking up as many 64: * array elements as needed.</li> 65: * 66: * <li>sRGB pixel int value: a pixel in sRGB color space, encoded in 67: * default 0xAARRGGBB format, assumed not alpha premultiplied.</li> 68: * 69: * <li>single [0, 255] scaled int samples from default sRGB color 70: * space. These are always assumed to be alpha non-premultiplied.</li> 71: * 72: * <li>arrays of unnormalized component samples of single pixel: these 73: * samples are scaled and multiplied according to the color model, but 74: * is otherwise not packed or encoded. Each element of the array is one 75: * separate component sample. The color model only operate on the 76: * components from one pixel at a time, but using offsets, allows 77: * manipulation of arrays that contain the components of more than one 78: * pixel.</li> 79: * 80: * </ul> 81: * 82: * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) 83: * @author C. Brian Jones (cbj@gnu.org) 84: */ 85: public abstract class ColorModel implements Transparency 86: { 87: protected int pixel_bits; 88: protected int transferType; 89: 90: int[] bits; 91: ColorSpace cspace; 92: int transparency; 93: boolean hasAlpha; 94: boolean isAlphaPremultiplied; 95: 96: /** 97: * The standard color model for the common sRGB. 98: */ 99: private static final ColorModel S_RGB_MODEL = new SRGBColorModel(); 100: 101: static int[] nArray(int value, int times) 102: { 103: int[] array = new int[times]; 104: java.util.Arrays.fill(array, value); 105: return array; 106: } 107: 108: static byte[] nArray(byte value, int times) 109: { 110: byte[] array = new byte[times]; 111: java.util.Arrays.fill(array, value); 112: return array; 113: } 114: 115: /** 116: * Constructs the default color model. The default color model 117: * can be obtained by calling <code>getRGBdefault</code> of this 118: * class. 119: * @param bits the number of bits wide used for bit size of pixel values 120: */ 121: public ColorModel(int bits) 122: { 123: this(bits * 4, // total bits, sRGB, four channels 124: nArray(bits, 4), // bits for each channel 125: ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB 126: true, // has alpha 127: false, // not premultiplied 128: TRANSLUCENT, 129: Buffers.smallestAppropriateTransferType(bits * 4)); 130: } 131: 132: /** 133: * Constructs a ColorModel that translates pixel values to 134: * color/alpha components. 135: * 136: * @exception IllegalArgumentException If the length of the bit array is less 137: * than the number of color or alpha components in this ColorModel, or if the 138: * transparency is not a valid value, or if the sum of the number of bits in 139: * bits is less than 1 or if any of the elements in bits is less than 0. 140: */ 141: protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace, 142: boolean hasAlpha, boolean isAlphaPremultiplied, 143: int transparency, int transferType) 144: { 145: int bits_sum = 0; 146: for (int i = 0; i < bits.length; i++) 147: { 148: if (bits [i] < 0) 149: throw new IllegalArgumentException (); 150: 151: bits_sum |= bits [i]; 152: } 153: 154: if ((bits.length < cspace.getNumComponents()) 155: || (bits_sum < 1)) 156: throw new IllegalArgumentException (); 157: 158: this.pixel_bits = pixel_bits; 159: this.bits = bits; 160: this.cspace = cspace; 161: this.hasAlpha = hasAlpha; 162: this.isAlphaPremultiplied = isAlphaPremultiplied; 163: this.transparency = transparency; 164: this.transferType = transferType; 165: } 166: 167: // This is a hook for ColorConvertOp to create a colormodel with 168: // a new colorspace 169: ColorModel cloneColorModel(ColorSpace cspace) 170: { 171: Class cls = this.getClass(); 172: ColorModel cm; 173: try { 174: // This constructor will exist. 175: Constructor ctor = 176: cls.getConstructor(new Class[]{int.class, int[].class, 177: ColorSpace.class, boolean.class, 178: boolean.class, int.class, int.class}); 179: cm = (ColorModel)ctor. 180: newInstance(new Object[]{new Integer(pixel_bits), 181: bits, cspace, Boolean.valueOf(hasAlpha), 182: Boolean.valueOf(isAlphaPremultiplied), 183: new Integer(transparency), 184: new Integer(transferType)}); 185: } 186: catch (Exception e) 187: { 188: throw new IllegalArgumentException(); 189: } 190: return cm; 191: } 192: 193: public void finalize() 194: { 195: // Do nothing here. 196: } 197: 198: /** 199: * Returns the default color model which in Sun's case is an instance 200: * of <code>DirectColorModel</code>. 201: */ 202: public static ColorModel getRGBdefault() 203: { 204: return S_RGB_MODEL; 205: } 206: 207: public final boolean hasAlpha() 208: { 209: return hasAlpha; 210: } 211: 212: public final boolean isAlphaPremultiplied() 213: { 214: return isAlphaPremultiplied; 215: } 216: 217: /** 218: * Get get number of bits wide used for the bit size of pixel values 219: */ 220: public int getPixelSize() 221: { 222: return pixel_bits; 223: } 224: 225: public int getComponentSize(int componentIdx) 226: { 227: return bits[componentIdx]; 228: } 229: 230: public int[] getComponentSize() 231: { 232: return bits; 233: } 234: 235: public int getTransparency() 236: { 237: return transparency; 238: } 239: 240: public int getNumComponents() 241: { 242: return getNumColorComponents() + (hasAlpha ? 1 : 0); 243: } 244: 245: public int getNumColorComponents() 246: { 247: return cspace.getNumComponents(); 248: } 249: 250: /** 251: * Converts pixel value to sRGB and extract red int sample scaled 252: * to range [0, 255]. 253: * 254: * @param pixel pixel value that will be interpreted according to 255: * the color model, (assumed alpha premultiplied if color model says 256: * so.) 257: * 258: * @return red sample scaled to range [0, 255], from default color 259: * space sRGB, alpha non-premultiplied. 260: */ 261: public abstract int getRed(int pixel); 262: 263: /** 264: * Converts pixel value to sRGB and extract green int sample 265: * scaled to range [0, 255]. 266: * 267: * @see #getRed(int) 268: */ 269: public abstract int getGreen(int pixel); 270: 271: /** 272: * Converts pixel value to sRGB and extract blue int sample 273: * scaled to range [0, 255]. 274: * 275: * @see #getRed(int) 276: */ 277: public abstract int getBlue(int pixel); 278: 279: /** 280: * Extract alpha int sample from pixel value, scaled to [0, 255]. 281: * 282: * @param pixel pixel value that will be interpreted according to 283: * the color model. 284: * 285: * @return alpha sample, scaled to range [0, 255]. 286: */ 287: public abstract int getAlpha(int pixel); 288: 289: /** 290: * Converts a pixel int value of the color space of the color 291: * model to a sRGB pixel int value. 292: * 293: * This method is typically overriden in subclasses to provide a 294: * more efficient implementation. 295: * 296: * @param pixel pixel value that will be interpreted according to 297: * the color model. 298: * 299: * @return a pixel in sRGB color space, encoded in default 300: * 0xAARRGGBB format. */ 301: public int getRGB(int pixel) 302: { 303: return 304: ((getAlpha(pixel) & 0xff) << 24) | 305: (( getRed(pixel) & 0xff) << 16) | 306: ((getGreen(pixel) & 0xff) << 8) | 307: (( getBlue(pixel) & 0xff) << 0); 308: } 309: 310: 311: /** 312: * In this color model we know that the whole pixel value will 313: * always be contained within the first element of the pixel 314: * array. 315: */ 316: final int getPixelFromArray(Object inData) { 317: DataBuffer data = 318: Buffers.createBufferFromData(transferType, inData, 1); 319: Object da = Buffers.getData(data); 320: 321: return data.getElem(0); 322: } 323: 324: /** 325: * Converts pixel in the given array to sRGB and extract blue int 326: * sample scaled to range [0-255]. 327: * 328: * This method is typically overriden in subclasses to provide a 329: * more efficient implementation. 330: * 331: * @param inData array of transferType containing a single pixel. The 332: * pixel should be encoded in the natural way of the color model. 333: */ 334: public int getRed(Object inData) 335: { 336: return getRed(getPixelFromArray(inData)); 337: } 338: 339: /** 340: * @see #getRed(Object) 341: */ 342: public int getGreen(Object inData) 343: { 344: return getGreen(getPixelFromArray(inData)); 345: } 346: 347: /** 348: * @see #getRed(Object) 349: */ 350: public int getBlue(Object inData) { 351: return getBlue(getPixelFromArray(inData)); 352: } 353: 354: /** 355: * @see #getRed(Object) 356: */ 357: public int getAlpha(Object inData) { 358: return getAlpha(getPixelFromArray(inData)); 359: } 360: 361: /** 362: * Converts a pixel in the given array of the color space of the 363: * color model to an sRGB pixel int value. 364: * 365: * <p>This method performs the inverse function of 366: * <code>getDataElements(int rgb, Object pixel)</code>. 367: * I.e. <code>(rgb == cm.getRGB(cm.getDataElements(rgb, 368: * null)))</code>. 369: * 370: * @param inData array of transferType containing a single pixel. The 371: * pixel should be encoded in the natural way of the color model. 372: * 373: * @return a pixel in sRGB color space, encoded in default 374: * 0xAARRGGBB format. 375: * 376: * @see #getDataElements(int, Object) 377: */ 378: public int getRGB(Object inData) 379: { 380: return 381: ((getAlpha(inData) & 0xff) << 24) | 382: (( getRed(inData) & 0xff) << 16) | 383: ((getGreen(inData) & 0xff) << 8) | 384: (( getBlue(inData) & 0xff) << 0); 385: } 386: 387: /** 388: * Converts an sRGB pixel int value to an array containing a 389: * single pixel of the color space of the color model. 390: * 391: * <p>This method performs the inverse function of 392: * <code>getRGB(Object inData)</code>. 393: * 394: * Outline of conversion process: 395: * 396: * <ol> 397: * 398: * <li>Convert rgb to normalized [0.0, 1.0] sRGB values.</li> 399: * 400: * <li>Convert to color space components using fromRGB in 401: * ColorSpace.</li> 402: * 403: * <li>If color model has alpha and should be premultiplied, 404: * multiply color space components with alpha value</li> 405: * 406: * <li>Scale the components to the correct number of bits.</li> 407: * 408: * <li>Arrange the components in the output array</li> 409: * 410: * </ol> 411: * 412: * @param rgb The color to be converted to dataElements. A pixel 413: * in sRGB color space, encoded in default 0xAARRGGBB format, 414: * assumed not alpha premultiplied. 415: * 416: * @param pixel to avoid needless creation of arrays, an array to 417: * use to return the pixel can be given. If null, a suitable array 418: * will be created. 419: * 420: * @return An array of transferType values representing the color, 421: * in the color model format. The color model defines whether the 422: * 423: * @see #getRGB(Object) 424: */ 425: public Object getDataElements(int rgb, Object pixel) 426: { 427: // subclasses has to implement this method. 428: throw new UnsupportedOperationException(); 429: } 430: 431: /** 432: * Fills an array with the unnormalized component samples from a 433: * pixel value. I.e. decompose the pixel, but not perform any 434: * color conversion. 435: * 436: * This method is typically overriden in subclasses to provide a 437: * more efficient implementation. 438: * 439: * @param pixel pixel value encoded according to the color model. 440: * 441: * @return arrays of unnormalized component samples of single 442: * pixel. The scale and multiplication state of the samples are 443: * according to the color model. Each component sample is stored 444: * as a separate element in the array. 445: */ 446: public int[] getComponents(int pixel, int[] components, int offset) 447: { 448: // subclasses has to implement this method. 449: throw new UnsupportedOperationException(); 450: } 451: 452: /** 453: * Fills an array with the unnormalized component samples from an 454: * array of transferType containing a single pixel. I.e. decompose 455: * the pixel, but not perform any color conversion. 456: * 457: * This method is typically overriden in subclasses to provide a 458: * more efficient implementation. 459: * 460: * @param pixel an array of transferType containing a single pixel. The 461: * pixel should be encoded in the natural way of the color model. If 462: * this argument is not an array, as expected, a {@link ClassCastException} 463: * will be thrown. 464: * @param components an array that will be filled with the color component 465: * of the pixel. If this is null, a new array will be allocated 466: * @param offset index into the components array at which the result 467: * will be stored 468: * 469: * @return arrays of unnormalized component samples of single 470: * pixel. The scale and multiplication state of the samples are 471: * according to the color model. Each component sample is stored 472: * as a separate element in the array. 473: */ 474: public int[] getComponents(Object pixel, int[] components, int offset) 475: { 476: // subclasses has to implement this method. 477: throw new UnsupportedOperationException(); 478: } 479: 480: /** 481: * Convert normalized components to unnormalized components. 482: */ 483: public int[] getUnnormalizedComponents(float[] normComponents, 484: int normOffset, 485: int[] components, 486: int offset) 487: { 488: int numComponents = getNumComponents(); 489: if (components == null) 490: { 491: components = new int[offset + numComponents]; 492: } 493: 494: for (int i=0; i<numComponents; i++) 495: { 496: float in = normComponents[normOffset++]; 497: int out = (int) (in * ((1<<getComponentSize(i)) - 1)); 498: components[offset++] = out; 499: } 500: return components; 501: } 502: 503: /** 504: * Convert unnormalized components to normalized components. 505: */ 506: public float[] getNormalizedComponents(int[] components, 507: int offset, 508: float[] normComponents, 509: int normOffset) 510: { 511: int numComponents = getNumComponents(); 512: if (normComponents == null) 513: { 514: normComponents = new float[normOffset + numComponents]; 515: } 516: 517: for (int i=0; i<numComponents; i++) 518: { 519: float in = components[offset++]; 520: float out = in / ((1<<getComponentSize(i)) - 1); 521: normComponents[normOffset++] = out; 522: } 523: return normComponents; 524: } 525: 526: /** 527: * Convert unnormalized components to normalized components. 528: * 529: * @since 1.4 530: */ 531: public float[] getNormalizedComponents (Object pixel, 532: float[] normComponents, 533: int normOffset) 534: { 535: int[] components = getComponents(pixel, null, 0); 536: return getNormalizedComponents(components, 0, normComponents, normOffset); 537: } 538: 539: /** 540: * Converts the unnormalized component samples from an array to a 541: * pixel value. I.e. composes the pixel from component samples, but 542: * does not perform any color conversion or scaling of the samples. 543: * 544: * This method performs the inverse function of 545: * <code>getComponents(int pixel, int[] components, 546: * int offset)</code>. I.e. 547: * 548: * <code>(pixel == cm.getDataElement(cm.getComponents(pixel, null, 549: * 0), 0))</code>. 550: * 551: * This method is overriden in subclasses since this abstract class throws 552: * UnsupportedOperationException(). 553: * 554: * @param components Array of unnormalized component samples of single 555: * pixel. The scale and multiplication state of the samples are according 556: * to the color model. Each component sample is stored as a separate element 557: * in the array. 558: * @param offset Position of the first value of the pixel in components. 559: * 560: * @return pixel value encoded according to the color model. 561: */ 562: public int getDataElement(int[] components, int offset) 563: { 564: // subclasses have to implement this method. 565: throw new UnsupportedOperationException(); 566: } 567: 568: /** 569: * Converts the normalized component samples from an array to a pixel 570: * value. I.e. composes the pixel from component samples, but does not 571: * perform any color conversion or scaling of the samples. 572: * 573: * This method is typically overriden in subclasses to provide a 574: * more efficient implementation. The method provided by this abstract 575: * class converts the components to unnormalized form and returns 576: * getDataElement(int[], int). 577: * 578: * @param components Array of normalized component samples of single pixel. 579: * The scale and multiplication state of the samples are according to the 580: * color model. Each component sample is stored as a separate element in the 581: * array. 582: * @param offset Position of the first value of the pixel in components. 583: * 584: * @return pixel value encoded according to the color model. 585: * @since 1.4 586: */ 587: public int getDataElement (float[] components, int offset) 588: { 589: return 590: getDataElement(getUnnormalizedComponents(components, offset, null, 0), 591: 0); 592: } 593: 594: public Object getDataElements(int[] components, int offset, Object obj) 595: { 596: // subclasses have to implement this method. 597: throw new UnsupportedOperationException(); 598: } 599: 600: /** 601: * Converts the normalized component samples from an array to an array of 602: * TransferType values. I.e. composes the pixel from component samples, but 603: * does not perform any color conversion or scaling of the samples. 604: * 605: * If obj is null, a new array of TransferType is allocated and returned. 606: * Otherwise the results are stored in obj and obj is returned. If obj is 607: * not long enough, ArrayIndexOutOfBounds is thrown. If obj is not an array 608: * of primitives, ClassCastException is thrown. 609: * 610: * This method is typically overriden in subclasses to provide a 611: * more efficient implementation. The method provided by this abstract 612: * class converts the components to unnormalized form and returns 613: * getDataElement(int[], int, Object). 614: * 615: * @param components Array of normalized component samples of single pixel. 616: * The scale and multiplication state of the samples are according to the 617: * color model. Each component sample is stored as a separate element in the 618: * array. 619: * @param offset Position of the first value of the pixel in components. 620: * @param obj Array of TransferType or null. 621: * 622: * @return pixel value encoded according to the color model. 623: * @throws ArrayIndexOutOfBoundsException 624: * @throws ClassCastException 625: * @since 1.4 626: */ 627: public Object getDataElements(float[] components, int offset, Object obj) 628: { 629: return 630: getDataElements(getUnnormalizedComponents(components, offset, null, 0), 631: 0, obj); 632: } 633: 634: public boolean equals(Object obj) 635: { 636: if (!(obj instanceof ColorModel)) return false; 637: 638: ColorModel o = (ColorModel) obj; 639: return 640: (pixel_bits == o.pixel_bits) && 641: (transferType == o.transferType) && 642: (transparency == o.transparency) && 643: (hasAlpha == o.hasAlpha) && 644: (isAlphaPremultiplied == o.isAlphaPremultiplied) && 645: Arrays.equals(bits, o.bits) && 646: (cspace.equals(o.cspace)); 647: } 648: 649: public final ColorSpace getColorSpace() 650: { 651: return cspace; 652: } 653: 654: // Typically overridden 655: public ColorModel coerceData(WritableRaster raster, 656: boolean isAlphaPremultiplied) 657: { 658: if (this.isAlphaPremultiplied == isAlphaPremultiplied) 659: return this; 660: 661: int w = raster.getWidth(); 662: int h = raster.getHeight(); 663: int x = raster.getMinX(); 664: int y = raster.getMinY(); 665: int size = w*h; 666: int numColors = getNumColorComponents(); 667: int numComponents = getNumComponents(); 668: int alphaScale = (1<<getComponentSize(numColors)) - 1; 669: double[] pixels = raster.getPixels(x, y, w, h, (double[]) null); 670: 671: for (int i=0; i<size; i++) 672: { 673: double alpha = pixels[i*numComponents+numColors]*alphaScale; 674: for (int c=0; c<numColors; c++) 675: { 676: int offset = i*numComponents+c; 677: if (isAlphaPremultiplied) 678: pixels[offset] = pixels[offset]/alpha; 679: else 680: pixels[offset] = pixels[offset]*alpha; 681: } 682: } 683: 684: raster.setPixels(0, 0, w, h, pixels); 685: 686: // FIXME: what can we return? 687: return null; 688: } 689: 690: /** 691: * Checks if the given raster has a compatible data-layout (SampleModel). 692: * @param raster The Raster to test. 693: * @return true if raster is compatible. 694: */ 695: public boolean isCompatibleRaster(Raster raster) 696: { 697: SampleModel sampleModel = raster.getSampleModel(); 698: return isCompatibleSampleModel(sampleModel); 699: } 700: 701: // Typically overridden 702: public WritableRaster createCompatibleWritableRaster(int w, int h) 703: { 704: return new WritableRaster(createCompatibleSampleModel(w, h), 705: new Point(0, 0)); 706: } 707: 708: // Typically overridden 709: public SampleModel createCompatibleSampleModel(int w, int h) 710: { 711: throw new UnsupportedOperationException(); 712: } 713: 714: // Typically overridden 715: public boolean isCompatibleSampleModel(SampleModel sm) 716: { 717: return sm.getTransferType() == transferType; 718: } 719: 720: public final int getTransferType () 721: { 722: return transferType; 723: } 724: 725: /** 726: * Subclasses must override this method if it is possible for the 727: * color model to have an alpha channel. 728: * 729: * @return null, as per JDK 1.3 doc. Subclasses will only return 730: * null if no alpha raster exists. 731: */ 732: public WritableRaster getAlphaRaster(WritableRaster raster) 733: { 734: return null; 735: 736: /* It is a mystery to me why we couldn't use the following code... 737: 738: 739: if (!hasAlpha()) return null; 740: 741: SampleModel sm = raster.getSampleModel(); 742: int[] alphaBand = { sm.getNumBands() - 1 }; 743: SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand); 744: DataBuffer buffer = raster.getDataBuffer(); 745: Point origin = new Point(0, 0); 746: return Raster.createWritableRaster(alphaModel, buffer, origin); 747: 748: 749: ...here, and avoided overriding the method in subclasses, 750: but the Sun docs state that this method always will return 751: null, and that overriding is required. Oh, well. 752: */ 753: } 754: 755: String stringParam() 756: { 757: return "pixel_bits=" + pixel_bits + 758: ", cspace=" + cspace + 759: ", transferType=" + transferType + 760: ", transparency=" + transparency + 761: ", hasAlpha=" + hasAlpha + 762: ", isAlphaPremultiplied=" + isAlphaPremultiplied; 763: } 764: 765: public String toString() 766: { 767: return getClass().getName() + "[" + stringParam() + "]"; 768: } 769: 770: /** 771: * A color model optimized for standard sRGB. 772: */ 773: private static class SRGBColorModel 774: extends DirectColorModel 775: { 776: 777: SRGBColorModel() 778: { 779: super(32,0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); 780: } 781: 782: public int getAlpha(Object inData) 783: { 784: return ((((int[]) inData)[0]) >> 24) & 0xFF; 785: } 786: 787: public int getBlue(Object inData) 788: { 789: return ((((int[]) inData)[0])) & 0xFF; 790: } 791: 792: public int getGreen(Object inData) 793: { 794: return ((((int[]) inData)[0]) >> 8) & 0xFF; 795: } 796: 797: public int getRed(Object inData) 798: { 799: return ((((int[]) inData)[0]) >> 16) & 0xFF; 800: } 801: 802: public int getRGB(Object inData) 803: { 804: return ((int[]) inData)[0]; 805: } 806: 807: public Object getDataElements(int rgb, Object pixel) 808: { 809: if(pixel == null) 810: { 811: pixel = new int[]{rgb}; 812: } 813: else 814: { 815: ((int[]) pixel)[0] = rgb; 816: } 817: 818: return pixel; 819: } 820: } 821: }