KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > image > IndexColorModel


1 /*
2  * @(#)IndexColorModel.java 1.96 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.image;
9
10 import java.awt.Transparency JavaDoc;
11 import java.awt.color.ColorSpace JavaDoc;
12 import java.math.BigInteger JavaDoc;
13
14 /**
15  * The <code>IndexColorModel</code> class is a <code>ColorModel</code>
16  * class that works with pixel values consisting of a
17  * single sample that is an index into a fixed colormap in the default
18  * sRGB color space. The colormap specifies red, green, blue, and
19  * optional alpha components corresponding to each index. All components
20  * are represented in the colormap as 8-bit unsigned integral values.
21  * Some constructors allow the caller to specify "holes" in the colormap
22  * by indicating which colormap entries are valid and which represent
23  * unusable colors via the bits set in a <code>BigInteger</code> object.
24  * This color model is similar to an X11 PseudoColor visual.
25  * <p>
26  * Some constructors provide a means to specify an alpha component
27  * for each pixel in the colormap, while others either provide no
28  * such means or, in some cases, a flag to indicate whether the
29  * colormap data contains alpha values. If no alpha is supplied to
30  * the constructor, an opaque alpha component (alpha = 1.0) is
31  * assumed for each entry.
32  * An optional transparent pixel value can be supplied that indicates a
33  * pixel to be made completely transparent, regardless of any alpha
34  * component supplied or assumed for that pixel value.
35  * Note that the color components in the colormap of an
36  * <code>IndexColorModel</code> objects are never pre-multiplied with
37  * the alpha components.
38  * <p>
39  * <a name="transparency">
40  * The transparency of an <code>IndexColorModel</code> object is
41  * determined by examining the alpha components of the colors in the
42  * colormap and choosing the most specific value after considering
43  * the optional alpha values and any transparent index specified.
44  * The transparency value is <code>Transparency.OPAQUE</code>
45  * only if all valid colors in
46  * the colormap are opaque and there is no valid transparent pixel.
47  * If all valid colors
48  * in the colormap are either completely opaque (alpha = 1.0) or
49  * completely transparent (alpha = 0.0), which typically occurs when
50  * a valid transparent pixel is specified,
51  * the value is <code>Transparency.BITMASK</code>.
52  * Otherwise, the value is <code>Transparency.TRANSLUCENT</code>, indicating
53  * that some valid color has an alpha component that is
54  * neither completely transparent nor completely opaque (0.0 < alpha < 1.0).
55  * </a>
56  *
57  * <p>
58  * If an <code>IndexColorModel</code> object has
59  * a transparency value of <code>Transparency.OPAQUE</code>,
60  * then the <code>hasAlpha</code>
61  * and <code>getNumComponents</code> methods
62  * (both inherited from <code>ColorModel</code>)
63  * return false and 3, respectively.
64  * For any other transparency value,
65  * <code>hasAlpha</code> returns true
66  * and <code>getNumComponents</code> returns 4.
67  *
68  * <p>
69  * The index represented by a pixel value is stored in the least
70  * significant <em>n</em> bits of the pixel representations passed to the
71  * methods of this class, where <em>n</em> is the pixel size specified to the
72  * constructor for a particular <code>IndexColorModel</code> object;
73  * <em>n</em> must be between 1 and 16, inclusive.
74  * Higher order bits in pixel representations are assumed to be zero.
75  * For those methods that use a primitive array pixel representation of
76  * type <code>transferType</code>, the array length is always one.
77  * The transfer types supported are <code>DataBuffer.TYPE_BYTE</code> and
78  * <code>DataBuffer.TYPE_USHORT</code>. A single int pixel
79  * representation is valid for all objects of this class, since it is
80  * always possible to represent pixel values used with this class in a
81  * single int. Therefore, methods that use this representation do
82  * not throw an <code>IllegalArgumentException</code> due to an invalid
83  * pixel value.
84  * <p>
85  * Many of the methods in this class are final. The reason for
86  * this is that the underlying native graphics code makes assumptions
87  * about the layout and operation of this class and those assumptions
88  * are reflected in the implementations of the methods here that are
89  * marked final. You can subclass this class for other reasons, but
90  * you cannot override or modify the behaviour of those methods.
91  *
92  * @see ColorModel
93  * @see ColorSpace
94  * @see DataBuffer
95  *
96  * @version 10 Feb 1997
97  */

