KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)ColorModel.java 1.80 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.image;
9
10 import java.awt.Transparency JavaDoc;
11 import java.awt.color.ColorSpace JavaDoc;
12 import java.awt.color.ICC_ColorSpace JavaDoc;
13 import sun.awt.color.ICC_Transform;
14 import sun.awt.color.CMM;
15 import java.awt.Toolkit JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.Map JavaDoc;
18 import java.util.WeakHashMap JavaDoc;
19
20 /**
21  * The <code>ColorModel</code> abstract class encapsulates the
22  * methods for translating a pixel value to color components
23  * (for example, red, green, and blue) and an alpha component.
24  * In order to render an image to the screen, a printer, or another
25  * image, pixel values must be converted to color and alpha components.
26  * As arguments to or return values from methods of this class,
27  * pixels are represented as 32-bit ints or as arrays of primitive types.
28  * The number, order, and interpretation of color components for a
29  * <code>ColorModel</code> is specified by its <code>ColorSpace</code>.
30  * A <code>ColorModel</code> used with pixel data that does not include
31  * alpha information treats all pixels as opaque, which is an alpha
32  * value of 1.0.
33  * <p>
34  * This <code>ColorModel</code> class supports two representations of
35  * pixel values. A pixel value can be a single 32-bit int or an
36  * array of primitive types. The Java(tm) Platform 1.0 and 1.1 APIs
37  * represented pixels as single <code>byte</code> or single
38  * <code>int</code> values. For purposes of the <code>ColorModel</code>
39  * class, pixel value arguments were passed as ints. The Java(tm) 2
40  * Platform API introduced additional classes for representing images.
41  * With {@link BufferedImage} or {@link RenderedImage}
42  * objects, based on {@link Raster} and {@link SampleModel} classes, pixel
43  * values might not be conveniently representable as a single int.
44  * Consequently, <code>ColorModel</code> now has methods that accept
45  * pixel values represented as arrays of primitive types. The primitive
46  * type used by a particular <code>ColorModel</code> object is called its
47  * transfer type.
48  * <p>
49  * <code>ColorModel</code> objects used with images for which pixel values
50  * are not conveniently representable as a single int throw an
51  * {@link IllegalArgumentException} when methods taking a single int pixel
52  * argument are called. Subclasses of <code>ColorModel</code> must
53  * specify the conditions under which this occurs. This does not
54  * occur with {@link DirectColorModel} or {@link IndexColorModel} objects.
55  * <p>
56  * Currently, the transfer types supported by the Java 2D(tm) API are
57  * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT,
58  * DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, and DataBuffer.TYPE_DOUBLE.
59  * Most rendering operations will perform much faster when using ColorModels
60  * and images based on the first three of these types. In addition, some
61  * image filtering operations are not supported for ColorModels and
62  * images based on the latter three types.
63  * The transfer type for a particular <code>ColorModel</code> object is
64  * specified when the object is created, either explicitly or by default.
65  * All subclasses of <code>ColorModel</code> must specify what the
66  * possible transfer types are and how the number of elements in the
67  * primitive arrays representing pixels is determined.
68  * <p>
69  * For <code>BufferedImages</code>, the transfer type of its
70  * <code>Raster</code> and of the <code>Raster</code> object's
71  * <code>SampleModel</code> (available from the
72  * <code>getTransferType</code> methods of these classes) must match that
73  * of the <code>ColorModel</code>. The number of elements in an array
74  * representing a pixel for the <code>Raster</code> and
75  * <code>SampleModel</code> (available from the
76  * <code>getNumDataElements</code> methods of these classes) must match
77  * that of the <code>ColorModel</code>.
78  * <p>
79  * The algorithm used to convert from pixel values to color and alpha
80  * components varies by subclass. For example, there is not necessarily
81  * a one-to-one correspondence between samples obtained from the
82  * <code>SampleModel</code> of a <code>BufferedImage</code> object's
83  * <code>Raster</code> and color/alpha components. Even when
84  * there is such a correspondence, the number of bits in a sample is not
85  * necessarily the same as the number of bits in the corresponding color/alpha
86  * component. Each subclass must specify how the translation from
87  * pixel values to color/alpha components is done.
88  * <p>
89  * Methods in the <code>ColorModel</code> class use two different
90  * representations of color and alpha components - a normalized form
91  * and an unnormalized form. In the normalized form, each component is a
92  * <code>float</code> value between some minimum and maximum values. For
93  * the alpha component, the minimum is 0.0 and the maximum is 1.0. For
94  * color components the minimum and maximum values for each component can
95  * be obtained from the <code>ColorSpace</code> object. These values
96  * will often be 0.0 and 1.0 (e.g. normalized component values for the
97  * default sRGB color space range from 0.0 to 1.0), but some color spaces
98  * have component values with different upper and lower limits. These
99  * limits can be obtained using the <code>getMinValue</code> and
100  * <code>getMaxValue</code> methods of the <code>ColorSpace</code>
101  * class. Normalized color component values are not premultiplied.
102  * All <code>ColorModels</code> must support the normalized form.
103  * <p>
104  * In the unnormalized
105  * form, each component is an unsigned integral value between 0 and
106  * 2<sup>n</sup> - 1, where n is the number of significant bits for a
107  * particular component. If pixel values for a particular
108  * <code>ColorModel</code> represent color samples premultiplied by
109  * the alpha sample, unnormalized color component values are
110  * also premultiplied. The unnormalized form is used only with instances
111  * of <code>ColorModel</code> whose <code>ColorSpace</code> has minimum
112  * component values of 0.0 for all components and maximum values of
113  * 1.0 for all components.
114  * The unnormalized form for color and alpha components can be a convenient
115  * representation for <code>ColorModels</code> whose normalized component
116  * values all lie
117  * between 0.0 and 1.0. In such cases the integral value 0 maps to 0.0 and
118  * the value 2<sup>n</sup> - 1 maps to 1.0. In other cases, such as
119  * when the normalized component values can be either negative or positive,
120  * the unnormalized form is not convenient. Such <code>ColorModel</code>
121  * objects throw an {@link IllegalArgumentException} when methods involving
122  * an unnormalized argument are called. Subclasses of <code>ColorModel</code>
123  * must specify the conditions under which this occurs.
124  *
125  * @see IndexColorModel
126  * @see ComponentColorModel
127  * @see PackedColorModel
128  * @see DirectColorModel
129  * @see java.awt.Image
130  * @see BufferedImage
131  * @see RenderedImage
132  * @see java.awt.color.ColorSpace
133  * @see SampleModel
134  * @see Raster
135  * @see DataBuffer
136  * @version 10 Feb 1997
137  */

