KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)DirectColorModel.java 1.78 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.color.ColorSpace JavaDoc;
11 import java.awt.Transparency JavaDoc;
12
13 /**
14  * The <code>DirectColorModel</code> class is a <code>ColorModel</code>
15  * class that works with pixel values that represent RGB
16  * color and alpha information as separate samples and that pack all
17  * samples for a single pixel into a single int, short, or byte quantity.
18  * This class can be used only with ColorSpaces of type ColorSpace.TYPE_RGB.
19  * In addition, for each component of the ColorSpace, the minimum
20  * normalized component value obtained via the <code>getMinValue()</code>
21  * method of ColorSpace must be 0.0, and the maximum value obtained via
22  * the <code>getMaxValue()</code> method must be 1.0 (these min/max
23  * values are typical for RGB spaces).
24  * There must be three color samples in the pixel values and there can
25  * be a single alpha sample. For those methods that use a primitive array
26  * pixel representation of type <code>transferType</code>, the array
27  * length is always one. The transfer
28  * types supported are DataBuffer.TYPE_BYTE,
29  * DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
30  * Color and alpha samples are stored in the single
31  * element of the array in bits indicated by bit masks. Each bit mask
32  * must be contiguous and masks must not overlap. The same masks apply to
33  * the single int pixel representation used by other methods. The
34  * correspondence of masks and color/alpha samples is as follows:
35  * <ul>
36  * <li> Masks are identified by indices running from 0 through 2
37  * if no alpha is present, or 3 if an alpha is present.
38  * <li> The first three indices refer to color samples;
39  * index 0 corresponds to red, index 1 to green, and index 2 to blue.
40  * <li> Index 3 corresponds to the alpha sample, if present.
41  * </ul>
42  * <p>
43  * The translation from pixel values to color/alpha components for
44  * display or processing purposes is a one-to-one correspondence of
45  * samples to components. A <code>DirectColorModel</code> is
46  * typically used with image data which uses masks to define packed
47  * samples. For example, a <code>DirectColorModel</code> can be used in
48  * conjunction with a <code>SinglePixelPackedSampleModel</code> to
49  * construct a {@link BufferedImage}. Normally the masks used by the
50  * {@link SampleModel} and the <code>ColorModel</code> would be the
51  * same. However, if they are different, the color interpretation
52  * of pixel data will be done according to the masks of the
53  * <code>ColorModel</code>.
54  * <p>
55  * A single int pixel representation is valid for all objects of this
56  * class, since it is always possible to represent pixel values used with
57  * this class in a single int. Therefore, methods which use this
58  * representation will not throw an <code>IllegalArgumentException</code>
59  * due to an invalid pixel value.
60  * <p>
61  * This color model is similar to an X11 TrueColor visual.
62  * The default RGB ColorModel specified by the
63  * {@link ColorModel#getRGBdefault() getRGBdefault} method is a
64  * <code>DirectColorModel</code> with the following parameters:
65  * <pre>
66  * Number of bits: 32
67  * Red mask: 0x00ff0000
68  * Green mask: 0x0000ff00
69  * Blue mask: 0x000000ff
70  * Alpha mask: 0xff000000
71  * Color space: sRGB
72  * isAlphaPremultiplied: False
73  * Transparency: Transparency.TRANSLUCENT
74  * transferType: DataBuffer.TYPE_INT
75  * </pre>
76  * <p>
77  * Many of the methods in this class are final. This is because the
78  * underlying native graphics code makes assumptions about the layout
79  * and operation of this class and those assumptions are reflected in
80  * the implementations of the methods here that are marked final. You
81  * can subclass this class for other reasons, but you cannot override
82  * or modify the behavior of those methods.
83  *
84  * @see ColorModel
85  * @see ColorSpace
86  * @see SinglePixelPackedSampleModel
87  * @see BufferedImage
88  * @see ColorModel#getRGBdefault
89  *
90  * @version 10 Feb 1997
91  */

92 public class DirectColorModel extends PackedColorModel JavaDoc {
93     private int red_mask;
94     private int green_mask;
95     private int blue_mask;
96     private int alpha_mask;
97     private int red_offset;
98     private int green_offset;
99     private int blue_offset;
100     private int alpha_offset;
101     private int red_scale;
102     private int green_scale;
103     private int blue_scale;
104     private int alpha_scale;
105     private boolean is_LinearRGB;
106     private int lRGBprecision;
107     private byte[] tosRGB8LUT;
108     private byte[] fromsRGB8LUT8;
109     private short[] fromsRGB8LUT16;
110     
111     /**
112      * Constructs a <code>DirectColorModel</code> from the specified masks
113      * that indicate which bits in an <code>int</code> pixel representation
114      * contain the red, green and blue color samples. As pixel values do not
115      * contain alpha information, all pixels are treated as opaque, which
116      * means that alpha&nbsp;=&nbsp;1.0. All of the bits
117      * in each mask must be contiguous and fit in the specified number
118      * of least significant bits of an <code>int</code> pixel representation.
119      * The <code>ColorSpace</code> is the default sRGB space. The
120      * transparency value is Transparency.OPAQUE. The transfer type
121      * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
122      * or DataBuffer.TYPE_INT that can hold a single pixel.
123      * @param bits the number of bits in the pixel values; for example,
124      * the sum of the number of bits in the masks.
125      * @param rmask specifies a mask indicating which bits in an
126      * integer pixel contain the red component
127      * @param gmask specifies a mask indicating which bits in an
128      * integer pixel contain the green component
129      * @param bmask specifies a mask indicating which bits in an
130      * integer pixel contain the blue component
131      *
132      */

133     public DirectColorModel(int bits,
134                 int rmask, int gmask, int bmask) {
135     this(bits, rmask, gmask, bmask, 0);
136     }
137
138     /**
139      * Constructs a <code>DirectColorModel</code> from the specified masks
140      * that indicate which bits in an <code>int</code> pixel representation
141      * contain the red, green and blue color samples and the alpha sample,
142      * if present. If <code>amask</code> is 0, pixel values do not contain
143      * alpha information and all pixels are treated as opaque, which means
144      * that alpha&nbsp;=&nbsp;1.0. All of the bits in each mask must
145      * be contiguous and fit in the specified number of least significant bits
146      * of an <code>int</code> pixel representation. Alpha, if present, is not
147      * premultiplied. The <code>ColorSpace</code> is the default sRGB space.
148      * The transparency value is Transparency.OPAQUE if no alpha is
149      * present, or Transparency.TRANSLUCENT otherwise. The transfer type
150      * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
151      * or DataBuffer.TYPE_INT that can hold a single pixel.
152      * @param bits the number of bits in the pixel values; for example,
153      * the sum of the number of bits in the masks.
154      * @param rmask specifies a mask indicating which bits in an
155      * integer pixel contain the red component
156      * @param gmask specifies a mask indicating which bits in an
157      * integer pixel contain the green component
158      * @param bmask specifies a mask indicating which bits in an
159      * integer pixel contain the blue component
160      * @param amask specifies a mask indicating which bits in an
161      * integer pixel contain the alpha component
162      */

163     public DirectColorModel(int bits, int rmask, int gmask,
164                             int bmask, int amask) {
165         super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
166                bits, rmask, gmask, bmask, amask, false,
167                amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
168                ColorModel.getDefaultTransferType(bits));
169         setFields();
170     }
171
172     /**
173      * Constructs a <code>DirectColorModel</code> from the specified
174      * parameters. Color components are in the specified
175      * <code>ColorSpace</code>, which must be of type ColorSpace.TYPE_RGB
176      * and have minimum normalized component values which are all 0.0
177      * and maximum values which are all 1.0.
178      * The masks specify which bits in an <code>int</code> pixel
179      * representation contain the red, green and blue color samples and
180      * the alpha sample, if present. If <code>amask</code> is 0, pixel
181      * values do not contain alpha information and all pixels are treated
182      * as opaque, which means that alpha&nbsp;=&nbsp;1.0. All of the
183      * bits in each mask must be contiguous and fit in the specified number
184      * of least significant bits of an <code>int</code> pixel
185      * representation. If there is alpha, the <code>boolean</code>
186      * <code>isAlphaPremultiplied</code> specifies how to interpret
187      * color and alpha samples in pixel values. If the <code>boolean</code>
188      * is <code>true</code>, color samples are assumed to have been
189      * multiplied by the alpha sample. The transparency value is
190      * Transparency.OPAQUE, if no alpha is present, or
191      * Transparency.TRANSLUCENT otherwise. The transfer type
192      * is the type of primitive array used to represent pixel values and
193      * must be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or
194      * DataBuffer.TYPE_INT.
195      * @param space the specified <code>ColorSpace</code>
196      * @param bits the number of bits in the pixel values; for example,
197      * the sum of the number of bits in the masks.
198      * @param rmask specifies a mask indicating which bits in an
199      * integer pixel contain the red component
200      * @param gmask specifies a mask indicating which bits in an
201      * integer pixel contain the green component
202      * @param bmask specifies a mask indicating which bits in an
203      * integer pixel contain the blue component
204      * @param amask specifies a mask indicating which bits in an
205      * integer pixel contain the alpha component
206      * @param isAlphaPremultiplied <code>true</code> if color samples are
207      * premultiplied by the alpha sample; <code>false</code> otherwise
208      * @param transferType the type of array used to represent pixel values
209      * @throws IllegalArgumentException if <code>space</code> is not a
210      * TYPE_RGB space or if the min/max normalized component
211      * values are not 0.0/1.0.
212      */

