View Javadoc
1   /*
2    * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package java.awt.image;
27  
28  import java.awt.Transparency;
29  import java.awt.color.ColorSpace;
30  import java.awt.color.ICC_ColorSpace;
31  import sun.java2d.cmm.CMSManager;
32  import sun.java2d.cmm.ColorTransform;
33  import sun.java2d.cmm.PCMM;
34  import java.awt.Toolkit;
35  import java.util.Collections;
36  import java.util.Map;
37  import java.util.WeakHashMap;
38  
39  /**
40   * The <code>ColorModel</code> abstract class encapsulates the
41   * methods for translating a pixel value to color components
42   * (for example, red, green, and blue) and an alpha component.
43   * In order to render an image to the screen, a printer, or another
44   * image, pixel values must be converted to color and alpha components.
45   * As arguments to or return values from methods of this class,
46   * pixels are represented as 32-bit ints or as arrays of primitive types.
47   * The number, order, and interpretation of color components for a
48   * <code>ColorModel</code> is specified by its <code>ColorSpace</code>.
49   * A <code>ColorModel</code> used with pixel data that does not include
50   * alpha information treats all pixels as opaque, which is an alpha
51   * value of 1.0.
52   * <p>
53   * This <code>ColorModel</code> class supports two representations of
54   * pixel values.  A pixel value can be a single 32-bit int or an
55   * array of primitive types.  The Java(tm) Platform 1.0 and 1.1 APIs
56   * represented pixels as single <code>byte</code> or single
57   * <code>int</code> values.  For purposes of the <code>ColorModel</code>
58   * class, pixel value arguments were passed as ints.  The Java(tm) 2
59   * Platform API introduced additional classes for representing images.
60   * With {@link BufferedImage} or {@link RenderedImage}
61   * objects, based on {@link Raster} and {@link SampleModel} classes, pixel
62   * values might not be conveniently representable as a single int.
63   * Consequently, <code>ColorModel</code> now has methods that accept
64   * pixel values represented as arrays of primitive types.  The primitive
65   * type used by a particular <code>ColorModel</code> object is called its
66   * transfer type.
67   * <p>
68   * <code>ColorModel</code> objects used with images for which pixel values
69   * are not conveniently representable as a single int throw an
70   * {@link IllegalArgumentException} when methods taking a single int pixel
71   * argument are called.  Subclasses of <code>ColorModel</code> must
72   * specify the conditions under which this occurs.  This does not
73   * occur with {@link DirectColorModel} or {@link IndexColorModel} objects.
74   * <p>
75   * Currently, the transfer types supported by the Java 2D(tm) API are
76   * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT,
77   * DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, and DataBuffer.TYPE_DOUBLE.
78   * Most rendering operations will perform much faster when using ColorModels
79   * and images based on the first three of these types.  In addition, some
80   * image filtering operations are not supported for ColorModels and
81   * images based on the latter three types.
82   * The transfer type for a particular <code>ColorModel</code> object is
83   * specified when the object is created, either explicitly or by default.
84   * All subclasses of <code>ColorModel</code> must specify what the
85   * possible transfer types are and how the number of elements in the
86   * primitive arrays representing pixels is determined.
87   * <p>
88   * For <code>BufferedImages</code>, the transfer type of its
89   * <code>Raster</code> and of the <code>Raster</code> object's
90   * <code>SampleModel</code> (available from the
91   * <code>getTransferType</code> methods of these classes) must match that
92   * of the <code>ColorModel</code>.  The number of elements in an array
93   * representing a pixel for the <code>Raster</code> and
94   * <code>SampleModel</code> (available from the
95   * <code>getNumDataElements</code> methods of these classes) must match
96   * that of the <code>ColorModel</code>.
97   * <p>
98   * The algorithm used to convert from pixel values to color and alpha
99   * components varies by subclass.  For example, there is not necessarily
100  * a one-to-one correspondence between samples obtained from the
101  * <code>SampleModel</code> of a <code>BufferedImage</code> object's
102  * <code>Raster</code> and color/alpha components.  Even when
103  * there is such a correspondence, the number of bits in a sample is not
104  * necessarily the same as the number of bits in the corresponding color/alpha
105  * component.  Each subclass must specify how the translation from
106  * pixel values to color/alpha components is done.
107  * <p>
108  * Methods in the <code>ColorModel</code> class use two different
109  * representations of color and alpha components - a normalized form
110  * and an unnormalized form.  In the normalized form, each component is a
111  * <code>float</code> value between some minimum and maximum values.  For
112  * the alpha component, the minimum is 0.0 and the maximum is 1.0.  For
113  * color components the minimum and maximum values for each component can
114  * be obtained from the <code>ColorSpace</code> object.  These values
115  * will often be 0.0 and 1.0 (e.g. normalized component values for the
116  * default sRGB color space range from 0.0 to 1.0), but some color spaces
117  * have component values with different upper and lower limits.  These
118  * limits can be obtained using the <code>getMinValue</code> and
119  * <code>getMaxValue</code> methods of the <code>ColorSpace</code>
120  * class.  Normalized color component values are not premultiplied.
121  * All <code>ColorModels</code> must support the normalized form.
122  * <p>
123  * In the unnormalized
124  * form, each component is an unsigned integral value between 0 and
125  * 2<sup>n</sup> - 1, where n is the number of significant bits for a
126  * particular component.  If pixel values for a particular
127  * <code>ColorModel</code> represent color samples premultiplied by
128  * the alpha sample, unnormalized color component values are
129  * also premultiplied.  The unnormalized form is used only with instances
130  * of <code>ColorModel</code> whose <code>ColorSpace</code> has minimum
131  * component values of 0.0 for all components and maximum values of
132  * 1.0 for all components.
133  * The unnormalized form for color and alpha components can be a convenient
134  * representation for <code>ColorModels</code> whose normalized component
135  * values all lie
136  * between 0.0 and 1.0.  In such cases the integral value 0 maps to 0.0 and
137  * the value 2<sup>n</sup> - 1 maps to 1.0.  In other cases, such as
138  * when the normalized component values can be either negative or positive,
139  * the unnormalized form is not convenient.  Such <code>ColorModel</code>
140  * objects throw an {@link IllegalArgumentException} when methods involving
141  * an unnormalized argument are called.  Subclasses of <code>ColorModel</code>
142  * must specify the conditions under which this occurs.
143  *
144  * @see IndexColorModel
145  * @see ComponentColorModel
146  * @see PackedColorModel
147  * @see DirectColorModel
148  * @see java.awt.Image
149  * @see BufferedImage
150  * @see RenderedImage
151  * @see java.awt.color.ColorSpace
152  * @see SampleModel
153  * @see Raster
154  * @see DataBuffer
155  */
156 public abstract class ColorModel implements Transparency{
157     private long pData;         // Placeholder for data for native functions
158 
159     /**
160      * The total number of bits in the pixel.
161      */
162     protected int pixel_bits;
163     int nBits[];
164     int transparency = Transparency.TRANSLUCENT;
165     boolean supportsAlpha = true;
166     boolean isAlphaPremultiplied = false;
167     int numComponents = -1;
168     int numColorComponents = -1;
169     ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
170     int colorSpaceType = ColorSpace.TYPE_RGB;
171     int maxBits;
172     boolean is_sRGB = true;
173 
174     /**
175      * Data type of the array used to represent pixel values.
176      */
177     protected int transferType;
178 
179     /**
180      * This is copied from java.awt.Toolkit since we need the library
181      * loaded in java.awt.image also:
182      *
183      * WARNING: This is a temporary workaround for a problem in the
184      * way the AWT loads native libraries. A number of classes in the
185      * AWT package have a native method, initIDs(), which initializes
186      * the JNI field and method ids used in the native portion of
187      * their implementation.
188      *
189      * Since the use and storage of these ids is done by the
190      * implementation libraries, the implementation of these method is
191      * provided by the particular AWT implementations (for example,
192      * "Toolkit"s/Peer), such as Motif, Microsoft Windows, or Tiny. The
193      * problem is that this means that the native libraries must be
194      * loaded by the java.* classes, which do not necessarily know the
195      * names of the libraries to load. A better way of doing this
196      * would be to provide a separate library which defines java.awt.*
197      * initIDs, and exports the relevant symbols out to the
198      * implementation libraries.
199      *
200      * For now, we know it's done by the implementation, and we assume
201      * that the name of the library is "awt".  -br.
202      */
203     private static boolean loaded = false;
204     static void loadLibraries() {
205         if (!loaded) {
206             java.security.AccessController.doPrivileged(
207                 new java.security.PrivilegedAction<Void>() {
208                     public Void run() {
209                         System.loadLibrary("awt");
210                         return null;
211                     }
212                 });
213             loaded = true;
214         }
215     }
216     private static native void initIDs();
217     static {
218         /* ensure that the proper libraries are loaded */
219         loadLibraries();
220         initIDs();
221     }
222     private static ColorModel RGBdefault;
223 
224     /**
225      * Returns a <code>DirectColorModel</code> that describes the default
226      * format for integer RGB values used in many of the methods in the
227      * AWT image interfaces for the convenience of the programmer.
228      * The color space is the default {@link ColorSpace}, sRGB.
229      * The format for the RGB values is an integer with 8 bits
230      * each of alpha, red, green, and blue color components ordered
231      * correspondingly from the most significant byte to the least
232      * significant byte, as in:  0xAARRGGBB.  Color components are
233      * not premultiplied by the alpha component.  This format does not
234      * necessarily represent the native or the most efficient
235      * <code>ColorModel</code> for a particular device or for all images.
236      * It is merely used as a common color model format.
237      * @return a <code>DirectColorModel</code>object describing default
238      *          RGB values.
239      */
240     public static ColorModel getRGBdefault() {
241         if (RGBdefault == null) {
242             RGBdefault = new DirectColorModel(32,
243                                               0x00ff0000,       // Red
244                                               0x0000ff00,       // Green
245                                               0x000000ff,       // Blue
246                                               0xff000000        // Alpha
247                                               );
248         }
249         return RGBdefault;
250     }
251 
252     /**
253      * Constructs a <code>ColorModel</code> that translates pixels of the
254      * specified number of bits to color/alpha components.  The color
255      * space is the default RGB <code>ColorSpace</code>, which is sRGB.
256      * Pixel values are assumed to include alpha information.  If color
257      * and alpha information are represented in the pixel value as
258      * separate spatial bands, the color bands are assumed not to be
259      * premultiplied with the alpha value. The transparency type is
260      * java.awt.Transparency.TRANSLUCENT.  The transfer type will be the
261      * smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
262      * or DataBuffer.TYPE_INT that can hold a single pixel
263      * (or DataBuffer.TYPE_UNDEFINED if bits is greater
264      * than 32).  Since this constructor has no information about the
265      * number of bits per color and alpha component, any subclass calling
266      * this constructor should override any method that requires this
267      * information.
268      * @param bits the number of bits of a pixel
269      * @throws IllegalArgumentException if the number
270      *          of bits in <code>bits</code> is less than 1
271      */
272     public ColorModel(int bits) {
273         pixel_bits = bits;
274         if (bits < 1) {
275             throw new IllegalArgumentException("Number of bits must be > 0");
276         }
277         numComponents = 4;
278         numColorComponents = 3;
279         maxBits = bits;
280         // REMIND: make sure transferType is set correctly
281         transferType = ColorModel.getDefaultTransferType(bits);
282     }
283 
284     /**
285      * Constructs a <code>ColorModel</code> that translates pixel values
286      * to color/alpha components.  Color components will be in the
287      * specified <code>ColorSpace</code>. <code>pixel_bits</code> is the
288      * number of bits in the pixel values.  The bits array
289      * specifies the number of significant bits per color and alpha component.
290      * Its length should be the number of components in the
291      * <code>ColorSpace</code> if there is no alpha information in the
292      * pixel values, or one more than this number if there is alpha
293      * information.  <code>hasAlpha</code> indicates whether or not alpha
294      * information is present.  The <code>boolean</code>
295      * <code>isAlphaPremultiplied</code> specifies how to interpret pixel
296      * values in which color and alpha information are represented as
297      * separate spatial bands.  If the <code>boolean</code>
298      * is <code>true</code>, color samples are assumed to have been
299      * multiplied by the alpha sample.  The <code>transparency</code>
300      * specifies what alpha values can be represented by this color model.
301      * The transfer type is the type of primitive array used to represent
302      * pixel values.  Note that the bits array contains the number of
303      * significant bits per color/alpha component after the translation
304      * from pixel values.  For example, for an
305      * <code>IndexColorModel</code> with <code>pixel_bits</code> equal to
306      * 16, the bits array might have four elements with each element set
307      * to 8.
308      * @param pixel_bits the number of bits in the pixel values
309      * @param bits array that specifies the number of significant bits
310      *          per color and alpha component
311      * @param cspace the specified <code>ColorSpace</code>
312      * @param hasAlpha <code>true</code> if alpha information is present;
313      *          <code>false</code> otherwise
314      * @param isAlphaPremultiplied <code>true</code> if color samples are
315      *          assumed to be premultiplied by the alpha samples;
316      *          <code>false</code> otherwise
317      * @param transparency what alpha values can be represented by this
318      *          color model
319      * @param transferType the type of the array used to represent pixel
320      *          values
321      * @throws IllegalArgumentException if the length of
322      *          the bit array is less than the number of color or alpha
323      *          components in this <code>ColorModel</code>, or if the
324      *          transparency is not a valid value.
325      * @throws IllegalArgumentException if the sum of the number
326      *          of bits in <code>bits</code> is less than 1 or if
327      *          any of the elements in <code>bits</code> is less than 0.
328      * @see java.awt.Transparency
329      */
330     protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
331                          boolean hasAlpha,
332                          boolean isAlphaPremultiplied,
333                          int transparency,
334                          int transferType) {
335         colorSpace                = cspace;
336         colorSpaceType            = cspace.getType();
337         numColorComponents        = cspace.getNumComponents();
338         numComponents             = numColorComponents + (hasAlpha ? 1 : 0);
339         supportsAlpha             = hasAlpha;
340         if (bits.length < numComponents) {
341             throw new IllegalArgumentException("Number of color/alpha "+
342                                                "components should be "+
343                                                numComponents+
344                                                " but length of bits array is "+
345                                                bits.length);
346         }
347 
348         // 4186669
349         if (transparency < Transparency.OPAQUE ||
350             transparency > Transparency.TRANSLUCENT)
351         {
352             throw new IllegalArgumentException("Unknown transparency: "+
353                                                transparency);
354         }
355 
356         if (supportsAlpha == false) {
357             this.isAlphaPremultiplied = false;
358             this.transparency = Transparency.OPAQUE;
359         }
360         else {
361             this.isAlphaPremultiplied = isAlphaPremultiplied;
362             this.transparency         = transparency;
363         }
364 
365         nBits = bits.clone();
366         this.pixel_bits = pixel_bits;
367         if (pixel_bits <= 0) {
368             throw new IllegalArgumentException("Number of pixel bits must "+
369                                                "be > 0");
370         }
371         // Check for bits < 0
372         maxBits = 0;
373         for (int i=0; i < bits.length; i++) {
374             // bug 4304697
375             if (bits[i] < 0) {
376                 throw new
377                     IllegalArgumentException("Number of bits must be >= 0");
378             }
379             if (maxBits < bits[i]) {
380                 maxBits = bits[i];
381             }
382         }
383 
384         // Make sure that we don't have all 0-bit components
385         if (maxBits == 0) {
386             throw new IllegalArgumentException("There must be at least "+
387                                                "one component with > 0 "+
388                                               "pixel bits.");
389         }
390 
391         // Save this since we always need to check if it is the default CS
392         if (cspace != ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
393             is_sRGB = false;
394         }
395 
396         // Save the transfer type
397         this.transferType = transferType;
398     }
399 
400     /**
401      * Returns whether or not alpha is supported in this
402      * <code>ColorModel</code>.
403      * @return <code>true</code> if alpha is supported in this
404      * <code>ColorModel</code>; <code>false</code> otherwise.
405      */
406     final public boolean hasAlpha() {
407         return supportsAlpha;
408     }
409 
410     /**
411      * Returns whether or not the alpha has been premultiplied in the
412      * pixel values to be translated by this <code>ColorModel</code>.
413      * If the boolean is <code>true</code>, this <code>ColorModel</code>
414      * is to be used to interpret pixel values in which color and alpha
415      * information are represented as separate spatial bands, and color
416      * samples are assumed to have been multiplied by the
417      * alpha sample.
418      * @return <code>true</code> if the alpha values are premultiplied
419      *          in the pixel values to be translated by this
420      *          <code>ColorModel</code>; <code>false</code> otherwise.
421      */
422     final public boolean isAlphaPremultiplied() {
423         return isAlphaPremultiplied;
424     }
425 
426     /**
427      * Returns the transfer type of this <code>ColorModel</code>.
428      * The transfer type is the type of primitive array used to represent
429      * pixel values as arrays.
430      * @return the transfer type.
431      * @since 1.3
432      */
433     final public int getTransferType() {
434         return transferType;
435     }
436 
437     /**
438      * Returns the number of bits per pixel described by this
439      * <code>ColorModel</code>.
440      * @return the number of bits per pixel.
441      */
442     public int getPixelSize() {
443         return pixel_bits;
444     }
445 
446     /**
447      * Returns the number of bits for the specified color/alpha component.
448      * Color components are indexed in the order specified by the
449      * <code>ColorSpace</code>.  Typically, this order reflects the name
450      * of the color space type. For example, for TYPE_RGB, index 0
451      * corresponds to red, index 1 to green, and index 2
452      * to blue.  If this <code>ColorModel</code> supports alpha, the alpha
453      * component corresponds to the index following the last color
454      * component.
455      * @param componentIdx the index of the color/alpha component
456      * @return the number of bits for the color/alpha component at the
457      *          specified index.
458      * @throws ArrayIndexOutOfBoundsException if <code>componentIdx</code>
459      *         is greater than the number of components or
460      *         less than zero
461      * @throws NullPointerException if the number of bits array is
462      *         <code>null</code>
463      */
464     public int getComponentSize(int componentIdx) {
465         // REMIND:
466         if (nBits == null) {
467             throw new NullPointerException("Number of bits array is null.");
468         }
469 
470         return nBits[componentIdx];
471     }
472 
473     /**
474      * Returns an array of the number of bits per color/alpha component.
475      * The array contains the color components in the order specified by the
476      * <code>ColorSpace</code>, followed by the alpha component, if
477      * present.
478      * @return an array of the number of bits per color/alpha component
479      */
480     public int[] getComponentSize() {
481         if (nBits != null) {
482             return nBits.clone();
483         }
484 
485         return null;
486     }
487 
488     /**
489      * Returns the transparency.  Returns either OPAQUE, BITMASK,
490      * or TRANSLUCENT.
491      * @return the transparency of this <code>ColorModel</code>.
492      * @see Transparency#OPAQUE
493      * @see Transparency#BITMASK
494      * @see Transparency#TRANSLUCENT
495      */
496     public int getTransparency() {
497         return transparency;
498     }
499 
500     /**
501      * Returns the number of components, including alpha, in this
502      * <code>ColorModel</code>.  This is equal to the number of color
503      * components, optionally plus one, if there is an alpha component.
504      * @return the number of components in this <code>ColorModel</code>
505      */
506     public int getNumComponents() {
507         return numComponents;
508     }
509 
510     /**
511      * Returns the number of color components in this
512      * <code>ColorModel</code>.
513      * This is the number of components returned by
514      * {@link ColorSpace#getNumComponents}.
515      * @return the number of color components in this
516      * <code>ColorModel</code>.
517      * @see ColorSpace#getNumComponents
518      */
519     public int getNumColorComponents() {
520         return numColorComponents;
521     }
522 
523     /**
524      * Returns the red color component for the specified pixel, scaled
525      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
526      * is done if necessary.  The pixel value is specified as an int.
527      * An <code>IllegalArgumentException</code> is thrown if pixel
528      * values for this <code>ColorModel</code> are not conveniently
529      * representable as a single int.  The returned value is not a
530      * pre-multiplied value.  For example, if the
531      * alpha is premultiplied, this method divides it out before returning
532      * the value.  If the alpha value is 0, the red value is 0.
533      * @param pixel a specified pixel
534      * @return the value of the red component of the specified pixel.
535      */
536     public abstract int getRed(int pixel);
537 
538     /**
539      * Returns the green color component for the specified pixel, scaled
540      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
541      * is done if necessary.  The pixel value is specified as an int.
542      * An <code>IllegalArgumentException</code> is thrown if pixel
543      * values for this <code>ColorModel</code> are not conveniently
544      * representable as a single int.  The returned value is a non
545      * pre-multiplied value.  For example, if the alpha is premultiplied,
546      * this method divides it out before returning
547      * the value.  If the alpha value is 0, the green value is 0.
548      * @param pixel the specified pixel
549      * @return the value of the green component of the specified pixel.
550      */
551     public abstract int getGreen(int pixel);
552 
553     /**
554      * Returns the blue color component for the specified pixel, scaled
555      * from 0 to 255 in the default RGB ColorSpace, sRGB.  A color conversion
556      * is done if necessary.  The pixel value is specified as an int.
557      * An <code>IllegalArgumentException</code> is thrown if pixel values
558      * for this <code>ColorModel</code> are not conveniently representable
559      * as a single int.  The returned value is a non pre-multiplied
560      * value, for example, if the alpha is premultiplied, this method
561      * divides it out before returning the value.  If the alpha value is
562      * 0, the blue value is 0.
563      * @param pixel the specified pixel
564      * @return the value of the blue component of the specified pixel.
565      */
566     public abstract int getBlue(int pixel);
567 
568     /**
569      * Returns the alpha component for the specified pixel, scaled
570      * from 0 to 255.  The pixel value is specified as an int.
571      * An <code>IllegalArgumentException</code> is thrown if pixel
572      * values for this <code>ColorModel</code> are not conveniently
573      * representable as a single int.
574      * @param pixel the specified pixel
575      * @return the value of alpha component of the specified pixel.
576      */
577     public abstract int getAlpha(int pixel);
578 
579     /**
580      * Returns the color/alpha components of the pixel in the default
581      * RGB color model format.  A color conversion is done if necessary.
582      * The pixel value is specified as an int.
583      * An <code>IllegalArgumentException</code> thrown if pixel values
584      * for this <code>ColorModel</code> are not conveniently representable
585      * as a single int.  The returned value is in a non
586      * pre-multiplied format. For example, if the alpha is premultiplied,
587      * this method divides it out of the color components.  If the alpha
588      * value is 0, the color values are 0.
589      * @param pixel the specified pixel
590      * @return the RGB value of the color/alpha components of the
591      *          specified pixel.
592      * @see ColorModel#getRGBdefault
593      */
594     public int getRGB(int pixel) {
595         return (getAlpha(pixel) << 24)
596             | (getRed(pixel) << 16)
597             | (getGreen(pixel) << 8)
598             | (getBlue(pixel) << 0);
599     }
600 
601     /**
602      * Returns the red color component for the specified pixel, scaled
603      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
604      * color conversion is done if necessary.  The pixel value is
605      * specified by an array of data elements of type transferType passed
606      * in as an object reference.  The returned value is a non
607      * pre-multiplied value.  For example, if alpha is premultiplied,
608      * this method divides it out before returning
609      * the value.  If the alpha value is 0, the red value is 0.
610      * If <code>inData</code> is not a primitive array of type
611      * transferType, a <code>ClassCastException</code> is thrown.  An
612      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
613      * <code>inData</code> is not large enough to hold a pixel value for
614      * this <code>ColorModel</code>.
615      * If this <code>transferType</code> is not supported, a
616      * <code>UnsupportedOperationException</code> will be
617      * thrown.  Since
618      * <code>ColorModel</code> is an abstract class, any instance
619      * must be an instance of a subclass.  Subclasses inherit the
620      * implementation of this method and if they don't override it, this
621      * method throws an exception if the subclass uses a
622      * <code>transferType</code> other than
623      * <code>DataBuffer.TYPE_BYTE</code>,
624      * <code>DataBuffer.TYPE_USHORT</code>, or
625      * <code>DataBuffer.TYPE_INT</code>.
626      * @param inData an array of pixel values
627      * @return the value of the red component of the specified pixel.
628      * @throws ClassCastException if <code>inData</code>
629      *  is not a primitive array of type <code>transferType</code>
630      * @throws ArrayIndexOutOfBoundsException if
631      *  <code>inData</code> is not large enough to hold a pixel value
632      *  for this <code>ColorModel</code>
633      * @throws UnsupportedOperationException if this
634      *  <code>tranferType</code> is not supported by this
635      *  <code>ColorModel</code>
636      */
637     public int getRed(Object inData) {
638         int pixel=0,length=0;
639         switch (transferType) {
640             case DataBuffer.TYPE_BYTE:
641                byte bdata[] = (byte[])inData;
642                pixel = bdata[0] & 0xff;
643                length = bdata.length;
644             break;
645             case DataBuffer.TYPE_USHORT:
646                short sdata[] = (short[])inData;
647                pixel = sdata[0] & 0xffff;
648                length = sdata.length;
649             break;
650             case DataBuffer.TYPE_INT:
651                int idata[] = (int[])inData;
652                pixel = idata[0];
653                length = idata.length;
654             break;
655             default:
656                throw new UnsupportedOperationException("This method has not been "+
657                    "implemented for transferType " + transferType);
658         }
659         if (length == 1) {
660             return getRed(pixel);
661         }
662         else {
663             throw new UnsupportedOperationException
664                 ("This method is not supported by this color model");
665         }
666     }
667 
668     /**
669      * Returns the green color component for the specified pixel, scaled
670      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
671      * color conversion is done if necessary.  The pixel value is
672      * specified by an array of data elements of type transferType passed
673      * in as an object reference.  The returned value will be a non
674      * pre-multiplied value.  For example, if the alpha is premultiplied,
675      * this method divides it out before returning the value.  If the
676      * alpha value is 0, the green value is 0.  If <code>inData</code> is
677      * not a primitive array of type transferType, a
678      * <code>ClassCastException</code> is thrown.  An
679      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
680      * <code>inData</code> is not large enough to hold a pixel value for
681      * this <code>ColorModel</code>.
682      * If this <code>transferType</code> is not supported, a
683      * <code>UnsupportedOperationException</code> will be
684      * thrown.  Since
685      * <code>ColorModel</code> is an abstract class, any instance
686      * must be an instance of a subclass.  Subclasses inherit the
687      * implementation of this method and if they don't override it, this
688      * method throws an exception if the subclass uses a
689      * <code>transferType</code> other than
690      * <code>DataBuffer.TYPE_BYTE</code>,
691      * <code>DataBuffer.TYPE_USHORT</code>, or
692      * <code>DataBuffer.TYPE_INT</code>.
693      * @param inData an array of pixel values
694      * @return the value of the green component of the specified pixel.
695      * @throws ClassCastException if <code>inData</code>
696      *  is not a primitive array of type <code>transferType</code>
697      * @throws ArrayIndexOutOfBoundsException if
698      *  <code>inData</code> is not large enough to hold a pixel value
699      *  for this <code>ColorModel</code>
700      * @throws UnsupportedOperationException if this
701      *  <code>tranferType</code> is not supported by this
702      *  <code>ColorModel</code>
703      */
704     public int getGreen(Object inData) {
705         int pixel=0,length=0;
706         switch (transferType) {
707             case DataBuffer.TYPE_BYTE:
708                byte bdata[] = (byte[])inData;
709                pixel = bdata[0] & 0xff;
710                length = bdata.length;
711             break;
712             case DataBuffer.TYPE_USHORT:
713                short sdata[] = (short[])inData;
714                pixel = sdata[0] & 0xffff;
715                length = sdata.length;
716             break;
717             case DataBuffer.TYPE_INT:
718                int idata[] = (int[])inData;
719                pixel = idata[0];
720                length = idata.length;
721             break;
722             default:
723                throw new UnsupportedOperationException("This method has not been "+
724                    "implemented for transferType " + transferType);
725         }
726         if (length == 1) {
727             return getGreen(pixel);
728         }
729         else {
730             throw new UnsupportedOperationException
731                 ("This method is not supported by this color model");
732         }
733     }
734 
735     /**
736      * Returns the blue color component for the specified pixel, scaled
737      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
738      * color conversion is done if necessary.  The pixel value is
739      * specified by an array of data elements of type transferType passed
740      * in as an object reference.  The returned value is a non
741      * pre-multiplied value.  For example, if the alpha is premultiplied,
742      * this method divides it out before returning the value.  If the
743      * alpha value is 0, the blue value will be 0.  If
744      * <code>inData</code> is not a primitive array of type transferType,
745      * a <code>ClassCastException</code> is thrown.  An
746      * <code>ArrayIndexOutOfBoundsException</code> is
747      * thrown if <code>inData</code> is not large enough to hold a pixel
748      * value for this <code>ColorModel</code>.
749      * If this <code>transferType</code> is not supported, a
750      * <code>UnsupportedOperationException</code> will be
751      * thrown.  Since
752      * <code>ColorModel</code> is an abstract class, any instance
753      * must be an instance of a subclass.  Subclasses inherit the
754      * implementation of this method and if they don't override it, this
755      * method throws an exception if the subclass uses a
756      * <code>transferType</code> other than
757      * <code>DataBuffer.TYPE_BYTE</code>,
758      * <code>DataBuffer.TYPE_USHORT</code>, or
759      * <code>DataBuffer.TYPE_INT</code>.
760      * @param inData an array of pixel values
761      * @return the value of the blue component of the specified pixel.
762      * @throws ClassCastException if <code>inData</code>
763      *  is not a primitive array of type <code>transferType</code>
764      * @throws ArrayIndexOutOfBoundsException if
765      *  <code>inData</code> is not large enough to hold a pixel value
766      *  for this <code>ColorModel</code>
767      * @throws UnsupportedOperationException if this
768      *  <code>tranferType</code> is not supported by this
769      *  <code>ColorModel</code>
770      */
771     public int getBlue(Object inData) {
772         int pixel=0,length=0;
773         switch (transferType) {
774             case DataBuffer.TYPE_BYTE:
775                byte bdata[] = (byte[])inData;
776                pixel = bdata[0] & 0xff;
777                length = bdata.length;
778             break;
779             case DataBuffer.TYPE_USHORT:
780                short sdata[] = (short[])inData;
781                pixel = sdata[0] & 0xffff;
782                length = sdata.length;
783             break;
784             case DataBuffer.TYPE_INT:
785                int idata[] = (int[])inData;
786                pixel = idata[0];
787                length = idata.length;
788             break;
789             default:
790                throw new UnsupportedOperationException("This method has not been "+
791                    "implemented for transferType " + transferType);
792         }
793         if (length == 1) {
794             return getBlue(pixel);
795         }
796         else {
797             throw new UnsupportedOperationException
798                 ("This method is not supported by this color model");
799         }
800     }
801 
802     /**
803      * Returns the alpha component for the specified pixel, scaled
804      * from 0 to 255.  The pixel value is specified by an array of data
805      * elements of type transferType passed in as an object reference.
806      * If inData is not a primitive array of type transferType, a
807      * <code>ClassCastException</code> is thrown.  An
808      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
809      * <code>inData</code> is not large enough to hold a pixel value for
810      * this <code>ColorModel</code>.
811      * If this <code>transferType</code> is not supported, a
812      * <code>UnsupportedOperationException</code> will be
813      * thrown.  Since
814      * <code>ColorModel</code> is an abstract class, any instance
815      * must be an instance of a subclass.  Subclasses inherit the
816      * implementation of this method and if they don't override it, this
817      * method throws an exception if the subclass uses a
818      * <code>transferType</code> other than
819      * <code>DataBuffer.TYPE_BYTE</code>,
820      * <code>DataBuffer.TYPE_USHORT</code>, or
821      * <code>DataBuffer.TYPE_INT</code>.
822      * @param inData the specified pixel
823      * @return the alpha component of the specified pixel, scaled from
824      * 0 to 255.
825      * @throws ClassCastException if <code>inData</code>
826      *  is not a primitive array of type <code>transferType</code>
827      * @throws ArrayIndexOutOfBoundsException if
828      *  <code>inData</code> is not large enough to hold a pixel value
829      *  for this <code>ColorModel</code>
830      * @throws UnsupportedOperationException if this
831      *  <code>tranferType</code> is not supported by this
832      *  <code>ColorModel</code>
833      */
834     public int getAlpha(Object inData) {
835         int pixel=0,length=0;
836         switch (transferType) {
837             case DataBuffer.TYPE_BYTE:
838                byte bdata[] = (byte[])inData;
839                pixel = bdata[0] & 0xff;
840                length = bdata.length;
841             break;
842             case DataBuffer.TYPE_USHORT:
843                short sdata[] = (short[])inData;
844                pixel = sdata[0] & 0xffff;
845                length = sdata.length;
846             break;
847             case DataBuffer.TYPE_INT:
848                int idata[] = (int[])inData;
849                pixel = idata[0];
850                length = idata.length;
851             break;
852             default:
853                throw new UnsupportedOperationException("This method has not been "+
854                    "implemented for transferType " + transferType);
855         }
856         if (length == 1) {
857             return getAlpha(pixel);
858         }
859         else {
860             throw new UnsupportedOperationException
861                 ("This method is not supported by this color model");
862         }
863     }
864 
865     /**
866      * Returns the color/alpha components for the specified pixel in the
867      * default RGB color model format.  A color conversion is done if
868      * necessary.  The pixel value is specified by an array of data
869      * elements of type transferType passed in as an object reference.
870      * If inData is not a primitive array of type transferType, a
871      * <code>ClassCastException</code> is thrown.  An
872      * <code>ArrayIndexOutOfBoundsException</code> is
873      * thrown if <code>inData</code> is not large enough to hold a pixel
874      * value for this <code>ColorModel</code>.
875      * The returned value will be in a non pre-multiplied format, i.e. if
876      * the alpha is premultiplied, this method will divide it out of the
877      * color components (if the alpha value is 0, the color values will be 0).
878      * @param inData the specified pixel
879      * @return the color and alpha components of the specified pixel.
880      * @see ColorModel#getRGBdefault
881      */
882     public int getRGB(Object inData) {
883         return (getAlpha(inData) << 24)
884             | (getRed(inData) << 16)
885             | (getGreen(inData) << 8)
886             | (getBlue(inData) << 0);
887     }
888 
889     /**
890      * Returns a data element array representation of a pixel in this
891      * <code>ColorModel</code>, given an integer pixel representation in
892      * the default RGB color model.
893      * This array can then be passed to the
894      * {@link WritableRaster#setDataElements} method of
895      * a {@link WritableRaster} object.  If the pixel variable is
896      * <code>null</code>, a new array will be allocated.  If
897      * <code>pixel</code> is not
898      * <code>null</code>, it must be a primitive array of type
899      * <code>transferType</code>; otherwise, a
900      * <code>ClassCastException</code> is thrown.  An
901      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
902      * <code>pixel</code> is
903      * not large enough to hold a pixel value for this
904      * <code>ColorModel</code>. The pixel array is returned.
905      * If this <code>transferType</code> is not supported, a
906      * <code>UnsupportedOperationException</code> will be
907      * thrown.  Since <code>ColorModel</code> is an abstract class,
908      * any instance is an instance of a subclass.  Subclasses must
909      * override this method since the implementation in this abstract
910      * class throws an <code>UnsupportedOperationException</code>.
911      * @param rgb the integer pixel representation in the default RGB
912      * color model
913      * @param pixel the specified pixel
914      * @return an array representation of the specified pixel in this
915      *  <code>ColorModel</code>.
916      * @throws ClassCastException if <code>pixel</code>
917      *  is not a primitive array of type <code>transferType</code>
918      * @throws ArrayIndexOutOfBoundsException if
919      *  <code>pixel</code> is not large enough to hold a pixel value
920      *  for this <code>ColorModel</code>
921      * @throws UnsupportedOperationException if this
922      *  method is not supported by this <code>ColorModel</code>
923      * @see WritableRaster#setDataElements
924      * @see SampleModel#setDataElements
925      */
926     public Object getDataElements(int rgb, Object pixel) {
927         throw new UnsupportedOperationException
928             ("This method is not supported by this color model.");
929     }
930 
931     /**
932      * Returns an array of unnormalized color/alpha components given a pixel
933      * in this <code>ColorModel</code>.  The pixel value is specified as
934      * an <code>int</code>.  An <code>IllegalArgumentException</code>
935      * will be thrown if pixel values for this <code>ColorModel</code> are
936      * not conveniently representable as a single <code>int</code> or if
937      * color component values for this <code>ColorModel</code> are not
938      * conveniently representable in the unnormalized form.
939      * For example, this method can be used to retrieve the
940      * components for a specific pixel value in a
941      * <code>DirectColorModel</code>.  If the components array is
942      * <code>null</code>, a new array will be allocated.  The
943      * components array will be returned.  Color/alpha components are
944      * stored in the components array starting at <code>offset</code>
945      * (even if the array is allocated by this method).  An
946      * <code>ArrayIndexOutOfBoundsException</code> is thrown if  the
947      * components array is not <code>null</code> and is not large
948      * enough to hold all the color and alpha components (starting at offset).
949      * Since <code>ColorModel</code> is an abstract class,
950      * any instance is an instance of a subclass.  Subclasses must
951      * override this method since the implementation in this abstract
952      * class throws an <code>UnsupportedOperationException</code>.
953      * @param pixel the specified pixel
954      * @param components the array to receive the color and alpha
955      * components of the specified pixel
956      * @param offset the offset into the <code>components</code> array at
957      * which to start storing the color and alpha components
958      * @return an array containing the color and alpha components of the
959      * specified pixel starting at the specified offset.
960      * @throws UnsupportedOperationException if this
961      *          method is not supported by this <code>ColorModel</code>
962      */
963     public int[] getComponents(int pixel, int[] components, int offset) {
964         throw new UnsupportedOperationException
965             ("This method is not supported by this color model.");
966     }
967 
968     /**
969      * Returns an array of unnormalized color/alpha components given a pixel
970      * in this <code>ColorModel</code>.  The pixel value is specified by
971      * an array of data elements of type transferType passed in as an
972      * object reference.  If <code>pixel</code> is not a primitive array
973      * of type transferType, a <code>ClassCastException</code> is thrown.
974      * An <code>IllegalArgumentException</code> will be thrown if color
975      * component values for this <code>ColorModel</code> are not
976      * conveniently representable in the unnormalized form.
977      * An <code>ArrayIndexOutOfBoundsException</code> is
978      * thrown if <code>pixel</code> is not large enough to hold a pixel
979      * value for this <code>ColorModel</code>.
980      * This method can be used to retrieve the components for a specific
981      * pixel value in any <code>ColorModel</code>.  If the components
982      * array is <code>null</code>, a new array will be allocated.  The
983      * components array will be returned.  Color/alpha components are
984      * stored in the <code>components</code> array starting at
985      * <code>offset</code> (even if the array is allocated by this
986      * method).  An <code>ArrayIndexOutOfBoundsException</code>
987      * is thrown if  the components array is not <code>null</code> and is
988      * not large enough to hold all the color and alpha components
989      * (starting at <code>offset</code>).
990      * Since <code>ColorModel</code> is an abstract class,
991      * any instance is an instance of a subclass.  Subclasses must
992      * override this method since the implementation in this abstract
993      * class throws an <code>UnsupportedOperationException</code>.
994      * @param pixel the specified pixel
995      * @param components an array that receives the color and alpha
996      * components of the specified pixel
997      * @param offset the index into the <code>components</code> array at
998      * which to begin storing the color and alpha components of the
999      * specified pixel
1000      * @return an array containing the color and alpha components of the
1001      * specified pixel starting at the specified offset.
1002      * @throws UnsupportedOperationException if this
1003      *          method is not supported by this <code>ColorModel</code>
1004      */
1005     public int[] getComponents(Object pixel, int[] components, int offset) {
1006         throw new UnsupportedOperationException
1007             ("This method is not supported by this color model.");
1008     }
1009 
1010     /**
1011      * Returns an array of all of the color/alpha components in unnormalized
1012      * form, given a normalized component array.  Unnormalized components
1013      * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1014      * n is the number of bits for a particular component.  Normalized
1015      * components are float values between a per component minimum and
1016      * maximum specified by the <code>ColorSpace</code> object for this
1017      * <code>ColorModel</code>.  An <code>IllegalArgumentException</code>
1018      * will be thrown if color component values for this
1019      * <code>ColorModel</code> are not conveniently representable in the
1020      * unnormalized form.  If the
1021      * <code>components</code> array is <code>null</code>, a new array
1022      * will be allocated.  The <code>components</code> array will
1023      * be returned.  Color/alpha components are stored in the
1024      * <code>components</code> array starting at <code>offset</code> (even
1025      * if the array is allocated by this method). An
1026      * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1027      * <code>components</code> array is not <code>null</code> and is not
1028      * large enough to hold all the color and alpha
1029      * components (starting at <code>offset</code>).  An
1030      * <code>IllegalArgumentException</code> is thrown if the
1031      * <code>normComponents</code> array is not large enough to hold
1032      * all the color and alpha components starting at
1033      * <code>normOffset</code>.
1034      * @param normComponents an array containing normalized components
1035      * @param normOffset the offset into the <code>normComponents</code>
1036      * array at which to start retrieving normalized components
1037      * @param components an array that receives the components from
1038      * <code>normComponents</code>
1039      * @param offset the index into <code>components</code> at which to
1040      * begin storing normalized components from
1041      * <code>normComponents</code>
1042      * @return an array containing unnormalized color and alpha
1043      * components.
1044      * @throws IllegalArgumentException If the component values for this
1045      * <CODE>ColorModel</CODE> are not conveniently representable in the
1046      * unnormalized form.
1047      * @throws IllegalArgumentException if the length of
1048      *          <code>normComponents</code> minus <code>normOffset</code>
1049      *          is less than <code>numComponents</code>
1050      * @throws UnsupportedOperationException if the
1051      *          constructor of this <code>ColorModel</code> called the
1052      *          <code>super(bits)</code> constructor, but did not
1053      *          override this method.  See the constructor,
1054      *          {@link #ColorModel(int)}.
1055      */
1056     public int[] getUnnormalizedComponents(float[] normComponents,
1057                                            int normOffset,
1058                                            int[] components, int offset) {
1059         // Make sure that someone isn't using a custom color model
1060         // that called the super(bits) constructor.
1061         if (colorSpace == null) {
1062             throw new UnsupportedOperationException("This method is not supported "+
1063                                         "by this color model.");
1064         }
1065 
1066         if (nBits == null) {
1067             throw new UnsupportedOperationException ("This method is not supported.  "+
1068                                          "Unable to determine #bits per "+
1069                                          "component.");
1070         }
1071         if ((normComponents.length - normOffset) < numComponents) {
1072             throw new
1073                 IllegalArgumentException(
1074                         "Incorrect number of components.  Expecting "+
1075                         numComponents);
1076         }
1077 
1078         if (components == null) {
1079             components = new int[offset+numComponents];
1080         }
1081 
1082         if (supportsAlpha && isAlphaPremultiplied) {
1083             float normAlpha = normComponents[normOffset+numColorComponents];
1084             for (int i=0; i < numColorComponents; i++) {
1085                 components[offset+i] = (int) (normComponents[normOffset+i]
1086                                               * ((1<<nBits[i]) - 1)
1087                                               * normAlpha + 0.5f);
1088             }
1089             components[offset+numColorComponents] = (int)
1090                 (normAlpha * ((1<<nBits[numColorComponents]) - 1) + 0.5f);
1091         }
1092         else {
1093             for (int i=0; i < numComponents; i++) {
1094                 components[offset+i] = (int) (normComponents[normOffset+i]
1095                                               * ((1<<nBits[i]) - 1) + 0.5f);
1096             }
1097         }
1098 
1099         return components;
1100     }
1101 
1102     /**
1103      * Returns an array of all of the color/alpha components in normalized
1104      * form, given an unnormalized component array.  Unnormalized components
1105      * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1106      * n is the number of bits for a particular component.  Normalized
1107      * components are float values between a per component minimum and
1108      * maximum specified by the <code>ColorSpace</code> object for this
1109      * <code>ColorModel</code>.  An <code>IllegalArgumentException</code>
1110      * will be thrown if color component values for this
1111      * <code>ColorModel</code> are not conveniently representable in the
1112      * unnormalized form.  If the
1113      * <code>normComponents</code> array is <code>null</code>, a new array
1114      * will be allocated.  The <code>normComponents</code> array
1115      * will be returned.  Color/alpha components are stored in the
1116      * <code>normComponents</code> array starting at
1117      * <code>normOffset</code> (even if the array is allocated by this
1118      * method).  An <code>ArrayIndexOutOfBoundsException</code> is thrown
1119      * if the <code>normComponents</code> array is not <code>null</code>
1120      * and is not large enough to hold all the color and alpha components
1121      * (starting at <code>normOffset</code>).  An
1122      * <code>IllegalArgumentException</code> is thrown if the
1123      * <code>components</code> array is not large enough to hold all the
1124      * color and alpha components starting at <code>offset</code>.
1125      * <p>
1126      * Since <code>ColorModel</code> is an abstract class,
1127      * any instance is an instance of a subclass.  The default implementation
1128      * of this method in this abstract class assumes that component values
1129      * for this class are conveniently representable in the unnormalized
1130      * form.  Therefore, subclasses which may
1131      * have instances which do not support the unnormalized form must
1132      * override this method.
1133      * @param components an array containing unnormalized components
1134      * @param offset the offset into the <code>components</code> array at
1135      * which to start retrieving unnormalized components
1136      * @param normComponents an array that receives the normalized components
1137      * @param normOffset the index into <code>normComponents</code> at
1138      * which to begin storing normalized components
1139      * @return an array containing normalized color and alpha
1140      * components.
1141      * @throws IllegalArgumentException If the component values for this
1142      * <CODE>ColorModel</CODE> are not conveniently representable in the
1143      * unnormalized form.
1144      * @throws UnsupportedOperationException if the
1145      *          constructor of this <code>ColorModel</code> called the
1146      *          <code>super(bits)</code> constructor, but did not
1147      *          override this method.  See the constructor,
1148      *          {@link #ColorModel(int)}.
1149      * @throws UnsupportedOperationException if this method is unable
1150      *          to determine the number of bits per component
1151      */
1152     public float[] getNormalizedComponents(int[] components, int offset,
1153                                            float[] normComponents,
1154                                            int normOffset) {
1155         // Make sure that someone isn't using a custom color model
1156         // that called the super(bits) constructor.
1157         if (colorSpace == null) {
1158             throw new UnsupportedOperationException("This method is not supported by "+
1159                                         "this color model.");
1160         }
1161         if (nBits == null) {
1162             throw new UnsupportedOperationException ("This method is not supported.  "+
1163                                          "Unable to determine #bits per "+
1164                                          "component.");
1165         }
1166 
1167         if ((components.length - offset) < numComponents) {
1168             throw new
1169                 IllegalArgumentException(
1170                         "Incorrect number of components.  Expecting "+
1171                         numComponents);
1172         }
1173 
1174         if (normComponents == null) {
1175             normComponents = new float[numComponents+normOffset];
1176         }
1177 
1178         if (supportsAlpha && isAlphaPremultiplied) {
1179             // Normalized coordinates are non premultiplied
1180             float normAlpha = (float)components[offset+numColorComponents];
1181             normAlpha /= (float) ((1<<nBits[numColorComponents]) - 1);
1182             if (normAlpha != 0.0f) {
1183                 for (int i=0; i < numColorComponents; i++) {
1184                     normComponents[normOffset+i] =
1185                         ((float) components[offset+i]) /
1186                         (normAlpha * ((float) ((1<<nBits[i]) - 1)));
1187                 }
1188             } else {
1189                 for (int i=0; i < numColorComponents; i++) {
1190                     normComponents[normOffset+i] = 0.0f;
1191                 }
1192             }
1193             normComponents[normOffset+numColorComponents] = normAlpha;
1194         }
1195         else {
1196             for (int i=0; i < numComponents; i++) {
1197                 normComponents[normOffset+i] = ((float) components[offset+i]) /
1198                                                ((float) ((1<<nBits[i]) - 1));
1199             }
1200         }
1201 
1202         return normComponents;
1203     }
1204 
1205     /**
1206      * Returns a pixel value represented as an <code>int</code> in this
1207      * <code>ColorModel</code>, given an array of unnormalized color/alpha
1208      * components.  This method will throw an
1209      * <code>IllegalArgumentException</code> if component values for this
1210      * <code>ColorModel</code> are not conveniently representable as a
1211      * single <code>int</code> or if color component values for this
1212      * <code>ColorModel</code> are not conveniently representable in the
1213      * unnormalized form.  An
1214      * <code>ArrayIndexOutOfBoundsException</code> is thrown if  the
1215      * <code>components</code> array is not large enough to hold all the
1216      * color and alpha components (starting at <code>offset</code>).
1217      * Since <code>ColorModel</code> is an abstract class,
1218      * any instance is an instance of a subclass.  Subclasses must
1219      * override this method since the implementation in this abstract
1220      * class throws an <code>UnsupportedOperationException</code>.
1221      * @param components an array of unnormalized color and alpha
1222      * components
1223      * @param offset the index into <code>components</code> at which to
1224      * begin retrieving the color and alpha components
1225      * @return an <code>int</code> pixel value in this
1226      * <code>ColorModel</code> corresponding to the specified components.
1227      * @throws IllegalArgumentException if
1228      *  pixel values for this <code>ColorModel</code> are not
1229      *  conveniently representable as a single <code>int</code>
1230      * @throws IllegalArgumentException if
1231      *  component values for this <code>ColorModel</code> are not
1232      *  conveniently representable in the unnormalized form
1233      * @throws ArrayIndexOutOfBoundsException if
1234      *  the <code>components</code> array is not large enough to
1235      *  hold all of the color and alpha components starting at
1236      *  <code>offset</code>
1237      * @throws UnsupportedOperationException if this
1238      *  method is not supported by this <code>ColorModel</code>
1239      */
1240     public int getDataElement(int[] components, int offset) {
1241         throw new UnsupportedOperationException("This method is not supported "+
1242                                     "by this color model.");
1243     }
1244 
1245     /**
1246      * Returns a data element array representation of a pixel in this
1247      * <code>ColorModel</code>, given an array of unnormalized color/alpha
1248      * components.  This array can then be passed to the
1249      * <code>setDataElements</code> method of a <code>WritableRaster</code>
1250      * object.  This method will throw an <code>IllegalArgumentException</code>
1251      * if color component values for this <code>ColorModel</code> are not
1252      * conveniently representable in the unnormalized form.
1253      * An <code>ArrayIndexOutOfBoundsException</code> is thrown
1254      * if the <code>components</code> array is not large enough to hold
1255      * all the color and alpha components (starting at
1256      * <code>offset</code>).  If the <code>obj</code> variable is
1257      * <code>null</code>, a new array will be allocated.  If
1258      * <code>obj</code> is not <code>null</code>, it must be a primitive
1259      * array of type transferType; otherwise, a
1260      * <code>ClassCastException</code> is thrown.  An
1261      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
1262      * <code>obj</code> is not large enough to hold a pixel value for this
1263      * <code>ColorModel</code>.
1264      * Since <code>ColorModel</code> is an abstract class,
1265      * any instance is an instance of a subclass.  Subclasses must
1266      * override this method since the implementation in this abstract
1267      * class throws an <code>UnsupportedOperationException</code>.
1268      * @param components an array of unnormalized color and alpha
1269      * components
1270      * @param offset the index into <code>components</code> at which to
1271      * begin retrieving color and alpha components
1272      * @param obj the <code>Object</code> representing an array of color
1273      * and alpha components
1274      * @return an <code>Object</code> representing an array of color and
1275      * alpha components.
1276      * @throws ClassCastException if <code>obj</code>
1277      *  is not a primitive array of type <code>transferType</code>
1278      * @throws ArrayIndexOutOfBoundsException if
1279      *  <code>obj</code> is not large enough to hold a pixel value
1280      *  for this <code>ColorModel</code> or the <code>components</code>
1281      *  array is not large enough to hold all of the color and alpha
1282      *  components starting at <code>offset</code>
1283      * @throws IllegalArgumentException if
1284      *  component values for this <code>ColorModel</code> are not
1285      *  conveniently representable in the unnormalized form
1286      * @throws UnsupportedOperationException if this
1287      *  method is not supported by this <code>ColorModel</code>
1288      * @see WritableRaster#setDataElements
1289      * @see SampleModel#setDataElements
1290      */
1291     public Object getDataElements(int[] components, int offset, Object obj) {
1292         throw new UnsupportedOperationException("This method has not been implemented "+
1293                                     "for this color model.");
1294     }
1295 
1296     /**
1297      * Returns a pixel value represented as an <code>int</code> in this
1298      * <code>ColorModel</code>, given an array of normalized color/alpha
1299      * components.  This method will throw an
1300      * <code>IllegalArgumentException</code> if pixel values for this
1301      * <code>ColorModel</code> are not conveniently representable as a
1302      * single <code>int</code>.  An
1303      * <code>ArrayIndexOutOfBoundsException</code> is thrown if  the
1304      * <code>normComponents</code> array is not large enough to hold all the
1305      * color and alpha components (starting at <code>normOffset</code>).
1306      * Since <code>ColorModel</code> is an abstract class,
1307      * any instance is an instance of a subclass.  The default implementation
1308      * of this method in this abstract class first converts from the
1309      * normalized form to the unnormalized form and then calls
1310      * <code>getDataElement(int[], int)</code>.  Subclasses which may
1311      * have instances which do not support the unnormalized form must
1312      * override this method.
1313      * @param normComponents an array of normalized color and alpha
1314      * components
1315      * @param normOffset the index into <code>normComponents</code> at which to
1316      * begin retrieving the color and alpha components
1317      * @return an <code>int</code> pixel value in this
1318      * <code>ColorModel</code> corresponding to the specified components.
1319      * @throws IllegalArgumentException if
1320      *  pixel values for this <code>ColorModel</code> are not
1321      *  conveniently representable as a single <code>int</code>
1322      * @throws ArrayIndexOutOfBoundsException if
1323      *  the <code>normComponents</code> array is not large enough to
1324      *  hold all of the color and alpha components starting at
1325      *  <code>normOffset</code>
1326      * @since 1.4
1327      */
1328     public int getDataElement(float[] normComponents, int normOffset) {
1329         int components[] = getUnnormalizedComponents(normComponents,
1330                                                      normOffset, null, 0);
1331         return getDataElement(components, 0);
1332     }
1333 
1334     /**
1335      * Returns a data element array representation of a pixel in this
1336      * <code>ColorModel</code>, given an array of normalized color/alpha
1337      * components.  This array can then be passed to the
1338      * <code>setDataElements</code> method of a <code>WritableRaster</code>
1339      * object.  An <code>ArrayIndexOutOfBoundsException</code> is thrown
1340      * if the <code>normComponents</code> array is not large enough to hold
1341      * all the color and alpha components (starting at
1342      * <code>normOffset</code>).  If the <code>obj</code> variable is
1343      * <code>null</code>, a new array will be allocated.  If
1344      * <code>obj</code> is not <code>null</code>, it must be a primitive
1345      * array of type transferType; otherwise, a
1346      * <code>ClassCastException</code> is thrown.  An
1347      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
1348      * <code>obj</code> is not large enough to hold a pixel value for this
1349      * <code>ColorModel</code>.
1350      * Since <code>ColorModel</code> is an abstract class,
1351      * any instance is an instance of a subclass.  The default implementation
1352      * of this method in this abstract class first converts from the
1353      * normalized form to the unnormalized form and then calls
1354      * <code>getDataElement(int[], int, Object)</code>.  Subclasses which may
1355      * have instances which do not support the unnormalized form must
1356      * override this method.
1357      * @param normComponents an array of normalized color and alpha
1358      * components
1359      * @param normOffset the index into <code>normComponents</code> at which to
1360      * begin retrieving color and alpha components
1361      * @param obj a primitive data array to hold the returned pixel
1362      * @return an <code>Object</code> which is a primitive data array
1363      * representation of a pixel
1364      * @throws ClassCastException if <code>obj</code>
1365      *  is not a primitive array of type <code>transferType</code>
1366      * @throws ArrayIndexOutOfBoundsException if
1367      *  <code>obj</code> is not large enough to hold a pixel value
1368      *  for this <code>ColorModel</code> or the <code>normComponents</code>
1369      *  array is not large enough to hold all of the color and alpha
1370      *  components starting at <code>normOffset</code>
1371      * @see WritableRaster#setDataElements
1372      * @see SampleModel#setDataElements
1373      * @since 1.4
1374      */
1375     public Object getDataElements(float[] normComponents, int normOffset,
1376                                   Object obj) {
1377         int components[] = getUnnormalizedComponents(normComponents,
1378                                                      normOffset, null, 0);
1379         return getDataElements(components, 0, obj);
1380     }
1381 
1382     /**
1383      * Returns an array of all of the color/alpha components in normalized
1384      * form, given a pixel in this <code>ColorModel</code>.  The pixel
1385      * value is specified by an array of data elements of type transferType
1386      * passed in as an object reference.  If pixel is not a primitive array
1387      * of type transferType, a <code>ClassCastException</code> is thrown.
1388      * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
1389      * <code>pixel</code> is not large enough to hold a pixel value for this
1390      * <code>ColorModel</code>.
1391      * Normalized components are float values between a per component minimum
1392      * and maximum specified by the <code>ColorSpace</code> object for this
1393      * <code>ColorModel</code>.  If the
1394      * <code>normComponents</code> array is <code>null</code>, a new array
1395      * will be allocated.  The <code>normComponents</code> array
1396      * will be returned.  Color/alpha components are stored in the
1397      * <code>normComponents</code> array starting at
1398      * <code>normOffset</code> (even if the array is allocated by this
1399      * method).  An <code>ArrayIndexOutOfBoundsException</code> is thrown
1400      * if the <code>normComponents</code> array is not <code>null</code>
1401      * and is not large enough to hold all the color and alpha components
1402      * (starting at <code>normOffset</code>).
1403      * Since <code>ColorModel</code> is an abstract class,
1404      * any instance is an instance of a subclass.  The default implementation
1405      * of this method in this abstract class first retrieves color and alpha
1406      * components in the unnormalized form using
1407      * <code>getComponents(Object, int[], int)</code> and then calls
1408      * <code>getNormalizedComponents(int[], int, float[], int)</code>.
1409      * Subclasses which may
1410      * have instances which do not support the unnormalized form must
1411      * override this method.
1412      * @param pixel the specified pixel
1413      * @param normComponents an array to receive the normalized components
1414      * @param normOffset the offset into the <code>normComponents</code>
1415      * array at which to start storing normalized components
1416      * @return an array containing normalized color and alpha
1417      * components.
1418      * @throws ClassCastException if <code>pixel</code> is not a primitive
1419      *          array of type transferType
1420      * @throws ArrayIndexOutOfBoundsException if
1421      *          <code>normComponents</code> is not large enough to hold all
1422      *          color and alpha components starting at <code>normOffset</code>
1423      * @throws ArrayIndexOutOfBoundsException if
1424      *          <code>pixel</code> is not large enough to hold a pixel
1425      *          value for this <code>ColorModel</code>.
1426      * @throws UnsupportedOperationException if the
1427      *          constructor of this <code>ColorModel</code> called the
1428      *          <code>super(bits)</code> constructor, but did not
1429      *          override this method.  See the constructor,
1430      *          {@link #ColorModel(int)}.
1431      * @throws UnsupportedOperationException if this method is unable
1432      *          to determine the number of bits per component
1433      * @since 1.4
1434      */
1435     public float[] getNormalizedComponents(Object pixel,
1436                                            float[] normComponents,
1437                                            int normOffset) {
1438         int components[] = getComponents(pixel, null, 0);
1439         return getNormalizedComponents(components, 0,
1440                                        normComponents, normOffset);
1441     }
1442 
1443     /**
1444      * Tests if the specified <code>Object</code> is an instance of
1445      * <code>ColorModel</code> and if it equals this
1446      * <code>ColorModel</code>.
1447      * @param obj the <code>Object</code> to test for equality
1448      * @return <code>true</code> if the specified <code>Object</code>
1449      * is an instance of <code>ColorModel</code> and equals this
1450      * <code>ColorModel</code>; <code>false</code> otherwise.
1451      */
1452     public boolean equals(Object obj) {
1453         if (!(obj instanceof ColorModel)) {
1454             return false;
1455         }
1456         ColorModel cm = (ColorModel) obj;
1457 
1458         if (this == cm) {
1459             return true;
1460         }
1461         if (supportsAlpha != cm.hasAlpha() ||
1462             isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
1463             pixel_bits != cm.getPixelSize() ||
1464             transparency != cm.getTransparency() ||
1465             numComponents != cm.getNumComponents())
1466         {
1467             return false;
1468         }
1469 
1470         int[] nb = cm.getComponentSize();
1471 
1472         if ((nBits != null) && (nb != null)) {
1473             for (int i = 0; i < numComponents; i++) {
1474                 if (nBits[i] != nb[i]) {
1475                     return false;
1476                 }
1477             }
1478         } else {
1479             return ((nBits == null) && (nb == null));
1480         }
1481 
1482         return true;
1483     }
1484 
1485     /**
1486      * Returns the hash code for this ColorModel.
1487      *
1488      * @return    a hash code for this ColorModel.
1489      */
1490     public int hashCode() {
1491 
1492         int result = 0;
1493 
1494         result = (supportsAlpha ? 2 : 3) +
1495                  (isAlphaPremultiplied ? 4 : 5) +
1496                  pixel_bits * 6 +
1497                  transparency * 7 +
1498                  numComponents * 8;
1499 
1500         if (nBits != null) {
1501             for (int i = 0; i < numComponents; i++) {
1502                 result = result + nBits[i] * (i + 9);
1503             }
1504         }
1505 
1506         return result;
1507     }
1508 
1509     /**
1510      * Returns the <code>ColorSpace</code> associated with this
1511      * <code>ColorModel</code>.
1512      * @return the <code>ColorSpace</code> of this
1513      * <code>ColorModel</code>.
1514      */
1515     final public ColorSpace getColorSpace() {
1516         return colorSpace;
1517     }
1518 
1519     /**
1520      * Forces the raster data to match the state specified in the
1521      * <code>isAlphaPremultiplied</code> variable, assuming the data is
1522      * currently correctly described by this <code>ColorModel</code>.  It
1523      * may multiply or divide the color raster data by alpha, or do
1524      * nothing if the data is in the correct state.  If the data needs to
1525      * be coerced, this method will also return an instance of this
1526      * <code>ColorModel</code> with the <code>isAlphaPremultiplied</code>
1527      * flag set appropriately.  This method will throw a
1528      * <code>UnsupportedOperationException</code> if it is not supported
1529      * by this <code>ColorModel</code>.
1530      * Since <code>ColorModel</code> is an abstract class,
1531      * any instance is an instance of a subclass.  Subclasses must
1532      * override this method since the implementation in this abstract
1533      * class throws an <code>UnsupportedOperationException</code>.
1534      * @param raster the <code>WritableRaster</code> data
1535      * @param isAlphaPremultiplied <code>true</code> if the alpha is
1536      * premultiplied; <code>false</code> otherwise
1537      * @return a <code>ColorModel</code> object that represents the
1538      * coerced data.
1539      */
1540     public ColorModel coerceData (WritableRaster raster,
1541                                   boolean isAlphaPremultiplied) {
1542         throw new UnsupportedOperationException
1543             ("This method is not supported by this color model");
1544     }
1545 
1546     /**
1547       * Returns <code>true</code> if <code>raster</code> is compatible
1548       * with this <code>ColorModel</code> and <code>false</code> if it is
1549       * not.
1550       * Since <code>ColorModel</code> is an abstract class,
1551       * any instance is an instance of a subclass.  Subclasses must
1552       * override this method since the implementation in this abstract
1553       * class throws an <code>UnsupportedOperationException</code>.
1554       * @param raster the {@link Raster} object to test for compatibility
1555       * @return <code>true</code> if <code>raster</code> is compatible
1556       * with this <code>ColorModel</code>.
1557       * @throws UnsupportedOperationException if this
1558       *         method has not been implemented for this
1559       *         <code>ColorModel</code>
1560       */
1561     public boolean isCompatibleRaster(Raster raster) {
1562         throw new UnsupportedOperationException(
1563             "This method has not been implemented for this ColorModel.");
1564     }
1565 
1566     /**
1567      * Creates a <code>WritableRaster</code> with the specified width and
1568      * height that has a data layout (<code>SampleModel</code>) compatible
1569      * with this <code>ColorModel</code>.
1570      * Since <code>ColorModel</code> is an abstract class,
1571      * any instance is an instance of a subclass.  Subclasses must
1572      * override this method since the implementation in this abstract
1573      * class throws an <code>UnsupportedOperationException</code>.
1574      * @param w the width to apply to the new <code>WritableRaster</code>
1575      * @param h the height to apply to the new <code>WritableRaster</code>
1576      * @return a <code>WritableRaster</code> object with the specified
1577      * width and height.
1578      * @throws UnsupportedOperationException if this
1579      *          method is not supported by this <code>ColorModel</code>
1580      * @see WritableRaster
1581      * @see SampleModel
1582      */
1583     public WritableRaster createCompatibleWritableRaster(int w, int h) {
1584         throw new UnsupportedOperationException
1585             ("This method is not supported by this color model");
1586     }
1587 
1588     /**
1589      * Creates a <code>SampleModel</code> with the specified width and
1590      * height that has a data layout compatible with this
1591      * <code>ColorModel</code>.
1592      * Since <code>ColorModel</code> is an abstract class,
1593      * any instance is an instance of a subclass.  Subclasses must
1594      * override this method since the implementation in this abstract
1595      * class throws an <code>UnsupportedOperationException</code>.
1596      * @param w the width to apply to the new <code>SampleModel</code>
1597      * @param h the height to apply to the new <code>SampleModel</code>
1598      * @return a <code>SampleModel</code> object with the specified
1599      * width and height.
1600      * @throws UnsupportedOperationException if this
1601      *          method is not supported by this <code>ColorModel</code>
1602      * @see SampleModel
1603      */
1604     public SampleModel createCompatibleSampleModel(int w, int h) {
1605         throw new UnsupportedOperationException
1606             ("This method is not supported by this color model");
1607     }
1608 
1609     /** Checks if the <code>SampleModel</code> is compatible with this
1610      * <code>ColorModel</code>.
1611      * Since <code>ColorModel</code> is an abstract class,
1612      * any instance is an instance of a subclass.  Subclasses must
1613      * override this method since the implementation in this abstract
1614      * class throws an <code>UnsupportedOperationException</code>.
1615      * @param sm the specified <code>SampleModel</code>
1616      * @return <code>true</code> if the specified <code>SampleModel</code>
1617      * is compatible with this <code>ColorModel</code>; <code>false</code>
1618      * otherwise.
1619      * @throws UnsupportedOperationException if this
1620      *          method is not supported by this <code>ColorModel</code>
1621      * @see SampleModel
1622      */
1623     public boolean isCompatibleSampleModel(SampleModel sm) {
1624         throw new UnsupportedOperationException
1625             ("This method is not supported by this color model");
1626     }
1627 
1628     /**
1629      * Disposes of system resources associated with this
1630      * <code>ColorModel</code> once this <code>ColorModel</code> is no
1631      * longer referenced.
1632      */
1633     public void finalize() {
1634     }
1635 
1636 
1637     /**
1638      * Returns a <code>Raster</code> representing the alpha channel of an
1639      * image, extracted from the input <code>Raster</code>, provided that
1640      * pixel values of this <code>ColorModel</code> represent color and
1641      * alpha information as separate spatial bands (e.g.
1642      * {@link ComponentColorModel} and <code>DirectColorModel</code>).
1643      * This method assumes that <code>Raster</code> objects associated
1644      * with such a <code>ColorModel</code> store the alpha band, if
1645      * present, as the last band of image data.  Returns <code>null</code>
1646      * if there is no separate spatial alpha channel associated with this
1647      * <code>ColorModel</code>.  If this is an
1648      * <code>IndexColorModel</code> which has alpha in the lookup table,
1649      * this method will return <code>null</code> since
1650      * there is no spatially discrete alpha channel.
1651      * This method will create a new <code>Raster</code> (but will share
1652      * the data array).
1653      * Since <code>ColorModel</code> is an abstract class, any instance
1654      * is an instance of a subclass.  Subclasses must override this
1655      * method to get any behavior other than returning <code>null</code>
1656      * because the implementation in this abstract class returns
1657      * <code>null</code>.
1658      * @param raster the specified <code>Raster</code>
1659      * @return a <code>Raster</code> representing the alpha channel of
1660      * an image, obtained from the specified <code>Raster</code>.
1661      */
1662     public WritableRaster getAlphaRaster(WritableRaster raster) {
1663         return null;
1664     }
1665 
1666     /**
1667      * Returns the <code>String</code> representation of the contents of
1668      * this <code>ColorModel</code>object.
1669      * @return a <code>String</code> representing the contents of this
1670      * <code>ColorModel</code> object.
1671      */
1672     public String toString() {
1673        return new String("ColorModel: #pixelBits = "+pixel_bits
1674                          + " numComponents = "+numComponents
1675                          + " color space = "+colorSpace
1676                          + " transparency = "+transparency
1677                          + " has alpha = "+supportsAlpha
1678                          + " isAlphaPre = "+isAlphaPremultiplied
1679                          );
1680     }
1681 
1682     static int getDefaultTransferType(int pixel_bits) {
1683         if (pixel_bits <= 8) {
1684             return DataBuffer.TYPE_BYTE;
1685         } else if (pixel_bits <= 16) {
1686             return DataBuffer.TYPE_USHORT;
1687         } else if (pixel_bits <= 32) {
1688             return DataBuffer.TYPE_INT;
1689         } else {
1690             return DataBuffer.TYPE_UNDEFINED;
1691         }
1692     }
1693 
1694     static byte[] l8Tos8 = null;   // 8-bit linear to 8-bit non-linear sRGB LUT
1695     static byte[] s8Tol8 = null;   // 8-bit non-linear sRGB to 8-bit linear LUT
1696     static byte[] l16Tos8 = null;  // 16-bit linear to 8-bit non-linear sRGB LUT
1697     static short[] s8Tol16 = null; // 8-bit non-linear sRGB to 16-bit linear LUT
1698 
1699                                 // Maps to hold LUTs for grayscale conversions
1700     static Map<ICC_ColorSpace, byte[]> g8Tos8Map = null;     // 8-bit gray values to 8-bit sRGB values
1701     static Map<ICC_ColorSpace, byte[]> lg16Toog8Map = null;  // 16-bit linear to 8-bit "other" gray
1702     static Map<ICC_ColorSpace, byte[]> g16Tos8Map = null;    // 16-bit gray values to 8-bit sRGB values
1703     static Map<ICC_ColorSpace, short[]> lg16Toog16Map = null; // 16-bit linear to 16-bit "other" gray
1704 
1705     static boolean isLinearRGBspace(ColorSpace cs) {
1706         // Note: CMM.LINEAR_RGBspace will be null if the linear
1707         // RGB space has not been created yet.
1708         return (cs == CMSManager.LINEAR_RGBspace);
1709     }
1710 
1711     static boolean isLinearGRAYspace(ColorSpace cs) {
1712         // Note: CMM.GRAYspace will be null if the linear
1713         // gray space has not been created yet.
1714         return (cs == CMSManager.GRAYspace);
1715     }
1716 
1717     static byte[] getLinearRGB8TosRGB8LUT() {
1718         if (l8Tos8 == null) {
1719             l8Tos8 = new byte[256];
1720             float input, output;
1721             // algorithm for linear RGB to nonlinear sRGB conversion
1722             // is from the IEC 61966-2-1 International Standard,
1723             // Colour Management - Default RGB colour space - sRGB,
1724             // First Edition, 1999-10,
1725             // avaiable for order at http://www.iec.ch
1726             for (int i = 0; i <= 255; i++) {
1727                 input = ((float) i) / 255.0f;
1728                 if (input <= 0.0031308f) {
1729                     output = input * 12.92f;
1730                 } else {
1731                     output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4)))
1732                              - 0.055f;
1733                 }
1734                 l8Tos8[i] = (byte) Math.round(output * 255.0f);
1735             }
1736         }
1737         return l8Tos8;
1738     }
1739 
1740     static byte[] getsRGB8ToLinearRGB8LUT() {
1741         if (s8Tol8 == null) {
1742             s8Tol8 = new byte[256];
1743             float input, output;
1744             // algorithm from IEC 61966-2-1 International Standard
1745             for (int i = 0; i <= 255; i++) {
1746                 input = ((float) i) / 255.0f;
1747                 if (input <= 0.04045f) {
1748                     output = input / 12.92f;
1749                 } else {
1750                     output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4);
1751                 }
1752                 s8Tol8[i] = (byte) Math.round(output * 255.0f);
1753             }
1754         }
1755         return s8Tol8;
1756     }
1757 
1758     static byte[] getLinearRGB16TosRGB8LUT() {
1759         if (l16Tos8 == null) {
1760             l16Tos8 = new byte[65536];
1761             float input, output;
1762             // algorithm from IEC 61966-2-1 International Standard
1763             for (int i = 0; i <= 65535; i++) {
1764                 input = ((float) i) / 65535.0f;
1765                 if (input <= 0.0031308f) {
1766                     output = input * 12.92f;
1767                 } else {
1768                     output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4)))
1769                              - 0.055f;
1770                 }
1771                 l16Tos8[i] = (byte) Math.round(output * 255.0f);
1772             }
1773         }
1774         return l16Tos8;
1775     }
1776 
1777     static short[] getsRGB8ToLinearRGB16LUT() {
1778         if (s8Tol16 == null) {
1779             s8Tol16 = new short[256];
1780             float input, output;
1781             // algorithm from IEC 61966-2-1 International Standard
1782             for (int i = 0; i <= 255; i++) {
1783                 input = ((float) i) / 255.0f;
1784                 if (input <= 0.04045f) {
1785                     output = input / 12.92f;
1786                 } else {
1787                     output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4);
1788                 }
1789                 s8Tol16[i] = (short) Math.round(output * 65535.0f);
1790             }
1791         }
1792         return s8Tol16;
1793     }
1794 
1795     /*
1796      * Return a byte LUT that converts 8-bit gray values in the grayCS
1797      * ColorSpace to the appropriate 8-bit sRGB value.  I.e., if lut
1798      * is the byte array returned by this method and sval = lut[gval],
1799      * then the sRGB triple (sval,sval,sval) is the best match to gval.
1800      * Cache references to any computed LUT in a Map.
1801      */
1802     static byte[] getGray8TosRGB8LUT(ICC_ColorSpace grayCS) {
1803         if (isLinearGRAYspace(grayCS)) {
1804             return getLinearRGB8TosRGB8LUT();
1805         }
1806         if (g8Tos8Map != null) {
1807             byte[] g8Tos8LUT = g8Tos8Map.get(grayCS);
1808             if (g8Tos8LUT != null) {
1809                 return g8Tos8LUT;
1810             }
1811         }
1812         byte[] g8Tos8LUT = new byte[256];
1813         for (int i = 0; i <= 255; i++) {
1814             g8Tos8LUT[i] = (byte) i;
1815         }
1816         ColorTransform[] transformList = new ColorTransform[2];
1817         PCMM mdl = CMSManager.getModule();
1818         ICC_ColorSpace srgbCS =
1819             (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB);
1820         transformList[0] = mdl.createTransform(
1821             grayCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1822         transformList[1] = mdl.createTransform(
1823             srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1824         ColorTransform t = mdl.createTransform(transformList);
1825         byte[] tmp = t.colorConvert(g8Tos8LUT, null);
1826         for (int i = 0, j= 2; i <= 255; i++, j += 3) {
1827             // All three components of tmp should be equal, since
1828             // the input color space to colorConvert is a gray scale
1829             // space.  However, there are slight anomalies in the results.
1830             // Copy tmp starting at index 2, since colorConvert seems
1831             // to be slightly more accurate for the third component!
1832             g8Tos8LUT[i] = tmp[j];
1833         }
1834         if (g8Tos8Map == null) {
1835             g8Tos8Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, byte[]>(2));
1836         }
1837         g8Tos8Map.put(grayCS, g8Tos8LUT);
1838         return g8Tos8LUT;
1839     }
1840 
1841     /*
1842      * Return a byte LUT that converts 16-bit gray values in the CS_GRAY
1843      * linear gray ColorSpace to the appropriate 8-bit value in the
1844      * grayCS ColorSpace.  Cache references to any computed LUT in a Map.
1845      */
1846     static byte[] getLinearGray16ToOtherGray8LUT(ICC_ColorSpace grayCS) {
1847         if (lg16Toog8Map != null) {
1848             byte[] lg16Toog8LUT = lg16Toog8Map.get(grayCS);
1849             if (lg16Toog8LUT != null) {
1850                 return lg16Toog8LUT;
1851             }
1852         }
1853         short[] tmp = new short[65536];
1854         for (int i = 0; i <= 65535; i++) {
1855             tmp[i] = (short) i;
1856         }
1857         ColorTransform[] transformList = new ColorTransform[2];
1858         PCMM mdl = CMSManager.getModule();
1859         ICC_ColorSpace lgCS =
1860             (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY);
1861         transformList[0] = mdl.createTransform (
1862             lgCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1863         transformList[1] = mdl.createTransform (
1864             grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1865         ColorTransform t = mdl.createTransform(transformList);
1866         tmp = t.colorConvert(tmp, null);
1867         byte[] lg16Toog8LUT = new byte[65536];
1868         for (int i = 0; i <= 65535; i++) {
1869             // scale unsigned short (0 - 65535) to unsigned byte (0 - 255)
1870             lg16Toog8LUT[i] =
1871                 (byte) (((float) (tmp[i] & 0xffff)) * (1.0f /257.0f) + 0.5f);
1872         }
1873         if (lg16Toog8Map == null) {
1874             lg16Toog8Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, byte[]>(2));
1875         }
1876         lg16Toog8Map.put(grayCS, lg16Toog8LUT);
1877         return lg16Toog8LUT;
1878     }
1879 
1880     /*
1881      * Return a byte LUT that converts 16-bit gray values in the grayCS
1882      * ColorSpace to the appropriate 8-bit sRGB value.  I.e., if lut
1883      * is the byte array returned by this method and sval = lut[gval],
1884      * then the sRGB triple (sval,sval,sval) is the best match to gval.
1885      * Cache references to any computed LUT in a Map.
1886      */
1887     static byte[] getGray16TosRGB8LUT(ICC_ColorSpace grayCS) {
1888         if (isLinearGRAYspace(grayCS)) {
1889             return getLinearRGB16TosRGB8LUT();
1890         }
1891         if (g16Tos8Map != null) {
1892             byte[] g16Tos8LUT = g16Tos8Map.get(grayCS);
1893             if (g16Tos8LUT != null) {
1894                 return g16Tos8LUT;
1895             }
1896         }
1897         short[] tmp = new short[65536];
1898         for (int i = 0; i <= 65535; i++) {
1899             tmp[i] = (short) i;
1900         }
1901         ColorTransform[] transformList = new ColorTransform[2];
1902         PCMM mdl = CMSManager.getModule();
1903         ICC_ColorSpace srgbCS =
1904             (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB);
1905         transformList[0] = mdl.createTransform (
1906             grayCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1907         transformList[1] = mdl.createTransform (
1908             srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1909         ColorTransform t = mdl.createTransform(transformList);
1910         tmp = t.colorConvert(tmp, null);
1911         byte[] g16Tos8LUT = new byte[65536];
1912         for (int i = 0, j= 2; i <= 65535; i++, j += 3) {
1913             // All three components of tmp should be equal, since
1914             // the input color space to colorConvert is a gray scale
1915             // space.  However, there are slight anomalies in the results.
1916             // Copy tmp starting at index 2, since colorConvert seems
1917             // to be slightly more accurate for the third component!
1918 
1919             // scale unsigned short (0 - 65535) to unsigned byte (0 - 255)
1920             g16Tos8LUT[i] =
1921                 (byte) (((float) (tmp[j] & 0xffff)) * (1.0f /257.0f) + 0.5f);
1922         }
1923         if (g16Tos8Map == null) {
1924             g16Tos8Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, byte[]>(2));
1925         }
1926         g16Tos8Map.put(grayCS, g16Tos8LUT);
1927         return g16Tos8LUT;
1928     }
1929 
1930     /*
1931      * Return a short LUT that converts 16-bit gray values in the CS_GRAY
1932      * linear gray ColorSpace to the appropriate 16-bit value in the
1933      * grayCS ColorSpace.  Cache references to any computed LUT in a Map.
1934      */
1935     static short[] getLinearGray16ToOtherGray16LUT(ICC_ColorSpace grayCS) {
1936         if (lg16Toog16Map != null) {
1937             short[] lg16Toog16LUT = lg16Toog16Map.get(grayCS);
1938             if (lg16Toog16LUT != null) {
1939                 return lg16Toog16LUT;
1940             }
1941         }
1942         short[] tmp = new short[65536];
1943         for (int i = 0; i <= 65535; i++) {
1944             tmp[i] = (short) i;
1945         }
1946         ColorTransform[] transformList = new ColorTransform[2];
1947         PCMM mdl = CMSManager.getModule();
1948         ICC_ColorSpace lgCS =
1949             (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY);
1950         transformList[0] = mdl.createTransform (
1951             lgCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1952         transformList[1] = mdl.createTransform(
1953             grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1954         ColorTransform t = mdl.createTransform(
1955             transformList);
1956         short[] lg16Toog16LUT = t.colorConvert(tmp, null);
1957         if (lg16Toog16Map == null) {
1958             lg16Toog16Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, short[]>(2));
1959         }
1960         lg16Toog16Map.put(grayCS, lg16Toog16LUT);
1961         return lg16Toog16LUT;
1962     }
1963 
1964 }