138 public abstract class ColorModel implements Transparency JavaDoc{
139     private long pData; // Placeholder for data for native functions
140

141     /**
142      * The total number of bits in the pixel.
143      */

144     protected int pixel_bits;
145     int nBits[];
146     int transparency = Transparency.TRANSLUCENT;
147     boolean supportsAlpha = true;
148     boolean isAlphaPremultiplied = false;
149     int numComponents = -1;
150     int numColorComponents = -1;
151     ColorSpace JavaDoc colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
152     int colorSpaceType = ColorSpace.TYPE_RGB;
153     int maxBits;
154     boolean is_sRGB = true;
155
156     /**
157      * Data type of the array used to represent pixel values.
158      */

159     protected int transferType;
160
161     /**
162      * This is copied from java.awt.Toolkit since we need the library
163      * loaded in java.awt.image also:
164      *
165      * WARNING: This is a temporary workaround for a problem in the
166      * way the AWT loads native libraries. A number of classes in the
167      * AWT package have a native method, initIDs(), which initializes
168      * the JNI field and method ids used in the native portion of
169      * their implementation.
170      *
171      * Since the use and storage of these ids is done by the
172      * implementation libraries, the implementation of these method is
173      * provided by the particular AWT implementations (for example,
174      * "Toolkit"s/Peer), such as Motif, Microsoft Windows, or Tiny. The
175      * problem is that this means that the native libraries must be
176      * loaded by the java.* classes, which do not necessarily know the
177      * names of the libraries to load. A better way of doing this
178      * would be to provide a separate library which defines java.awt.*
179      * initIDs, and exports the relevant symbols out to the
180      * implementation libraries.
181      *
182      * For now, we know it's done by the implementation, and we assume
183      * that the name of the library is "awt". -br.
184      */

185     private static boolean loaded = false;
186     static void loadLibraries() {
187     if (!loaded) {
188         java.security.AccessController.doPrivileged(
189           new sun.security.action.LoadLibraryAction("awt"));
190         loaded = true;
191     }
192     }
193     private static native void initIDs();
194     static {
195     /* ensure that the proper libraries are loaded */
196         loadLibraries();
197     initIDs();
198     }
199     private static ColorModel JavaDoc RGBdefault;
200
201     /**
202      * Returns a <code>DirectColorModel</code> that describes the default
203      * format for integer RGB values used in many of the methods in the
204      * AWT image interfaces for the convenience of the programmer.
205      * The color space is the default {@link ColorSpace}, sRGB.
206      * The format for the RGB values is an integer with 8 bits
207      * each of alpha, red, green, and blue color components ordered
208      * correspondingly from the most significant byte to the least
209      * significant byte, as in: 0xAARRGGBB. Color components are
210      * not premultiplied by the alpha component. This format does not
211      * necessarily represent the native or the most efficient
212      * <code>ColorModel</code> for a particular device or for all images.
213      * It is merely used as a common color model format.
214      * @return a <code>DirectColorModel</code>object describing default
215      * RGB values.
216      */

217     public static ColorModel JavaDoc getRGBdefault() {
218     if (RGBdefault == null) {
219         RGBdefault = new DirectColorModel JavaDoc(32,
220                           0x00ff0000, // Red
221
0x0000ff00, // Green
222
0x000000ff, // Blue
223
0xff000000 // Alpha
224
);
225     }
226     return RGBdefault;
227     }
228
229     /**
230      * Constructs a <code>ColorModel</code> that translates pixels of the
231      * specified number of bits to color/alpha components. The color
232      * space is the default RGB <code>ColorSpace</code>, which is sRGB.
233      * Pixel values are assumed to include alpha information. If color
234      * and alpha information are represented in the pixel value as
235      * separate spatial bands, the color bands are assumed not to be
236      * premultiplied with the alpha value. The transparency type is
237      * java.awt.Transparency.TRANSLUCENT. The transfer type will be the
238      * smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
239      * or DataBuffer.TYPE_INT that can hold a single pixel
240      * (or DataBuffer.TYPE_UNDEFINED if bits is greater
241      * than 32). Since this constructor has no information about the
242      * number of bits per color and alpha component, any subclass calling
243      * this constructor should override any method that requires this
244      * information.
245      * @param bits the number of bits of a pixel
246      * @throws IllegalArgumentException if the number
247      * of bits in <code>bits</code> is less than 1
248      */

249     public ColorModel(int bits) {
250     pixel_bits = bits;
251         if (bits < 1) {
252             throw new IllegalArgumentException JavaDoc("Number of bits must be > 0");
253         }
254         numComponents = 4;
255         numColorComponents = 3;
256         maxBits = bits;
257         // REMIND: make sure transferType is set correctly
258
transferType = ColorModel.getDefaultTransferType(bits);
259     }
260
261     /**
262      * Constructs a <code>ColorModel</code> that translates pixel values
263      * to color/alpha components. Color components will be in the
264      * specified <code>ColorSpace</code>. <code>pixel_bits</code> is the
265      * number of bits in the pixel values. The bits array
266      * specifies the number of significant bits per color and alpha component.
267      * Its length should be the number of components in the
268      * <code>ColorSpace</code> if there is no alpha information in the
269      * pixel values, or one more than this number if there is alpha
270      * information. <code>hasAlpha</code> indicates whether or not alpha
271      * information is present. The <code>boolean</code>
272      * <code>isAlphaPremultiplied</code> specifies how to interpret pixel
273      * values in which color and alpha information are represented as
274      * separate spatial bands. If the <code>boolean</code>
275      * is <code>true</code>, color samples are assumed to have been
276      * multiplied by the alpha sample. The <code>transparency</code>
277      * specifies what alpha values can be represented by this color model.
278      * The transfer type is the type of primitive array used to represent
279      * pixel values. Note that the bits array contains the number of
280      * significant bits per color/alpha component after the translation
281      * from pixel values. For example, for an
282      * <code>IndexColorModel</code> with <code>pixel_bits</code> equal to
283      * 16, the bits array might have four elements with each element set
284      * to 8.
285      * @param pixel_bits the number of bits in the pixel values
286      * @param bits array that specifies the number of significant bits
287      * per color and alpha component
288      * @param cspace the specified <code>ColorSpace</code>
289      * @param hasAlpha <code>true</code> if alpha information is present;
290      * <code>false</code> otherwise
291      * @param isAlphaPremultiplied <code>true</code> if color samples are
292      * assumed to be premultiplied by the alpha samples;
293      * <code>false</code> otherwise
294      * @param transparency what alpha values can be represented by this
295      * color model
296      * @param transferType the type of the array used to represent pixel
297      * values
298      * @throws IllegalArgumentException if the length of
299      * the bit array is less than the number of color or alpha
300      * components in this <code>ColorModel</code>, or if the
301      * transparency is not a valid value.
302      * @throws IllegalArgumentException if the sum of the number
303      * of bits in <code>bits</code> is less than 1 or if
304      * any of the elements in <code>bits</code> is less than 0.
305      * @see java.awt.Transparency
306      */

307     protected ColorModel(int pixel_bits, int[] bits, ColorSpace JavaDoc cspace,
308                          boolean hasAlpha,
309                          boolean isAlphaPremultiplied,
310                          int transparency,
311                          int transferType) {
312         colorSpace = cspace;
313         colorSpaceType = cspace.getType();
314         numColorComponents = cspace.getNumComponents();
315         numComponents = numColorComponents + (hasAlpha ? 1 : 0);
316         supportsAlpha = hasAlpha;
317         if (bits.length < numComponents) {
318             throw new IllegalArgumentException JavaDoc("Number of color/alpha "+
319                                                "components should be "+
320                                                numComponents+
321                                                " but length of bits array is "+
322                                                bits.length);
323         }
324
325         // 4186669
326
if (transparency < Transparency.OPAQUE ||
327             transparency > Transparency.TRANSLUCENT)
328         {
329             throw new IllegalArgumentException JavaDoc("Unknown transparency: "+
330                                                transparency);
331         }
332         
333         if (supportsAlpha == false) {
334             this.isAlphaPremultiplied = false;
335             this.transparency = Transparency.OPAQUE;
336         }
337         else {
338             this.isAlphaPremultiplied = isAlphaPremultiplied;
339             this.transparency = transparency;
340         }
341
342         nBits = (int[]) bits.clone();
343         this.pixel_bits = pixel_bits;
344         if (pixel_bits <= 0) {
345             throw new IllegalArgumentException JavaDoc("Number of pixel bits must "+
346                                                "be > 0");
347         }
348         // Check for bits < 0
349
maxBits = 0;
350         for (int i=0; i < bits.length; i++) {
351             // bug 4304697
352
if (bits[i] < 0) {
353                 throw new
354                     IllegalArgumentException JavaDoc("Number of bits must be >= 0");
355             }
356             if (maxBits < bits[i]) {
357                 maxBits = bits[i];
358             }
359         }
360
361         // Make sure that we don't have all 0-bit components
362
if (maxBits == 0) {
363             throw new IllegalArgumentException JavaDoc("There must be at least "+
364                                                "one component with > 0 "+
365                                               "pixel bits.");
366         }
367
368         // Save this since we always need to check if it is the default CS
369
if (cspace != ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
370             is_sRGB = false;
371         }
372
373         // Save the transfer type
374
this.transferType = transferType;
375     }
376
377     /**
378      * Returns whether or not alpha is supported in this
379      * <code>ColorModel</code>.
380      * @return <code>true</code> if alpha is supported in this
381      * <code>ColorModel</code>; <code>false</code> otherwise.
382      */

383     final public boolean hasAlpha() {
384         return supportsAlpha;
385     }
386     
387     /**
388      * Returns whether or not the alpha has been premultiplied in the
389      * pixel values to be translated by this <code>ColorModel</code>.
390      * If the boolean is <code>true</code>, this <code>ColorModel</code>
391      * is to be used to interpret pixel values in which color and alpha
392      * information are represented as separate spatial bands, and color
393      * samples are assumed to have been multiplied by the
394      * alpha sample.
395      * @return <code>true</code> if the alpha values are premultiplied
396      * in the pixel values to be translated by this
397      * <code>ColorModel</code>; <code>false</code> otherwise.
398      */

399     final public boolean isAlphaPremultiplied() {
400         return isAlphaPremultiplied;
401     }
402
403     /**
404      * Returns the transfer type of this <code>ColorModel</code>.
405      * The transfer type is the type of primitive array used to represent
406      * pixel values as arrays.
407      * @return the transfer type.
408      */

409     final public int getTransferType() {
410         return transferType;
411     }
412     
413     /**
414      * Returns the number of bits per pixel described by this
415      * <code>ColorModel</code>.
416      * @return the number of bits per pixel.
417      */

418     public int getPixelSize() {
419     return pixel_bits;
420     }
421
422     /**
423      * Returns the number of bits for the specified color/alpha component.
424      * Color components are indexed in the order specified by the
425      * <code>ColorSpace</code>. Typically, this order reflects the name
426      * of the color space type. For example, for TYPE_RGB, index 0
427      * corresponds to red, index 1 to green, and index 2
428      * to blue. If this <code>ColorModel</code> supports alpha, the alpha
429      * component corresponds to the index following the last color
430      * component.
431      * @param componentIdx the index of the color/alpha component
432      * @return the number of bits for the color/alpha component at the
433      * specified index.
434      * @throws ArrayIndexOutOfBoundsException if <code>componentIdx</code>
435      * is greater than the number of components or
436      * less than zero
437      * @throws NullPointerException if the number of bits array is
438      * <code>null</code>
439      */

440     public int getComponentSize(int componentIdx) {
441         // REMIND:
442
if (nBits == null) {
443             throw new NullPointerException JavaDoc("Number of bits array is null.");
444         }
445         
446         return nBits[componentIdx];
447     }
448     
449     /**
450      * Returns an array of the number of bits per color/alpha component.
451      * The array contains the color components in the order specified by the
452      * <code>ColorSpace</code>, followed by the alpha component, if
453      * present.
454      * @return an array of the number of bits per color/alpha component
455      */

456     public int[] getComponentSize() {
457         if (nBits != null) {
458             return (int[]) nBits.clone();
459         }
460
461         return null;
462     }
463
464     /**
465      * Returns the transparency. Returns either OPAQUE, BITMASK,
466      * or TRANSLUCENT.
467      * @return the transparency of this <code>ColorModel</code>.
468      * @see Transparency#OPAQUE
469      * @see Transparency#BITMASK
470      * @see Transparency#TRANSLUCENT
471      */

472     public int getTransparency() {
473         return transparency;
474     }
475
476     /**
477      * Returns the number of components, including alpha, in this
478      * <code>ColorModel</code>. This is equal to the number of color
479      * components, optionally plus one, if there is an alpha component.
480      * @return the number of components in this <code>ColorModel</code>
481      */

482     public int getNumComponents() {
483         return numComponents;
484     }
485     
486     /**
487      * Returns the number of color components in this
488      * <code>ColorModel</code>.
489      * This is the number of components returned by
490      * {@link ColorSpace#getNumComponents}.
491      * @return the number of color components in this
492      * <code>ColorModel</code>.
493      * @see ColorSpace#getNumComponents
494      */

495     public int getNumColorComponents() {
496         return numColorComponents;
497     }
498
499     /**
500      * Returns the red color component for the specified pixel, scaled
501      * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
502      * is done if necessary. The pixel value is specified as an int.
503      * An <code>IllegalArgumentException</code> is thrown if pixel
504      * values for this <code>ColorModel</code> are not conveniently
505      * representable as a single int. The returned value is not a
506      * pre-multiplied value. For example, if the
507      * alpha is premultiplied, this method divides it out before returning
508      * the value. If the alpha value is 0, the red value is 0.
509      * @param pixel a specified pixel
510      * @return the value of the red component of the specified pixel.
511      */

512     public abstract int getRed(int pixel);
513
514     /**
515      * Returns the green color component for the specified pixel, scaled
516      * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
517      * is done if necessary. The pixel value is specified as an int.
518      * An <code>IllegalArgumentException</code> is thrown if pixel
519      * values for this <code>ColorModel</code> are not conveniently
520      * representable as a single int. The returned value is a non
521      * pre-multiplied value. For example, if the alpha is premultiplied,
522      * this method divides it out before returning
523      * the value. If the alpha value is 0, the green value is 0.
524      * @param pixel the specified pixel
525      * @return the value of the green component of the specified pixel.
526      */

527     public abstract int getGreen(int pixel);
528
529     /**
530      * Returns the blue color component for the specified pixel, scaled
531      * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
532      * is done if necessary. The pixel value is specified as an int.
533      * An <code>IllegalArgumentException</code> is thrown if pixel values
534      * for this <code>ColorModel</code> are not conveniently representable
535      * as a single int. The returned value is a non pre-multiplied
536      * value, for example, if the alpha is premultiplied, this method
537      * divides it out before returning the value. If the alpha value is
538      * 0, the blue value is 0.
539      * @param pixel the specified pixel
540      * @return the value of the blue component of the specified pixel.
541      */

542     public abstract int getBlue(int pixel);
543
544     /**
545      * Returns the alpha component for the specified pixel, scaled
546      * from 0 to 255. The pixel value is specified as an int.
547      * An <code>IllegalArgumentException</code> is thrown if pixel
548      * values for this <code>ColorModel</code> are not conveniently
549      * representable as a single int.
550      * @param pixel the specified pixel
551      * @return the value of alpha component of the specified pixel.
552      */

553     public abstract int getAlpha(int pixel);
554
555     /**
556      * Returns the color/alpha components of the pixel in the default
557      * RGB color model format. A color conversion is done if necessary.
558      * The pixel value is specified as an int.
559      * An <code>IllegalArgumentException</code> thrown if pixel values
560      * for this <code>ColorModel</code> are not conveniently representable
561      * as a single int. The returned value is in a non
562      * pre-multiplied format. For example, if the alpha is premultiplied,
563      * this method divides it out of the color components. If the alpha
564      * value is 0, the color values are 0.
565      * @param pixel the specified pixel
566      * @return the RGB value of the color/alpha components of the
567      * specified pixel.
568      * @see ColorModel#getRGBdefault
569      */

570     public int getRGB(int pixel) {
571     return (getAlpha(pixel) << 24)
572         | (getRed(pixel) << 16)
573         | (getGreen(pixel) << 8)
574         | (getBlue(pixel) << 0);
575     }
576
577     /**
578      * Returns the red color component for the specified pixel, scaled
579      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
580      * color conversion is done if necessary. The pixel value is
581      * specified by an array of data elements of type transferType passed
582      * in as an object reference. The returned value is a non
583      * pre-multiplied value. For example, if alpha is premultiplied,
584      * this method divides it out before returning
585      * the value. If the alpha value is 0, the red value is 0.
586      * If <code>inData</code> is not a primitive array of type
587      * transferType, a <code>ClassCastException</code> is thrown. An
588      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
589      * <code>inData</code> is not large enough to hold a pixel value for
590      * this <code>ColorModel</code>.
591      * If this <code>transferType</code> is not supported, a
592      * <code>UnsupportedOperationException</code> will be
593      * thrown. Since
594      * <code>ColorModel</code> is an abstract class, any instance
595      * must be an instance of a subclass. Subclasses inherit the
596      * implementation of this method and if they don't override it, this
597      * method throws an exception if the subclass uses a
598      * <code>transferType</code> other than
599      * <code>DataBuffer.TYPE_BYTE</code>,
600      * <code>DataBuffer.TYPE_USHORT</code>, or
601      * <code>DataBuffer.TYPE_INT</code>.
602      * @param inData an array of pixel values
603      * @return the value of the red component of the specified pixel.
604      * @throws ClassCastException if <code>inData</code>
605      * is not a primitive array of type <code>transferType</code>
606      * @throws ArrayIndexOutOfBoundsException if
607      * <code>inData</code> is not large enough to hold a pixel value
608      * for this <code>ColorModel</code>
609      * @throws UnsupportedOperationException if this
610      * <code>tranferType</code> is not supported by this
611      * <code>ColorModel</code>
612      */

613     public int getRed(Object JavaDoc inData) {
614         int pixel=0,length=0;
615         switch (transferType) {
616             case DataBuffer.TYPE_BYTE:
617                byte bdata[] = (byte[])inData;
618                pixel = bdata[0] & 0xff;
619                length = bdata.length;
620             break;
621             case DataBuffer.TYPE_USHORT:
622                short sdata[] = (short[])inData;
623                pixel = sdata[0] & 0xffff;
624                length = sdata.length;
625             break;
626             case DataBuffer.TYPE_INT:
627                int idata[] = (int[])inData;
628                pixel = idata[0];
629                length = idata.length;
630             break;
631             default:
632                throw new UnsupportedOperationException JavaDoc("This method has not been "+
633                    "implemented for transferType " + transferType);
634         }
635         if (length == 1) {
636             return getRed(pixel);
637         }
638         else {
639             throw new UnsupportedOperationException JavaDoc
640                 ("This method is not supported by this color model");
641         }
642     }
643
644     /**
645      * Returns the green color component for the specified pixel, scaled
646      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
647      * color conversion is done if necessary. The pixel value is
648      * specified by an array of data elements of type transferType passed
649      * in as an object reference. The returned value will be a non
650      * pre-multiplied value. For example, if the alpha is premultiplied,
651      * this method divides it out before returning the value. If the
652      * alpha value is 0, the green value is 0. If <code>inData</code> is
653      * not a primitive array of type transferType, a
654      * <code>ClassCastException</code> is thrown. An
655      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
656      * <code>inData</code> is not large enough to hold a pixel value for
657      * this <code>ColorModel</code>.
658      * If this <code>transferType</code> is not supported, a
659      * <code>UnsupportedOperationException</code> will be
660      * thrown. Since
661      * <code>ColorModel</code> is an abstract class, any instance
662      * must be an instance of a subclass. Subclasses inherit the
663      * implementation of this method and if they don't override it, this
664      * method throws an exception if the subclass uses a
665      * <code>transferType</code> other than
666      * <code>DataBuffer.TYPE_BYTE</code>,
667      * <code>DataBuffer.TYPE_USHORT</code>, or
668      * <code>DataBuffer.TYPE_INT</code>.
669      * @param inData an array of pixel values
670      * @return the value of the green component of the specified pixel.
671      * @throws <code>ClassCastException</code> if <code>inData</code>
672      * is not a primitive array of type <code>transferType</code>
673      * @throws <code>ArrayIndexOutOfBoundsException</code> if
674      * <code>inData</code> is not large enough to hold a pixel value
675      * for this <code>ColorModel</code>
676      * @throws <code>UnsupportedOperationException</code> if this
677      * <code>tranferType</code> is not supported by this
678      * <code>ColorModel</code>
679      */

680     public int getGreen(Object JavaDoc inData) {
681         int pixel=0,length=0;
682         switch (transferType) {
683             case DataBuffer.TYPE_BYTE:
684                byte bdata[] = (byte[])inData;
685                pixel = bdata[0] & 0xff;
686                length = bdata.length;
687             break;
688             case DataBuffer.TYPE_USHORT:
689                short sdata[] = (short[])inData;
690                pixel = sdata[0] & 0xffff;
691                length = sdata.length;
692             break;
693             case DataBuffer.TYPE_INT:
694                int idata[] = (int[])inData;
695                pixel = idata[0];
696                length = idata.length;
697             break;
698             default:
699                throw new UnsupportedOperationException JavaDoc("This method has not been "+
700                    "implemented for transferType " + transferType);
701         }
702         if (length == 1) {
703             return getGreen(pixel);
704         }
705         else {
706             throw new UnsupportedOperationException JavaDoc
707                 ("This method is not supported by this color model");
708         }
709     }
710     
711     /**
712      * Returns the blue color component for the specified pixel, scaled
713      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
714      * color conversion is done if necessary. The pixel value is
715      * specified by an array of data elements of type transferType passed
716      * in as an object reference. The returned value is a non
717      * pre-multiplied value. For example, if the alpha is premultiplied,
718      * this method divides it out before returning the value. If the
719      * alpha value is 0, the blue value will be 0. If
720      * <code>inData</code> is not a primitive array of type transferType,
721      * a <code>ClassCastException</code> is thrown. An
722      * <code>ArrayIndexOutOfBoundsException</code> is
723      * thrown if <code>inData</code> is not large enough to hold a pixel
724      * value for this <code>ColorModel</code>.
725      * If this <code>transferType</code> is not supported, a
726      * <code>UnsupportedOperationException</code> will be
727      * thrown. Since
728      * <code>ColorModel</code> is an abstract class, any instance
729      * must be an instance of a subclass. Subclasses inherit the
730      * implementation of this method and if they don't override it, this
731      * method throws an exception if the subclass uses a
732      * <code>transferType</code> other than
733      * <code>DataBuffer.TYPE_BYTE</code>,
734      * <code>DataBuffer.TYPE_USHORT</code>, or
735      * <code>DataBuffer.TYPE_INT</code>.
736      * @param inData an array of pixel values
737      * @return the value of the blue component of the specified pixel.
738      * @throws ClassCastException if <code>inData</code>
739      * is not a primitive array of type <code>transferType</code>
740      * @throws ArrayIndexOutOfBoundsException if
741      * <code>inData</code> is not large enough to hold a pixel value
742      * for this <code>ColorModel</code>
743      * @throws UnsupportedOperationException if this
744      * <code>tranferType</code> is not supported by this
745      * <code>ColorModel</code>
746      */

747     public int getBlue(Object JavaDoc inData) {
748         int pixel=0,length=0;
749         switch (transferType) {
750             case DataBuffer.TYPE_BYTE:
751                byte bdata[] = (byte[])inData;
752                pixel = bdata[0] & 0xff;
753                length = bdata.length;
754             break;
755             case DataBuffer.TYPE_USHORT:
756                short sdata[] = (short[])inData;
757                pixel = sdata[0] & 0xffff;
758                length = sdata.length;
759             break;
760             case DataBuffer.TYPE_INT:
761                int idata[] = (int[])inData;
762                pixel = idata[0];
763                length = idata.length;
764             break;
765             default:
766                throw new UnsupportedOperationException JavaDoc("This method has not been "+
767                    "implemented for transferType " + transferType);
768         }
769         if (length == 1) {
770             return getBlue(pixel);
771         }
772         else {
773             throw new UnsupportedOperationException JavaDoc
774                 ("This method is not supported by this color model");
775         }
776     }
777
778     /**
779      * Returns the alpha component for the specified pixel, scaled
780      * from 0 to 255. The pixel value is specified by an array of data
781      * elements of type transferType passed in as an object reference.
782      * If inData is not a primitive array of type transferType, a
783      * <code>ClassCastException</code> is thrown. An
784      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
785      * <code>inData</code> is not large enough to hold a pixel value for
786      * this <code>ColorModel</code>.
787      * If this <code>transferType</code> is not supported, a
788      * <code>UnsupportedOperationException</code> will be
789      * thrown. Since
790      * <code>ColorModel</code> is an abstract class, any instance
791      * must be an instance of a subclass. Subclasses inherit the
792      * implementation of this method and if they don't override it, this
793      * method throws an exception if the subclass uses a
794      * <code>transferType</code> other than
795      * <code>DataBuffer.TYPE_BYTE</code>,
796      * <code>DataBuffer.TYPE_USHORT</code>, or
797      * <code>DataBuffer.TYPE_INT</code>.
798      * @param inData the specified pixel
799      * @return the alpha component of the specified pixel, scaled from
800      * 0 to 255.
801      * @throws ClassCastException if <code>inData</code>
802      * is not a primitive array of type <code>transferType</code>
803      * @throws ArrayIndexOutOfBoundsException if
804      * <code>inData</code> is not large enough to hold a pixel value
805      * for this <code>ColorModel</code>
806      * @throws UnsupportedOperationException if this
807      * <code>tranferType</code> is not supported by this
808      * <code>ColorModel</code>
809      */

810     public int getAlpha(Object JavaDoc inData) {
811         int pixel=0,length=0;
812         switch (transferType) {
813             case DataBuffer.TYPE_BYTE:
814                byte bdata[] = (byte[])inData;
815                pixel = bdata[0] & 0xff;
816                length = bdata.length;
817             break;
818             case DataBuffer.TYPE_USHORT:
819                short sdata[] = (short[])inData;
820                pixel = sdata[0] & 0xffff;
821                length = sdata.length;
822             break;
823             case DataBuffer.TYPE_INT:
824                int idata[] = (int[])inData;
825                pixel = idata[0];
826                length = idata.length;
827             break;
828             default:
829                throw new UnsupportedOperationException JavaDoc("This method has not been "+
830                    "implemented for transferType " + transferType);
831         }
832         if (length == 1) {
833             return getAlpha(pixel);
834         }
835         else {
836             throw new UnsupportedOperationException JavaDoc
837                 ("This method is not supported by this color model");
838         }
839     }
840
841     /**
842      * Returns the color/alpha components for the specified pixel in the
843      * default RGB color model format. A color conversion is done if
844      * necessary. The pixel value is specified by an array of data
845      * elements of type transferType passed in as an object reference.
846      * If inData is not a primitive array of type transferType, a
847      * <code>ClassCastException</code> is thrown. An
848      * <code>ArrayIndexOutOfBoundsException</code> is
849      * thrown if <code>inData</code> is not large enough to hold a pixel
850      * value for this <code>ColorModel</code>.
851      * The returned value will be in a non pre-multiplied format, i.e. if
852      * the alpha is premultiplied, this method will divide it out of the
853      * color components (if the alpha value is 0, the color values will be 0).
854      * @param inData the specified pixel
855      * @return the color and alpha components of the specified pixel.
856      * @see ColorModel#getRGBdefault
857      */

858     public int getRGB(Object JavaDoc inData) {
859         return (getAlpha(inData) << 24)
860             | (getRed(inData) << 16)
861             | (getGreen(inData) << 8)
862             | (getBlue(inData) << 0);
863     }
864
865     /**
866      * Returns a data element array representation of a pixel in this
867      * <code>ColorModel</code>, given an integer pixel representation in
868      * the default RGB color model.
869      * This array can then be passed to the
870      * {@link WritableRaster#setDataElements} method of
871      * a {@link WritableRaster} object. If the pixel variable is
872      * <code>null</code>, a new array will be allocated. If
873      * <code>pixel</code> is not
874      * <code>null</code>, it must be a primitive array of type
875      * <code>transferType</code>; otherwise, a
876      * <code>ClassCastException</code> is thrown. An
877      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
878      * <code>pixel</code> is
879      * not large enough to hold a pixel value for this
880      * <code>ColorModel</code>. The pixel array is returned.
881      * If this <code>transferType</code> is not supported, a
882      * <code>UnsupportedOperationException</code> will be
883      * thrown. Since <code>ColorModel</code> is an abstract class,
884      * any instance is an instance of a subclass. Subclasses must
885      * override this method since the implementation in this abstract
886      * class throws an <code>UnsupportedOperationException</code>.
887      * @param rgb the integer pixel representation in the default RGB
888      * color model
889      * @param pixel the specified pixel
890      * @return an array representation of the specified pixel in this
891      * <code>ColorModel</code>.
892      * @throws ClassCastException if <code>pixel</code>
893      * is not a primitive array of type <code>transferType</code>
894      * @throws ArrayIndexOutOfBoundsException if
895      * <code>pixel</code> is not large enough to hold a pixel value
896      * for this <code>ColorModel</code>
897      * @throws UnsupportedOperationException if this
898      * method is not supported by this <code>ColorModel</code>
899      * @see WritableRaster#setDataElements
900      * @see SampleModel#setDataElements
901      */

902     public Object JavaDoc getDataElements(int rgb, Object JavaDoc pixel) {
903         throw new UnsupportedOperationException JavaDoc
904             ("This method is not supported by this color model.");
905     }
906     
907     /**
908      * Returns an array of unnormalized color/alpha components given a pixel
909      * in this <code>ColorModel</code>. The pixel value is specified as
910      * an <code>int</code>. An <code>IllegalArgumentException</code>
911      * will be thrown if pixel values for this <code>ColorModel</code> are
912      * not conveniently representable as a single <code>int</code> or if
913      * color component values for this <code>ColorModel</code> are not
914      * conveniently representable in the unnormalized form.
915      * For example, this method can be used to retrieve the
916      * components for a specific pixel value in a
917      * <code>DirectColorModel</code>. If the components array is
918      * <code>null</code>, a new array will be allocated. The
919      * components array will be returned. Color/alpha components are
920      * stored in the components array starting at <code>offset</code>
921      * (even if the array is allocated by this method). An
922      * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
923      * components array is not <code>null</code> and is not large
924      * enough to hold all the color and alpha components (starting at offset).
925      * Since <code>ColorModel</code> is an abstract class,
926      * any instance is an instance of a subclass. Subclasses must
927      * override this method since the implementation in this abstract
928      * class throws an <code>UnsupportedOperationException</code>.
929      * @param pixel the specified pixel
930      * @param components the array to receive the color and alpha
931      * components of the specified pixel
932      * @param offset the offset into the <code>components</code> array at
933      * which to start storing the color and alpha components
934      * @return an array containing the color and alpha components of the
935      * specified pixel starting at the specified offset.
936      * @throws UnsupportedOperationException if this
937      * method is not supported by this <code>ColorModel</code>
938      */

939     public int[] getComponents(int pixel, int[] components, int offset) {
940         throw new UnsupportedOperationException JavaDoc
941             ("This method is not supported by this color model.");
942     }
943     
944     /**
945      * Returns an array of unnormalized color/alpha components given a pixel
946      * in this <code>ColorModel</code>. The pixel value is specified by
947      * an array of data elements of type transferType passed in as an
948      * object reference. If <code>pixel</code> is not a primitive array
949      * of type transferType, a <code>ClassCastException</code> is thrown.
950      * An <code>IllegalArgumentException</code> will be thrown if color
951      * component values for this <code>ColorModel</code> are not
952      * conveniently representable in the unnormalized form.
953      * An <code>ArrayIndexOutOfBoundsException</code> is
954      * thrown if <code>pixel</code> is not large enough to hold a pixel
955      * value for this <code>ColorModel</code>.
956      * This method can be used to retrieve the components for a specific
957      * pixel value in any <code>ColorModel</code>. If the components
958      * array is <code>null</code>, a new array will be allocated. The
959      * components array will be returned. Color/alpha components are
960      * stored in the <code>components</code> array starting at
961      * <code>offset</code> (even if the array is allocated by this
962      * method). An <code>ArrayIndexOutOfBoundsException</code>
963      * is thrown if the components array is not <code>null</code> and is
964      * not large enough to hold all the color and alpha components
965      * (starting at <code>offset</code>).
966      * Since <code>ColorModel</code> is an abstract class,
967      * any instance is an instance of a subclass. Subclasses must
968      * override this method since the implementation in this abstract
969      * class throws an <code>UnsupportedOperationException</code>.
970      * @param pixel the specified pixel
971      * @param components an array that receives the color and alpha
972      * components of the specified pixel
973      * @param offset the index into the <code>components</code> array at
974      * which to begin storing the color and alpha components of the
975      * specified pixel
976      * @return an array containing the color and alpha components of the
977      * specified pixel starting at the specified offset.
978      * @throws UnsupportedOperationException if this
979      * method is not supported by this <code>ColorModel</code>
980      */

981     public int[] getComponents(Object JavaDoc pixel, int[] components, int offset) {
982         throw new UnsupportedOperationException JavaDoc
983             ("This method is not supported by this color model.");
984     }
985
986     /**
987      * Returns an array of all of the color/alpha components in unnormalized
988      * form, given a normalized component array. Unnormalized components
989      * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
990      * n is the number of bits for a particular component. Normalized
991      * components are float values between a per component minimum and
992      * maximum specified by the <code>ColorSpace</code> object for this
993      * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
994      * will be thrown if color component values for this
995      * <code>ColorModel</code> are not conveniently representable in the
996      * unnormalized form. If the
997      * <code>components</code> array is <code>null</code>, a new array
998      * will be allocated. The <code>components</code> array will
999      * be returned. Color/alpha components are stored in the
1000     * <code>components</code> array starting at <code>offset</code> (even
1001     * if the array is allocated by this method). An
1002     * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1003     * <code>components</code> array is not <code>null</code> and is not
1004     * large enough to hold all the color and alpha
1005     * components (starting at <code>offset</code>). An
1006     * <code>IllegalArgumentException</code> is thrown if the
1007     * <code>normComponents</code> array is not large enough to hold
1008     * all the color and alpha components starting at
1009     * <code>normOffset</code>.
1010     * @param normComponents an array containing normalized components
1011     * @param normOffset the offset into the <code>normComponents</code>
1012     * array at which to start retrieving normalized components
1013     * @param components an array that receives the components from
1014     * <code>normComponents</code>
1015     * @param offset the index into <code>components</code> at which to
1016     * begin storing normalized components from
1017     * <code>normComponents</code>
1018     * @return an array containing unnormalized color and alpha
1019     * components.
1020     * @throws IllegalArgumentException If the component values for this
1021     * <CODE>ColorModel</CODE> are not conveniently representable in the
1022     * unnormalized form.
1023     * @throws IllegalArgumentException if the length of
1024     * <code>normComponents</code> minus <code>normOffset</code>
1025     * is less than <code>numComponents</code>
1026     * @throws UnsupportedOperationException if the
1027     * constructor of this <code>ColorModel</code> called the
1028     * <code>super(bits)</code> constructor, but did not
1029     * override this method. See the constructor,
1030     * {@link #ColorModel(int)}.
1031     */

1032    public int[] getUnnormalizedComponents(float[] normComponents,
1033                                           int normOffset,
1034                                           int[] components, int offset) {
1035        // Make sure that someone isn't using a custom color model
1036
// that called the super(bits) constructor.
1037
if (colorSpace == null) {
1038            throw new UnsupportedOperationException JavaDoc("This method is not supported "+
1039                                        "by this color model.");
1040        }
1041
1042        if (nBits == null) {
1043            throw new UnsupportedOperationException JavaDoc ("This method is not supported. "+
1044                                         "Unable to determine #bits per "+
1045                                         "component.");
1046        }
1047        if ((normComponents.length - normOffset) < numComponents) {
1048            throw new
1049                IllegalArgumentException JavaDoc(
1050                        "Incorrect number of components. Expecting "+
1051                        numComponents);
1052        }
1053        
1054        if (components == null) {
1055            components = new int[offset+numComponents];
1056        }
1057
1058        if (supportsAlpha && isAlphaPremultiplied) {
1059            float normAlpha = normComponents[normOffset+numColorComponents];
1060            for (int i=0; i < numColorComponents; i++) {
1061                components[offset+i] = (int) (normComponents[normOffset+i]
1062                                              * ((1<<nBits[i]) - 1)
1063                                              * normAlpha + 0.5f);
1064            }
1065            components[offset+numColorComponents] = (int)
1066                (normAlpha * ((1<<nBits[numColorComponents]) - 1) + 0.5f);
1067        }
1068        else {
1069            for (int i=0; i < numComponents; i++) {
1070                components[offset+i] = (int) (normComponents[normOffset+i]
1071                                              * ((1<<nBits[i]) - 1) + 0.5f);
1072            }
1073        }
1074        
1075        return components;
1076    }
1077
1078    /**
1079     * Returns an array of all of the color/alpha components in normalized
1080     * form, given an unnormalized component array. Unnormalized components
1081     * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1082     * n is the number of bits for a particular component. Normalized
1083     * components are float values between a per component minimum and
1084     * maximum specified by the <code>ColorSpace</code> object for this
1085     * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
1086     * will be thrown if color component values for this
1087     * <code>ColorModel</code> are not conveniently representable in the
1088     * unnormalized form. If the
1089     * <code>normComponents</code> array is <code>null</code>, a new array
1090     * will be allocated. The <code>normComponents</code> array
1091     * will be returned. Color/alpha components are stored in the
1092     * <code>normComponents</code> array starting at
1093     * <code>normOffset</code> (even if the array is allocated by this
1094     * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
1095     * if the <code>normComponents</code> array is not <code>null</code>
1096     * and is not large enough to hold all the color and alpha components
1097     * (starting at <code>normOffset</code>). An
1098     * <code>IllegalArgumentException</code> is thrown if the
1099     * <code>components</code> array is not large enough to hold all the
1100     * color and alpha components starting at <code>offset</code>.
1101     * <p>
1102     * Since <code>ColorModel</code> is an abstract class,
1103     * any instance is an instance of a subclass. The default implementation
1104     * of this method in this abstract class assumes that component values
1105     * for this class are conveniently representable in the unnormalized
1106     * form. Therefore, subclasses which may
1107     * have instances which do not support the unnormalized form must
1108     * override this method.
1109     * @param components an array containing unnormalized components
1110     * @param offset the offset into the <code>components</code> array at
1111     * which to start retrieving unnormalized components
1112     * @param normComponents an array that receives the normalized components
1113     * @param normOffset the index into <code>normComponents</code> at
1114     * which to begin storing normalized components
1115     * @return an array containing normalized color and alpha
1116     * components.
1117     * @throws IllegalArgumentException If the component values for this
1118     * <CODE>ColorModel</CODE> are not conveniently representable in the
1119     * unnormalized form.
1120     * @throws UnsupportedOperationException if the
1121     * constructor of this <code>ColorModel</code> called the
1122     * <code>super(bits)</code> constructor, but did not
1123     * override this method. See the constructor,
1124     * {@link #ColorModel(int)}.
1125     * @throws UnsupportedOperationException if this method is unable
1126     * to determine the number of bits per component
1127     */

1128    public float[] getNormalizedComponents(int[] components, int offset,
1129                                           float[] normComponents,
1130                                           int normOffset) {
1131        // Make sure that someone isn't using a custom color model
1132
// that called the super(bits) constructor.
1133
if (colorSpace == null) {
1134            throw new UnsupportedOperationException JavaDoc("This method is not supported by "+
1135                                        "this color model.");
1136        }
1137        if (nBits == null) {
1138            throw new UnsupportedOperationException JavaDoc ("This method is not supported. "+
1139                                         "Unable to determine #bits per "+
1140                                         "component.");
1141        }
1142        
1143        if ((components.length - offset) < numComponents) {
1144            throw new
1145                IllegalArgumentException JavaDoc(
1146                        "Incorrect number of components. Expecting "+
1147                        numComponents);
1148        }
1149        
1150        if (normComponents == null) {
1151            normComponents = new float[numComponents+normOffset];
1152        }
1153
1154        if (supportsAlpha && isAlphaPremultiplied) {
1155            // Normalized coordinates are non premultiplied
1156
float normAlpha = (float)components[offset+numColorComponents];
1157            normAlpha /= (float) ((1<<nBits[numColorComponents]) - 1);
1158            if (normAlpha != 0.0f) {
1159                for (int i=0; i < numColorComponents; i++) {
1160                    normComponents[normOffset+i] =
1161                        ((float) components[offset+i]) /
1162                        (normAlpha * ((float) ((1<<nBits[i]) - 1)));
1163                }
1164            } else {
1165                for (int i=0; i < numColorComponents; i++) {
1166                    normComponents[normOffset+i] = 0.0f;
1167                }
1168            }
1169            normComponents[normOffset+numColorComponents] = normAlpha;
1170        }
1171        else {
1172            for (int i=0; i < numComponents; i++) {
1173                normComponents[normOffset+i] = ((float) components[offset+i]) /
1174                                               ((float) ((1<<nBits[i]) - 1));
1175            }
1176        }
1177
1178        return normComponents;
1179    }
1180
1181    /**
1182     * Returns a pixel value represented as an <code>int</code> in this
1183     * <code>ColorModel</code>, given an array of unnormalized color/alpha
1184     * components. This method will throw an
1185     * <code>IllegalArgumentException</code> if component values for this
1186     * <code>ColorModel</code> are not conveniently representable as a
1187     * single <code>int</code> or if color component values for this
1188     * <code>ColorModel</code> are not conveniently representable in the
1189     * unnormalized form. An
1190     * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1191     * <code>components</code> array is not large enough to hold all the
1192     * color and alpha components (starting at <code>offset</code>).
1193     * Since <code>ColorModel</code> is an abstract class,
1194     * any instance is an instance of a subclass. Subclasses must
1195     * override this method since the implementation in this abstract
1196     * class throws an <code>UnsupportedOperationException</code>.
1197     * @param components an array of unnormalized color and alpha
1198     * components
1199     * @param offset the index into <code>components</code> at which to
1200     * begin retrieving the color and alpha components
1201     * @return an <code>int</code> pixel value in this
1202     * <code>ColorModel</code> corresponding to the specified components.
1203     * @throws IllegalArgumentException if
1204     * pixel values for this <code>ColorModel</code> are not
1205     * conveniently representable as a single <code>int</code>
1206     * @throws IllegalArgumentException if
1207     * component values for this <code>ColorModel</code> are not
1208     * conveniently representable in the unnormalized form
1209     * @throws ArrayIndexOutOfBoundsException if
1210     * the <code>components</code> array is not large enough to
1211     * hold all of the color and alpha components starting at
1212     * <code>offset</code>
1213     * @throws UnsupportedOperationException if this
1214     * method is not supported by this <code>ColorModel</code>
1215     */

1216    public int getDataElement(int[] components, int offset) {
1217        throw new UnsupportedOperationException JavaDoc("This method is not supported "+
1218                                    "by this color model.");
1219    }
1220    
1221    /**
1222     * Returns a data element array representation of a pixel in this
1223     * <code>ColorModel</code>, given an array of unnormalized color/alpha
1224     * components. This array can then be passed to the
1225     * <code>setDataElements</code> method of a <code>WritableRaster</code>
1226     * object. This method will throw an <code>IllegalArgumentException</code>
1227     * if color component values for this <code>ColorModel</code> are not
1228     * conveniently representable in the unnormalized form.
1229     * An <code>ArrayIndexOutOfBoundsException</code> is thrown
1230     * if the <code>components</code> array is not large enough to hold
1231     * all the color and alpha components (starting at
1232     * <code>offset</code>). If the <code>obj</code> variable is
1233     * <code>null</code>, a new array will be allocated. If
1234     * <code>obj</code> is not <code>null</code>, it must be a primitive
1235     * array of type transferType; otherwise, a
1236     * <code>ClassCastException</code> is thrown. An
1237     * <code>ArrayIndexOutOfBoundsException</code> is thrown if
1238     * <code>obj</code> is not large enough to hold a pixel value for this
1239     * <code>ColorModel</code>.
1240     * Since <code>ColorModel</code> is an abstract class,
1241     * any instance is an instance of a subclass. Subclasses must
1242     * override this method since the implementation in this abstract
1243     * class throws an <code>UnsupportedOperationException</code>.
1244     * @param components an array of unnormalized color and alpha
1245     * components
1246     * @param offset the index into <code>components</code> at which to
1247     * begin retrieving color and alpha components
1248     * @param obj the <code>Object</code> representing an array of color
1249     * and alpha components
1250     * @return an <code>Object</code> representing an array of color and
1251     * alpha components.
1252     * @throws ClassCastException if <code>obj</code>
1253     * is not a primitive array of type <code>transferType</code>
1254     * @throws ArrayIndexOutOfBoundsException if
1255     * <code>obj</code> is not large enough to hold a pixel value
1256     * for this <code>ColorModel</code> or the <code>components</code>
1257     * array is not large enough to hold all of the color and alpha
1258     * components starting at <code>offset</code>
1259     * @throws IllegalArgumentException if
1260     * component values for this <code>ColorModel</code> are not
1261     * conveniently representable in the unnormalized form
1262     * @throws UnsupportedOperationException if this
1263     * method is not supported by this <code>ColorModel</code>
1264     * @see WritableRaster#setDataElements
1265     * @see SampleModel#setDataElements
1266     */

1267    public Object JavaDoc getDataElements(int[] components, int offset, Object JavaDoc obj) {
1268        throw new UnsupportedOperationException JavaDoc("This method has not been implemented "+
1269                                    "for this color model.");
1270    }
1271
1272    /**
1273     * Returns a pixel value represented as an <code>int</code> in this
1274     * <code>ColorModel</code>, given an array of normalized color/alpha
1275     * components. This method will throw an
1276     * <code>IllegalArgumentException</code> if pixel values for this
1277     * <code>ColorModel</code> are not conveniently representable as a
1278     * single <code>int</code>. An
1279     * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1280     * <code>normComponents</code> array is not large enough to hold all the
1281     * color and alpha components (starting at <code>normOffset</code>).
1282     * Since <code>ColorModel</code> is an abstract class,
1283     * any instance is an instance of a subclass. The default implementation
1284     * of this method in this abstract class first converts from the
1285     * normalized form to the unnormalized form and then calls
1286     * <code>getDataElement(int[], int)</code>. Subclasses which may
1287     * have instances which do not support the unnormalized form must
1288     * override this method.
1289     * @param normComponents an array of normalized color and alpha
1290     * components
1291     * @param normOffset the index into <code>normComponents</code> at which to
1292     * begin retrieving the color and alpha components
1293     * @return an <code>int</code> pixel value in this
1294     * <code>ColorModel</code> corresponding to the specified components.
1295     * @throws IllegalArgumentException if
1296     * pixel values for this <code>ColorModel</code> are not
1297     * conveniently representable as a single <code>int</code>
1298     * @throws ArrayIndexOutOfBoundsException if
1299     * the <code>normComponents</code> array is not large enough to
1300     * hold all of the color and alpha components starting at
1301     * <code>normOffset</code>
1302     * @since 1.4
1303     */

1304    public int getDataElement(float[] normComponents, int normOffset) {
1305        int components[] = getUnnormalizedComponents(normComponents,
1306                                                     normOffset, null, 0);
1307        return getDataElement(components, 0);
1308    }
1309    
1310    /**
1311     * Returns a data element array representation of a pixel in this
1312     * <code>ColorModel</code>, given an array of normalized color/alpha
1313     * components. This array can then be passed to the
1314     * <code>setDataElements</code> method of a <code>WritableRaster</code>
1315     * object. An <code>ArrayIndexOutOfBoundsException</code> is thrown
1316     * if the <code>normComponents</code> array is not large enough to hold
1317     * all the color and alpha components (starting at
1318     * <code>normOffset</code>). If the <code>obj</code> variable is
1319     * <code>null</code>, a new array will be allocated. If
1320     * <code>obj</code> is not <code>null</code>, it must be a primitive
1321     * array of type transferType; otherwise, a
1322     * <code>ClassCastException</code> is thrown. An
1323     * <code>ArrayIndexOutOfBoundsException</code> is thrown if
1324     * <code>obj</code> is not large enough to hold a pixel value for this
1325     * <code>ColorModel</code>.
1326     * Since <code>ColorModel</code> is an abstract class,
1327     * any instance is an instance of a subclass. The default implementation
1328     * of this method in this abstract class first converts from the
1329     * normalized form to the unnormalized form and then calls
1330     * <code>getDataElement(int[], int, Object)</code>. Subclasses which may
1331     * have instances which do not support the unnormalized form must
1332     * override this method.
1333     * @param normComponents an array of normalized color and alpha
1334     * components
1335     * @param normOffset the index into <code>normComponents</code> at which to
1336     * begin retrieving color and alpha components
1337     * @param obj a primitive data array to hold the returned pixel
1338     * @return an <code>Object</code> which is a primitive data array
1339     * representation of a pixel
1340     * @throws ClassCastException if <code>obj</code>
1341     * is not a primitive array of type <code>transferType</code>
1342     * @throws ArrayIndexOutOfBoundsException if
1343     * <code>obj</code> is not large enough to hold a pixel value
1344     * for this <code>ColorModel</code> or the <code>normComponents</code>
1345     * array is not large enough to hold all of the color and alpha
1346     * components starting at <code>normOffset</code>
1347     * @see WritableRaster#setDataElements
1348     * @see SampleModel#setDataElements
1349     * @since 1.4
1350     */

1351    public Object JavaDoc getDataElements(float[] normComponents, int normOffset,
1352                                  Object JavaDoc obj) {
1353        int components[] = getUnnormalizedComponents(normComponents,
1354                                                     normOffset, null, 0);
1355        return getDataElements(components, 0, obj);
1356    }
1357
1358    /**
1359     * Returns an array of all of the color/alpha components in normalized
1360     * form, given a pixel in this <code>ColorModel</code>. The pixel
1361     * value is specified by an array of data elements of type transferType
1362     * passed in as an object reference. If pixel is not a primitive array
1363     * of type transferType, a <code>ClassCastException</code> is thrown.
1364     * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
1365     * <code>pixel</code> is not large enough to hold a pixel value for this
1366     * <code>ColorModel</code>.
1367     * Normalized components are float values between a per component minimum
1368     * and maximum specified by the <code>ColorSpace</code> object for this
1369     * <code>ColorModel</code>. If the
1370     * <code>normComponents</code> array is <code>null</code>, a new array
1371     * will be allocated. The <code>normComponents</code> array
1372     * will be returned. Color/alpha components are stored in the
1373     * <code>normComponents</code> array starting at
1374     * <code>normOffset</code> (even if the array is allocated by this
1375     * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
1376     * if the <code>normComponents</code> array is not <code>null</code>
1377     * and is not large enough to hold all the color and alpha components
1378     * (starting at <code>normOffset</code>).
1379     * Since <code>ColorModel</code> is an abstract class,
1380     * any instance is an instance of a subclass. The default implementation
1381     * of this method in this abstract class first retrieves color and alpha
1382     * components in the unnormalized form using
1383     * <code>getComponents(Object, int[], int)</code> and then calls
1384     * <code>getNormalizedComponents(int[], int, float[], int)</code>.
1385     * Subclasses which may
1386     * have instances which do not support the unnormalized form must
1387     * override this method.
1388     * @param pixel the specified pixel
1389     * @param normComponents an array to receive the normalized components
1390     * @param normOffset the offset into the <code>normComponents</code>
1391     * array at which to start storing normalized components
1392     * @return an array containing normalized color and alpha
1393     * components.
1394     * @throws ClassCastException if <code>pixel</code> is not a primitive
1395     * array of type transferType
1396     * @throws ArrayIndexOutOfBoundsException if
1397     * <code>normComponents</code> is not large enough to hold all
1398     * color and alpha components starting at <code>normOffset</code>
1399     * @throws ArrayIndexOutOfBoundsException if
1400     * <code>pixel</code> is not large enough to hold a pixel
1401     * value for this <code>ColorModel</code>.
1402     * @throws UnsupportedOperationException if the
1403     * constructor of this <code>ColorModel</code> called the
1404     * <code>super(bits)</code> constructor, but did not
1405     * override this method. See the constructor,
1406     * {@link #ColorModel(int)}.
1407     * @throws UnsupportedOperationException if this method is unable
1408     * to determine the number of bits per component
1409     * @since 1.4
1410     */

1411    public float[] getNormalizedComponents(Object JavaDoc pixel,
1412                                           float[] normComponents,
1413                                           int normOffset) {
1414        int components[] = getComponents(pixel, null, 0);
1415        return getNormalizedComponents(components, 0,
1416                                       normComponents, normOffset);
1417    }
1418
1419    /**
1420     * Tests if the specified <code>Object</code> is an instance of
1421     * <code>ColorModel</code> and if it equals this
1422     * <code>ColorModel</code>.
1423     * @param obj the <code>Object</code> to test for equality
1424     * @return <code>true</code> if the specified <code>Object</code>
1425     * is an instance of <code>ColorModel</code> and equals this
1426     * <code>ColorModel</code>; <code>false</code> otherwise.
1427     */

1428    public boolean equals(Object JavaDoc obj) {
1429        if (!(obj instanceof ColorModel JavaDoc)) {
1430            return false;
1431        }
1432        ColorModel JavaDoc cm = (ColorModel JavaDoc) obj;
1433        
1434        if (this == cm) {
1435            return true;
1436        }
1437        if (supportsAlpha != cm.hasAlpha() ||
1438            isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
1439            pixel_bits != cm.getPixelSize() ||
1440            transparency != cm.getTransparency() ||
1441            numComponents != cm.getNumComponents())
1442        {
1443            return false;
1444        }
1445
1446        int[] nb = cm.getComponentSize();
1447
1448        if ((nBits != null) && (nb != null)) {
1449            for (int i = 0; i < numComponents; i++) {
1450                if (nBits[i] != nb[i]) {
1451                    return false;
1452                }
1453            }
1454        } else {
1455            return ((nBits == null) && (nb == null));
1456        }
1457
1458        return true;
1459    }
1460
1461    /**
1462     * Returns the hash code for this ColorModel.
1463     *
1464     * @return a hash code for this ColorModel.
1465     */

1466    public int hashCode() {
1467        
1468        int result = 0;
1469
1470        result = (supportsAlpha ? 2 : 3) +
1471                 (isAlphaPremultiplied ? 4 : 5) +
1472                 pixel_bits * 6 +
1473                 transparency * 7 +
1474                 numComponents * 8;
1475
1476        if (nBits != null) {
1477            for (int i = 0; i < numComponents; i++) {
1478                result = result + nBits[i] * (i + 9);
1479            }
1480        }
1481
1482        return result;
1483    }
1484    
1485    /**
1486     * Returns the <code>ColorSpace</code> associated with this
1487     * <code>ColorModel</code>.
1488     * @return the <code>ColorSpace</code> of this
1489     * <code>ColorModel</code>.
1490     */

1491    final public ColorSpace JavaDoc getColorSpace() {
1492        return colorSpace;
1493    }
1494
1495    /**
1496     * Forces the raster data to match the state specified in the
1497     * <code>isAlphaPremultiplied</code> variable, assuming the data is
1498     * currently correctly described by this <code>ColorModel</code>. It
1499     * may multiply or divide the color raster data by alpha, or do
1500     * nothing if the data is in the correct state. If the data needs to
1501     * be coerced, this method will also return an instance of this
1502     * <code>ColorModel</code> with the <code>isAlphaPremultiplied</code>
1503     * flag set appropriately. This method will throw a
1504     * <code>UnsupportedOperationException</code> if it is not supported
1505     * by this <code>ColorModel</code>.
1506     * Since <code>ColorModel</code> is an abstract class,
1507     * any instance is an instance of a subclass. Subclasses must
1508     * override this method since the implementation in this abstract
1509     * class throws an <code>UnsupportedOperationException</code>.
1510     * @param raster the <code>WritableRaster</code> data
1511     * @param isAlphaPremultiplied <code>true</code> if the alpha is
1512     * premultiplied; <code>false</code> otherwise
1513     * @return a <code>ColorModel</code> object that represents the
1514     * coerced data.
1515     */

1516    public ColorModel JavaDoc coerceData (WritableRaster JavaDoc raster,
1517                                  boolean isAlphaPremultiplied) {
1518        throw new UnsupportedOperationException JavaDoc
1519            ("This method is not supported by this color model");
1520    }
1521
1522    /**
1523      * Returns <code>true</code> if <code>raster</code> is compatible
1524      * with this <code>ColorModel</code> and <code>false</code> if it is
1525      * not.
1526      * Since <code>ColorModel</code> is an abstract class,
1527      * any instance is an instance of a subclass. Subclasses must
1528      * override this method since the implementation in this abstract
1529      * class throws an <code>UnsupportedOperationException</code>.
1530      * @param raster the {@link Raster} object to test for compatibility
1531      * @return <code>true</code> if <code>raster</code> is compatible
1532      * with this <code>ColorModel</code>.
1533      * @throws UnsupportedOperationException if this
1534      * method has not been implemented for this
1535      * <code>ColorModel</code>
1536      */

1537    public boolean isCompatibleRaster(Raster JavaDoc raster) {
1538    throw new UnsupportedOperationException JavaDoc(
1539            "This method has not been implemented for this ColorModel.");
1540    }
1541
1542    /**
1543     * Creates a <code>WritableRaster</code> with the specified width and
1544     * height that has a data layout (<code>SampleModel</code>) compatible
1545     * with this <code>ColorModel</code>.
1546     * Since <code>ColorModel</code> is an abstract class,
1547     * any instance is an instance of a subclass. Subclasses must
1548     * override this method since the implementation in this abstract
1549     * class throws an <code>UnsupportedOperationException</code>.
1550     * @param w the width to apply to the new <code>WritableRaster</code>
1551     * @param h the height to apply to the new <code>WritableRaster</code>
1552     * @return a <code>WritableRaster</code> object with the specified
1553     * width and height.
1554     * @throws UnsupportedOperationException if this
1555     * method is not supported by this <code>ColorModel</code>
1556     * @see WritableRaster
1557     * @see SampleModel
1558     */

1559    public WritableRaster JavaDoc createCompatibleWritableRaster(int w, int h) {
1560    throw new UnsupportedOperationException JavaDoc
1561            ("This method is not supported by this color model");
1562    }
1563    
1564    /**
1565     * Creates a <code>SampleModel</code> with the specified width and
1566     * height that has a data layout compatible with this
1567     * <code>ColorModel</code>.
1568     * Since <code>ColorModel</code> is an abstract class,
1569     * any instance is an instance of a subclass. Subclasses must
1570     * override this method since the implementation in this abstract
1571     * class throws an <code>UnsupportedOperationException</code>.
1572     * @param w the width to apply to the new <code>SampleModel</code>
1573     * @param h the height to apply to the new <code>SampleModel</code>
1574     * @return a <code>SampleModel</code> object with the specified
1575     * width and height.
1576     * @throws UnsupportedOperationException if this
1577     * method is not supported by this <code>ColorModel</code>
1578     * @see SampleModel
1579     */

1580    public SampleModel JavaDoc createCompatibleSampleModel(int w, int h) {
1581    throw new UnsupportedOperationException JavaDoc
1582            ("This method is not supported by this color model");
1583    }
1584
1585    /** Checks if the <code>SampleModel</code> is compatible with this
1586     * <code>ColorModel</code>.
1587     * Since <code>ColorModel</code> is an abstract class,
1588     * any instance is an instance of a subclass. Subclasses must
1589     * override this method since the implementation in this abstract
1590     * class throws an <code>UnsupportedOperationException</code>.
1591     * @param sm the specified <code>SampleModel</code>
1592     * @return <code>true</code> if the specified <code>SampleModel</code>
1593     * is compatible with this <code>ColorModel</code>; <code>false</code>
1594     * otherwise.
1595     * @throws UnsupportedOperationException if this
1596     * method is not supported by this <code>ColorModel</code>
1597     * @see SampleModel
1598     */

1599    public boolean isCompatibleSampleModel(SampleModel JavaDoc sm) {
1600    throw new UnsupportedOperationException JavaDoc
1601            ("This method is not supported by this color model");
1602    }
1603    
1604    /**
1605     * Disposes of system resources associated with this
1606     * <code>ColorModel</code> once this <code>ColorModel</code> is no
1607     * longer referenced.
1608     */

1609    public void finalize() {
1610    }
1611
1612
1613    /**
1614     * Returns a <code>Raster</code> representing the alpha channel of an
1615     * image, extracted from the input <code>Raster</code>, provided that
1616     * pixel values of this <code>ColorModel</code> represent color and
1617     * alpha information as separate spatial bands (e.g.
1618     * {@link ComponentColorModel} and <code>DirectColorModel</code>).
1619     * This method assumes that <code>Raster</code> objects associated
1620     * with such a <code>ColorModel</code> store the alpha band, if
1621     * present, as the last band of image data. Returns <code>null</code>
1622     * if there is no separate spatial alpha channel associated with this
1623     * <code>ColorModel</code>. If this is an
1624     * <code>IndexColorModel</code> which has alpha in the lookup table,
1625     * this method will return <code>null</code> since
1626     * there is no spatially discrete alpha channel.
1627     * This method will create a new <code>Raster</code> (but will share
1628     * the data array).
1629     * Since <code>ColorModel</code> is an abstract class, any instance
1630     * is an instance of a subclass. Subclasses must override this
1631     * method to get any behavior other than returning <code>null</code>
1632     * because the implementation in this abstract class returns
1633     * <code>null</code>.
1634     * @param raster the specified <code>Raster</code>
1635     * @return a <code>Raster</code> representing the alpha channel of
1636     * an image, obtained from the specified <code>Raster</code>.
1637     */

1638    public WritableRaster JavaDoc getAlphaRaster(WritableRaster JavaDoc raster) {
1639        return null;
1640    }
1641
1642    /**
1643     * Returns the <code>String</code> representation of the contents of
1644     * this <code>ColorModel</code>object.
1645     * @return a <code>String</code> representing the contents of this
1646     * <code>ColorModel</code> object.
1647     */

1648    public String JavaDoc toString() {
1649       return new String JavaDoc("ColorModel: #pixelBits = "+pixel_bits
1650                         + " numComponents = "+numComponents
1651                         + " color space = "+colorSpace
1652                         + " transparency = "+transparency
1653                         + " has alpha = "+supportsAlpha
1654                         + " isAlphaPre = "+isAlphaPremultiplied
1655                         );
1656    }
1657
1658    static int getDefaultTransferType(int pixel_bits) {
1659        if (pixel_bits <= 8) {
1660            return DataBuffer.TYPE_BYTE;
1661        } else if (pixel_bits <= 16) {
1662            return DataBuffer.TYPE_USHORT;
1663        } else if (pixel_bits <= 32) {
1664            return DataBuffer.TYPE_INT;
1665        } else {
1666            return DataBuffer.TYPE_UNDEFINED;
1667        }
1668    }
1669
1670    static byte[] l8Tos8 = null; // 8-bit linear to 8-bit non-linear sRGB LUT
1671
static byte[] s8Tol8 = null; // 8-bit non-linear sRGB to 8-bit linear LUT
1672
static byte[] l16Tos8 = null; // 16-bit linear to 8-bit non-linear sRGB LUT
1673
static short[] s8Tol16 = null; // 8-bit non-linear sRGB to 16-bit linear LUT
1674

1675                                // Maps to hold LUTs for grayscale conversions
1676
static Map JavaDoc g8Tos8Map = null; // 8-bit gray values to 8-bit sRGB values
1677
static Map JavaDoc lg16Toog8Map = null; // 16-bit linear to 8-bit "other" gray
1678
static Map JavaDoc g16Tos8Map = null; // 16-bit gray values to 8-bit sRGB values
1679
static Map JavaDoc lg16Toog16Map = null; // 16-bit linear to 16-bit "other" gray
1680

1681    static boolean isLinearRGBspace(ColorSpace JavaDoc cs) {
1682        // Note: CMM.LINEAR_RGBspace will be null if the linear
1683
// RGB space has not been created yet.
1684
return (cs == CMM.LINEAR_RGBspace);
1685    }
1686
1687    static boolean isLinearGRAYspace(ColorSpace JavaDoc cs) {
1688        // Note: CMM.GRAYspace will be null if the linear
1689
// gray space has not been created yet.
1690
return (cs == CMM.GRAYspace);
1691    }
1692
1693    static byte[] getLinearRGB8TosRGB8LUT() {
1694        if (l8Tos8 == null) {
1695            l8Tos8 = new byte[256];
1696            float input, output;
1697            // algorithm for linear RGB to nonlinear sRGB conversion
1698
// is from the IEC 61966-2-1 International Standard,
1699
// Colour Management - Default RGB colour space - sRGB,
1700
// First Edition, 1999-10,
1701
// avaiable for order at http://www.iec.ch
1702
for (int i = 0; i <= 255; i++) {
1703                input = ((float) i) / 255.0f;
1704                if (input <= 0.0031308f) {
1705                    output = input * 12.92f;
1706                } else {
1707                    output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4)))
1708                             - 0.055f;
1709                }
1710                l8Tos8[i] = (byte) Math.round(output * 255.0f);
1711            }
1712        }
1713        return l8Tos8;
1714    }
1715
1716    static byte[] getsRGB8ToLinearRGB8LUT() {
1717        if (s8Tol8 == null) {
1718            s8Tol8 = new byte[256];
1719            float input, output;
1720            // algorithm from IEC 61966-2-1 International Standard
1721
for (int i = 0; i <= 255; i++) {
1722                input = ((float) i) / 255.0f;
1723                if (input <= 0.04045f) {
1724                    output = input / 12.92f;
1725                } else {
1726                    output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4);
1727                }
1728                s8Tol8[i] = (byte) Math.round(output * 255.0f);
1729            }
1730        }
1731        return s8Tol8;
1732    }
1733
1734    static byte[] getLinearRGB16TosRGB8LUT() {
1735        if (l16Tos8 == null) {
1736            l16Tos8 = new byte[65536];
1737            float input, output;
1738            // algorithm from IEC 61966-2-1 International Standard
1739
for (int i = 0; i <= 65535; i++) {
1740                input = ((float) i) / 65535.0f;
1741                if (input <= 0.0031308f) {
1742                    output = input * 12.92f;
1743                } else {
1744                    output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4)))
1745                             - 0.055f;
1746                }
1747                l16Tos8[i] = (byte) Math.round(output * 255.0f);
1748            }
1749        }
1750        return l16Tos8;
1751    }
1752
1753    static short[] getsRGB8ToLinearRGB16LUT() {
1754        if (s8Tol16 == null) {
1755            s8Tol16 = new short[256];
1756            float input, output;
1757            // algorithm from IEC 61966-2-1 International Standard
1758
for (int i = 0; i <= 255; i++) {
1759                input = ((float) i) / 255.0f;
1760                if (input <= 0.04045f) {
1761                    output = input / 12.92f;
1762                } else {
1763                    output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4);
1764                }
1765                s8Tol16[i] = (short) Math.round(output * 65535.0f);
1766            }
1767        }
1768        return s8Tol16;
1769    }
1770
1771    /*
1772     * Return a byte LUT that converts 8-bit gray values in the grayCS
1773     * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut
1774     * is the byte array returned by this method and sval = lut[gval],
1775     * then the sRGB triple (sval,sval,sval) is the best match to gval.
1776     * Cache references to any computed LUT in a Map.
1777     */