213     public DirectColorModel(ColorSpace JavaDoc space, int bits, int rmask,
214                             int gmask, int bmask, int amask,
215                             boolean isAlphaPremultiplied,
216                             int transferType) {
217         super (space, bits, rmask, gmask, bmask, amask,
218                isAlphaPremultiplied,
219                amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
220                transferType);
221         if (ColorModel.isLinearRGBspace(colorSpace)) {
222             is_LinearRGB = true;
223             if (maxBits <= 8) {
224                 lRGBprecision = 8;
225                 tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
226                 fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
227             } else {
228                 lRGBprecision = 16;
229                 tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
230                 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
231             }
232         } else if (!is_sRGB) {
233             for (int i = 0; i < 3; i++) {
234                 // super constructor checks that space is TYPE_RGB
235
// check here that min/max are all 0.0/1.0
236
if ((space.getMinValue(i) != 0.0f) ||
237                     (space.getMaxValue(i) != 1.0f)) {
238                     throw new IllegalArgumentException JavaDoc(
239                         "Illegal min/max RGB component value");
240                 }
241             }
242         }
243         setFields();
244     }
245
246     /**
247      * Returns the mask indicating which bits in an <code>int</code> pixel
248      * representation contain the red color component.
249      * @return the mask, which indicates which bits of the <code>int</code>
250      * pixel representation contain the red color sample.
251      */

252     final public int getRedMask() {
253     return maskArray[0];
254     }
255
256     /**
257      * Returns the mask indicating which bits in an <code>int</code> pixel
258      * representation contain the green color component.
259      * @return the mask, which indicates which bits of the <code>int</code>
260      * pixel representation contain the green color sample.
261      */

262     final public int getGreenMask() {
263     return maskArray[1];
264     }
265
266     /**
267      * Returns the mask indicating which bits in an <code>int</code> pixel
268      * representation contain the blue color component.
269      * @return the mask, which indicates which bits of the <code>int</code>
270      * pixel representation contain the blue color sample.
271      */

272     final public int getBlueMask() {
273     return maskArray[2];
274     }
275
276     /**
277      * Returns the mask indicating which bits in an <code>int</code> pixel
278      * representation contain the alpha component.
279      * @return the mask, which indicates which bits of the <code>int</code>
280      * pixel representation contain the alpha sample.
281      */

282     final public int getAlphaMask() {
283         if (supportsAlpha) {
284             return maskArray[3];
285         } else {
286             return 0;
287         }
288     }
289
290
291     /*
292      * Given an int pixel in this ColorModel's ColorSpace, converts
293      * it to the default sRGB ColorSpace and returns the R, G, and B
294      * components as float values between 0.0 and 1.0.
295      */

296     private float[] getDefaultRGBComponents(int pixel) {
297         int components[] = getComponents(pixel, null, 0);
298         float norm[] = getNormalizedComponents(components, 0, null, 0);
299         // Note that getNormalizedComponents returns non-premultiplied values
300
return colorSpace.toRGB(norm);
301     }
302
303
304     private int getsRGBComponentFromsRGB(int pixel, int idx) {
305     int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
306         if (isAlphaPremultiplied) {
307             int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
308             c = (a == 0) ? 0 :
309                          (int) (((c * scaleFactors[idx]) * 255.0f /
310                                  (a * scaleFactors[3])) + 0.5f);
311         } else if (scaleFactors[idx] != 1.0f) {
312         c = (int) ((c * scaleFactors[idx]) + 0.5f);
313         }
314     return c;
315     }
316
317
318     private int getsRGBComponentFromLinearRGB(int pixel, int idx) {
319     int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
320         if (isAlphaPremultiplied) {
321             float factor = (float) ((1 << lRGBprecision) - 1);
322             int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
323             c = (a == 0) ? 0 :
324                          (int) (((c * scaleFactors[idx]) * factor /
325                                  (a * scaleFactors[3])) + 0.5f);
326         } else if (nBits[idx] != lRGBprecision) {
327             if (lRGBprecision == 16) {
328                 c = (int) ((c * scaleFactors[idx] * 257.0f) + 0.5f);
329             } else {
330             c = (int) ((c * scaleFactors[idx]) + 0.5f);
331             }
332         }
333         // now range of c is 0-255 or 0-65535, depending on lRGBprecision
334
return tosRGB8LUT[c] & 0xff;
335     }
336
337
338     /**
339      * Returns the red color component for the specified pixel, scaled
340      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
341      * color conversion is done if necessary. The pixel value is specified
342      * as an <code>int</code>.
343      * The returned value is a non pre-multiplied value. Thus, if the
344      * alpha is premultiplied, this method divides it out before returning
345      * the value. If the alpha value is 0, for example, the red value
346      * is 0.
347      * @param pixel the specified pixel
348      * @return the red color component for the specified pixel, from
349      * 0 to 255 in the sRGB <code>ColorSpace</code>.
350      */

