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} class is a {@code ColorModel}
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 intshort, 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()}
39  * method of ColorSpace must be 0.0, and the maximum value obtained via
40  * the {@code getMaxValue()} 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}, 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} is
64  * typically used with image data which uses masks to define packed
65  * samples.  For example, a {@code DirectColorModel} can be used in
66  * conjunction with a {@code SinglePixelPackedSampleModel} to
67  * construct a {@link BufferedImage}.  Normally the masks used by the
68  * {@link SampleModel} and the {@code ColorModel} 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}.
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}
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} 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} from the specified masks
130      * that indicate which bits in an {@code int} 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} pixel representation.
136      *  The {@code ColorSpace} 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} from the specified masks
157      * that indicate which bits in an {@code int} pixel representation
158      * contain the red, green and blue color samples and the alpha sample,
159      * if present.  If {@code amask} 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} pixel representation.  Alpha, if present, is not
164      * premultiplied.  The {@code ColorSpace} 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} from the specified
191      * parameters.  Color components are in the specified
192      * {@code ColorSpace}, 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} pixel
196      * representation contain the red, green and blue color samples and
197      * the alpha sample, if present.  If {@code amask} 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} pixel
202      * representation.  If there is alpha, the {@code boolean}
203      * {@code isAlphaPremultiplied} specifies how to interpret
204      * color and alpha samples in pixel values.  If the {@code boolean}
205      * is {@code true}, 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}
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 trueif color samples are
224      *        premultiplied by the alpha sample; {@code false} otherwise
225      * @param transferType the type of array used to represent pixel values
226      * @throws IllegalArgumentException if {@code space} 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} pixel
265      * representation contain the red color component.
266      * @return the mask, which indicates which bits of the {@code int}
267      *         pixel representation contain the red color sample.
268      */

269     public final int getRedMask() {
270         return maskArray[0];
271     }
272
273     /**
274      * Returns the mask indicating which bits in an {@code int} pixel
275      * representation contain the green color component.
276      * @return the mask, which indicates which bits of the {@code int}
277      *         pixel representation contain the green color sample.
278      */

279     public final int getGreenMask() {
280         return maskArray[1];
281     }
282
283     /**
284      * Returns the mask indicating which bits in an {@code int} pixel
285      * representation contain the blue color component.
286      * @return the mask, which indicates which bits of the {@code int}
287      *         pixel representation contain the blue color sample.
288      */

289     public final int getBlueMask() {
290         return maskArray[2];
291     }
292
293     /**
294      * Returns the mask indicating which bits in an {@code int} pixel
295      * representation contain the alpha component.
296      * @return the mask, which indicates which bits of the {@code int}
297      *         pixel representation contain the alpha sample.
298      */

299     public final 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}, sRGB.  A
358      * color conversion is done if necessary.  The pixel value is specified
359      * as an {@code int}.
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}.
367      */

368     public final 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}, sRGB.  A
381      * color conversion is done if necessary.  The pixel value is specified
382      * as an {@code int}.
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}.
390      */

391     public final 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}, sRGB.  A
404      * color conversion is done if necessary.  The pixel value is specified
405      * as an {@code int}.
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}.
413      */

414     public final 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}.
427      * @param pixel the specified pixel
428      * @return the value of the alpha component of {@code pixel}
429      *         from 0 to 255.
430      */