1778    static byte[] getGray8TosRGB8LUT(ICC_ColorSpace JavaDoc grayCS) {
1779        if (isLinearGRAYspace(grayCS)) {
1780            return getLinearRGB8TosRGB8LUT();
1781        }
1782        if (g8Tos8Map != null) {
1783            byte[] g8Tos8LUT = (byte []) g8Tos8Map.get(grayCS);
1784            if (g8Tos8LUT != null) {
1785                return g8Tos8LUT;
1786            }
1787        }
1788        byte[] g8Tos8LUT = new byte[256];
1789        for (int i = 0; i <= 255; i++) {
1790            g8Tos8LUT[i] = (byte) i;
1791        }
1792        ICC_Transform[] transformList = new ICC_Transform[2];
1793        ICC_ColorSpace JavaDoc srgbCS =
1794            (ICC_ColorSpace JavaDoc) ColorSpace.getInstance(ColorSpace.CS_sRGB);
1795        transformList[0] = new ICC_Transform (
1796            grayCS.getProfile(), ICC_Transform.Any, ICC_Transform.In);
1797        transformList[1] = new ICC_Transform (
1798            srgbCS.getProfile(), ICC_Transform.Any, ICC_Transform.Out);
1799        ICC_Transform t = new ICC_Transform(transformList);
1800        byte[] tmp = t.colorConvert(g8Tos8LUT, null);
1801        for (int i = 0, j= 2; i <= 255; i++, j += 3) {
1802            // All three components of tmp should be equal, since
1803
// the input color space to colorConvert is a gray scale
1804
// space. However, there are slight anomalies in the results.
1805
// Copy tmp starting at index 2, since colorConvert seems
1806
// to be slightly more accurate for the third component!
1807
g8Tos8LUT[i] = tmp[j];
1808        }
1809        if (g8Tos8Map == null) {
1810            g8Tos8Map = Collections.synchronizedMap(new WeakHashMap JavaDoc(2));
1811        }
1812        g8Tos8Map.put(grayCS, g8Tos8LUT);
1813        return g8Tos8LUT;
1814    }
1815
1816    /*
1817     * Return a byte LUT that converts 16-bit gray values in the CS_GRAY
1818     * linear gray ColorSpace to the appropriate 8-bit value in the
1819     * grayCS ColorSpace. Cache references to any computed LUT in a Map.
1820     */