351     final public int getRed(int pixel) {
352         if (is_sRGB) {
353             return getsRGBComponentFromsRGB(pixel, 0);
354         } else if (is_LinearRGB) {
355             return getsRGBComponentFromLinearRGB(pixel, 0);
356         }
357         float rgb[] = getDefaultRGBComponents(pixel);
358         return (int) (rgb[0] * 255.0f + 0.5f);
359     }
360
361     /**
362      * Returns the green color component for the specified pixel, scaled
363      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
364      * color conversion is done if necessary. The pixel value is specified
365      * as an <code>int</code>.
366      * The returned value is a non pre-multiplied value. Thus, if the
367      * alpha is premultiplied, this method divides it out before returning
368      * the value. If the alpha value is 0, for example, the green value
369      * is 0.
370      * @param pixel the specified pixel
371      * @return the green color component for the specified pixel, from
372      * 0 to 255 in the sRGB <code>ColorSpace</code>.
373      */

374     final public int getGreen(int pixel) {
375         if (is_sRGB) {
376             return getsRGBComponentFromsRGB(pixel, 1);
377         } else if (is_LinearRGB) {
378             return getsRGBComponentFromLinearRGB(pixel, 1);
379         }
380         float rgb[] = getDefaultRGBComponents(pixel);
381         return (int) (rgb[1] * 255.0f + 0.5f);
382     }
383
384     /**
385      * Returns the blue color component for the specified pixel, scaled
386      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
387      * color conversion is done if necessary. The pixel value is specified
388      * as an <code>int</code>.
389      * The returned value is a non pre-multiplied value. Thus, if the
390      * alpha is premultiplied, this method divides it out before returning
391      * the value. If the alpha value is 0, for example, the blue value
392      * is 0.
393      * @param pixel the specified pixel
394      * @return the blue color component for the specified pixel, from
395      * 0 to 255 in the sRGB <code>ColorSpace</code>.
396      */

397     final public int getBlue(int pixel) {
398         if (is_sRGB) {
399             return getsRGBComponentFromsRGB(pixel, 2);
400         } else if (is_LinearRGB) {
401             return getsRGBComponentFromLinearRGB(pixel, 2);
402         }
403         float rgb[] = getDefaultRGBComponents(pixel);
404         return (int) (rgb[2] * 255.0f + 0.5f);
405     }
406
407     /**
408      * Returns the alpha component for the specified pixel, scaled
409      * from 0 to 255. The pixel value is specified as an <code>int</code>.
410      * @param pixel the specified pixel
411      * @return the value of the alpha component of <code>pixel</code>
412      * from 0 to 255.
413      */

414     final public int getAlpha(int pixel) {
415     if (!supportsAlpha) return 255;
416     int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
417     if (scaleFactors[3] != 1.0f) {
418         a = (int)(a * scaleFactors[3] + 0.5f);
419     }
420     return a;
421     }
422
423     /**
424      * Returns the color/alpha components of the pixel in the default
425      * RGB color model format. A color conversion is done if necessary.
426      * The pixel value is specified as an <code>int</code>.
427      * The returned value is in a non pre-multiplied format. Thus, if
428      * the alpha is premultiplied, this method divides it out of the
429      * color components. If the alpha value is 0, for example, the color
430      * values are each 0.
431      * @param pixel the specified pixel
432      * @return the RGB value of the color/alpha components of the specified
433      * pixel.
434      * @see ColorModel#getRGBdefault
435      */

436     final public int getRGB(int pixel) {
437         if (is_sRGB || is_LinearRGB) {
438         return (getAlpha(pixel) << 24)
439             | (getRed(pixel) << 16)
440             | (getGreen(pixel) << 8)
441             | (getBlue(pixel) << 0);
442         }
443         float rgb[] = getDefaultRGBComponents(pixel);
444         return (getAlpha(pixel) << 24)
445             | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
446             | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
447             | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
448     }
449     
450     /**
451      * Returns the red color component for the specified pixel, scaled
452      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
453      * color conversion is done if necessary. The pixel value is specified
454      * by an array of data elements of type <code>transferType</code> passed
455      * in as an object reference.
456      * The returned value is a non pre-multiplied value. Thus, if the
457      * alpha is premultiplied, this method divides it out before returning
458      * the value. If the alpha value is 0, for example, the red value
459      * is 0.
460      * If <code>inData</code> is not a primitive array of type
461      * <code>transferType</code>, a <code>ClassCastException</code> is
462      * thrown. An <code>ArrayIndexOutOfBoundsException</code> is
463      * thrown if <code>inData</code> is not large enough to hold a
464      * pixel value for this <code>ColorModel</code>. Since
465      * <code>DirectColorModel</code> can be subclassed, subclasses inherit
466      * the implementation of this method and if they don't override it
467      * then they throw an exception if they use an unsupported
468      * <code>transferType</code>.
469      * An <code>UnsupportedOperationException</code> is thrown if this
470      * <code>transferType</code> is not supported by this
471      * <code>ColorModel</code>.
472      * @param inData the array containing the pixel value
473      * @return the value of the red component of the specified pixel.
474      * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
475      * large enough to hold a pixel value for this color model
476      * @throws ClassCastException if <code>inData</code> is not a
477      * primitive array of type <code>transferType</code>
478      * @throws UnsupportedOperationException if this <code>transferType</code>
479      * is not supported by this color model
480      */

481     public int getRed(Object JavaDoc inData) {
482         int pixel=0;
483         switch (transferType) {
484             case DataBuffer.TYPE_BYTE:
485                byte bdata[] = (byte[])inData;
486                pixel = bdata[0] & 0xff;
487             break;
488             case DataBuffer.TYPE_USHORT:
489                short sdata[] = (short[])inData;
490                pixel = sdata[0] & 0xffff;
491             break;
492             case DataBuffer.TYPE_INT:
493                int idata[] = (int[])inData;
494                pixel = idata[0];
495             break;
496             default:
497                throw new UnsupportedOperationException JavaDoc("This method has not been "+
498                    "implemented for transferType " + transferType);
499         }
500         return getRed(pixel);
501     }
502    
503
504     /**
505      * Returns the green color component for the specified pixel, scaled
506      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
507      * color conversion is done if necessary. The pixel value is specified
508      * by an array of data elements of type <code>transferType</code> passed
509      * in as an object reference.
510      * The returned value is a non pre-multiplied value. Thus, if the
511      * alpha is premultiplied, this method divides it out before returning
512      * the value. If the alpha value is 0, for example, the green value
513      * is 0. If <code>inData</code> is not a primitive array of type
514      * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
515      * An <code>ArrayIndexOutOfBoundsException</code> is
516      * thrown if <code>inData</code> is not large enough to hold a pixel
517      * value for this <code>ColorModel</code>. Since
518      * <code>DirectColorModel</code> can be subclassed, subclasses inherit
519      * the implementation of this method and if they don't override it
520      * then they throw an exception if they use an unsupported
521      * <code>transferType</code>.
522      * An <code>UnsupportedOperationException</code> is
523      * thrown if this <code>transferType</code> is not supported by this
524      * <code>ColorModel</code>.
525      * @param inData the array containing the pixel value
526      * @return the value of the green component of the specified pixel.
527      * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
528      * large enough to hold a pixel value for this color model
529      * @throws ClassCastException if <code>inData</code> is not a
530      * primitive array of type <code>transferType</code>
531      * @throws UnsupportedOperationException if this <code>transferType</code>
532      * is not supported by this color model
533      */