98 public class IndexColorModel extends ColorModel JavaDoc {
99     private int rgb[];
100     private int map_size;
101     private int transparent_index = -1;
102     private boolean allgrayopaque;
103     private BigInteger JavaDoc validBits;
104     
105     private static int[] opaqueBits = {8, 8, 8};
106     private static int[] alphaBits = {8, 8, 8, 8};
107
108     static private native void initIDs();
109     static {
110         ColorModel.loadLibraries();
111         initIDs();
112     }
113     /**
114      * Constructs an <code>IndexColorModel</code> from the specified
115      * arrays of red, green, and blue components. Pixels described
116      * by this color model all have alpha components of 255
117      * unnormalized (1.0&nbsp;normalized), which means they
118      * are fully opaque. All of the arrays specifying the color
119      * components must have at least the specified number of entries.
120      * The <code>ColorSpace</code> is the default sRGB space.
121      * Since there is no alpha information in any of the arguments
122      * to this constructor, the transparency value is always
123      * <code>Transparency.OPAQUE</code>.
124      * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
125      * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel.
126      * @param bits the number of bits each pixel occupies
127      * @param size the size of the color component arrays
128      * @param r the array of red color components
129      * @param g the array of green color components
130      * @param b the array of blue color components
131      * @throws IllegalArgumentException if <code>bits</code> is less
132      * than 1 or greater than 16
133      * @throws IllegalArgumentException if <code>size</code> is less
134      * than 1
135      */

136     public IndexColorModel(int bits, int size,
137                byte r[], byte g[], byte b[]) {
138     super(bits, opaqueBits,
139               ColorSpace.getInstance(ColorSpace.CS_sRGB),
140               false, false, OPAQUE,
141               ColorModel.getDefaultTransferType(bits));
142         if (bits < 1 || bits > 16) {
143             throw new IllegalArgumentException JavaDoc("Number of bits must be between"
144                                                +" 1 and 16.");
145         }
146     setRGBs(size, r, g, b, null);
147     }
148
149     /**
150      * Constructs an <code>IndexColorModel</code> from the given arrays
151      * of red, green, and blue components. Pixels described by this color
152      * model all have alpha components of 255 unnormalized
153      * (1.0&nbsp;normalized), which means they are fully opaque, except
154      * for the indicated pixel to be made transparent. All of the arrays
155      * specifying the color components must have at least the specified
156      * number of entries.
157      * The <code>ColorSpace</code> is the default sRGB space.
158      * The transparency value may be <code>Transparency.OPAQUE</code> or
159      * <code>Transparency.BITMASK</code> depending on the arguments, as
160      * specified in the <a HREF="#transparency">class description</a> above.
161      * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
162      * or <code>DataBuffer.TYPE_USHORT</code> that can hold a
163      * single pixel.
164      * @param bits the number of bits each pixel occupies
165      * @param size the size of the color component arrays
166      * @param r the array of red color components
167      * @param g the array of green color components
168      * @param b the array of blue color components
169      * @param trans the index of the transparent pixel
170      * @throws IllegalArgumentException if <code>bits</code> is less than
171      * 1 or greater than 16
172      * @throws IllegalArgumentException if <code>size</code> is less than
173      * 1
174      */

175     public IndexColorModel(int bits, int size,
176                byte r[], byte g[], byte b[], int trans) {
177     super(bits, opaqueBits,
178               ColorSpace.getInstance(ColorSpace.CS_sRGB),
179               false, false, OPAQUE,
180               ColorModel.getDefaultTransferType(bits));
181         if (bits < 1 || bits > 16) {
182             throw new IllegalArgumentException JavaDoc("Number of bits must be between"
183                                                +" 1 and 16.");
184         }
185     setRGBs(size, r, g, b, null);
186     setTransparentPixel(trans);
187     }
188  
189     /**
190      * Constructs an <code>IndexColorModel</code> from the given
191      * arrays of red, green, blue and alpha components. All of the
192      * arrays specifying the components must have at least the specified
193      * number of entries.
194      * The <code>ColorSpace</code> is the default sRGB space.
195      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
196      * <code>Transparency.BITMASK</code>,
197      * or <code>Transparency.TRANSLUCENT</code>
198      * depending on the arguments, as specified
199      * in the <a HREF="#transparency">class description</a> above.
200      * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
201      * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel.
202      * @param bits the number of bits each pixel occupies
203      * @param size the size of the color component arrays
204      * @param r the array of red color components
205      * @param g the array of green color components
206      * @param b the array of blue color components
207      * @param a the array of alpha value components
208      * @throws IllegalArgumentException if <code>bits</code> is less
209      * than 1 or greater than 16
210      * @throws IllegalArgumentException if <code>size</code> is less
211      * than 1
212      */

213     public IndexColorModel(int bits, int size,
214                byte r[], byte g[], byte b[], byte a[]) {
215         super (bits, alphaBits,
216                ColorSpace.getInstance(ColorSpace.CS_sRGB),
217                true, false, TRANSLUCENT,
218                ColorModel.getDefaultTransferType(bits));
219         if (bits < 1 || bits > 16) {
220             throw new IllegalArgumentException JavaDoc("Number of bits must be between"
221                                                +" 1 and 16.");
222         }
223         setRGBs (size, r, g, b, a);
224     }
225
226     /**
227      * Constructs an <code>IndexColorModel</code> from a single
228      * array of interleaved red, green, blue and optional alpha
229      * components. The array must have enough values in it to
230      * fill all of the needed component arrays of the specified
231      * size. The <code>ColorSpace</code> is the default sRGB space.
232      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
233      * <code>Transparency.BITMASK</code>,
234      * or <code>Transparency.TRANSLUCENT</code>
235      * depending on the arguments, as specified
236      * in the <a HREF="#transparency">class description</a> above.
237      * The transfer type is the smallest of
238      * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code>
239      * that can hold a single pixel.
240      *
241      * @param bits the number of bits each pixel occupies
242      * @param size the size of the color component arrays
243      * @param cmap the array of color components
244      * @param start the starting offset of the first color component
245      * @param hasalpha indicates whether alpha values are contained in
246      * the <code>cmap</code> array
247      * @throws IllegalArgumentException if <code>bits</code> is less
248      * than 1 or greater than 16
249      * @throws IllegalArgumentException if <code>size</code> is less
250      * than 1
251      */

252     public IndexColorModel(int bits, int size, byte cmap[], int start,
253                boolean hasalpha) {
254     this(bits, size, cmap, start, hasalpha, -1);
255         if (bits < 1 || bits > 16) {
256             throw new IllegalArgumentException JavaDoc("Number of bits must be between"
257                                                +" 1 and 16.");
258         }
259     }
260
261     /**
262      * Constructs an <code>IndexColorModel</code> from a single array of
263      * interleaved red, green, blue and optional alpha components. The
264      * specified transparent index represents a pixel that is made
265      * entirely transparent regardless of any alpha value specified
266      * for it. The array must have enough values in it to fill all
267      * of the needed component arrays of the specified size.
268      * The <code>ColorSpace</code> is the default sRGB space.
269      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
270      * <code>Transparency.BITMASK</code>,
271      * or <code>Transparency.TRANSLUCENT</code>
272      * depending on the arguments, as specified
273      * in the <a HREF="#transparency">class description</a> above.
274      * The transfer type is the smallest of
275      * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code>
276      * that can hold a single pixel.
277      * @param bits the number of bits each pixel occupies
278      * @param size the size of the color component arrays
279      * @param cmap the array of color components
280      * @param start the starting offset of the first color component
281      * @param hasalpha indicates whether alpha values are contained in
282      * the <code>cmap</code> array
283      * @param trans the index of the fully transparent pixel
284      * @throws IllegalArgumentException if <code>bits</code> is less than
285      * 1 or greater than 16
286      * @throws IllegalArgumentException if <code>size</code> is less than
287      * 1
288      */

289     public IndexColorModel(int bits, int size, byte cmap[], int start,
290                boolean hasalpha, int trans) {
291     // REMIND: This assumes the ordering: RGB[A]
292
super(bits, opaqueBits,
293               ColorSpace.getInstance(ColorSpace.CS_sRGB),
294               false, false, OPAQUE,
295               ColorModel.getDefaultTransferType(bits));
296
297         if (bits < 1 || bits > 16) {
298             throw new IllegalArgumentException JavaDoc("Number of bits must be between"
299                                                +" 1 and 16.");
300         }
301         if (size < 1) {
302             throw new IllegalArgumentException JavaDoc("Map size ("+size+
303                                                ") must be >= 1");
304         }
305     map_size = size;
306     rgb = new int[calcRealMapSize(bits, size)];
307     int j = start;
308     int alpha = 0xff;
309     boolean allgray = true;
310         int transparency = OPAQUE;
311     for (int i = 0; i < size; i++) {
312         int r = cmap[j++] & 0xff;
313         int g = cmap[j++] & 0xff;
314         int b = cmap[j++] & 0xff;
315         allgray = allgray && (r == g) && (g == b);
316         if (hasalpha) {
317         alpha = cmap[j++] & 0xff;
318         if (alpha != 0xff) {
319             if (alpha == 0x00) {
320             if (transparency == OPAQUE) {
321                 transparency = BITMASK;
322             }
323             if (transparent_index < 0) {
324                 transparent_index = i;
325             }
326             } else {
327             transparency = TRANSLUCENT;
328             }
329             allgray = false;
330         }
331         }
332         rgb[i] = (alpha << 24) | (r << 16) | (g << 8) | b;
333     }
334     this.allgrayopaque = allgray;
335     setTransparency(transparency);
336     setTransparentPixel(trans);
337     }
338
339     /**
340      * Constructs an <code>IndexColorModel</code> from an array of
341      * ints where each int is comprised of red, green, blue, and
342      * optional alpha components in the default RGB color model format.
343      * The specified transparent index represents a pixel that is made
344      * entirely transparent regardless of any alpha value specified
345      * for it. The array must have enough values in it to fill all
346      * of the needed component arrays of the specified size.
347      * The <code>ColorSpace</code> is the default sRGB space.
348      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
349      * <code>Transparency.BITMASK</code>,
350      * or <code>Transparency.TRANSLUCENT</code>
351      * depending on the arguments, as specified
352      * in the <a HREF="#transparency">class description</a> above.
353      * @param bits the number of bits each pixel occupies
354      * @param size the size of the color component arrays
355      * @param cmap the array of color components
356      * @param start the starting offset of the first color component
357      * @param hasalpha indicates whether alpha values are contained in
358      * the <code>cmap</code> array
359      * @param trans the index of the fully transparent pixel
360      * @param transferType the data type of the array used to represent
361      * pixel values. The data type must be either
362      * <code>DataBuffer.TYPE_BYTE</code> or
363      * <code>DataBuffer.TYPE_USHORT</code>.
364      * @throws IllegalArgumentException if <code>bits</code> is less
365      * than 1 or greater than 16
366      * @throws IllegalArgumentException if <code>size</code> is less
367      * than 1
368      * @throws IllegalArgumentException if <code>transferType</code> is not
369      * one of <code>DataBuffer.TYPE_BYTE</code> or
370      * <code>DataBuffer.TYPE_USHORT</code>
371      */

372     public IndexColorModel(int bits, int size,
373                            int cmap[], int start,
374                boolean hasalpha, int trans, int transferType) {
375     // REMIND: This assumes the ordering: RGB[A]
376
super(bits, opaqueBits,
377               ColorSpace.getInstance(ColorSpace.CS_sRGB),
378               false, false, OPAQUE,
379               transferType);
380
381         if (bits < 1 || bits > 16) {
382             throw new IllegalArgumentException JavaDoc("Number of bits must be between"
383                                                +" 1 and 16.");
384         }
385         if (size < 1) {
386             throw new IllegalArgumentException JavaDoc("Map size ("+size+
387                                                ") must be >= 1");
388         }
389         if ((transferType != DataBuffer.TYPE_BYTE) &&
390             (transferType != DataBuffer.TYPE_USHORT)) {
391             throw new IllegalArgumentException JavaDoc("transferType must be either" +
392                 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT");
393         }
394
395     setRGBs(size, cmap, start, hasalpha);
396         setTransparentPixel(trans);
397     }
398
399     /**
400      * Constructs an <code>IndexColorModel</code> from an
401      * <code>int</code> array where each <code>int</code> is
402      * comprised of red, green, blue, and alpha
403      * components in the default RGB color model format.
404      * The array must have enough values in it to fill all
405      * of the needed component arrays of the specified size.
406      * The <code>ColorSpace</code> is the default sRGB space.
407      * The transparency value may be any of <code>Transparency.OPAQUE</code>,
408      * <code>Transparency.BITMASK</code>,
409      * or <code>Transparency.TRANSLUCENT</code>
410      * depending on the arguments, as specified
411      * in the <a HREF="#transparency">class description</a> above.
412      * The transfer type must be one of <code>DataBuffer.TYPE_BYTE</code>
413      * <code>DataBuffer.TYPE_USHORT</code>.
414      * The <code>BigInteger</code> object specifies the valid/invalid pixels
415      * in the <code>cmap</code> array. A pixel is valid if the
416      * <code>BigInteger</code> value at that index is set, and is invalid
417      * if the <code>BigInteger</code> bit at that index is not set.
418      * @param bits the number of bits each pixel occupies
419      * @param size the size of the color component array
420      * @param cmap the array of color components
421      * @param start the starting offset of the first color component
422      * @param transferType the specified data type
423      * @param validBits a <code>BigInteger</code> object. If a bit is
424      * set in the BigInteger, the pixel at that index is valid.
425      * If a bit is not set, the pixel at that index
426      * is considered invalid. If null, all pixels are valid.
427      * Only bits from 0 to the map size are considered.
428      * @throws IllegalArgumentException if <code>bits</code> is less
429      * than 1 or greater than 16
430      * @throws IllegalArgumentException if <code>size</code> is less
431      * than 1
432      * @throws IllegalArgumentException if <code>transferType</code> is not
433      * one of <code>DataBuffer.TYPE_BYTE</code> or
434      * <code>DataBuffer.TYPE_USHORT</code>
435      *
436      */

437     public IndexColorModel(int bits, int size, int cmap[], int start,
438                            int transferType, BigInteger JavaDoc validBits) {
439         super (bits, alphaBits,
440                ColorSpace.getInstance(ColorSpace.CS_sRGB),
441                true, false, TRANSLUCENT,
442                transferType);
443         
444         if (bits < 1 || bits > 16) {
445             throw new IllegalArgumentException JavaDoc("Number of bits must be between"
446                                                +" 1 and 16.");
447         }
448         if (size < 1) {
449             throw new IllegalArgumentException JavaDoc("Map size ("+size+
450                                                ") must be >= 1");
451         }
452         if ((transferType != DataBuffer.TYPE_BYTE) &&
453             (transferType != DataBuffer.TYPE_USHORT)) {
454             throw new IllegalArgumentException JavaDoc("transferType must be either" +
455                 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT");
456         }
457
458         if (validBits != null) {
459             // Check to see if it is all valid
460
for (int i=0; i < size; i++) {
461                 if (!validBits.testBit(i)) {
462                     this.validBits = validBits;
463                     break;
464                 }
465             }
466         }
467         
468     setRGBs(size, cmap, start, true);
469     }
470     
471     private void setRGBs(int size, byte r[], byte g[], byte b[], byte a[]) {
472         if (size < 1) {
473             throw new IllegalArgumentException JavaDoc("Map size ("+size+
474                                                ") must be >= 1");
475         }
476     map_size = size;
477     rgb = new int[calcRealMapSize(pixel_bits, size)];
478     int alpha = 0xff;
479         int transparency = OPAQUE;
480     boolean allgray = true;
481     for (int i = 0; i < size; i++) {
482         int rc = r[i] & 0xff;
483         int gc = g[i] & 0xff;
484         int bc = b[i] & 0xff;
485         allgray = allgray && (rc == gc) && (gc == bc);
486         if (a != null) {
487         alpha = a[i] & 0xff;
488         if (alpha != 0xff) {
489             if (alpha == 0x00) {
490             if (transparency == OPAQUE) {
491                 transparency = BITMASK;
492             }
493             if (transparent_index < 0) {
494                 transparent_index = i;
495             }
496             } else {
497             transparency = TRANSLUCENT;
498             }
499             allgray = false;
500         }
501         }
502         rgb[i] = (alpha << 24) | (rc << 16) | (gc << 8) | bc;
503     }
504     this.allgrayopaque = allgray;
505     setTransparency(transparency);
506     }
507
508     private void setRGBs(int size, int cmap[], int start, boolean hasalpha) {
509     map_size = size;
510     rgb = new int[calcRealMapSize(pixel_bits, size)];
511     int j = start;
512         int transparency = OPAQUE;
513     boolean allgray = true;
514     BigInteger JavaDoc validBits = this.validBits;
515     for (int i = 0; i < size; i++, j++) {
516         if (validBits != null && !validBits.testBit(i)) {
517         continue;
518         }
519         int cmaprgb = cmap[j];
520         int r = (cmaprgb >> 16) & 0xff;
521         int g = (cmaprgb >> 8) & 0xff;
522         int b = (cmaprgb ) & 0xff;
523         allgray = allgray && (r == g) && (g == b);
524         if (hasalpha) {
525         int alpha = cmaprgb >>> 24;
526         if (alpha != 0xff) {
527             if (alpha == 0x00) {
528             if (transparency == OPAQUE) {
529                 transparency = BITMASK;
530             }
531             if (transparent_index < 0) {
532                 transparent_index = i;
533             }
534             } else {
535             transparency = TRANSLUCENT;
536             }
537             allgray = false;
538         }
539         } else {
540         cmaprgb |= 0xff000000;
541         }
542         rgb[i] = cmaprgb;
543     }
544     this.allgrayopaque = allgray;
545     setTransparency(transparency);
546     }
547
548     private int calcRealMapSize(int bits, int size) {
549     int newSize = Math.max(1 << bits, size);
550     return Math.max(newSize, 256);
551     }
552
553     private BigInteger JavaDoc getAllValid() {
554     int numbytes = (map_size+7)/8;
555     byte[] valid = new byte[numbytes];
556     java.util.Arrays.fill(valid, (byte)0xff);
557     valid[0] = (byte)(0xff >>> (numbytes*8 - map_size));
558
559     return new BigInteger JavaDoc(1, valid);
560     }
561
562     /**
563      * Returns the transparency. Returns either OPAQUE, BITMASK,
564      * or TRANSLUCENT
565      * @return the transparency of this <code>IndexColorModel</code>
566      * @see Transparency#OPAQUE
567      * @see Transparency#BITMASK
568      * @see Transparency#TRANSLUCENT
569      */

570     public int getTransparency() {
571         return transparency;
572     }
573
574     /**
575      * Returns an array of the number of bits for each color/alpha component.
576      * The array contains the color components in the order red, green,
577      * blue, followed by the alpha component, if present.
578      * @return an array containing the number of bits of each color
579      * and alpha component of this <code>IndexColorModel</code>
580      */

581     public int[] getComponentSize() {
582         if (nBits == null) {
583             if (supportsAlpha) {
584                 nBits = new int[4];
585                 nBits[3] = 8;
586             }
587             else {
588                 nBits = new int[3];
589             }
590             nBits[0] = nBits[1] = nBits[2] = 8;
591         }
592         return nBits;
593     }
594     
595     /**
596      * Returns the size of the color/alpha component arrays in this
597      * <code>IndexColorModel</code>.
598      * @return the size of the color and alpha component arrays.
599      */

600     final public int getMapSize() {
601         return map_size;
602     }
603
604     /**
605      * Returns the index of a transparent pixel in this
606      * <code>IndexColorModel</code> or -1 if there is no pixel
607      * with an alpha value of 0. If a transparent pixel was
608      * explicitly specified in one of the constructors by its
609      * index, then that index will be preferred, otherwise,
610      * the index of any pixel which happens to be fully transparent
611      * may be returned.
612      * @return the index of a transparent pixel in this
613      * <code>IndexColorModel</code> object, or -1 if there
614      * is no such pixel
615      */

616     final public int getTransparentPixel() {
617     return transparent_index;
618     }
619
620     /**
621      * Copies the array of red color components into the specified array.
622      * Only the initial entries of the array as specified by
623      * {@link #getMapSize() getMapSize} are written.
624      * @param r the specified array into which the elements of the
625      * array of red color components are copied
626      */

627     final public void getReds(byte r[]) {
628     for (int i = 0; i < map_size; i++) {
629         r[i] = (byte) (rgb[i] >> 16);
630     }
631     }
632
633     /**
634      * Copies the array of green color components into the specified array.
635      * Only the initial entries of the array as specified by
636      * <code>getMapSize</code> are written.
637      * @param g the specified array into which the elements of the
638      * array of green color components are copied
639      */

640     final public void getGreens(byte g[]) {
641     for (int i = 0; i < map_size; i++) {
642         g[i] = (byte) (rgb[i] >> 8);
643     }
644     }
645
646     /**
647      * Copies the array of blue color components into the specified array.
648      * Only the initial entries of the array as specified by
649      * <code>getMapSize</code> are written.
650      * @param b the specified array into which the elements of the
651      * array of blue color components are copied
652      */

653     final public void getBlues(byte b[]) {
654         for (int i = 0; i < map_size; i++) {
655             b[i] = (byte) rgb[i];
656         }
657     }
658
659     /**
660      * Copies the array of alpha transparency components into the
661      * specified array. Only the initial entries of the array as specified
662      * by <code>getMapSize</code> are written.
663      * @param a the specified array into which the elements of the
664      * array of alpha components are copied
665      */

666     final public void getAlphas(byte a[]) {
667         for (int i = 0; i < map_size; i++) {
668             a[i] = (byte) (rgb[i] >> 24);
669         }
670     }
671
672     /**
673      * Converts data for each index from the color and alpha component
674      * arrays to an int in the default RGB ColorModel format and copies
675      * the resulting 32-bit ARGB values into the specified array. Only
676      * the initial entries of the array as specified by
677      * <code>getMapSize</code> are
678      * written.
679      * @param rgb the specified array into which the converted ARGB
680      * values from this array of color and alpha components
681      * are copied.
682      */

683     final public void getRGBs(int rgb[]) {
684         System.arraycopy(this.rgb, 0, rgb, 0, map_size);
685     }
686
687     private void setTransparentPixel(int trans) {
688     if (trans >= 0 && trans < map_size) {
689         rgb[trans] &= 0x00ffffff;
690         transparent_index = trans;
691         allgrayopaque = false;
692         if (this.transparency == OPAQUE) {
693         setTransparency(BITMASK);
694         }
695     }
696     }
697
698     private void setTransparency(int transparency) {
699     if (this.transparency != transparency) {
700         this.transparency = transparency;
701         if (transparency == OPAQUE) {
702         supportsAlpha = false;
703         numComponents = 3;
704         nBits = opaqueBits;
705         } else {
706         supportsAlpha = true;
707         numComponents = 4;
708         nBits = alphaBits;
709         }
710     }
711     }
712
713     /**
714      * Returns the red color component for the specified pixel, scaled
715      * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
716      * is specified as an int. The returned value is a
717      * non pre-multiplied value.
718      * @param pixel the specified pixel
719      * @return the value of the red color component for the specified pixel
720      */

721     final public int getRed(int pixel) {
722     return (rgb[pixel] >> 16) & 0xff;
723     }
724
725     /**
726      * Returns the green color component for the specified pixel, scaled
727      * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
728      * is specified as an int. The returned value is a
729      * non pre-multiplied value.
730      * @param pixel the specified pixel
731      * @return the value of the green color component for the specified pixel
732      */

733     final public int getGreen(int pixel) {
734     return (rgb[pixel] >> 8) & 0xff;
735     }
736
737     /**
738      * Returns the blue color component for the specified pixel, scaled
739      * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
740      * is specified as an int. The returned value is a
741      * non pre-multiplied value.
742      * @param pixel the specified pixel
743      * @return the value of the blue color component for the specified pixel
744      */

745     final public int getBlue(int pixel) {
746     return rgb[pixel] & 0xff;
747     }
748
749     /**
750      * Returns the alpha component for the specified pixel, scaled
751      * from 0 to 255. The pixel value is specified as an int.
752      * @param pixel the specified pixel
753      * @return the value of the alpha component for the specified pixel
754      */

755     final public int getAlpha(int pixel) {
756     return (rgb[pixel] >> 24) & 0xff;
757     }
758
759     /**
760      * Returns the color/alpha components of the pixel in the default
761      * RGB color model format. The pixel value is specified as an int.
762      * The returned value is in a non pre-multiplied format.
763      * @param pixel the specified pixel
764      * @return the color and alpha components of the specified pixel
765      * @see ColorModel#getRGBdefault
766      */

767     final public int getRGB(int pixel) {
768     return rgb[pixel];
769     }
770
771     private static final int CACHESIZE = 40;
772     private int lookupcache[] = new int[CACHESIZE];
773
774     /**
775      * Returns a data element array representation of a pixel in this
776      * ColorModel, given an integer pixel representation in the
777      * default RGB color model. This array can then be passed to the
778      * {@link WritableRaster#setDataElements(int, int, java.lang.Object) setDataElements}
779      * method of a {@link WritableRaster} object. If the pixel variable is
780      * <code>null</code>, a new array is allocated. If <code>pixel</code>
781      * is not <code>null</code>, it must be
782      * a primitive array of type <code>transferType</code>; otherwise, a
783      * <code>ClassCastException</code> is thrown. An
784      * <code>ArrayIndexOutOfBoundsException</code> is
785      * thrown if <code>pixel</code> is not large enough to hold a pixel
786      * value for this <code>ColorModel</code>. The pixel array is returned.
787      * <p>
788      * Since <code>IndexColorModel</code> can be subclassed, subclasses
789      * inherit the implementation of this method and if they don't
790      * override it then they throw an exception if they use an
791      * unsupported <code>transferType</code>.
792      *
793      * @param rgb the integer pixel representation in the default RGB
794      * color model
795      * @param pixel the specified pixel
796      * @return an array representation of the specified pixel in this
797      * <code>IndexColorModel</code>.
798      * @throws ClassCastException if <code>pixel</code>
799      * is not a primitive array of type <code>transferType</code>
800      * @throws ArrayIndexOutOfBoundsException if
801      * <code>pixel</code> is not large enough to hold a pixel value
802      * for this <code>ColorModel</code>
803      * @throws UnsupportedOperationException if <code>transferType</code>
804      * is invalid
805      * @see WritableRaster#setDataElements
806      * @see SampleModel#setDataElements
807      */

808     public synchronized Object JavaDoc getDataElements(int rgb, Object JavaDoc pixel) {
809         int red = (rgb>>16) & 0xff;
810         int green = (rgb>>8) & 0xff;
811         int blue = rgb & 0xff;
812         int alpha = (rgb>>>24);
813         int pix = 0;
814
815     for (int i = CACHESIZE - 2; i >= 0; i -= 2) {
816         if ((pix = lookupcache[i]) == 0) {
817         break;
818         }
819         if (rgb == lookupcache[i+1]) {
820         return installpixel(pixel, ~pix);
821         }
822     }
823
824     if (allgrayopaque) {
825         int minDist = 256;
826         int d;
827         int gray = (int) (red*77 + green*150 + blue*29 + 128)/256;
828
829         for (int i = 0; i < map_size; i++) {
830         if (this.rgb[i] == 0x0) {
831             // For allgrayopaque colormaps, entries are 0
832
// iff they are an invalid color and should be
833
// ignored during color searches.
834
continue;
835         }
836         d = (this.rgb[i] & 0xff) - gray;
837         if (d < 0) d = -d;
838         if (d < minDist) {
839             pix = i;
840             if (d == 0) {
841             break;
842             }
843             minDist = d;
844         }
845         }
846     } else if (alpha == 0) {
847             // Return transparent pixel if we have one
848
if (transparent_index >= 0) {
849                 pix = transparent_index;
850             }
851             else {
852                 // Search for smallest alpha
853
int smallestAlpha = 256;
854                 for (int i = 0; i < map_size; i++) {
855             int a = this.rgb[i] >>> 24;
856             if (smallestAlpha > alpha &&
857             (validBits == null || validBits.testBit(i)))
858             {
859             smallestAlpha = alpha;
860             pix = i;
861                     }
862                 }
863             }
864         } else {
865             // a heuristic which says find the closest color,
866
// after finding the closest alpha
867
// if user wants different behavior, they can derive
868
// a class and override this method
869
// SLOW --- but accurate
870
// REMIND - need a native implementation, and inverse color-map
871
int smallestError = 255 * 255 * 255; // largest possible
872
int smallestAlphaError = 255;
873
874         if (false && red == green && green == blue) {
875         // Grayscale
876
}
877
878             for (int i=0; i < map_size; i++) {
879         int lutrgb = this.rgb[i];
880         if (lutrgb == rgb) {
881             pix = i;
882             break;
883         }
884                 int tmp = (lutrgb>>>24) - alpha;
885         if (tmp < 0) {
886             tmp = -tmp;
887         }
888         if (tmp <= smallestAlphaError) {
889             smallestAlphaError = tmp;
890             tmp = ((lutrgb>>16) & 0xff) - red;
891             int currentError = tmp * tmp;
892             if (currentError < smallestError) {
893             tmp = ((lutrgb>>8) & 0xff) - green;
894             currentError += tmp * tmp;
895             if (currentError < smallestError) {
896                 tmp = (lutrgb & 0xff) - blue;
897                 currentError += tmp * tmp;
898                 if (currentError < smallestError &&
899                 (validBits == null || validBits.testBit(i)))
900                 {
901                 pix = i;
902                 smallestError = currentError;
903                 }
904             }
905             }
906         }
907             }
908         }
909     System.arraycopy(lookupcache, 2, lookupcache, 0, CACHESIZE - 2);
910     lookupcache[CACHESIZE - 1] = rgb;
911     lookupcache[CACHESIZE - 2] = ~pix;
912     return installpixel(pixel, pix);
913     }
914
915     private Object JavaDoc installpixel(Object JavaDoc pixel, int pix) {
916         switch (transferType) {
917         case DataBuffer.TYPE_INT:
918         int[] intObj;
919         if (pixel == null) {
920         pixel = intObj = new int[1];
921         } else {
922         intObj = (int[]) pixel;
923         }
924         intObj[0] = pix;
925             break;
926         case DataBuffer.TYPE_BYTE:
927         byte[] byteObj;
928         if (pixel == null) {
929         pixel = byteObj = new byte[1];
930         } else {
931         byteObj = (byte[]) pixel;
932         }
933         byteObj[0] = (byte) pix;
934             break;
935         case DataBuffer.TYPE_USHORT:
936         short[] shortObj;
937         if (pixel == null) {
938         pixel = shortObj = new short[1];
939         } else {
940         shortObj = (short[]) pixel;
941         }
942         shortObj[0] = (short) pix;
943             break;
944         default:
945             throw new UnsupportedOperationException JavaDoc("This method has not been "+
946                              "implemented for transferType " + transferType);
947         }
948         return pixel;
949     }
950
951     /**
952      * Returns an array of unnormalized color/alpha components for a
953      * specified pixel in this <code>ColorModel</code>. The pixel value
954      * is specified as an int. If the <code>components</code> array is <code>null</code>,
955      * a new array is allocated that contains
956      * <code>offset + getNumComponents()</code> elements.
957      * The <code>components</code> array is returned,
958      * with the alpha component included
959      * only if <code>hasAlpha</code> returns true.
960      * Color/alpha components are stored in the <code>components</code> array starting
961      * at <code>offset</code> even if the array is allocated by this method.
962      * An <code>ArrayIndexOutOfBoundsException</code>
963      * is thrown if the <code>components</code> array is not <code>null</code> and is
964      * not large enough to hold all the color and alpha components
965      * starting at <code>offset</code>.
966      * @param pixel the specified pixel
967      * @param components the array to receive the color and alpha
968      * components of the specified pixel
969      * @param offset the offset into the <code>components</code> array at
970      * which to start storing the color and alpha components
971      * @return an array containing the color and alpha components of the
972      * specified pixel starting at the specified offset.
973      * @see ColorModel#hasAlpha
974      * @see ColorModel#getNumComponents
975      */

976     public int[] getComponents(int pixel, int[] components, int offset) {
977         if (components == null) {
978             components = new int[offset+numComponents];
979         }
980
981         // REMIND: Needs to change if different color space
982
components[offset+0] = getRed(pixel);
983         components[offset+1] = getGreen(pixel);
984         components[offset+2] = getBlue(pixel);
985         if (supportsAlpha && (components.length-offset) > 3) {
986             components[offset+3] = getAlpha(pixel);
987         }
988         
989         return components;
990     }
991     
992     /**
993      * Returns an array of unnormalized color/alpha components for
994      * a specified pixel in this <code>ColorModel</code>. The pixel
995      * value is specified by an array of data elements of type
996      * <code>transferType</code> passed in as an object reference.
997      * If <code>pixel</code> is not a primitive array of type
998      * <code>transferType</code>, a <code>ClassCastException</code>
999      * is thrown. An <code>ArrayIndexOutOfBoundsException</code>
1000     * is thrown if <code>pixel</code> is not large enough to hold
1001     * a pixel value for this <code>ColorModel</code>. If the
1002     * <code>components</code> array is <code>null</code>, a new array
1003     * is allocated that contains
1004     * <code>offset + getNumComponents()</code> elements.
1005     * The <code>components</code> array is returned,
1006     * with the alpha component included
1007     * only if <code>hasAlpha</code> returns true.
1008     * Color/alpha components are stored in the <code>components</code>
1009     * array starting at <code>offset</code> even if the array is
1010     * allocated by this method. An
1011     * <code>ArrayIndexOutOfBoundsException</code> is also
1012     * thrown if the <code>components</code> array is not
1013     * <code>null</code> and is not large enough to hold all the color
1014     * and alpha components starting at <code>offset</code>.
1015     * <p>
1016     * Since <code>IndexColorModel</code> can be subclassed, subclasses
1017     * inherit the implementation of this method and if they don't
1018     * override it then they throw an exception if they use an
1019     * unsupported <code>transferType</code>.
1020     *
1021     * @param pixel the specified pixel
1022     * @param components an array that receives the color and alpha
1023     * components of the specified pixel
1024     * @param offset the index into the <code>components</code> array at
1025     * which to begin storing the color and alpha components of the
1026     * specified pixel
1027     * @return an array containing the color and alpha components of the
1028     * specified pixel starting at the specified offset.
1029     * @throws ArrayIndexOutOfBoundsException if <code>pixel</code>
1030     * is not large enough to hold a pixel value for this
1031     * <code>ColorModel</code> or if the
1032     * <code>components</code> array is not <code>null</code>
1033     * and is not large enough to hold all the color
1034     * and alpha components starting at <code>offset</code>
1035     * @throws ClassCastException if <code>pixel</code> is not a
1036     * primitive array of type <code>transferType</code>
1037     * @throws UnsupportedOperationException if <code>transferType</code>
1038     * is not one of the supported transer types
1039     * @see ColorModel#hasAlpha
1040     * @see ColorModel#getNumComponents
1041     */

1042    public int[] getComponents(Object JavaDoc pixel, int[] components, int offset) {
1043        int intpixel;
1044        switch (transferType) {
1045            case DataBuffer.TYPE_BYTE:
1046               byte bdata[] = (byte[])pixel;
1047               intpixel = bdata[0] & 0xff;
1048            break;
1049            case DataBuffer.TYPE_USHORT:
1050               short sdata[] = (short[])pixel;
1051               intpixel = sdata[0] & 0xffff;
1052            break;
1053            case DataBuffer.TYPE_INT:
1054               int idata[] = (int[])pixel;
1055               intpixel = idata[0];
1056            break;
1057            default:
1058               throw new UnsupportedOperationException JavaDoc("This method has not been "+
1059                   "implemented for transferType " + transferType);
1060        }
1061        return getComponents(intpixel, components, offset);
1062    }
1063    
1064    /**
1065     * Returns a pixel value represented as an int in this
1066     * <code>ColorModel</code> given an array of unnormalized
1067     * color/alpha components. An
1068     * <code>ArrayIndexOutOfBoundsException</code>
1069     * is thrown if the <code>components</code> array is not large
1070     * enough to hold all of the color and alpha components starting
1071     * at <code>offset</code>. Since
1072     * <code>ColorModel</code> can be subclassed, subclasses inherit the
1073     * implementation of this method and if they don't override it then
1074     * they throw an exception if they use an unsupported transferType.
1075     * @param components an array of unnormalized color and alpha
1076     * components
1077     * @param offset the index into <code>components</code> at which to
1078     * begin retrieving the color and alpha components
1079     * @return an <code>int</code> pixel value in this
1080     * <code>ColorModel</code> corresponding to the specified components.
1081     * @throws ArrayIndexOutOfBoundsException if
1082     * the <code>components</code> array is not large enough to
1083     * hold all of the color and alpha components starting at
1084     * <code>offset</code>
1085     * @throws UnsupportedOperationException if <code>transferType</code>
1086     * is invalid
1087     */

1088    public int getDataElement(int[] components, int offset) {
1089        int rgb = (components[offset+0]<<16)
1090            | (components[offset+1]<<8) | (components[offset+2]);
1091        if (supportsAlpha) {
1092            rgb |= (components[offset+3]<<24);
1093        }
1094        else {
1095            rgb |= 0xff000000;
1096        }
1097        Object JavaDoc inData = getDataElements(rgb, null);
1098        int pixel;
1099        switch (transferType) {
1100            case DataBuffer.TYPE_BYTE:
1101               byte bdata[] = (byte[])inData;
1102               pixel = bdata[0] & 0xff;
1103            break;
1104            case DataBuffer.TYPE_USHORT:
1105               short sdata[] = (short[])inData;
1106               pixel = sdata[0];
1107            break;
1108            case DataBuffer.TYPE_INT:
1109               int idata[] = (int[])inData;
1110               pixel = idata[0];
1111            break;
1112            default:
1113               throw new UnsupportedOperationException JavaDoc("This method has not been "+
1114                   "implemented for transferType " + transferType);
1115        }
1116        return pixel;
1117    }
1118    
1119    /**
1120     * Returns a data element array representation of a pixel in this
1121     * <code>ColorModel</code> given an array of unnormalized color/alpha
1122     * components. This array can then be passed to the
1123     * <code>setDataElements</code> method of a <code>WritableRaster</code>
1124     * object. An <code>ArrayIndexOutOfBoundsException</code> is
1125     * thrown if the
1126     * <code>components</code> array is not large enough to hold all of the
1127     * color and alpha components starting at <code>offset</code>.
1128     * If the pixel variable is <code>null</code>, a new array
1129     * is allocated. If <code>pixel</code> is not <code>null</code>,
1130     * it must be a primitive array of type <code>transferType</code>;
1131     * otherwise, a <code>ClassCastException</code> is thrown.
1132     * An <code>ArrayIndexOutOfBoundsException</code> is thrown if pixel
1133     * is not large enough to hold a pixel value for this
1134     * <code>ColorModel</code>.
1135     * <p>
1136     * Since <code>IndexColorModel</code> can be subclassed, subclasses
1137     * inherit the implementation of this method and if they don't
1138     * override it then they throw an exception if they use an
1139     * unsupported <code>transferType</code>
1140     *
1141     * @param components an array of unnormalized color and alpha
1142     * components
1143     * @param offset the index into <code>components</code> at which to
1144     * begin retrieving color and alpha components
1145     * @param pixel the <code>Object</code> representing an array of color
1146     * and alpha components
1147     * @return an <code>Object</code> representing an array of color and
1148     * alpha components.
1149     * @throws ClassCastException if <code>pixel</code>
1150     * is not a primitive array of type <code>transferType</code>
1151     * @throws ArrayIndexOutOfBoundsException if
1152     * <code>pixel</code> is not large enough to hold a pixel value
1153     * for this <code>ColorModel</code> or the <code>components</code>
1154     * array is not large enough to hold all of the color and alpha
1155     * components starting at <code>offset</code>
1156     * @throws UnsupportedOperationException if <code>transferType</code>
1157     * is not one of the supported transer types
1158     * @see WritableRaster#setDataElements
1159     * @see SampleModel#setDataElements
1160     */

1161    public Object JavaDoc getDataElements(int[] components, int offset, Object JavaDoc pixel) {
1162        int rgb = (components[offset+0]<<16) | (components[offset+1]<<8)
1163            | (components[offset+2]);
1164        if (supportsAlpha) {
1165            rgb |= (components[offset+3]<<24);
1166        }
1167        else {
1168            rgb &= 0xff000000;
1169        }
1170        return getDataElements(rgb, pixel);
1171    }
1172
1173    /**
1174     * Creates a <code>WritableRaster</code> with the specified width
1175     * and height that has a data layout (<code>SampleModel</code>)
1176     * compatible with this <code>ColorModel</code>. This method
1177     * only works for color models with 16 or fewer bits per pixel.
1178     * <p>
1179     * Since <code>IndexColorModel</code> can be subclassed, any
1180     * subclass that supports greater than 16 bits per pixel must
1181     * override this method.
1182     *
1183     * @param w the width to apply to the new <code>WritableRaster</code>
1184     * @param h the height to apply to the new <code>WritableRaster</code>
1185     * @return a <code>WritableRaster</code> object with the specified
1186     * width and height.
1187     * @throws UnsupportedOperationException if the number of bits in a
1188     * pixel is greater than 16
1189     * @see WritableRaster
1190     * @see SampleModel
1191     */

1192    public WritableRaster JavaDoc createCompatibleWritableRaster(int w, int h) {
1193        WritableRaster JavaDoc raster;
1194
1195        if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
1196            // TYPE_BINARY
1197
raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
1198                                               w, h, 1, pixel_bits, null);
1199        }
1200        else if (pixel_bits <= 8) {
1201            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
1202                                                  w,h,1,null);
1203        }
1204        else if (pixel_bits <= 16) {
1205            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT,
1206                                                  w,h,1,null);
1207        }
1208        else {
1209            throw new
1210                UnsupportedOperationException JavaDoc("This method is not supported "+
1211                                              " for pixel bits > 16.");
1212        }
1213        return raster;
1214    }
1215
1216    /**
1217      * Returns <code>true</code> if <code>raster</code> is compatible
1218      * with this <code>ColorModel</code> or <code>false</code> if it
1219      * is not compatible with this <code>ColorModel</code>.
1220      * @param raster the {@link Raster} object to test for compatibility
1221      * @return <code>true</code> if <code>raster</code> is compatible
1222      * with this <code>ColorModel</code>; <code>false</code> otherwise.
1223      *
1224      */