1821    static byte[] getLinearGray16ToOtherGray8LUT(ICC_ColorSpace JavaDoc grayCS) {
1822        if (lg16Toog8Map != null) {
1823            byte[] lg16Toog8LUT = (byte []) lg16Toog8Map.get(grayCS);
1824            if (lg16Toog8LUT != null) {
1825                return lg16Toog8LUT;
1826            }
1827        }
1828        short[] tmp = new short[65536];
1829        for (int i = 0; i <= 65535; i++) {
1830            tmp[i] = (short) i;
1831        }
1832        ICC_Transform[] transformList = new ICC_Transform[2];
1833        ICC_ColorSpace JavaDoc lgCS =
1834            (ICC_ColorSpace JavaDoc) ColorSpace.getInstance(ColorSpace.CS_GRAY);
1835        transformList[0] = new ICC_Transform (
1836            lgCS.getProfile(), ICC_Transform.Any, ICC_Transform.In);
1837        transformList[1] = new ICC_Transform (
1838            grayCS.getProfile(), ICC_Transform.Any, ICC_Transform.Out);
1839        ICC_Transform t = new ICC_Transform(transformList);
1840        tmp = t.colorConvert(tmp, null);
1841        byte[] lg16Toog8LUT = new byte[65536];
1842        for (int i = 0; i <= 65535; i++) {
1843            // scale unsigned short (0 - 65535) to unsigned byte (0 - 255)
1844
lg16Toog8LUT[i] =
1845                (byte) (((float) (tmp[i] & 0xffff)) * (1.0f /257.0f) + 0.5f);
1846        }
1847        if (lg16Toog8Map == null) {
1848            lg16Toog8Map = Collections.synchronizedMap(new WeakHashMap JavaDoc(2));
1849        }
1850        lg16Toog8Map.put(grayCS, lg16Toog8LUT);
1851        return lg16Toog8LUT;
1852    }
1853
1854    /*
1855     * Return a byte LUT that converts 16-bit gray values in the grayCS
1856     * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut
1857     * is the byte array returned by this method and sval = lut[gval],
1858     * then the sRGB triple (sval,sval,sval) is the best match to gval.
1859     * Cache references to any computed LUT in a Map.
1860     */