534     public int getGreen(Object JavaDoc inData) {
535         int pixel=0;
536         switch (transferType) {
537             case DataBuffer.TYPE_BYTE:
538                byte bdata[] = (byte[])inData;
539                pixel = bdata[0] & 0xff;
540             break;
541             case DataBuffer.TYPE_USHORT:
542                short sdata[] = (short[])inData;
543                pixel = sdata[0] & 0xffff;
544             break;
545             case DataBuffer.TYPE_INT:
546                int idata[] = (int[])inData;
547                pixel = idata[0];
548             break;
549             default:
550                throw new UnsupportedOperationException JavaDoc("This method has not been "+
551                    "implemented for transferType " + transferType);
552         }
553         return getGreen(pixel);
554     }
555    
556
557     /**
558      * Returns the blue color component for the specified pixel, scaled
559      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
560      * color conversion is done if necessary. The pixel value is specified
561      * by an array of data elements of type <code>transferType</code> passed
562      * in as an object reference.
563      * The returned value is a non pre-multiplied value. Thus, if the
564      * alpha is premultiplied, this method divides it out before returning
565      * the value. If the alpha value is 0, for example, the blue value
566      * is 0. If <code>inData</code> is not a primitive array of type
567      * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
568      * An <code>ArrayIndexOutOfBoundsException</code> is
569      * thrown if <code>inData</code> is not large enough to hold a pixel
570      * value for this <code>ColorModel</code>. Since
571      * <code>DirectColorModel</code> can be subclassed, subclasses inherit
572      * the implementation of this method and if they don't override it
573      * then they throw an exception if they use an unsupported
574      * <code>transferType</code>.
575      * An <code>UnsupportedOperationException</code> is
576      * thrown if this <code>transferType</code> is not supported by this
577      * <code>ColorModel</code>.
578      * @param inData the array containing the pixel value
579      * @return the value of the blue component of the specified pixel.
580      * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
581      * large enough to hold a pixel value for this color model
582      * @throws ClassCastException if <code>inData</code> is not a
583      * primitive array of type <code>transferType</code>
584      * @throws UnsupportedOperationException if this <code>transferType</code>
585      * is not supported by this color model
586      */

587     public int getBlue(Object JavaDoc inData) {
588         int pixel=0;
589         switch (transferType) {
590             case DataBuffer.TYPE_BYTE:
591                byte bdata[] = (byte[])inData;
592                pixel = bdata[0] & 0xff;
593             break;
594             case DataBuffer.TYPE_USHORT:
595                short sdata[] = (short[])inData;
596                pixel = sdata[0] & 0xffff;
597             break;
598             case DataBuffer.TYPE_INT:
599                int idata[] = (int[])inData;
600                pixel = idata[0];
601             break;
602             default:
603                throw new UnsupportedOperationException JavaDoc("This method has not been "+
604                    "implemented for transferType " + transferType);
605         }
606         return getBlue(pixel);
607     }
608
609     /**
610      * Returns the alpha component for the specified pixel, scaled
611      * from 0 to 255. The pixel value is specified by an array of data
612      * elements of type <code>transferType</code> passed in as an object
613      * reference.
614      * If <code>inData</code> is not a primitive array of type
615      * <code>transferType</code>, a <code>ClassCastException</code> is
616      * thrown. An <code>ArrayIndexOutOfBoundsException</code> is
617      * thrown if <code>inData</code> is not large enough to hold a pixel
618      * value for this <code>ColorModel</code>. Since
619      * <code>DirectColorModel</code> can be subclassed, subclasses inherit
620      * the implementation of this method and if they don't override it
621      * then they throw an exception if they use an unsupported
622      * <code>transferType</code>.
623      * If this <code>transferType</code> is not supported, an
624      * <code>UnsupportedOperationException</code> is thrown.
625      * @param inData the specified pixel
626      * @return the alpha component of the specified pixel, scaled from
627      * 0 to 255.
628      * @exception <code>ClassCastException</code> if <code>inData</code>
629      * is not a primitive array of type <code>transferType</code>
630      * @exception <code>ArrayIndexOutOfBoundsException</code> if
631      * <code>inData</code> is not large enough to hold a pixel value
632      * for this <code>ColorModel</code>
633      * @exception <code>UnsupportedOperationException</code> if this
634      * <code>tranferType</code> is not supported by this
635      * <code>ColorModel</code>
636      */

637     public int getAlpha(Object JavaDoc inData) {
638         int pixel=0;
639         switch (transferType) {
640             case DataBuffer.TYPE_BYTE:
641                byte bdata[] = (byte[])inData;
642                pixel = bdata[0] & 0xff;
643             break;
644             case DataBuffer.TYPE_USHORT:
645                short sdata[] = (short[])inData;
646                pixel = sdata[0] & 0xffff;
647             break;
648             case DataBuffer.TYPE_INT:
649                int idata[] = (int[])inData;
650                pixel = idata[0];
651             break;
652             default:
653                throw new UnsupportedOperationException JavaDoc("This method has not been "+
654                    "implemented for transferType " + transferType);
655         }
656         return getAlpha(pixel);
657     }
658
659     /**
660      * Returns the color/alpha components for the specified pixel in the
661      * default RGB color model format. A color conversion is done if
662      * necessary. The pixel value is specified by an array of data
663      * elements of type <code>transferType</code> passed in as an object
664      * reference. If <code>inData</code> is not a primitive array of type
665      * <code>transferType</code>, a <code>ClassCastException</code> is
666      * thrown. An <code>ArrayIndexOutOfBoundsException</code> is
667      * thrown if <code>inData</code> is not large enough to hold a pixel
668      * value for this <code>ColorModel</code>.
669      * The returned value is in a non pre-multiplied format. Thus, if
670      * the alpha is premultiplied, this method divides it out of the
671      * color components. If the alpha value is 0, for example, the color
672      * values is 0. Since <code>DirectColorModel</code> can be
673      * subclassed, subclasses inherit the implementation of this method
674      * and if they don't override it then
675      * they throw an exception if they use an unsupported
676      * <code>transferType</code>.
677      *
678      * @param inData the specified pixel
679      * @return the color and alpha components of the specified pixel.
680      * @exception UnsupportedOperationException if this
681      * <code>transferType</code> is not supported by this
682      * <code>ColorModel</code>
683      * @see ColorModel#getRGBdefault
684      */