431     public final 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}.
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     public final 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}, 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} 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} is not a primitive array of type
478      * {@code transferType}, a {@code ClassCastException} is
479      * thrown.  An {@code ArrayIndexOutOfBoundsException} is
480      * thrown if {@code inData} is not large enough to hold a
481      * pixel value for this {@code ColorModel}.  Since
482      * {@code DirectColorModel} 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}.
486      * An {@code UnsupportedOperationException} is thrown if this
487      * {@code transferType} is not supported by this
488      * {@code ColorModel}.
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} is not
492      *         large enough to hold a pixel value for this color model
493      * @throws ClassCastException if {@code inData} is not a
494      *         primitive array of type {@code transferType}
495      * @throws UnsupportedOperationException if this {@code transferType}
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}, 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} 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} is not a primitive array of type
531      * {@code transferType}, a {@code ClassCastException} is thrown.
532      *  An {@code ArrayIndexOutOfBoundsException} is
533      * thrown if {@code inData} is not large enough to hold a pixel
534      * value for this {@code ColorModel}.  Since
535      * {@code DirectColorModel} 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}.
539      * An {@code UnsupportedOperationException} is
540      * thrown if this {@code transferType} is not supported by this
541      * {@code ColorModel}.
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} is not
545      *         large enough to hold a pixel value for this color model
546      * @throws ClassCastException if {@code inData} is not a
547      *         primitive array of type {@code transferType}
548      * @throws UnsupportedOperationException if this {@code transferType}
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}, 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} 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} is not a primitive array of type
584      * {@code transferType}, a {@code ClassCastException} is thrown.
585      *  An {@code ArrayIndexOutOfBoundsException} is
586      * thrown if {@code inData} is not large enough to hold a pixel
587      * value for this {@code ColorModel}.  Since
588      * {@code DirectColorModel} 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}.
592      * An {@code UnsupportedOperationException} is
593      * thrown if this {@code transferType} is not supported by this
594      * {@code ColorModel}.
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} is not
598      *         large enough to hold a pixel value for this color model
599      * @throws ClassCastException if {@code inData} is not a
600      *         primitive array of type {@code transferType}
601      * @throws UnsupportedOperationException if this {@code transferType}
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} passed in as an object
630      * reference.
631      * If {@code inData} is not a primitive array of type
632      * {@code transferType}, a {@code ClassCastException} is
633      * thrown.  An {@code ArrayIndexOutOfBoundsException} is
634      * thrown if {@code inData} is not large enough to hold a pixel
635      * value for this {@code ColorModel}.  Since
636      * {@code DirectColorModel} 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}.
640      * If this {@code transferType} is not supported, an
641      * {@code UnsupportedOperationException} 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}
646      *  is not a primitive array of type {@code transferType}
647      * @exception ArrayIndexOutOfBoundsException if
648      *  {@code inData} is not large enough to hold a pixel value
649      *  for this {@code ColorModel}
650      * @exception UnsupportedOperationException if this
651      *  {@code tranferType} is not supported by this
652      *  {@code ColorModel}
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} passed in as an object
681      * reference.  If {@code inData} is not a primitive array of type
682      * {@code transferType}, a {@code ClassCastException} is
683      * thrown.  An {@code ArrayIndexOutOfBoundsException} is
684      * thrown if {@code inData} is not large enough to hold a pixel
685      * value for this {@code ColorModel}.
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} 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}.
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} is not supported by this
699      *            {@code ColorModel}
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}, given an integer pixel representation in the
727      * default RGB color model.
728      * This array can then be passed to the {@code setDataElements}
729      * method of a {@code WritableRaster} object.  If the pixel variable
730      * is {@code null}, a new array is allocated.  If {@code pixel}
731      * is not {@code null}, it must be a primitive array of type
732      * {@code transferType}; otherwise, a
733      * {@code ClassCastException} is thrown.  An
734      * {@code ArrayIndexOutOfBoundsException} is
735      * thrown if {@code pixel} is not large enough to hold a pixel
736      * value for this {@code ColorModel}.  The pixel array is returned.
737      * Since {@code DirectColorModel} 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}.
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}
747      * @exception ClassCastException if {@code pixel}
748      *  is not a primitive array of type {@code transferType}
749      * @exception ArrayIndexOutOfBoundsException if
750      *  {@code pixel} is not large enough to hold a pixel value
751      *  for this {@code ColorModel}
752      * @exception UnsupportedOperationException if this
753      *  {@code transferType} is not supported by this
754      *  {@code ColorModel}
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}.  The pixel value is specified as an
909      * {@code int}.  If the {@code components} array is
910      * {@code null}, a new array is allocated.  The
911      * {@code components} array is returned.  Color/alpha components are
912      * stored in the {@code components} array starting at
913      * {@code offset}, even if the array is allocated by this method.
914      * An {@code ArrayIndexOutOfBoundsException} is thrown if the
915      * {@code components} array is not {@code null} and is not large
916      * enough to hold all the color and alpha components, starting at
917      * {@code offset}.
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} 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     public final 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}.  The pixel value is specified by an
941      * array of data elements of type {@code transferType} passed in as
942      * an object reference.  If {@code pixel} is not a primitive array
943      * of type {@code transferType}, a {@code ClassCastException}
944      * is thrown.  An {@code ArrayIndexOutOfBoundsException} is
945      * thrown if {@code pixel} is not large enough to hold a
946      * pixel value for this {@code ColorModel}.  If the
947      * {@code components} array is {@code null}, a new
948      * array is allocated.  The {@code components} array is returned.
949      * Color/alpha components are stored in the {@code components} array
950      * starting at {@code offset}, even if the array is allocated by
951      * this method.  An {@code ArrayIndexOutOfBoundsException}
952      * is thrown if the {@code components} array is not
953      * {@code null} and is not large enough to hold all the color and
954      * alpha components, starting at {@code offset}.
955      * Since {@code DirectColorModel} 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}.
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} 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}
967      *  is not a primitive array of type {@code transferType}
968      * @exception ArrayIndexOutOfBoundsException if
969      *  {@code pixel} is not large enough to hold a pixel value
970      *  for this {@code ColorModel}, or if {@code components}
971      *  is not {@code null} and is not large enough to hold all the
972      *  color and alpha components, starting at {@code offset}
973      * @exception UnsupportedOperationException if this
974      *            {@code transferType} is not supported by this
975      *            color model
976      */