1861    static byte[] getGray16TosRGB8LUT(ICC_ColorSpace JavaDoc grayCS) {
1862        if (isLinearGRAYspace(grayCS)) {
1863            return getLinearRGB16TosRGB8LUT();
1864        }
1865        if (g16Tos8Map != null) {
1866            byte[] g16Tos8LUT = (byte []) g16Tos8Map.get(grayCS);
1867            if (g16Tos8LUT != null) {
1868                return g16Tos8LUT;
1869            }
1870        }
1871        short[] tmp = new short[65536];
1872        for (int i = 0; i <= 65535; i++) {
1873            tmp[i] = (short) i;
1874        }
1875        ICC_Transform[] transformList = new ICC_Transform[2];
1876        ICC_ColorSpace JavaDoc srgbCS =
1877            (ICC_ColorSpace JavaDoc) ColorSpace.getInstance(ColorSpace.CS_sRGB);
1878        transformList[0] = new ICC_Transform (
1879            grayCS.getProfile(), ICC_Transform.Any, ICC_Transform.In);
1880        transformList[1] = new ICC_Transform (
1881            srgbCS.getProfile(), ICC_Transform.Any, ICC_Transform.Out);
1882        ICC_Transform t = new ICC_Transform(transformList);
1883        tmp = t.colorConvert(tmp, null);
1884        byte[] g16Tos8LUT = new byte[65536];
1885        for (int i = 0, j= 2; i <= 65535; i++, j += 3) {
1886            // All three components of tmp should be equal, since
1887
// the input color space to colorConvert is a gray scale
1888
// space. However, there are slight anomalies in the results.
1889
// Copy tmp starting at index 2, since colorConvert seems
1890
// to be slightly more accurate for the third component!
1891

1892            // scale unsigned short (0 - 65535) to unsigned byte (0 - 255)
1893
g16Tos8LUT[i] =
1894                (byte) (((float) (tmp[j] & 0xffff)) * (1.0f /257.0f) + 0.5f);
1895        }
1896        if (g16Tos8Map == null) {
1897            g16Tos8Map = Collections.synchronizedMap(new WeakHashMap JavaDoc(2));
1898        }
1899        g16Tos8Map.put(grayCS, g16Tos8LUT);
1900        return g16Tos8LUT;
1901    }
1902
1903    /*
1904     * Return a short LUT that converts 16-bit gray values in the CS_GRAY
1905     * linear gray ColorSpace to the appropriate 16-bit value in the
1906     * grayCS ColorSpace. Cache references to any computed LUT in a Map.
1907     */