685     public int getRGB(Object JavaDoc inData) {
686         int pixel=0;
687         switch (transferType) {
688             case DataBuffer.TYPE_BYTE:
689                byte bdata[] = (byte[])inData;
690                pixel = bdata[0] & 0xff;
691             break;
692             case DataBuffer.TYPE_USHORT:
693                short sdata[] = (short[])inData;
694                pixel = sdata[0] & 0xffff;
695             break;
696             case DataBuffer.TYPE_INT:
697                int idata[] = (int[])inData;
698                pixel = idata[0];
699             break;
700             default:
701                throw new UnsupportedOperationException JavaDoc("This method has not been "+
702                    "implemented for transferType " + transferType);
703         }
704         return getRGB(pixel);
705     }
706
707     /**
708      * Returns a data element array representation of a pixel in this
709      * <code>ColorModel</code>, given an integer pixel representation in the
710      * default RGB color model.
711      * This array can then be passed to the <code>setDataElements</code>
712      * method of a <code>WritableRaster</code> object. If the pixel variable
713      * is <code>null</code>, a new array is allocated. If <code>pixel</code>
714      * is not <code>null</code>, it must be a primitive array of type
715      * <code>transferType</code>; otherwise, a
716      * <code>ClassCastException</code> is thrown. An
717      * <code>ArrayIndexOutOfBoundsException</code> is
718      * thrown if <code>pixel</code> is not large enough to hold a pixel
719      * value for this <code>ColorModel</code>. The pixel array is returned.
720      * Since <code>DirectColorModel</code> can be subclassed, subclasses
721      * inherit the implementation of this method and if they don't
722      * override it then they throw an exception if they use an unsupported
723      * <code>transferType</code>.
724      *
725      * @param rgb the integer pixel representation in the default RGB
726      * color model
727      * @param pixel the specified pixel
728      * @return an array representation of the specified pixel in this
729      * <code>ColorModel</code>
730      * @exception ClassCastException if <code>pixel</code>
731      * is not a primitive array of type <code>transferType</code>
732      * @exception ArrayIndexOutOfBoundsException if
733      * <code>pixel</code> is not large enough to hold a pixel value
734      * for this <code>ColorModel</code>
735      * @exception UnsupportedOperationException if this
736      * <code>transferType</code> is not supported by this
737      * <code>ColorModel</code>
738      * @see WritableRaster#setDataElements
739      * @see SampleModel#setDataElements
740      */

741     public Object JavaDoc getDataElements(int rgb, Object JavaDoc pixel) {
742         //REMIND: maybe more efficient not to use int array for
743
//DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
744
int intpixel[] = null;
745         if (transferType == DataBuffer.TYPE_INT &&
746             pixel != null) {
747             intpixel = (int[])pixel;
748             intpixel[0] = 0;
749         } else {
750             intpixel = new int[1];
751         }
752
753         ColorModel JavaDoc defaultCM = ColorModel.getRGBdefault();
754         if (this == defaultCM || equals(defaultCM)) {
755             intpixel[0] = rgb;
756             return intpixel;
757         }
758
759         int red, grn, blu, alp;
760         red = (rgb>>16) & 0xff;
761         grn = (rgb>>8) & 0xff;
762         blu = rgb & 0xff;
763         if (is_sRGB || is_LinearRGB) {
764             int precision;
765             float factor;
766             if (is_LinearRGB) {
767                 if (lRGBprecision == 8) {
768                     red = fromsRGB8LUT8[red] & 0xff;
769                     grn = fromsRGB8LUT8[grn] & 0xff;
770                     blu = fromsRGB8LUT8[blu] & 0xff;
771                     precision = 8;
772                     factor = 1.0f / 255.0f;
773                 } else {
774                     red = fromsRGB8LUT16[red] & 0xffff;
775                     grn = fromsRGB8LUT16[grn] & 0xffff;
776                     blu = fromsRGB8LUT16[blu] & 0xffff;
777                     precision = 16;
778                     factor = 1.0f / 65535.0f;
779                 }
780             } else {
781                 precision = 8;
782                 factor = 1.0f / 255.0f;
783             }
784             if (supportsAlpha) {
785                 alp = (rgb>>24) & 0xff;
786                 if (isAlphaPremultiplied) {
787                     factor *= (alp * (1.0f / 255.0f));
788                     precision = -1; // force component calculations below
789
}
790                 if (nBits[3] != 8) {
791                     alp = (int)
792                         ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
793                     if (alp > ((1<<nBits[3]) - 1)) {
794                         // fix 4412670 - see comment below
795
alp = (1<<nBits[3]) - 1;
796                     }
797                 }
798                 intpixel[0] = alp << maskOffsets[3];
799             }
800             if (nBits[0] != precision) {
801                 red = (int) ((red * factor * ((1<<nBits[0]) - 1)) + 0.5f);
802             }
803             if (nBits[1] != precision) {
804                 grn = (int) ((grn * factor * ((1<<nBits[1]) - 1)) + 0.5f);
805             }
806             if (nBits[2] != precision) {
807                 blu = (int) ((blu * factor * ((1<<nBits[2]) - 1)) + 0.5f);
808             }
809         } else {
810             // Need to convert the color
811
float[] norm = new float[3];
812             float factor = 1.0f / 255.0f;
813             norm[0] = red * factor;
814             norm[1] = grn * factor;
815             norm[2] = blu * factor;
816             norm = colorSpace.fromRGB(norm);
817             if (supportsAlpha) {
818                 alp = (rgb>>24) & 0xff;
819                 if (isAlphaPremultiplied) {
820                     factor *= alp;
821                     for (int i = 0; i < 3; i++) {
822                         norm[i] *= factor;
823                     }
824                 }
825                 if (nBits[3] != 8) {
826                     alp = (int)
827                         ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
828                     if (alp > ((1<<nBits[3]) - 1)) {
829                         // fix 4412670 - see comment below
830
alp = (1<<nBits[3]) - 1;
831                     }
832                 }
833                 intpixel[0] = alp << maskOffsets[3];
834             }
835             red = (int) ((norm[0] * ((1<<nBits[0]) - 1)) + 0.5f);
836             grn = (int) ((norm[1] * ((1<<nBits[1]) - 1)) + 0.5f);
837             blu = (int) ((norm[2] * ((1<<nBits[2]) - 1)) + 0.5f);
838         }
839
840         if (maxBits > 23) {
841             // fix 4412670 - for components of 24 or more bits
842
// some calculations done above with float precision
843
// may lose enough precision that the integer result
844
// overflows nBits, so we need to clamp.
845
if (red > ((1<<nBits[0]) - 1)) {
846                 red = (1<<nBits[0]) - 1;
847             }
848             if (grn > ((1<<nBits[1]) - 1)) {
849                 grn = (1<<nBits[1]) - 1;
850             }
851             if (blu > ((1<<nBits[2]) - 1)) {
852                 blu = (1<<nBits[2]) - 1;
853             }
854         }
855
856         intpixel[0] |= (red << maskOffsets[0]) |
857                        (grn << maskOffsets[1]) |
858                        (blu << maskOffsets[2]);
859
860         switch (transferType) {
861             case DataBuffer.TYPE_BYTE: {
862                byte bdata[];
863                if (pixel == null) {
864                    bdata = new byte[1];
865                } else {
866                    bdata = (byte[])pixel;
867                }
868                bdata[0] = (byte)(0xff&intpixel[0]);
869                return bdata;
870             }
871             case DataBuffer.TYPE_USHORT:{
872                short sdata[];
873                if (pixel == null) {
874                    sdata = new short[1];
875                } else {
876                    sdata = (short[])pixel;
877                }
878                sdata[0] = (short)(intpixel[0]&0xffff);
879                return sdata;
880             }
881             case DataBuffer.TYPE_INT:
882                return intpixel;
883         }
884         throw new UnsupportedOperationException JavaDoc("This method has not been "+
885                  "implemented for transferType " + transferType);
886
887     }
888
889     /**
890      * Returns an array of unnormalized color/alpha components given a pixel
891      * in this <code>ColorModel</code>. The pixel value is specified as an
892      * <code>int</code>. If the <code>components</code> array is
893      * <code>null</code>, a new array is allocated. The
894      * <code>components</code> array is returned. Color/alpha components are
895      * stored in the <code>components</code> array starting at
896      * <code>offset</code>, even if the array is allocated by this method.
897      * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
898      * <code>components</code> array is not <code>null</code> and is not large
899      * enough to hold all the color and alpha components, starting at
900      * <code>offset</code>.
901      * @param pixel the specified pixel
902      * @param components the array to receive the color and alpha
903      * components of the specified pixel
904      * @param offset the offset into the <code>components</code> array at
905      * which to start storing the color and alpha components
906      * @return an array containing the color and alpha components of the
907      * specified pixel starting at the specified offset.
908      */