1225    public boolean isCompatibleRaster(Raster JavaDoc raster) {
1226
1227    int size = raster.getSampleModel().getSampleSize(0);
1228        return ((raster.getTransferType() == transferType) &&
1229        (raster.getNumBands() == 1) && ((1 << size) >= map_size));
1230    }
1231    
1232    /**
1233     * Creates a <code>SampleModel</code> with the specified
1234     * width and height that has a data layout compatible with
1235     * this <code>ColorModel</code>.
1236     * @param w the width to apply to the new <code>SampleModel</code>
1237     * @param h the height to apply to the new <code>SampleModel</code>
1238     * @return a <code>SampleModel</code> object with the specified
1239     * width and height.
1240     * @throws IllegalArgumentException if <code>w</code> or
1241     * <code>h</code> is not greater than 0
1242     * @see SampleModel
1243     */

1244    public SampleModel JavaDoc createCompatibleSampleModel(int w, int h) {
1245        int[] off = new int[1];
1246        off[0] = 0;
1247        if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
1248            return new MultiPixelPackedSampleModel JavaDoc(transferType, w, h,
1249                                                   pixel_bits);
1250        }
1251        else {
1252            return new ComponentSampleModel JavaDoc(transferType, w, h, 1, w,
1253                                            off);
1254        }
1255    }
1256    
1257    /**
1258     * Checks if the specified <code>SampleModel</code> is compatible
1259     * with this <code>ColorModel</code>. If <code>sm</code> is
1260     * <code>null</code>, this method returns <code>false</code>.
1261     * @param sm the specified <code>SampleModel</code>,
1262     * or <code>null</code>
1263     * @return <code>true</code> if the specified <code>SampleModel</code>
1264     * is compatible with this <code>ColorModel</code>; <code>false</code>
1265     * otherwise.
1266     * @see SampleModel
1267     */