1908    static short[] getLinearGray16ToOtherGray16LUT(ICC_ColorSpace JavaDoc grayCS) {
1909        if (lg16Toog16Map != null) {
1910            short[] lg16Toog16LUT = (short []) lg16Toog16Map.get(grayCS);
1911            if (lg16Toog16LUT != null) {
1912                return lg16Toog16LUT;
1913            }
1914        }
1915        short[] tmp = new short[65536];
1916        for (int i = 0; i <= 65535; i++) {
1917            tmp[i] = (short) i;
1918        }
1919        ICC_Transform[] transformList = new ICC_Transform[2];
1920        ICC_ColorSpace JavaDoc lgCS =
1921            (ICC_ColorSpace JavaDoc) ColorSpace.getInstance(ColorSpace.CS_GRAY);
1922        transformList[0] = new ICC_Transform (
1923            lgCS.getProfile(), ICC_Transform.Any, ICC_Transform.In);
1924        transformList[1] = new ICC_Transform (
1925            grayCS.getProfile(), ICC_Transform.Any, ICC_Transform.Out);
1926        ICC_Transform t = new ICC_Transform(transformList);
1927        short[] lg16Toog16LUT = t.colorConvert(tmp, null);
1928        if (lg16Toog16Map == null) {
1929            lg16Toog16Map = Collections.synchronizedMap(new WeakHashMap JavaDoc(2));
1930        }
1931        lg16Toog16Map.put(grayCS, lg16Toog16LUT);
1932        return lg16Toog16LUT;
1933    }
1934
1935}
1936
Popular Tags