909     final public int[] getComponents(int pixel, int[] components, int offset) {
910         if (components == null) {
911             components = new int[offset+numComponents];
912         }
913
914         for (int i=0; i < numComponents; i++) {
915             components[offset+i] = (pixel & maskArray[i]) >>> maskOffsets[i];
916         }
917
918         return components;
919     }
920     
921     /**
922      * Returns an array of unnormalized color/alpha components given a pixel
923      * in this <code>ColorModel</code>. The pixel value is specified by an
924      * array of data elements of type <code>transferType</code> passed in as
925      * an object reference. If <code>pixel</code> is not a primitive array
926      * of type <code>transferType</code>, a <code>ClassCastException</code>
927      * is thrown. An <code>ArrayIndexOutOfBoundsException</code> is
928      * thrown if <code>pixel</code> is not large enough to hold a
929      * pixel value for this <code>ColorModel</code>. If the
930      * <code>components</code> array is <code>null</code>, a new
931      * array is allocated. The <code>components</code> array is returned.
932      * Color/alpha components are stored in the <code>components</code> array
933      * starting at <code>offset</code>, even if the array is allocated by
934      * this method. An <code>ArrayIndexOutOfBoundsException</code>
935      * is thrown if the <code>components</code> array is not
936      * <code>null</code> and is not large enough to hold all the color and
937      * alpha components, starting at <code>offset</code>.
938      * Since <code>DirectColorModel</code> can be subclassed, subclasses
939      * inherit the implementation of this method and if they don't
940      * override it then they throw an exception if they use an unsupported
941      * <code>transferType</code>.
942      * @param pixel the specified pixel
943      * @param components the array to receive the color and alpha
944      * components of the specified pixel
945      * @param offset the offset into the <code>components</code> array at
946      * which to start storing the color and alpha components
947      * @return an array containing the color and alpha components of the
948      * specified pixel starting at the specified offset.
949      * @exception ClassCastException if <code>pixel</code>
950      * is not a primitive array of type <code>transferType</code>
951      * @exception ArrayIndexOutOfBoundsException if
952      * <code>pixel</code> is not large enough to hold a pixel value
953      * for this <code>ColorModel</code>, or if <code>components</code>
954      * is not <code>null</code> and is not large enough to hold all the
955      * color and alpha components, starting at <code>offset</code>
956      * @exception UnsupportedOperationException if this
957      * <code>transferType</code> is not supported by this
958      * color model
959      */

960     final public int[] getComponents(Object JavaDoc pixel, int[] components,
961                                      int offset) {
962         int intpixel=0;
963         switch (transferType) {
964             case DataBuffer.TYPE_BYTE:
965                byte bdata[] = (byte[])pixel;
966                intpixel = bdata[0] & 0xff;
967             break;
968             case DataBuffer.TYPE_USHORT:
969                short sdata[] = (short[])pixel;
970                intpixel = sdata[0] & 0xffff;
971             break;
972             case DataBuffer.TYPE_INT:
973                int idata[] = (int[])pixel;
974                intpixel = idata[0];
975             break;
976             default:
977                throw new UnsupportedOperationException JavaDoc("This method has not been "+
978                    "implemented for transferType " + transferType);
979         }
980         return getComponents(intpixel, components, offset);
981     }
982     
983     /**
984      * Creates a <code>WritableRaster</code> with the specified width and
985      * height that has a data layout (<code>SampleModel</code>) compatible
986      * with this <code>ColorModel</code>.
987      * @param w the width to apply to the new <code>WritableRaster</code>
988      * @param h the height to apply to the new <code>WritableRaster</code>
989      * @return a <code>WritableRaster</code> object with the specified
990      * width and height.
991      * @throws IllegalArgumentException if <code>w</code> or <code>h</code>
992      * is less than or equal to zero
993      * @see WritableRaster
994      * @see SampleModel
995      */

996     final public WritableRaster JavaDoc createCompatibleWritableRaster (int w,
997                                                                 int h) {
998         if ((w <= 0) || (h <= 0)) {
999             throw new IllegalArgumentException JavaDoc("Width (" + w + ") and height (" + h +
1000                                               ") cannot be <= 0");
1001        }
1002        int[] bandmasks;
1003        if (supportsAlpha) {
1004            bandmasks = new int[4];
1005            bandmasks[3] = alpha_mask;
1006        }
1007        else {
1008            bandmasks = new int[3];
1009        }
1010        bandmasks[0] = red_mask;
1011        bandmasks[1] = green_mask;
1012        bandmasks[2] = blue_mask;
1013        
1014        if (pixel_bits > 16) {
1015        return Raster.createPackedRaster(DataBuffer.TYPE_INT,
1016                                             w,h,bandmasks,null);
1017        }
1018        else if (pixel_bits > 8) {
1019        return Raster.createPackedRaster(DataBuffer.TYPE_USHORT,
1020                                             w,h,bandmasks,null);
1021        }
1022        else {
1023        return Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
1024                                             w,h,bandmasks,null);
1025        }
1026    }
1027
1028    /**
1029     * Returns a pixel value represented as an <code>int</code> in this
1030     * <code>ColorModel</code>, given an array of unnormalized color/alpha
1031     * components. An <code>ArrayIndexOutOfBoundsException</code> is
1032     * thrown if the <code>components</code> array is
1033     * not large enough to hold all the color and alpha components, starting
1034     * at <code>offset</code>.
1035     * @param components an array of unnormalized color and alpha
1036     * components
1037     * @param offset the index into <code>components</code> at which to
1038     * begin retrieving the color and alpha components
1039     * @return an <code>int</code> pixel value in this
1040     * <code>ColorModel</code> corresponding to the specified components.
1041     * @exception <code>ArrayIndexOutOfBoundsException</code> if
1042     * the <code>components</code> array is not large enough to
1043     * hold all of the color and alpha components starting at
1044     * <code>offset</code>
1045     */