1268    public boolean isCompatibleSampleModel(SampleModel JavaDoc sm) {
1269        // fix 4238629
1270
if (! (sm instanceof ComponentSampleModel JavaDoc) &&
1271            ! (sm instanceof MultiPixelPackedSampleModel JavaDoc) ) {
1272            return false;
1273        }
1274
1275        // Transfer type must be the same
1276
if (sm.getTransferType() != transferType) {
1277            return false;
1278        }
1279
1280        if (sm.getNumBands() != 1) {
1281            return false;
1282        }
1283        
1284        return true;
1285    }
1286    
1287    /**
1288     * Returns a new <code>BufferedImage</code> of TYPE_INT_ARGB or
1289     * TYPE_INT_RGB that has a <code>Raster</code> with pixel data
1290     * computed by expanding the indices in the source <code>Raster</code>
1291     * using the color/alpha component arrays of this <code>ColorModel</code>.
1292     * If <code>forceARGB</code> is <code>true</code>, a TYPE_INT_ARGB image is
1293     * returned regardless of whether or not this <code>ColorModel</code>
1294     * has an alpha component array or a transparent pixel.
1295     * @param raster the specified <code>Raster</code>
1296     * @param forceARGB if <code>true</code>, the returned
1297     * <code>BufferedImage</code> is TYPE_INT_ARGB; otherwise it is
1298     * TYPE_INT_RGB
1299     * @return a <code>BufferedImage</code> created with the specified
1300     * <code>Raster</code>
1301     * @throws IllegalArgumentException if the raster argument is not
1302     * compatible with this IndexColorModel
1303     */

