1 /*
2  * Copyright (c) 1995, 2018, 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 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()}
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      */
DirectColorModel(int bits, int rmask, int gmask, int bmask)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      */
DirectColorModel(int bits, int rmask, int gmask, int bmask, int amask)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 true} if 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      */
DirectColorModel(ColorSpace space, int bits, int rmask, int gmask, int bmask, int amask, boolean isAlphaPremultiplied, int transferType)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      */
getRedMask()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      */
getGreenMask()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      */
getBlueMask()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      */
getAlphaMask()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      */
getDefaultRGBComponents(int pixel)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 
getsRGBComponentFromsRGB(int pixel, int idx)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 
getsRGBComponentFromLinearRGB(int pixel, int idx)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      */
getRed(int pixel)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      */
getGreen(int pixel)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      */
getBlue(int pixel)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      */
getAlpha(int pixel)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      */
getRGB(int pixel)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      */
getRed(Object inData)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      */
getGreen(Object inData)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      */
getBlue(Object inData)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      */
getAlpha(Object inData)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      */
getRGB(Object inData)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      */
getDataElements(int rgb, Object pixel)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      */
getComponents(int pixel, int[] components, int offset)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      */
getComponents(Object pixel, int[] components, int offset)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      */
createCompatibleWritableRaster(int w, int h)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      */
getDataElement(int[] components, int offset)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      */
getDataElements(int[] components, int offset, Object obj)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 true} if 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      */
coerceData(WritableRaster raster, boolean isAlphaPremultiplied)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 true} if {@code raster} is compatible
1347       * with this {@code ColorModel} and {@code false} if it is
1348       * not.
1349       * @param raster the {@link Raster} object to test for compatibility
1350       * @return {@code true} if {@code raster} is compatible
1351       * with this {@code ColorModel}; {@code false} otherwise.
1352       */
isCompatibleRaster(Raster raster)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 
setFields()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      */
toString()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