1046    public int getDataElement(int[] components, int offset) {
1047        int pixel = 0;
1048        for (int i=0; i < numComponents; i++) {
1049            pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
1050        }
1051        return pixel;
1052    }
1053    
1054    /**
1055     * Returns a data element array representation of a pixel in this
1056     * <code>ColorModel</code>, given an array of unnormalized color/alpha
1057     * components.
1058     * This array can then be passed to the <code>setDataElements</code>
1059     * method of a <code>WritableRaster</code> object.
1060     * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1061     * <code>components</code> array
1062     * is not large enough to hold all the color and alpha components,
1063     * starting at offset. If the <code>obj</code> variable is
1064     * <code>null</code>, a new array is allocated. If <code>obj</code> is
1065     * not <code>null</code>, it must be a primitive array
1066     * of type <code>transferType</code>; otherwise, a
1067     * <code>ClassCastException</code> is thrown.
1068     * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
1069     * <code>obj</code> is not large enough to hold a pixel value for this
1070     * <code>ColorModel</code>.
1071     * Since <code>DirectColorModel</code> can be subclassed, subclasses
1072     * inherit the implementation of this method and if they don't
1073     * override it then they throw an exception if they use an unsupported
1074     * <code>transferType</code>.
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 color and alpha components
1079     * @param obj the <code>Object</code> representing an array of color
1080     * and alpha components
1081     * @return an <code>Object</code> representing an array of color and
1082     * alpha components.
1083     * @exception <code>ClassCastException</code> if <code>obj</code>
1084     * is not a primitive array of type <code>transferType</code>
1085     * @exception <code>ArrayIndexOutOfBoundsException</code> if
1086     * <code>obj</code> is not large enough to hold a pixel value
1087     * for this <code>ColorModel</code> or the <code>components</code>
1088     * array is not large enough to hold all of the color and alpha
1089     * components starting at <code>offset</code>
1090     * @exception UnsupportedOperationException if this
1091     * <code>transferType</code> is not supported by this
1092     * color model
1093     * @see WritableRaster#setDataElements
1094     * @see SampleModel#setDataElements
1095     */

1096    public Object JavaDoc getDataElements(int[] components, int offset, Object JavaDoc obj) {
1097        int pixel = 0;
1098        for (int i=0; i < numComponents; i++) {
1099            pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
1100        }
1101        switch (transferType) {
1102            case DataBuffer.TYPE_BYTE:
1103               if (obj instanceof byte[]) {
1104                   byte bdata[] = (byte[])obj;
1105                   bdata[0] = (byte)(pixel&0xff);
1106                   return bdata;
1107               } else {
1108                   byte bdata[] = {(byte)(pixel&0xff)};
1109                   return bdata;
1110               }
1111            case DataBuffer.TYPE_USHORT:
1112               if (obj instanceof short[]) {
1113                   short sdata[] = (short[])obj;
1114                   sdata[0] = (short)(pixel&0xffff);
1115                   return sdata;
1116               } else {
1117                   short sdata[] = {(short)(pixel&0xffff)};
1118                   return sdata;
1119               }
1120            case DataBuffer.TYPE_INT:
1121               if (obj instanceof int[]) {
1122                   int idata[] = (int[])obj;
1123                   idata[0] = pixel;
1124                   return idata;
1125               } else {
1126                   int idata[] = {pixel};
1127                   return idata;
1128               }
1129            default:
1130               throw new ClassCastException JavaDoc("This method has not been "+
1131                   "implemented for transferType " + transferType);
1132        }
1133    }
1134
1135    /**
1136     * Forces the raster data to match the state specified in the
1137     * <code>isAlphaPremultiplied</code> variable, assuming the data is
1138     * currently correctly described by this <code>ColorModel</code>. It
1139     * may multiply or divide the color raster data by alpha, or do
1140     * nothing if the data is in the correct state. If the data needs to
1141     * be coerced, this method will also return an instance of this
1142     * <code>ColorModel</code> with the <code>isAlphaPremultiplied</code>
1143     * flag set appropriately. This method will throw a
1144     * <code>UnsupportedOperationException</code> if this transferType is
1145     * not supported by this <code>ColorModel</code>. Since
1146     * <code>ColorModel</code> can be subclassed, subclasses inherit the
1147     * implementation of this method and if they don't override it then
1148     * they throw an exception if they use an unsupported transferType.
1149     *
1150     * @param raster the <code>WritableRaster</code> data
1151     * @param isAlphaPremultiplied <code>true</code> if the alpha is
1152     * premultiplied; <code>false</code> otherwise
1153     * @return a <code>ColorModel</code> object that represents the
1154     * coerced data.
1155     * @exception UnsupportedOperationException if this
1156     * <code>transferType</code> is not supported by this
1157     * color model
1158     */