977     public final 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} with the specified width and
1002      * height that has a data layout ({@code SampleModel}) compatible
1003      * with this {@code ColorModel}.
1004      * @param w the width to apply to the new {@code WritableRaster}
1005      * @param h the height to apply to the new {@code WritableRaster}
1006      * @return a {@code WritableRaster} object with the specified
1007      * width and height.
1008      * @throws IllegalArgumentException if {@code w} or {@code h}
1009      *         is less than or equal to zero
1010      * @see WritableRaster
1011      * @see SampleModel
1012      */

1013     public final 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} in this
1047      * {@code ColorModel}, given an array of unnormalized color/alpha
1048      * components.   An {@code ArrayIndexOutOfBoundsException} is
1049      * thrown if the {@code components} array is
1050      * not large enough to hold all the color and alpha components, starting
1051      * at {@code offset}.
1052      * @param components an array of unnormalized color and alpha
1053      * components
1054      * @param offset the index into {@code components} at which to
1055      * begin retrieving the color and alpha components
1056      * @return an {@code int} pixel value in this
1057      * {@code ColorModel} corresponding to the specified components.
1058      * @exception ArrayIndexOutOfBoundsException if
1059      *  the {@code components} array is not large enough to
1060      *  hold all of the color and alpha components starting at
1061      *  {@code offset}
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}, given an array of unnormalized color/alpha
1074      * components.
1075      * This array can then be passed to the {@code setDataElements}
1076      * method of a {@code WritableRaster} object.
1077      * An {@code ArrayIndexOutOfBoundsException} is thrown if the
1078      * {@code components} array
1079      * is not large enough to hold all the color and alpha components,
1080      * starting at offset.  If the {@code obj} variable is
1081      * {@code null}, a new array is allocated.  If {@code obj} is
1082      * not {@code null}, it must be a primitive array
1083      * of type {@code transferType}; otherwise, a
1084      * {@code ClassCastException} is thrown.
1085      * An {@code ArrayIndexOutOfBoundsException} is thrown if
1086      * {@code obj} is not large enough to hold a pixel value for this
1087      * {@code ColorModel}.
1088      * Since {@code DirectColorModel} 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}.
1092      * @param components an array of unnormalized color and alpha
1093      * components
1094      * @param offset the index into {@code components} at which to
1095      * begin retrieving color and alpha components
1096      * @param obj the {@code Object} representing an array of color
1097      * and alpha components
1098      * @return an {@code Object} representing an array of color and
1099      * alpha components.
1100      * @exception ClassCastException if {@code obj}
1101      *  is not a primitive array of type {@code transferType}
1102      * @exception ArrayIndexOutOfBoundsException if
1103      *  {@code obj} is not large enough to hold a pixel value
1104      *  for this {@code ColorModel} or the {@code components}
1105      *  array is not large enough to hold all of the color and alpha
1106      *  components starting at {@code offset}
1107      * @exception UnsupportedOperationException if this
1108      *            {@code transferType} 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} variable, assuming the data is
1155      * currently correctly described by this {@code ColorModel}.  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} with the {@code isAlphaPremultiplied}
1160      * flag set appropriately.  This method will throw a
1161      * {@code UnsupportedOperationException} if this transferType is
1162      * not supported by this {@code ColorModel}.  Since
1163      * {@code ColorModel} 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} data
1168      * @param isAlphaPremultiplied {@code trueif the alpha is
1169      * premultiplied; {@code false} otherwise
1170      * @return a {@code ColorModel} object that represents the
1171      * coerced data.
1172      * @exception UnsupportedOperationException if this
1173      *            {@code transferType} is not supported by this
1174      *            color model
1175      */

1176     public final 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 trueif {@code raster} is compatible
1347       * with this {@code ColorModel} and {@code falseif it is
1348       * not.
1349       * @param raster the {@link Raster} object to test for compatibility
1350       * @return {@code trueif {@code raster} is compatible
1351       * with this {@code ColorModel}; {@code false} 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} that represents this
1405      * {@code DirectColorModel}.
1406      * @return a {@code String} representing this
1407      * {@code DirectColorModel}.
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 }
1417