1304    public BufferedImage JavaDoc convertToIntDiscrete(Raster JavaDoc raster,
1305                                              boolean forceARGB) {
1306        ColorModel JavaDoc cm;
1307
1308        if (!isCompatibleRaster(raster)) {
1309            throw new IllegalArgumentException JavaDoc("This raster is not compatible" +
1310                 "with this IndexColorModel.");
1311        }
1312        if (forceARGB || transparency == TRANSLUCENT) {
1313            cm = ColorModel.getRGBdefault();
1314        }
1315        else if (transparency == BITMASK) {
1316            cm = new DirectColorModel JavaDoc(25, 0xff0000, 0x00ff00, 0x0000ff,
1317                                      0x1000000);
1318        }
1319        else {
1320            cm = new DirectColorModel JavaDoc(24, 0xff0000, 0x00ff00, 0x0000ff);
1321        }
1322
1323        int w = raster.getWidth();
1324        int h = raster.getHeight();
1325        WritableRaster JavaDoc discreteRaster =
1326                  cm.createCompatibleWritableRaster(w, h);
1327        Object JavaDoc obj = null;
1328        int[] data = null;
1329
1330        int rX = raster.getMinX();
1331        int rY = raster.getMinY();
1332
1333        for (int y=0; y < h; y++, rY++) {
1334            obj = raster.getDataElements(rX, rY, w, 1, obj);
1335            if (obj instanceof int[]) {
1336                data = (int[])obj;
1337            } else {
1338                data = DataBuffer.toIntArray(obj);
1339            }
1340            for (int x=0; x < w; x++) {
1341                data[x] = rgb[data[x]];
1342            }
1343            discreteRaster.setDataElements(0, y, w, 1, data);
1344        }
1345        
1346        return new BufferedImage JavaDoc(cm, discreteRaster, false, null);
1347    }
1348
1349    /**
1350     * Returns whether or not the pixel is valid.
1351     * @param pixel the specified pixel value
1352     * @return <code>true</code> if <code>pixel</code>
1353     * is valid; <code>false</code> otherwise.
1354     */