1159    final public ColorModel JavaDoc coerceData (WritableRaster JavaDoc raster,
1160                                        boolean isAlphaPremultiplied)
1161    {
1162        if (!supportsAlpha ||
1163            this.isAlphaPremultiplied() == isAlphaPremultiplied) {
1164            return this;
1165        }
1166        
1167        int w = raster.getWidth();
1168        int h = raster.getHeight();
1169        int aIdx = numColorComponents;
1170        float normAlpha;
1171        float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
1172
1173        int rminX = raster.getMinX();
1174        int rY = raster.getMinY();
1175        int rX;
1176        int pixel[] = null;
1177        int zpixel[] = null;
1178
1179        if (isAlphaPremultiplied) {
1180            // Must mean that we are currently not premultiplied so
1181
// multiply by alpha
1182
switch (transferType) {
1183                case DataBuffer.TYPE_BYTE: {
1184                    for (int y = 0; y < h; y++, rY++) {
1185                        rX = rminX;
1186                        for (int x = 0; x < w; x++, rX++) {
1187                            pixel = raster.getPixel(rX, rY, pixel);
1188                            normAlpha = pixel[aIdx] * alphaScale;
1189                            if (normAlpha != 0.f) {
1190                                for (int c=0; c < aIdx; c++) {
1191                                    pixel[c] = (int) (pixel[c] * normAlpha +
1192                                                      0.5f);
1193                                }
1194                                raster.setPixel(rX, rY, pixel);
1195                            } else {
1196                                if (zpixel == null) {
1197                                    zpixel = new int[numComponents];
1198                                    java.util.Arrays.fill(zpixel, 0);
1199                                }
1200                                raster.setPixel(rX, rY, zpixel);
1201                            }
1202                        }
1203                    }
1204                }
1205                break;
1206                case DataBuffer.TYPE_USHORT: {
1207                    for (int y = 0; y < h; y++, rY++) {
1208                        rX = rminX;
1209                        for (int x = 0; x < w; x++, rX++) {
1210                            pixel = raster.getPixel(rX, rY, pixel);
1211                            normAlpha = pixel[aIdx] * alphaScale;
1212                            if (normAlpha != 0.f) {
1213                                for (int c=0; c < aIdx; c++) {
1214                                    pixel[c] = (int) (pixel[c] * normAlpha +
1215                                                      0.5f);
1216                                }
1217                                raster.setPixel(rX, rY, pixel);
1218                            } else {
1219                                if (zpixel == null) {
1220                                    zpixel = new int[numComponents];
1221                                    java.util.Arrays.fill(zpixel, 0);
1222                                }
1223                                raster.setPixel(rX, rY, zpixel);
1224                            }
1225                        }
1226                    }
1227                }
1228                break;
1229                case DataBuffer.TYPE_INT: {
1230                    for (int y = 0; y < h; y++, rY++) {
1231                        rX = rminX;
1232                        for (int x = 0; x < w; x++, rX++) {
1233                            pixel = raster.getPixel(rX, rY, pixel);
1234                            normAlpha = pixel[aIdx] * alphaScale;
1235                            if (normAlpha != 0.f) {
1236                                for (int c=0; c < aIdx; c++) {
1237                                    pixel[c] = (int) (pixel[c] * normAlpha +
1238                                                      0.5f);
1239                                }
1240                                raster.setPixel(rX, rY, pixel);
1241                            } else {
1242                                if (zpixel == null) {
1243                                    zpixel = new int[numComponents];
1244                                    java.util.Arrays.fill(zpixel, 0);
1245                                }
1246                                raster.setPixel(rX, rY, zpixel);
1247                            }
1248                        }
1249                    }
1250                }
1251                break;
1252                default:
1253                    throw new UnsupportedOperationException JavaDoc("This method has not been "+
1254                         "implemented for transferType " + transferType);
1255            }
1256        }
1257        else {
1258            // We are premultiplied and want to divide it out
1259
switch (transferType) {
1260                case DataBuffer.TYPE_BYTE: {
1261                    for (int y = 0; y < h; y++, rY++) {
1262                        rX = rminX;
1263                        for (int x = 0; x < w; x++, rX++) {
1264                            pixel = raster.getPixel(rX, rY, pixel);
1265                            normAlpha = pixel[aIdx] * alphaScale;
1266                            if (normAlpha != 0.0f) {
1267                                float invAlpha = 1.0f / normAlpha;
1268                                for (int c=0; c < aIdx; c++) {
1269                                    pixel[c] = (int) (pixel[c] * invAlpha +
1270                                                      0.5f);
1271                                }
1272                                raster.setPixel(rX, rY, pixel);
1273                            }
1274                        }
1275                    }
1276                }
1277                break;
1278                case DataBuffer.TYPE_USHORT: {
1279                    for (int y = 0; y < h; y++, rY++) {
1280                        rX = rminX;
1281                        for (int x = 0; x < w; x++, rX++) {
1282                            pixel = raster.getPixel(rX, rY, pixel);
1283                            normAlpha = pixel[aIdx] * alphaScale;
1284                            if (normAlpha != 0) {
1285                                float invAlpha = 1.0f / normAlpha;
1286                                for (int c=0; c < aIdx; c++) {
1287                                    pixel[c] = (int) (pixel[c] * invAlpha +
1288                                                      0.5f);
1289                                }
1290                                raster.setPixel(rX, rY, pixel);
1291                            }
1292                        }
1293                    }
1294                }
1295                break;
1296                case DataBuffer.TYPE_INT: {
1297                    for (int y = 0; y < h; y++, rY++) {
1298                        rX = rminX;
1299                        for (int x = 0; x < w; x++, rX++) {
1300                            pixel = raster.getPixel(rX, rY, pixel);
1301                            normAlpha = pixel[aIdx] * alphaScale;
1302                            if (normAlpha != 0) {
1303                                float invAlpha = 1.0f / normAlpha;
1304                                for (int c=0; c < aIdx; c++) {
1305                                    pixel[c] = (int) (pixel[c] * invAlpha +
1306                                                      0.5f);
1307                                }
1308                                raster.setPixel(rX, rY, pixel);
1309                            }
1310                        }
1311                    }
1312                }
1313                break;
1314                default:
1315                    throw new UnsupportedOperationException JavaDoc("This method has not been "+
1316                         "implemented for transferType " + transferType);
1317            }
1318        }
1319
1320        // Return a new color model
1321
return new DirectColorModel JavaDoc(colorSpace, pixel_bits, maskArray[0],
1322                                    maskArray[1], maskArray[2], maskArray[3],
1323                                    isAlphaPremultiplied,
1324                                    transferType);
1325                                    
1326    }
1327
1328    /**
1329      * Returns <code>true</code> if <code>raster</code> is compatible
1330      * with this <code>ColorModel</code> and <code>false</code> if it is
1331      * not.
1332      * @param raster the {@link Raster} object to test for compatibility
1333      * @return <code>true</code> if <code>raster</code> is compatible
1334      * with this <code>ColorModel</code>; <code>false</code> otherwise.
1335      */

1336    public boolean isCompatibleRaster(Raster JavaDoc raster) {
1337        SampleModel JavaDoc sm = raster.getSampleModel();
1338        SinglePixelPackedSampleModel JavaDoc spsm;
1339        if (sm instanceof SinglePixelPackedSampleModel JavaDoc) {
1340            spsm = (SinglePixelPackedSampleModel JavaDoc) sm;
1341        }
1342        else {
1343            return false;
1344        }
1345        if (spsm.getNumBands() != getNumComponents()) {
1346            return false;
1347        }
1348
1349    int[] bitMasks = spsm.getBitMasks();
1350    for (int i=0; i<numComponents; i++) {
1351        if (bitMasks[i] != maskArray[i]) {
1352        return false;
1353        }
1354    }
1355        
1356        return (raster.getTransferType() == transferType);
1357    }
1358    
1359    private void setFields() {
1360        // Set the private fields
1361
// REMIND: Get rid of these from the native code
1362
red_mask = maskArray[0];
1363        red_offset = maskOffsets[0];
1364        green_mask = maskArray[1];
1365        green_offset = maskOffsets[1];
1366        blue_mask = maskArray[2];
1367        blue_offset = maskOffsets[2];
1368        if (nBits[0] < 8) {
1369            red_scale = (1 << nBits[0]) - 1;
1370        }
1371        if (nBits[1] < 8) {
1372            green_scale = (1 << nBits[1]) - 1;
1373        }
1374        if (nBits[2] < 8) {
1375            blue_scale = (1 << nBits[2]) - 1;
1376        }
1377        if (supportsAlpha) {
1378            alpha_mask = maskArray[3];
1379            alpha_offset = maskOffsets[3];
1380            if (nBits[3] < 8) {
1381                alpha_scale = (1 << nBits[3]) - 1;
1382            }
1383        }
1384    }
1385
1386    /**
1387     * Returns a <code>String</code> that represents this
1388     * <code>DirectColorModel</code>.
1389     * @return a <code>String</code> representing this
1390     * <code>DirectColorModel</code>.
1391     */

1392    public String JavaDoc toString() {
1393        return new String JavaDoc("DirectColorModel: rmask="
1394                          +Integer.toHexString(red_mask)+" gmask="
1395                          +Integer.toHexString(green_mask)+" bmask="
1396                          +Integer.toHexString(blue_mask)+" amask="
1397                          +Integer.toHexString(alpha_mask));
1398    }
1399}
1400
1401
Popular Tags