View Javadoc
1   /*
2    * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package java.awt.image;
27  
28  import java.awt.color.ColorSpace;
29  import java.awt.Transparency;
30  
31  /**
32   * The <code>DirectColorModel</code> class is a <code>ColorModel</code>
33   * class that works with pixel values that represent RGB
34   * color and alpha information as separate samples and that pack all
35   * samples for a single pixel into a single int, short, or byte quantity.
36   * This class can be used only with ColorSpaces of type ColorSpace.TYPE_RGB.
37   * In addition, for each component of the ColorSpace, the minimum
38   * normalized component value obtained via the <code>getMinValue()</code>
39   * method of ColorSpace must be 0.0, and the maximum value obtained via
40   * the <code>getMaxValue()</code> method must be 1.0 (these min/max
41   * values are typical for RGB spaces).
42   * There must be three color samples in the pixel values and there can
43   * be a single alpha sample.  For those methods that use a primitive array
44   * pixel representation of type <code>transferType</code>, the array
45   * length is always one.  The transfer
46   * types supported are DataBuffer.TYPE_BYTE,
47   * DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
48   * Color and alpha samples are stored in the single
49   * element of the array in bits indicated by bit masks.  Each bit mask
50   * must be contiguous and masks must not overlap.  The same masks apply to
51   * the single int pixel representation used by other methods.  The
52   * correspondence of masks and color/alpha samples is as follows:
53   * <ul>
54   * <li> Masks are identified by indices running from 0 through 2
55   * if no alpha is present, or 3 if an alpha is present.
56   * <li> The first three indices refer to color samples;
57   * index 0 corresponds to red, index 1 to green, and index 2 to blue.
58   * <li> Index 3 corresponds to the alpha sample, if present.
59   * </ul>
60   * <p>
61   * The translation from pixel values to color/alpha components for
62   * display or processing purposes is a one-to-one correspondence of
63   * samples to components.  A <code>DirectColorModel</code> is
64   * typically used with image data which uses masks to define packed
65   * samples.  For example, a <code>DirectColorModel</code> can be used in
66   * conjunction with a <code>SinglePixelPackedSampleModel</code> to
67   * construct a {@link BufferedImage}.  Normally the masks used by the
68   * {@link SampleModel} and the <code>ColorModel</code> would be the
69   * same.  However, if they are different, the color interpretation
70   * of pixel data will be done according to the masks of the
71   * <code>ColorModel</code>.
72   * <p>
73   * A single int pixel representation is valid for all objects of this
74   * class, since it is always possible to represent pixel values used with
75   * this class in a single int.  Therefore, methods which use this
76   * representation will not throw an <code>IllegalArgumentException</code>
77   * due to an invalid pixel value.
78   * <p>
79   * This color model is similar to an X11 TrueColor visual.
80   * The default RGB ColorModel specified by the
81   * {@link ColorModel#getRGBdefault() getRGBdefault} method is a
82   * <code>DirectColorModel</code> with the following parameters:
83   * <pre>
84   * Number of bits:        32
85   * Red mask:              0x00ff0000
86   * Green mask:            0x0000ff00
87   * Blue mask:             0x000000ff
88   * Alpha mask:            0xff000000
89   * Color space:           sRGB
90   * isAlphaPremultiplied:  False
91   * Transparency:          Transparency.TRANSLUCENT
92   * transferType:          DataBuffer.TYPE_INT
93   * </pre>
94   * <p>
95   * Many of the methods in this class are final. This is because the
96   * underlying native graphics code makes assumptions about the layout
97   * and operation of this class and those assumptions are reflected in
98   * the implementations of the methods here that are marked final.  You
99   * can subclass this class for other reasons, but you cannot override
100  * or modify the behavior of those methods.
101  *
102  * @see ColorModel
103  * @see ColorSpace
104  * @see SinglePixelPackedSampleModel
105  * @see BufferedImage
106  * @see ColorModel#getRGBdefault
107  *
108  */
109 public class DirectColorModel extends PackedColorModel {
110     private int red_mask;
111     private int green_mask;
112     private int blue_mask;
113     private int alpha_mask;
114     private int red_offset;
115     private int green_offset;
116     private int blue_offset;
117     private int alpha_offset;
118     private int red_scale;
119     private int green_scale;
120     private int blue_scale;
121     private int alpha_scale;
122     private boolean is_LinearRGB;
123     private int lRGBprecision;
124     private byte[] tosRGB8LUT;
125     private byte[] fromsRGB8LUT8;
126     private short[] fromsRGB8LUT16;
127 
128     /**
129      * Constructs a <code>DirectColorModel</code> from the specified masks
130      * that indicate which bits in an <code>int</code> pixel representation
131      * contain the red, green and blue color samples.  As pixel values do not
132      * contain alpha information, all pixels are treated as opaque, which
133      * means that alpha&nbsp;=&nbsp;1.0.  All of the bits
134      * in each mask must be contiguous and fit in the specified number
135      * of least significant bits of an <code>int</code> pixel representation.
136      *  The <code>ColorSpace</code> is the default sRGB space. The
137      * transparency value is Transparency.OPAQUE.  The transfer type
138      * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
139      * or DataBuffer.TYPE_INT that can hold a single pixel.
140      * @param bits the number of bits in the pixel values; for example,
141      *         the sum of the number of bits in the masks.
142      * @param rmask specifies a mask indicating which bits in an
143      *         integer pixel contain the red component
144      * @param gmask specifies a mask indicating which bits in an
145      *         integer pixel contain the green component
146      * @param bmask specifies a mask indicating which bits in an
147      *         integer pixel contain the blue component
148      *
149      */
150     public DirectColorModel(int bits,
151                             int rmask, int gmask, int bmask) {
152         this(bits, rmask, gmask, bmask, 0);
153     }
154 
155     /**
156      * Constructs a <code>DirectColorModel</code> from the specified masks
157      * that indicate which bits in an <code>int</code> pixel representation
158      * contain the red, green and blue color samples and the alpha sample,
159      * if present.  If <code>amask</code> is 0, pixel values do not contain
160      * alpha information and all pixels are treated as opaque, which means
161      * that alpha&nbsp;=&nbsp;1.0.  All of the bits in each mask must
162      * be contiguous and fit in the specified number of least significant bits
163      * of an <code>int</code> pixel representation.  Alpha, if present, is not
164      * premultiplied.  The <code>ColorSpace</code> is the default sRGB space.
165      * The transparency value is Transparency.OPAQUE if no alpha is
166      * present, or Transparency.TRANSLUCENT otherwise.  The transfer type
167      * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
168      * or DataBuffer.TYPE_INT that can hold a single pixel.
169      * @param bits the number of bits in the pixel values; for example,
170      *         the sum of the number of bits in the masks.
171      * @param rmask specifies a mask indicating which bits in an
172      *         integer pixel contain the red component
173      * @param gmask specifies a mask indicating which bits in an
174      *         integer pixel contain the green component
175      * @param bmask specifies a mask indicating which bits in an
176      *         integer pixel contain the blue component
177      * @param amask specifies a mask indicating which bits in an
178      *         integer pixel contain the alpha component
179      */
180     public DirectColorModel(int bits, int rmask, int gmask,
181                             int bmask, int amask) {
182         super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
183                bits, rmask, gmask, bmask, amask, false,
184                amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
185                ColorModel.getDefaultTransferType(bits));
186         setFields();
187     }
188 
189     /**
190      * Constructs a <code>DirectColorModel</code> from the specified
191      * parameters.  Color components are in the specified
192      * <code>ColorSpace</code>, which must be of type ColorSpace.TYPE_RGB
193      * and have minimum normalized component values which are all 0.0
194      * and maximum values which are all 1.0.
195      * The masks specify which bits in an <code>int</code> pixel
196      * representation contain the red, green and blue color samples and
197      * the alpha sample, if present.  If <code>amask</code> is 0, pixel
198      * values do not contain alpha information and all pixels are treated
199      * as opaque, which means that alpha&nbsp;=&nbsp;1.0.  All of the
200      * bits in each mask must be contiguous and fit in the specified number
201      * of least significant bits of an <code>int</code> pixel
202      * representation.  If there is alpha, the <code>boolean</code>
203      * <code>isAlphaPremultiplied</code> specifies how to interpret
204      * color and alpha samples in pixel values.  If the <code>boolean</code>
205      * is <code>true</code>, color samples are assumed to have been
206      * multiplied by the alpha sample.  The transparency value is
207      * Transparency.OPAQUE, if no alpha is present, or
208      * Transparency.TRANSLUCENT otherwise.  The transfer type
209      * is the type of primitive array used to represent pixel values and
210      * must be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or
211      * DataBuffer.TYPE_INT.
212      * @param space the specified <code>ColorSpace</code>
213      * @param bits the number of bits in the pixel values; for example,
214      *         the sum of the number of bits in the masks.
215      * @param rmask specifies a mask indicating which bits in an
216      *         integer pixel contain the red component
217      * @param gmask specifies a mask indicating which bits in an
218      *         integer pixel contain the green component
219      * @param bmask specifies a mask indicating which bits in an
220      *         integer pixel contain the blue component
221      * @param amask specifies a mask indicating which bits in an
222      *         integer pixel contain the alpha component
223      * @param isAlphaPremultiplied <code>true</code> if color samples are
224      *        premultiplied by the alpha sample; <code>false</code> otherwise
225      * @param transferType the type of array used to represent pixel values
226      * @throws IllegalArgumentException if <code>space</code> is not a
227      *         TYPE_RGB space or if the min/max normalized component
228      *         values are not 0.0/1.0.
229      */
230     public DirectColorModel(ColorSpace space, int bits, int rmask,
231                             int gmask, int bmask, int amask,
232                             boolean isAlphaPremultiplied,
233                             int transferType) {
234         super (space, bits, rmask, gmask, bmask, amask,
235                isAlphaPremultiplied,
236                amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
237                transferType);
238         if (ColorModel.isLinearRGBspace(colorSpace)) {
239             is_LinearRGB = true;
240             if (maxBits <= 8) {
241                 lRGBprecision = 8;
242                 tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
243                 fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
244             } else {
245                 lRGBprecision = 16;
246                 tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
247                 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
248             }
249         } else if (!is_sRGB) {
250             for (int i = 0; i < 3; i++) {
251                 // super constructor checks that space is TYPE_RGB
252                 // check here that min/max are all 0.0/1.0
253                 if ((space.getMinValue(i) != 0.0f) ||
254                     (space.getMaxValue(i) != 1.0f)) {
255                     throw new IllegalArgumentException(
256                         "Illegal min/max RGB component value");
257                 }
258             }
259         }
260         setFields();
261     }
262 
263     /**
264      * Returns the mask indicating which bits in an <code>int</code> pixel
265      * representation contain the red color component.
266      * @return the mask, which indicates which bits of the <code>int</code>
267      *         pixel representation contain the red color sample.
268      */
269     final public int getRedMask() {
270         return maskArray[0];
271     }
272 
273     /**
274      * Returns the mask indicating which bits in an <code>int</code> pixel
275      * representation contain the green color component.
276      * @return the mask, which indicates which bits of the <code>int</code>
277      *         pixel representation contain the green color sample.
278      */
279     final public int getGreenMask() {
280         return maskArray[1];
281     }
282 
283     /**
284      * Returns the mask indicating which bits in an <code>int</code> pixel
285      * representation contain the blue color component.
286      * @return the mask, which indicates which bits of the <code>int</code>
287      *         pixel representation contain the blue color sample.
288      */
289     final public int getBlueMask() {
290         return maskArray[2];
291     }
292 
293     /**
294      * Returns the mask indicating which bits in an <code>int</code> pixel
295      * representation contain the alpha component.
296      * @return the mask, which indicates which bits of the <code>int</code>
297      *         pixel representation contain the alpha sample.
298      */
299     final public int getAlphaMask() {
300         if (supportsAlpha) {
301             return maskArray[3];
302         } else {
303             return 0;
304         }
305     }
306 
307 
308     /*
309      * Given an int pixel in this ColorModel's ColorSpace, converts
310      * it to the default sRGB ColorSpace and returns the R, G, and B
311      * components as float values between 0.0 and 1.0.
312      */
313     private float[] getDefaultRGBComponents(int pixel) {
314         int components[] = getComponents(pixel, null, 0);
315         float norm[] = getNormalizedComponents(components, 0, null, 0);
316         // Note that getNormalizedComponents returns non-premultiplied values
317         return colorSpace.toRGB(norm);
318     }
319 
320 
321     private int getsRGBComponentFromsRGB(int pixel, int idx) {
322         int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
323         if (isAlphaPremultiplied) {
324             int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
325             c = (a == 0) ? 0 :
326                          (int) (((c * scaleFactors[idx]) * 255.0f /
327                                  (a * scaleFactors[3])) + 0.5f);
328         } else if (scaleFactors[idx] != 1.0f) {
329             c = (int) ((c * scaleFactors[idx]) + 0.5f);
330         }
331         return c;
332     }
333 
334 
335     private int getsRGBComponentFromLinearRGB(int pixel, int idx) {
336         int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
337         if (isAlphaPremultiplied) {
338             float factor = (float) ((1 << lRGBprecision) - 1);
339             int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
340             c = (a == 0) ? 0 :
341                          (int) (((c * scaleFactors[idx]) * factor /
342                                  (a * scaleFactors[3])) + 0.5f);
343         } else if (nBits[idx] != lRGBprecision) {
344             if (lRGBprecision == 16) {
345                 c = (int) ((c * scaleFactors[idx] * 257.0f) + 0.5f);
346             } else {
347                 c = (int) ((c * scaleFactors[idx]) + 0.5f);
348             }
349         }
350         // now range of c is 0-255 or 0-65535, depending on lRGBprecision
351         return tosRGB8LUT[c] & 0xff;
352     }
353 
354 
355     /**
356      * Returns the red color component for the specified pixel, scaled
357      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
358      * color conversion is done if necessary.  The pixel value is specified
359      * as an <code>int</code>.
360      * The returned value is a non pre-multiplied value.  Thus, if the
361      * alpha is premultiplied, this method divides it out before returning
362      * the value.  If the alpha value is 0, for example, the red value
363      * is 0.
364      * @param pixel the specified pixel
365      * @return the red color component for the specified pixel, from
366      *         0 to 255 in the sRGB <code>ColorSpace</code>.
367      */
368     final public int getRed(int pixel) {
369         if (is_sRGB) {
370             return getsRGBComponentFromsRGB(pixel, 0);
371         } else if (is_LinearRGB) {
372             return getsRGBComponentFromLinearRGB(pixel, 0);
373         }
374         float rgb[] = getDefaultRGBComponents(pixel);
375         return (int) (rgb[0] * 255.0f + 0.5f);
376     }
377 
378     /**
379      * Returns the green color component for the specified pixel, scaled
380      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
381      * color conversion is done if necessary.  The pixel value is specified
382      * as an <code>int</code>.
383      * The returned value is a non pre-multiplied value.  Thus, if the
384      * alpha is premultiplied, this method divides it out before returning
385      * the value.  If the alpha value is 0, for example, the green value
386      * is 0.
387      * @param pixel the specified pixel
388      * @return the green color component for the specified pixel, from
389      *         0 to 255 in the sRGB <code>ColorSpace</code>.
390      */
391     final public int getGreen(int pixel) {
392         if (is_sRGB) {
393             return getsRGBComponentFromsRGB(pixel, 1);
394         } else if (is_LinearRGB) {
395             return getsRGBComponentFromLinearRGB(pixel, 1);
396         }
397         float rgb[] = getDefaultRGBComponents(pixel);
398         return (int) (rgb[1] * 255.0f + 0.5f);
399     }
400 
401     /**
402      * Returns the blue color component for the specified pixel, scaled
403      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
404      * color conversion is done if necessary.  The pixel value is specified
405      * as an <code>int</code>.
406      * The returned value is a non pre-multiplied value.  Thus, if the
407      * alpha is premultiplied, this method divides it out before returning
408      * the value.  If the alpha value is 0, for example, the blue value
409      * is 0.
410      * @param pixel the specified pixel
411      * @return the blue color component for the specified pixel, from
412      *         0 to 255 in the sRGB <code>ColorSpace</code>.
413      */
414     final public int getBlue(int pixel) {
415         if (is_sRGB) {
416             return getsRGBComponentFromsRGB(pixel, 2);
417         } else if (is_LinearRGB) {
418             return getsRGBComponentFromLinearRGB(pixel, 2);
419         }
420         float rgb[] = getDefaultRGBComponents(pixel);
421         return (int) (rgb[2] * 255.0f + 0.5f);
422     }
423 
424     /**
425      * Returns the alpha component for the specified pixel, scaled
426      * from 0 to 255.  The pixel value is specified as an <code>int</code>.
427      * @param pixel the specified pixel
428      * @return the value of the alpha component of <code>pixel</code>
429      *         from 0 to 255.
430      */
431     final public int getAlpha(int pixel) {
432         if (!supportsAlpha) return 255;
433         int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
434         if (scaleFactors[3] != 1.0f) {
435             a = (int)(a * scaleFactors[3] + 0.5f);
436         }
437         return a;
438     }
439 
440     /**
441      * Returns the color/alpha components of the pixel in the default
442      * RGB color model format.  A color conversion is done if necessary.
443      * The pixel value is specified as an <code>int</code>.
444      * The returned value is in a non pre-multiplied format.  Thus, if
445      * the alpha is premultiplied, this method divides it out of the
446      * color components.  If the alpha value is 0, for example, the color
447      * values are each 0.
448      * @param pixel the specified pixel
449      * @return the RGB value of the color/alpha components of the specified
450      *         pixel.
451      * @see ColorModel#getRGBdefault
452      */
453     final public int getRGB(int pixel) {
454         if (is_sRGB || is_LinearRGB) {
455             return (getAlpha(pixel) << 24)
456                 | (getRed(pixel) << 16)
457                 | (getGreen(pixel) << 8)
458                 | (getBlue(pixel) << 0);
459         }
460         float rgb[] = getDefaultRGBComponents(pixel);
461         return (getAlpha(pixel) << 24)
462             | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
463             | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
464             | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
465     }
466 
467     /**
468      * Returns the red color component for the specified pixel, scaled
469      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
470      * color conversion is done if necessary.  The pixel value is specified
471      * by an array of data elements of type <code>transferType</code> passed
472      * in as an object reference.
473      * The returned value is a non pre-multiplied value.  Thus, if the
474      * alpha is premultiplied, this method divides it out before returning
475      * the value.  If the alpha value is 0, for example, the red value
476      * is 0.
477      * If <code>inData</code> is not a primitive array of type
478      * <code>transferType</code>, a <code>ClassCastException</code> is
479      * thrown.  An <code>ArrayIndexOutOfBoundsException</code> is
480      * thrown if <code>inData</code> is not large enough to hold a
481      * pixel value for this <code>ColorModel</code>.  Since
482      * <code>DirectColorModel</code> can be subclassed, subclasses inherit
483      * the implementation of this method and if they don't override it
484      * then they throw an exception if they use an unsupported
485      * <code>transferType</code>.
486      * An <code>UnsupportedOperationException</code> is thrown if this
487      * <code>transferType</code> is not supported by this
488      * <code>ColorModel</code>.
489      * @param inData the array containing the pixel value
490      * @return the value of the red component of the specified pixel.
491      * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
492      *         large enough to hold a pixel value for this color model
493      * @throws ClassCastException if <code>inData</code> is not a
494      *         primitive array of type <code>transferType</code>
495      * @throws UnsupportedOperationException if this <code>transferType</code>
496      *         is not supported by this color model
497      */
498     public int getRed(Object inData) {
499         int pixel=0;
500         switch (transferType) {
501             case DataBuffer.TYPE_BYTE:
502                byte bdata[] = (byte[])inData;
503                pixel = bdata[0] & 0xff;
504             break;
505             case DataBuffer.TYPE_USHORT:
506                short sdata[] = (short[])inData;
507                pixel = sdata[0] & 0xffff;
508             break;
509             case DataBuffer.TYPE_INT:
510                int idata[] = (int[])inData;
511                pixel = idata[0];
512             break;
513             default:
514                throw new UnsupportedOperationException("This method has not been "+
515                    "implemented for transferType " + transferType);
516         }
517         return getRed(pixel);
518     }
519 
520 
521     /**
522      * Returns the green color component for the specified pixel, scaled
523      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
524      * color conversion is done if necessary.  The pixel value is specified
525      * by an array of data elements of type <code>transferType</code> passed
526      * in as an object reference.
527      * The returned value is a non pre-multiplied value.  Thus, if the
528      * alpha is premultiplied, this method divides it out before returning
529      * the value.  If the alpha value is 0, for example, the green value
530      * is 0.  If <code>inData</code> is not a primitive array of type
531      * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
532      *  An <code>ArrayIndexOutOfBoundsException</code> is
533      * thrown if <code>inData</code> is not large enough to hold a pixel
534      * value for this <code>ColorModel</code>.  Since
535      * <code>DirectColorModel</code> can be subclassed, subclasses inherit
536      * the implementation of this method and if they don't override it
537      * then they throw an exception if they use an unsupported
538      * <code>transferType</code>.
539      * An <code>UnsupportedOperationException</code> is
540      * thrown if this <code>transferType</code> is not supported by this
541      * <code>ColorModel</code>.
542      * @param inData the array containing the pixel value
543      * @return the value of the green component of the specified pixel.
544      * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
545      *         large enough to hold a pixel value for this color model
546      * @throws ClassCastException if <code>inData</code> is not a
547      *         primitive array of type <code>transferType</code>
548      * @throws UnsupportedOperationException if this <code>transferType</code>
549      *         is not supported by this color model
550      */
551     public int getGreen(Object inData) {
552         int pixel=0;
553         switch (transferType) {
554             case DataBuffer.TYPE_BYTE:
555                byte bdata[] = (byte[])inData;
556                pixel = bdata[0] & 0xff;
557             break;
558             case DataBuffer.TYPE_USHORT:
559                short sdata[] = (short[])inData;
560                pixel = sdata[0] & 0xffff;
561             break;
562             case DataBuffer.TYPE_INT:
563                int idata[] = (int[])inData;
564                pixel = idata[0];
565             break;
566             default:
567                throw new UnsupportedOperationException("This method has not been "+
568                    "implemented for transferType " + transferType);
569         }
570         return getGreen(pixel);
571     }
572 
573 
574     /**
575      * Returns the blue color component for the specified pixel, scaled
576      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
577      * color conversion is done if necessary.  The pixel value is specified
578      * by an array of data elements of type <code>transferType</code> passed
579      * in as an object reference.
580      * The returned value is a non pre-multiplied value.  Thus, if the
581      * alpha is premultiplied, this method divides it out before returning
582      * the value.  If the alpha value is 0, for example, the blue value
583      * is 0.  If <code>inData</code> is not a primitive array of type
584      * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
585      *  An <code>ArrayIndexOutOfBoundsException</code> is
586      * thrown if <code>inData</code> is not large enough to hold a pixel
587      * value for this <code>ColorModel</code>.  Since
588      * <code>DirectColorModel</code> can be subclassed, subclasses inherit
589      * the implementation of this method and if they don't override it
590      * then they throw an exception if they use an unsupported
591      * <code>transferType</code>.
592      * An <code>UnsupportedOperationException</code> is
593      * thrown if this <code>transferType</code> is not supported by this
594      * <code>ColorModel</code>.
595      * @param inData the array containing the pixel value
596      * @return the value of the blue component of the specified pixel.
597      * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
598      *         large enough to hold a pixel value for this color model
599      * @throws ClassCastException if <code>inData</code> is not a
600      *         primitive array of type <code>transferType</code>
601      * @throws UnsupportedOperationException if this <code>transferType</code>
602      *         is not supported by this color model
603      */
604     public int getBlue(Object inData) {
605         int pixel=0;
606         switch (transferType) {
607             case DataBuffer.TYPE_BYTE:
608                byte bdata[] = (byte[])inData;
609                pixel = bdata[0] & 0xff;
610             break;
611             case DataBuffer.TYPE_USHORT:
612                short sdata[] = (short[])inData;
613                pixel = sdata[0] & 0xffff;
614             break;
615             case DataBuffer.TYPE_INT:
616                int idata[] = (int[])inData;
617                pixel = idata[0];
618             break;
619             default:
620                throw new UnsupportedOperationException("This method has not been "+
621                    "implemented for transferType " + transferType);
622         }
623         return getBlue(pixel);
624     }
625 
626     /**
627      * Returns the alpha component for the specified pixel, scaled
628      * from 0 to 255.  The pixel value is specified by an array of data
629      * elements of type <code>transferType</code> passed in as an object
630      * reference.
631      * If <code>inData</code> is not a primitive array of type
632      * <code>transferType</code>, a <code>ClassCastException</code> is
633      * thrown.  An <code>ArrayIndexOutOfBoundsException</code> is
634      * thrown if <code>inData</code> is not large enough to hold a pixel
635      * value for this <code>ColorModel</code>.  Since
636      * <code>DirectColorModel</code> can be subclassed, subclasses inherit
637      * the implementation of this method and if they don't override it
638      * then they throw an exception if they use an unsupported
639      * <code>transferType</code>.
640      * If this <code>transferType</code> is not supported, an
641      * <code>UnsupportedOperationException</code> is thrown.
642      * @param inData the specified pixel
643      * @return the alpha component of the specified pixel, scaled from
644      *         0 to 255.
645      * @exception ClassCastException if <code>inData</code>
646      *  is not a primitive array of type <code>transferType</code>
647      * @exception ArrayIndexOutOfBoundsException if
648      *  <code>inData</code> is not large enough to hold a pixel value
649      *  for this <code>ColorModel</code>
650      * @exception UnsupportedOperationException if this
651      *  <code>tranferType</code> is not supported by this
652      *  <code>ColorModel</code>
653      */
654     public int getAlpha(Object inData) {
655         int pixel=0;
656         switch (transferType) {
657             case DataBuffer.TYPE_BYTE:
658                byte bdata[] = (byte[])inData;
659                pixel = bdata[0] & 0xff;
660             break;
661             case DataBuffer.TYPE_USHORT:
662                short sdata[] = (short[])inData;
663                pixel = sdata[0] & 0xffff;
664             break;
665             case DataBuffer.TYPE_INT:
666                int idata[] = (int[])inData;
667                pixel = idata[0];
668             break;
669             default:
670                throw new UnsupportedOperationException("This method has not been "+
671                    "implemented for transferType " + transferType);
672         }
673         return getAlpha(pixel);
674     }
675 
676     /**
677      * Returns the color/alpha components for the specified pixel in the
678      * default RGB color model format.  A color conversion is done if
679      * necessary.  The pixel value is specified by an array of data
680      * elements of type <code>transferType</code> passed in as an object
681      * reference.  If <code>inData</code> is not a primitive array of type
682      * <code>transferType</code>, a <code>ClassCastException</code> is
683      * thrown.  An <code>ArrayIndexOutOfBoundsException</code> is
684      * thrown if <code>inData</code> is not large enough to hold a pixel
685      * value for this <code>ColorModel</code>.
686      * The returned value is in a non pre-multiplied format.  Thus, if
687      * the alpha is premultiplied, this method divides it out of the
688      * color components.  If the alpha value is 0, for example, the color
689      * values is 0.  Since <code>DirectColorModel</code> can be
690      * subclassed, subclasses inherit the implementation of this method
691      * and if they don't override it then
692      * they throw an exception if they use an unsupported
693      * <code>transferType</code>.
694      *
695      * @param inData the specified pixel
696      * @return the color and alpha components of the specified pixel.
697      * @exception UnsupportedOperationException if this
698      *            <code>transferType</code> is not supported by this
699      *            <code>ColorModel</code>
700      * @see ColorModel#getRGBdefault
701      */
702     public int getRGB(Object inData) {
703         int pixel=0;
704         switch (transferType) {
705             case DataBuffer.TYPE_BYTE:
706                byte bdata[] = (byte[])inData;
707                pixel = bdata[0] & 0xff;
708             break;
709             case DataBuffer.TYPE_USHORT:
710                short sdata[] = (short[])inData;
711                pixel = sdata[0] & 0xffff;
712             break;
713             case DataBuffer.TYPE_INT:
714                int idata[] = (int[])inData;
715                pixel = idata[0];
716             break;
717             default:
718                throw new UnsupportedOperationException("This method has not been "+
719                    "implemented for transferType " + transferType);
720         }
721         return getRGB(pixel);
722     }
723 
724     /**
725      * Returns a data element array representation of a pixel in this
726      * <code>ColorModel</code>, given an integer pixel representation in the
727      * default RGB color model.
728      * This array can then be passed to the <code>setDataElements</code>
729      * method of a <code>WritableRaster</code> object.  If the pixel variable
730      * is <code>null</code>, a new array is allocated.  If <code>pixel</code>
731      * is not <code>null</code>, it must be a primitive array of type
732      * <code>transferType</code>; otherwise, a
733      * <code>ClassCastException</code> is thrown.  An
734      * <code>ArrayIndexOutOfBoundsException</code> is
735      * thrown if <code>pixel</code> is not large enough to hold a pixel
736      * value for this <code>ColorModel</code>.  The pixel array is returned.
737      * Since <code>DirectColorModel</code> can be subclassed, subclasses
738      * inherit the implementation of this method and if they don't
739      * override it then they throw an exception if they use an unsupported
740      * <code>transferType</code>.
741      *
742      * @param rgb the integer pixel representation in the default RGB
743      *            color model
744      * @param pixel the specified pixel
745      * @return an array representation of the specified pixel in this
746      *         <code>ColorModel</code>
747      * @exception ClassCastException if <code>pixel</code>
748      *  is not a primitive array of type <code>transferType</code>
749      * @exception ArrayIndexOutOfBoundsException if
750      *  <code>pixel</code> is not large enough to hold a pixel value
751      *  for this <code>ColorModel</code>
752      * @exception UnsupportedOperationException if this
753      *  <code>transferType</code> is not supported by this
754      *  <code>ColorModel</code>
755      * @see WritableRaster#setDataElements
756      * @see SampleModel#setDataElements
757      */
758     public Object getDataElements(int rgb, Object pixel) {
759         //REMIND: maybe more efficient not to use int array for
760         //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
761         int intpixel[] = null;
762         if (transferType == DataBuffer.TYPE_INT &&
763             pixel != null) {
764             intpixel = (int[])pixel;
765             intpixel[0] = 0;
766         } else {
767             intpixel = new int[1];
768         }
769 
770         ColorModel defaultCM = ColorModel.getRGBdefault();
771         if (this == defaultCM || equals(defaultCM)) {
772             intpixel[0] = rgb;
773             return intpixel;
774         }
775 
776         int red, grn, blu, alp;
777         red = (rgb>>16) & 0xff;
778         grn = (rgb>>8) & 0xff;
779         blu = rgb & 0xff;
780         if (is_sRGB || is_LinearRGB) {
781             int precision;
782             float factor;
783             if (is_LinearRGB) {
784                 if (lRGBprecision == 8) {
785                     red = fromsRGB8LUT8[red] & 0xff;
786                     grn = fromsRGB8LUT8[grn] & 0xff;
787                     blu = fromsRGB8LUT8[blu] & 0xff;
788                     precision = 8;
789                     factor = 1.0f / 255.0f;
790                 } else {
791                     red = fromsRGB8LUT16[red] & 0xffff;
792                     grn = fromsRGB8LUT16[grn] & 0xffff;
793                     blu = fromsRGB8LUT16[blu] & 0xffff;
794                     precision = 16;
795                     factor = 1.0f / 65535.0f;
796                 }
797             } else {
798                 precision = 8;
799                 factor = 1.0f / 255.0f;
800             }
801             if (supportsAlpha) {
802                 alp = (rgb>>24) & 0xff;
803                 if (isAlphaPremultiplied) {
804                     factor *= (alp * (1.0f / 255.0f));
805                     precision = -1;  // force component calculations below
806                 }
807                 if (nBits[3] != 8) {
808                     alp = (int)
809                         ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
810                     if (alp > ((1<<nBits[3]) - 1)) {
811                         // fix 4412670 - see comment below
812                         alp = (1<<nBits[3]) - 1;
813                     }
814                 }
815                 intpixel[0] = alp << maskOffsets[3];
816             }
817             if (nBits[0] != precision) {
818                 red = (int) ((red * factor * ((1<<nBits[0]) - 1)) + 0.5f);
819             }
820             if (nBits[1] != precision) {
821                 grn = (int) ((grn * factor * ((1<<nBits[1]) - 1)) + 0.5f);
822             }
823             if (nBits[2] != precision) {
824                 blu = (int) ((blu * factor * ((1<<nBits[2]) - 1)) + 0.5f);
825             }
826         } else {
827             // Need to convert the color
828             float[] norm = new float[3];
829             float factor = 1.0f / 255.0f;
830             norm[0] = red * factor;
831             norm[1] = grn * factor;
832             norm[2] = blu * factor;
833             norm = colorSpace.fromRGB(norm);
834             if (supportsAlpha) {
835                 alp = (rgb>>24) & 0xff;
836                 if (isAlphaPremultiplied) {
837                     factor *= alp;
838                     for (int i = 0; i < 3; i++) {
839                         norm[i] *= factor;
840                     }
841                 }
842                 if (nBits[3] != 8) {
843                     alp = (int)
844                         ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
845                     if (alp > ((1<<nBits[3]) - 1)) {
846                         // fix 4412670 - see comment below
847                         alp = (1<<nBits[3]) - 1;
848                     }
849                 }
850                 intpixel[0] = alp << maskOffsets[3];
851             }
852             red = (int) ((norm[0] * ((1<<nBits[0]) - 1)) + 0.5f);
853             grn = (int) ((norm[1] * ((1<<nBits[1]) - 1)) + 0.5f);
854             blu = (int) ((norm[2] * ((1<<nBits[2]) - 1)) + 0.5f);
855         }
856 
857         if (maxBits > 23) {
858             // fix 4412670 - for components of 24 or more bits
859             // some calculations done above with float precision
860             // may lose enough precision that the integer result
861             // overflows nBits, so we need to clamp.
862             if (red > ((1<<nBits[0]) - 1)) {
863                 red = (1<<nBits[0]) - 1;
864             }
865             if (grn > ((1<<nBits[1]) - 1)) {
866                 grn = (1<<nBits[1]) - 1;
867             }
868             if (blu > ((1<<nBits[2]) - 1)) {
869                 blu = (1<<nBits[2]) - 1;
870             }
871         }
872 
873         intpixel[0] |= (red << maskOffsets[0]) |
874                        (grn << maskOffsets[1]) |
875                        (blu << maskOffsets[2]);
876 
877         switch (transferType) {
878             case DataBuffer.TYPE_BYTE: {
879                byte bdata[];
880                if (pixel == null) {
881                    bdata = new byte[1];
882                } else {
883                    bdata = (byte[])pixel;
884                }
885                bdata[0] = (byte)(0xff&intpixel[0]);
886                return bdata;
887             }
888             case DataBuffer.TYPE_USHORT:{
889                short sdata[];
890                if (pixel == null) {
891                    sdata = new short[1];
892                } else {
893                    sdata = (short[])pixel;
894                }
895                sdata[0] = (short)(intpixel[0]&0xffff);
896                return sdata;
897             }
898             case DataBuffer.TYPE_INT:
899                return intpixel;
900         }
901         throw new UnsupportedOperationException("This method has not been "+
902                  "implemented for transferType " + transferType);
903 
904     }
905 
906     /**
907      * Returns an array of unnormalized color/alpha components given a pixel
908      * in this <code>ColorModel</code>.  The pixel value is specified as an
909      * <code>int</code>.  If the <code>components</code> array is
910      * <code>null</code>, a new array is allocated.  The
911      * <code>components</code> array is returned.  Color/alpha components are
912      * stored in the <code>components</code> array starting at
913      * <code>offset</code>, even if the array is allocated by this method.
914      * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
915      * <code>components</code> array is not <code>null</code> and is not large
916      * enough to hold all the color and alpha components, starting at
917      * <code>offset</code>.
918      * @param pixel the specified pixel
919      * @param components the array to receive the color and alpha
920      * components of the specified pixel
921      * @param offset the offset into the <code>components</code> array at
922      * which to start storing the color and alpha components
923      * @return an array containing the color and alpha components of the
924      * specified pixel starting at the specified offset.
925      */
926     final public int[] getComponents(int pixel, int[] components, int offset) {
927         if (components == null) {
928             components = new int[offset+numComponents];
929         }
930 
931         for (int i=0; i < numComponents; i++) {
932             components[offset+i] = (pixel & maskArray[i]) >>> maskOffsets[i];
933         }
934 
935         return components;
936     }
937 
938     /**
939      * Returns an array of unnormalized color/alpha components given a pixel
940      * in this <code>ColorModel</code>.  The pixel value is specified by an
941      * array of data elements of type <code>transferType</code> passed in as
942      * an object reference.  If <code>pixel</code> is not a primitive array
943      * of type <code>transferType</code>, a <code>ClassCastException</code>
944      * is thrown.  An <code>ArrayIndexOutOfBoundsException</code> is
945      * thrown if <code>pixel</code> is not large enough to hold a
946      * pixel value for this <code>ColorModel</code>.  If the
947      * <code>components</code> array is <code>null</code>, a new
948      * array is allocated.  The <code>components</code> array is returned.
949      * Color/alpha components are stored in the <code>components</code> array
950      * starting at <code>offset</code>, even if the array is allocated by
951      * this method.  An <code>ArrayIndexOutOfBoundsException</code>
952      * is thrown if the <code>components</code> array is not
953      * <code>null</code> and is not large enough to hold all the color and
954      * alpha components, starting at <code>offset</code>.
955      * Since <code>DirectColorModel</code> can be subclassed, subclasses
956      * inherit the implementation of this method and if they don't
957      * override it then they throw an exception if they use an unsupported
958      * <code>transferType</code>.
959      * @param pixel the specified pixel
960      * @param components the array to receive the color and alpha
961      *        components of the specified pixel
962      * @param offset the offset into the <code>components</code> array at
963      *        which to start storing the color and alpha components
964      * @return an array containing the color and alpha components of the
965      * specified pixel starting at the specified offset.
966      * @exception ClassCastException if <code>pixel</code>
967      *  is not a primitive array of type <code>transferType</code>
968      * @exception ArrayIndexOutOfBoundsException if
969      *  <code>pixel</code> is not large enough to hold a pixel value
970      *  for this <code>ColorModel</code>, or if <code>components</code>
971      *  is not <code>null</code> and is not large enough to hold all the
972      *  color and alpha components, starting at <code>offset</code>
973      * @exception UnsupportedOperationException if this
974      *            <code>transferType</code> is not supported by this
975      *            color model
976      */
977     final public int[] getComponents(Object pixel, int[] components,
978                                      int offset) {
979         int intpixel=0;
980         switch (transferType) {
981             case DataBuffer.TYPE_BYTE:
982                byte bdata[] = (byte[])pixel;
983                intpixel = bdata[0] & 0xff;
984             break;
985             case DataBuffer.TYPE_USHORT:
986                short sdata[] = (short[])pixel;
987                intpixel = sdata[0] & 0xffff;
988             break;
989             case DataBuffer.TYPE_INT:
990                int idata[] = (int[])pixel;
991                intpixel = idata[0];
992             break;
993             default:
994                throw new UnsupportedOperationException("This method has not been "+
995                    "implemented for transferType " + transferType);
996         }
997         return getComponents(intpixel, components, offset);
998     }
999 
1000     /**
1001      * Creates a <code>WritableRaster</code> with the specified width and
1002      * height that has a data layout (<code>SampleModel</code>) compatible
1003      * with this <code>ColorModel</code>.
1004      * @param w the width to apply to the new <code>WritableRaster</code>
1005      * @param h the height to apply to the new <code>WritableRaster</code>
1006      * @return a <code>WritableRaster</code> object with the specified
1007      * width and height.
1008      * @throws IllegalArgumentException if <code>w</code> or <code>h</code>
1009      *         is less than or equal to zero
1010      * @see WritableRaster
1011      * @see SampleModel
1012      */
1013     final public WritableRaster createCompatibleWritableRaster (int w,
1014                                                                 int h) {
1015         if ((w <= 0) || (h <= 0)) {
1016             throw new IllegalArgumentException("Width (" + w + ") and height (" + h +
1017                                                ") cannot be <= 0");
1018         }
1019         int[] bandmasks;
1020         if (supportsAlpha) {
1021             bandmasks = new int[4];
1022             bandmasks[3] = alpha_mask;
1023         }
1024         else {
1025             bandmasks = new int[3];
1026         }
1027         bandmasks[0] = red_mask;
1028         bandmasks[1] = green_mask;
1029         bandmasks[2] = blue_mask;
1030 
1031         if (pixel_bits > 16) {
1032             return Raster.createPackedRaster(DataBuffer.TYPE_INT,
1033                                              w,h,bandmasks,null);
1034         }
1035         else if (pixel_bits > 8) {
1036             return Raster.createPackedRaster(DataBuffer.TYPE_USHORT,
1037                                              w,h,bandmasks,null);
1038         }
1039         else {
1040             return Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
1041                                              w,h,bandmasks,null);
1042         }
1043     }
1044 
1045     /**
1046      * Returns a pixel value represented as an <code>int</code> in this
1047      * <code>ColorModel</code>, given an array of unnormalized color/alpha
1048      * components.   An <code>ArrayIndexOutOfBoundsException</code> is
1049      * thrown if the <code>components</code> array is
1050      * not large enough to hold all the color and alpha components, starting
1051      * at <code>offset</code>.
1052      * @param components an array of unnormalized color and alpha
1053      * components
1054      * @param offset the index into <code>components</code> at which to
1055      * begin retrieving the color and alpha components
1056      * @return an <code>int</code> pixel value in this
1057      * <code>ColorModel</code> corresponding to the specified components.
1058      * @exception ArrayIndexOutOfBoundsException if
1059      *  the <code>components</code> array is not large enough to
1060      *  hold all of the color and alpha components starting at
1061      *  <code>offset</code>
1062      */
1063     public int getDataElement(int[] components, int offset) {
1064         int pixel = 0;
1065         for (int i=0; i < numComponents; i++) {
1066             pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
1067         }
1068         return pixel;
1069     }
1070 
1071     /**
1072      * Returns a data element array representation of a pixel in this
1073      * <code>ColorModel</code>, given an array of unnormalized color/alpha
1074      * components.
1075      * This array can then be passed to the <code>setDataElements</code>
1076      * method of a <code>WritableRaster</code> object.
1077      * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1078      * <code>components</code> array
1079      * is not large enough to hold all the color and alpha components,
1080      * starting at offset.  If the <code>obj</code> variable is
1081      * <code>null</code>, a new array is allocated.  If <code>obj</code> is
1082      * not <code>null</code>, it must be a primitive array
1083      * of type <code>transferType</code>; otherwise, a
1084      * <code>ClassCastException</code> is thrown.
1085      * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
1086      * <code>obj</code> is not large enough to hold a pixel value for this
1087      * <code>ColorModel</code>.
1088      * Since <code>DirectColorModel</code> can be subclassed, subclasses
1089      * inherit the implementation of this method and if they don't
1090      * override it then they throw an exception if they use an unsupported
1091      * <code>transferType</code>.
1092      * @param components an array of unnormalized color and alpha
1093      * components
1094      * @param offset the index into <code>components</code> at which to
1095      * begin retrieving color and alpha components
1096      * @param obj the <code>Object</code> representing an array of color
1097      * and alpha components
1098      * @return an <code>Object</code> representing an array of color and
1099      * alpha components.
1100      * @exception ClassCastException if <code>obj</code>
1101      *  is not a primitive array of type <code>transferType</code>
1102      * @exception ArrayIndexOutOfBoundsException if
1103      *  <code>obj</code> is not large enough to hold a pixel value
1104      *  for this <code>ColorModel</code> or the <code>components</code>
1105      *  array is not large enough to hold all of the color and alpha
1106      *  components starting at <code>offset</code>
1107      * @exception UnsupportedOperationException if this
1108      *            <code>transferType</code> is not supported by this
1109      *            color model
1110      * @see WritableRaster#setDataElements
1111      * @see SampleModel#setDataElements
1112      */
1113     public Object getDataElements(int[] components, int offset, Object obj) {
1114         int pixel = 0;
1115         for (int i=0; i < numComponents; i++) {
1116             pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
1117         }
1118         switch (transferType) {
1119             case DataBuffer.TYPE_BYTE:
1120                if (obj instanceof byte[]) {
1121                    byte bdata[] = (byte[])obj;
1122                    bdata[0] = (byte)(pixel&0xff);
1123                    return bdata;
1124                } else {
1125                    byte bdata[] = {(byte)(pixel&0xff)};
1126                    return bdata;
1127                }
1128             case DataBuffer.TYPE_USHORT:
1129                if (obj instanceof short[]) {
1130                    short sdata[] = (short[])obj;
1131                    sdata[0] = (short)(pixel&0xffff);
1132                    return sdata;
1133                } else {
1134                    short sdata[] = {(short)(pixel&0xffff)};
1135                    return sdata;
1136                }
1137             case DataBuffer.TYPE_INT:
1138                if (obj instanceof int[]) {
1139                    int idata[] = (int[])obj;
1140                    idata[0] = pixel;
1141                    return idata;
1142                } else {
1143                    int idata[] = {pixel};
1144                    return idata;
1145                }
1146             default:
1147                throw new ClassCastException("This method has not been "+
1148                    "implemented for transferType " + transferType);
1149         }
1150     }
1151 
1152     /**
1153      * Forces the raster data to match the state specified in the
1154      * <code>isAlphaPremultiplied</code> variable, assuming the data is
1155      * currently correctly described by this <code>ColorModel</code>.  It
1156      * may multiply or divide the color raster data by alpha, or do
1157      * nothing if the data is in the correct state.  If the data needs to
1158      * be coerced, this method will also return an instance of this
1159      * <code>ColorModel</code> with the <code>isAlphaPremultiplied</code>
1160      * flag set appropriately.  This method will throw a
1161      * <code>UnsupportedOperationException</code> if this transferType is
1162      * not supported by this <code>ColorModel</code>.  Since
1163      * <code>ColorModel</code> can be subclassed, subclasses inherit the
1164      * implementation of this method and if they don't override it then
1165      * they throw an exception if they use an unsupported transferType.
1166      *
1167      * @param raster the <code>WritableRaster</code> data
1168      * @param isAlphaPremultiplied <code>true</code> if the alpha is
1169      * premultiplied; <code>false</code> otherwise
1170      * @return a <code>ColorModel</code> object that represents the
1171      * coerced data.
1172      * @exception UnsupportedOperationException if this
1173      *            <code>transferType</code> is not supported by this
1174      *            color model
1175      */
1176     final public ColorModel coerceData (WritableRaster raster,
1177                                         boolean isAlphaPremultiplied)
1178     {
1179         if (!supportsAlpha ||
1180             this.isAlphaPremultiplied() == isAlphaPremultiplied) {
1181             return this;
1182         }
1183 
1184         int w = raster.getWidth();
1185         int h = raster.getHeight();
1186         int aIdx = numColorComponents;
1187         float normAlpha;
1188         float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
1189 
1190         int rminX = raster.getMinX();
1191         int rY = raster.getMinY();
1192         int rX;
1193         int pixel[] = null;
1194         int zpixel[] = null;
1195 
1196         if (isAlphaPremultiplied) {
1197             // Must mean that we are currently not premultiplied so
1198             // multiply by alpha
1199             switch (transferType) {
1200                 case DataBuffer.TYPE_BYTE: {
1201                     for (int y = 0; y < h; y++, rY++) {
1202                         rX = rminX;
1203                         for (int x = 0; x < w; x++, rX++) {
1204                             pixel = raster.getPixel(rX, rY, pixel);
1205                             normAlpha = pixel[aIdx] * alphaScale;
1206                             if (normAlpha != 0.f) {
1207                                 for (int c=0; c < aIdx; c++) {
1208                                     pixel[c] = (int) (pixel[c] * normAlpha +
1209                                                       0.5f);
1210                                 }
1211                                 raster.setPixel(rX, rY, pixel);
1212                             } else {
1213                                 if (zpixel == null) {
1214                                     zpixel = new int[numComponents];
1215                                     java.util.Arrays.fill(zpixel, 0);
1216                                 }
1217                                 raster.setPixel(rX, rY, zpixel);
1218                             }
1219                         }
1220                     }
1221                 }
1222                 break;
1223                 case DataBuffer.TYPE_USHORT: {
1224                     for (int y = 0; y < h; y++, rY++) {
1225                         rX = rminX;
1226                         for (int x = 0; x < w; x++, rX++) {
1227                             pixel = raster.getPixel(rX, rY, pixel);
1228                             normAlpha = pixel[aIdx] * alphaScale;
1229                             if (normAlpha != 0.f) {
1230                                 for (int c=0; c < aIdx; c++) {
1231                                     pixel[c] = (int) (pixel[c] * normAlpha +
1232                                                       0.5f);
1233                                 }
1234                                 raster.setPixel(rX, rY, pixel);
1235                             } else {
1236                                 if (zpixel == null) {
1237                                     zpixel = new int[numComponents];
1238                                     java.util.Arrays.fill(zpixel, 0);
1239                                 }
1240                                 raster.setPixel(rX, rY, zpixel);
1241                             }
1242                         }
1243                     }
1244                 }
1245                 break;
1246                 case DataBuffer.TYPE_INT: {
1247                     for (int y = 0; y < h; y++, rY++) {
1248                         rX = rminX;
1249                         for (int x = 0; x < w; x++, rX++) {
1250                             pixel = raster.getPixel(rX, rY, pixel);
1251                             normAlpha = pixel[aIdx] * alphaScale;
1252                             if (normAlpha != 0.f) {
1253                                 for (int c=0; c < aIdx; c++) {
1254                                     pixel[c] = (int) (pixel[c] * normAlpha +
1255                                                       0.5f);
1256                                 }
1257                                 raster.setPixel(rX, rY, pixel);
1258                             } else {
1259                                 if (zpixel == null) {
1260                                     zpixel = new int[numComponents];
1261                                     java.util.Arrays.fill(zpixel, 0);
1262                                 }
1263                                 raster.setPixel(rX, rY, zpixel);
1264                             }
1265                         }
1266                     }
1267                 }
1268                 break;
1269                 default:
1270                     throw new UnsupportedOperationException("This method has not been "+
1271                          "implemented for transferType " + transferType);
1272             }
1273         }
1274         else {
1275             // We are premultiplied and want to divide it out
1276             switch (transferType) {
1277                 case DataBuffer.TYPE_BYTE: {
1278                     for (int y = 0; y < h; y++, rY++) {
1279                         rX = rminX;
1280                         for (int x = 0; x < w; x++, rX++) {
1281                             pixel = raster.getPixel(rX, rY, pixel);
1282                             normAlpha = pixel[aIdx] * alphaScale;
1283                             if (normAlpha != 0.0f) {
1284                                 float invAlpha = 1.0f / normAlpha;
1285                                 for (int c=0; c < aIdx; c++) {
1286                                     pixel[c] = (int) (pixel[c] * invAlpha +
1287                                                       0.5f);
1288                                 }
1289                                 raster.setPixel(rX, rY, pixel);
1290                             }
1291                         }
1292                     }
1293                 }
1294                 break;
1295                 case DataBuffer.TYPE_USHORT: {
1296                     for (int y = 0; y < h; y++, rY++) {
1297                         rX = rminX;
1298                         for (int x = 0; x < w; x++, rX++) {
1299                             pixel = raster.getPixel(rX, rY, pixel);
1300                             normAlpha = pixel[aIdx] * alphaScale;
1301                             if (normAlpha != 0) {
1302                                 float invAlpha = 1.0f / normAlpha;
1303                                 for (int c=0; c < aIdx; c++) {
1304                                     pixel[c] = (int) (pixel[c] * invAlpha +
1305                                                       0.5f);
1306                                 }
1307                                 raster.setPixel(rX, rY, pixel);
1308                             }
1309                         }
1310                     }
1311                 }
1312                 break;
1313                 case DataBuffer.TYPE_INT: {
1314                     for (int y = 0; y < h; y++, rY++) {
1315                         rX = rminX;
1316                         for (int x = 0; x < w; x++, rX++) {
1317                             pixel = raster.getPixel(rX, rY, pixel);
1318                             normAlpha = pixel[aIdx] * alphaScale;
1319                             if (normAlpha != 0) {
1320                                 float invAlpha = 1.0f / normAlpha;
1321                                 for (int c=0; c < aIdx; c++) {
1322                                     pixel[c] = (int) (pixel[c] * invAlpha +
1323                                                       0.5f);
1324                                 }
1325                                 raster.setPixel(rX, rY, pixel);
1326                             }
1327                         }
1328                     }
1329                 }
1330                 break;
1331                 default:
1332                     throw new UnsupportedOperationException("This method has not been "+
1333                          "implemented for transferType " + transferType);
1334             }
1335         }
1336 
1337         // Return a new color model
1338         return new DirectColorModel(colorSpace, pixel_bits, maskArray[0],
1339                                     maskArray[1], maskArray[2], maskArray[3],
1340                                     isAlphaPremultiplied,
1341                                     transferType);
1342 
1343     }
1344 
1345     /**
1346       * Returns <code>true</code> if <code>raster</code> is compatible
1347       * with this <code>ColorModel</code> and <code>false</code> if it is
1348       * not.
1349       * @param raster the {@link Raster} object to test for compatibility
1350       * @return <code>true</code> if <code>raster</code> is compatible
1351       * with this <code>ColorModel</code>; <code>false</code> otherwise.
1352       */
1353     public boolean isCompatibleRaster(Raster raster) {
1354         SampleModel sm = raster.getSampleModel();
1355         SinglePixelPackedSampleModel spsm;
1356         if (sm instanceof SinglePixelPackedSampleModel) {
1357             spsm = (SinglePixelPackedSampleModel) sm;
1358         }
1359         else {
1360             return false;
1361         }
1362         if (spsm.getNumBands() != getNumComponents()) {
1363             return false;
1364         }
1365 
1366         int[] bitMasks = spsm.getBitMasks();
1367         for (int i=0; i<numComponents; i++) {
1368             if (bitMasks[i] != maskArray[i]) {
1369                 return false;
1370             }
1371         }
1372 
1373         return (raster.getTransferType() == transferType);
1374     }
1375 
1376     private void setFields() {
1377         // Set the private fields
1378         // REMIND: Get rid of these from the native code
1379         red_mask     = maskArray[0];
1380         red_offset   = maskOffsets[0];
1381         green_mask   = maskArray[1];
1382         green_offset = maskOffsets[1];
1383         blue_mask    = maskArray[2];
1384         blue_offset  = maskOffsets[2];
1385         if (nBits[0] < 8) {
1386             red_scale = (1 << nBits[0]) - 1;
1387         }
1388         if (nBits[1] < 8) {
1389             green_scale = (1 << nBits[1]) - 1;
1390         }
1391         if (nBits[2] < 8) {
1392             blue_scale = (1 << nBits[2]) - 1;
1393         }
1394         if (supportsAlpha) {
1395             alpha_mask   = maskArray[3];
1396             alpha_offset = maskOffsets[3];
1397             if (nBits[3] < 8) {
1398                 alpha_scale = (1 << nBits[3]) - 1;
1399             }
1400         }
1401     }
1402 
1403     /**
1404      * Returns a <code>String</code> that represents this
1405      * <code>DirectColorModel</code>.
1406      * @return a <code>String</code> representing this
1407      * <code>DirectColorModel</code>.
1408      */
1409     public String toString() {
1410         return new String("DirectColorModel: rmask="
1411                           +Integer.toHexString(red_mask)+" gmask="
1412                           +Integer.toHexString(green_mask)+" bmask="
1413                           +Integer.toHexString(blue_mask)+" amask="
1414                           +Integer.toHexString(alpha_mask));
1415     }
1416 }