1355    public boolean isValid(int pixel) {
1356    return ((pixel >= 0 && pixel < map_size) &&
1357        (validBits == null || validBits.testBit(pixel)));
1358    }
1359        
1360    /**
1361     * Returns whether or not all of the pixels are valid.
1362     * @return <code>true</code> if all pixels are valid;
1363     * <code>false</code> otherwise.
1364     */

1365    public boolean isValid() {
1366        return (validBits == null);
1367    }
1368        
1369    /**
1370     * Returns a <code>BigInteger</code> that indicates the valid/invalid
1371     * pixels in the colormap. A bit is valid if the
1372     * <code>BigInteger</code> value at that index is set, and is invalid
1373     * if the <code>BigInteger</code> value at that index is not set.
1374     * The only valid ranges to query in the <code>BigInteger</code> are
1375     * between 0 and the map size.
1376     * @return a <code>BigInteger</code> indicating the valid/invalid pixels.
1377     */

1378    public BigInteger JavaDoc getValidPixels() {
1379        if (validBits == null) {
1380            return getAllValid();
1381        }
1382        else {
1383            return validBits;
1384        }
1385    }
1386 
1387    /**
1388     * Disposes of system resources associated with this
1389     * <code>ColorModel</code> once this <code>ColorModel</code> is no
1390     * longer referenced.
1391     */

1392    public void finalize() {
1393    sun.awt.image.BufImgSurfaceData.freeNativeICMData(this);
1394    }
1395
1396    /**
1397     * Returns the <code>String</code> representation of the contents of
1398     * this <code>ColorModel</code>object.
1399     * @return a <code>String</code> representing the contents of this
1400     * <code>ColorModel</code> object.
1401     */

1402    public String JavaDoc toString() {
1403       return new String JavaDoc("IndexColorModel: #pixelBits = "+pixel_bits
1404                         + " numComponents = "+numComponents
1405                         + " color space = "+colorSpace
1406                         + " transparency = "+transparency
1407                         + " transIndex = "+transparent_index
1408                         + " has alpha = "+supportsAlpha
1409                         + " isAlphaPre = "+isAlphaPremultiplied
1410                         );
1411    }
1412}
1413
Popular Tags