KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)ComponentColorModel.java 1.68 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.color.ColorSpace JavaDoc;
11 import java.awt.color.ICC_ColorSpace JavaDoc;
12
13 /**
14  * A <CODE>ColorModel</CODE> class that works with pixel values that
15  * represent color and alpha information as separate samples and that
16  * store each sample in a separate data element. This class can be
17  * used with an arbitrary <CODE>ColorSpace</CODE>. The number of
18  * color samples in the pixel values must be same as the number of
19  * color components in the <CODE>ColorSpace</CODE>. There may be a
20  * single alpha sample.
21  * <p>
22  * For those methods that use
23  * a primitive array pixel representation of type <CODE>transferType</CODE>,
24  * the array length is the same as the number of color and alpha samples.
25  * Color samples are stored first in the array followed by the alpha
26  * sample, if present. The order of the color samples is specified
27  * by the <CODE>ColorSpace</CODE>. Typically, this order reflects the
28  * name of the color space type. For example, for <CODE>TYPE_RGB</CODE>,
29  * index 0 corresponds to red, index 1 to green, and index 2 to blue.
30  * <p>
31  * The translation from pixel sample values to color/alpha components for
32  * display or processing purposes is based on a one-to-one correspondence of
33  * samples to components.
34  * Depending on the transfer type used to create an instance of
35  * <code>ComponentColorModel</code>, the pixel sample values
36  * represented by that instance may be signed or unsigned and may
37  * be of integral type or float or double (see below for details).
38  * The translation from sample values to normalized color/alpha components
39  * must follow certain rules. For float and double samples, the translation
40  * is an identity, i.e. normalized component values are equal to the
41  * corresponding sample values. For integral samples, the translation
42  * should be only a simple scale and offset, where the scale and offset
43  * constants may be different for each component. The result of
44  * applying the scale and offset constants is a set of color/alpha
45  * component values, which are guaranteed to fall within a certain
46  * range. Typically, the range for a color component will be the range
47  * defined by the <code>getMinValue</code> and <code>getMaxValue</code>
48  * methods of the <code>ColorSpace</code> class. The range for an
49  * alpha component should be 0.0 to 1.0.
50  * <p>
51  * Instances of <code>ComponentColorModel</code> created with transfer types
52  * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
53  * and <CODE>DataBuffer.TYPE_INT</CODE> have pixel sample values which
54  * are treated as unsigned integral values.
55  * The number of bits in a color or alpha sample of a pixel value might not
56  * be the same as the number of bits for the corresponding color or alpha
57  * sample passed to the
58  * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
59  * constructor. In
60  * that case, this class assumes that the least significant n bits of a sample
61  * value hold the component value, where n is the number of significant bits
62  * for the component passed to the constructor. It also assumes that
63  * any higher-order bits in a sample value are zero. Thus, sample values
64  * range from 0 to 2<sup>n</sup> - 1. This class maps these sample values
65  * to normalized color component values such that 0 maps to the value
66  * obtained from the <code>ColorSpace's</code> <code>getMinValue</code>
67  * method for each component and 2<sup>n</sup> - 1 maps to the value
68  * obtained from <code>getMaxValue</code>. To create a
69  * <code>ComponentColorModel</code> with a different color sample mapping
70  * requires subclassing this class and overriding the
71  * <code>getNormalizedComponents(Object, float[], int)</code> method.
72  * The mapping for an alpha sample always maps 0 to 0.0 and
73  * 2<sup>n</sup> - 1 to 1.0.
74  * <p>
75  * For instances with unsigned sample values,
76  * the unnormalized color/alpha component representation is only
77  * supported if two conditions hold. First, sample value value 0 must
78  * map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1
79  * to 1.0. Second the min/max range of all color components of the
80  * <code>ColorSpace</code> must be 0.0 to 1.0. In this case, the
81  * component representation is the n least
82  * significant bits of the corresponding sample. Thus each component is
83  * an unsigned integral value between 0 and 2<sup>n</sup> - 1, where
84  * n is the number of significant bits for a particular component.
85  * If these conditions are not met, any method taking an unnormalized
86  * component argument will throw an <code>IllegalArgumentException</code>.
87  * <p>
88  * Instances of <code>ComponentColorModel</code> created with transfer types
89  * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
90  * <CODE>DataBuffer.TYPE_DOUBLE</CODE> have pixel sample values which
91  * are treated as signed short, float, or double values.
92  * Such instances do not support the unnormalized color/alpha component
93  * representation, so any methods taking such a representation as an argument
94  * will throw an <code>IllegalArgumentException</code> when called on one
95  * of these instances. The normalized component values of instances
96  * of this class have a range which depends on the transfer
97  * type as follows: for float samples, the full range of the float data
98  * type; for double samples, the full range of the float data type
99  * (resulting from casting double to float); for short samples,
100  * from approximately -maxVal to +maxVal, where maxVal is the per
101  * component maximum value for the <code>ColorSpace</code>
102  * (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps
103  * to +maxVal). A subclass may override the scaling for short sample
104  * values to normalized component values by overriding the
105  * <code>getNormalizedComponents(Object, float[], int)</code> method.
106  * For float and double samples, the normalized component values are
107  * taken to be equal to the corresponding sample values, and subclasses
108  * should not attempt to add any non-identity scaling for these transfer
109  * types.
110  * <p>
111  * Instances of <code>ComponentColorModel</code> created with transfer types
112  * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and
113  * <CODE>DataBuffer.TYPE_DOUBLE</CODE>
114  * use all the bits of all sample values. Thus all color/alpha components
115  * have 16 bits when using <CODE>DataBuffer.TYPE_SHORT</CODE>, 32 bits when
116  * using <CODE>DataBuffer.TYPE_FLOAT</CODE>, and 64 bits when using
117  * <CODE>DataBuffer.TYPE_DOUBLE</CODE>. When the
118  * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
119  * form of constructor is used with one of these transfer types, the
120  * bits array argument is ignored.
121  * <p>
122  * It is possible to have color/alpha sample values
123  * which cannot be reasonably interpreted as component values for rendering.
124  * This can happen when <code>ComponentColorModel</code> is subclassed to
125  * override the mapping of unsigned sample values to normalized color
126  * component values or when signed sample values outside a certain range
127  * are used. (As an example, specifying an alpha component as a signed
128  * short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can
129  * lead to unexpected results.) It is the
130  * responsibility of applications to appropriately scale pixel data before
131  * rendering such that color components fall within the normalized range
132  * of the <code>ColorSpace</code> (obtained using the <code>getMinValue</code>
133  * and <code>getMaxValue</code> methods of the <code>ColorSpace</code> class)
134  * and the alpha component is between 0.0 and 1.0. If color or alpha
135  * component values fall outside these ranges, rendering results are
136  * indeterminate.
137  * <p>
138  * Methods that use a single int pixel representation throw
139  * an <CODE>IllegalArgumentException</CODE>, unless the number of components
140  * for the <CODE>ComponentColorModel</CODE> is one and the component
141  * value is unsigned -- in other words, a single color component using
142  * a transfer type of <CODE>DataBuffer.TYPE_BYTE</CODE>,
143  * <CODE>DataBuffer.TYPE_USHORT</CODE>, or <CODE>DataBuffer.TYPE_INT</CODE>
144  * and no alpha.
145  * <p>
146  * A <CODE>ComponentColorModel</CODE> can be used in conjunction with a
147  * <CODE>ComponentSampleModel</CODE>, a <CODE>BandedSampleModel</CODE>,
148  * or a <CODE>PixelInterleavedSampleModel</CODE> to construct a
149  * <CODE>BufferedImage</CODE>.
150  *
151  * @see ColorModel
152  * @see ColorSpace
153  * @see ComponentSampleModel
154  * @see BandedSampleModel
155  * @see PixelInterleavedSampleModel
156  * @see BufferedImage
157  *
158  * @version 10 Feb 1997
159  */

160 public class ComponentColorModel extends ColorModel JavaDoc {
161     
162     /**
163      * <code>signed</code> is <code>true</code> for <code>short</code>,
164      * <code>float</code>, and <code>double</code> transfer types; it
165      * is <code>false</code> for <code>byte</code>, <code>ushort</code>,
166      * and <code>int</code> transfer types.
167      */

168     private boolean signed; // true for transfer types short, float, double
169
// false for byte, ushort, int
170
private boolean is_sRGB_stdScale;
171     private boolean is_LinearRGB_stdScale;
172     private boolean is_LinearGray_stdScale;
173     private boolean is_ICCGray_stdScale;
174     private byte[] tosRGB8LUT;
175     private byte[] fromsRGB8LUT8;
176     private short[] fromsRGB8LUT16;
177     private byte[] fromLinearGray16ToOtherGray8LUT;
178     private short[] fromLinearGray16ToOtherGray16LUT;
179     private boolean needScaleInit;
180     private boolean noUnnorm;
181     private boolean nonStdScale;
182     private float[] min;
183     private float[] diffMinMax;
184     private float[] compOffset;
185     private float[] compScale;
186
187     /**
188      * Constructs a <CODE>ComponentColorModel</CODE> from the specified
189      * parameters. Color components will be in the specified
190      * <CODE>ColorSpace</CODE>. The supported transfer types are
191      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
192      * <CODE>DataBuffer.TYPE_INT</CODE>,
193      * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
194      * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
195      * If not null, the <CODE>bits</CODE> array specifies the
196      * number of significant bits per color and alpha component and its
197      * length should be at least the number of components in the
198      * <CODE>ColorSpace</CODE> if there is no alpha
199      * information in the pixel values, or one more than this number if
200      * there is alpha information. When the <CODE>transferType</CODE> is
201      * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
202      * or <CODE>DataBuffer.TYPE_DOUBLE</CODE> the <CODE>bits</CODE> array
203      * argument is ignored. <CODE>hasAlpha</CODE> indicates whether alpha
204      * information is present. If <CODE>hasAlpha</CODE> is true, then
205      * the boolean <CODE>isAlphaPremultiplied</CODE>
206      * specifies how to interpret color and alpha samples in pixel values.
207      * If the boolean is true, color samples are assumed to have been
208      * multiplied by the alpha sample. The <CODE>transparency</CODE>
209      * specifies what alpha values can be represented by this color model.
210      * The acceptable <code>transparency</code> values are
211      * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
212      * The <CODE>transferType</CODE> is the type of primitive array used
213      * to represent pixel values.
214      *
215      * @param colorSpace The <CODE>ColorSpace</CODE> associated
216      * with this color model.
217      * @param bits The number of significant bits per component.
218      * May be null, in which case all bits of all
219      * component samples will be significant.
220      * Ignored if transferType is one of
221      * <CODE>DataBuffer.TYPE_SHORT</CODE>,
222      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
223      * <CODE>DataBuffer.TYPE_DOUBLE</CODE>,
224      * in which case all bits of all component
225      * samples will be significant.
226      * @param hasAlpha If true, this color model supports alpha.
227      * @param isAlphaPremultiplied If true, alpha is premultiplied.
228      * @param transparency Specifies what alpha values can be represented
229      * by this color model.
230      * @param transferType Specifies the type of primitive array used to
231      * represent pixel values.
232      *
233      * @throws IllegalArgumentException If the <CODE>bits</CODE> array
234      * argument is not null, its length is less than the number of
235      * color and alpha components, and transferType is one of
236      * <CODE>DataBuffer.TYPE_BYTE</CODE>,
237      * <CODE>DataBuffer.TYPE_USHORT</CODE>, or
238      * <CODE>DataBuffer.TYPE_INT</CODE>.
239      * @throws IllegalArgumentException If transferType is not one of
240      * <CODE>DataBuffer.TYPE_BYTE</CODE>,
241      * <CODE>DataBuffer.TYPE_USHORT</CODE>,
242      * <CODE>DataBuffer.TYPE_INT</CODE>,
243      * <CODE>DataBuffer.TYPE_SHORT</CODE>,
244      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
245      * <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
246      *
247      * @see ColorSpace
248      * @see java.awt.Transparency
249      */

250     public ComponentColorModel (ColorSpace JavaDoc colorSpace,
251                                 int[] bits,
252                                 boolean hasAlpha,
253                                 boolean isAlphaPremultiplied,
254                                 int transparency,
255                                 int transferType) {
256         super (bitsHelper(transferType, colorSpace, hasAlpha),
257                bitsArrayHelper(bits, transferType, colorSpace, hasAlpha),
258                colorSpace, hasAlpha, isAlphaPremultiplied, transparency,
259                transferType);
260         switch(transferType) {
261             case DataBuffer.TYPE_BYTE:
262             case DataBuffer.TYPE_USHORT:
263             case DataBuffer.TYPE_INT:
264                 signed = false;
265                 needScaleInit = true;
266                 break;
267             case DataBuffer.TYPE_SHORT:
268                 signed = true;
269                 needScaleInit = true;
270                 break;
271             case DataBuffer.TYPE_FLOAT:
272             case DataBuffer.TYPE_DOUBLE:
273                 signed = true;
274                 needScaleInit = false;
275                 noUnnorm = true;
276                 nonStdScale = false;
277                 break;
278             default:
279                 throw new IllegalArgumentException JavaDoc("This constructor is not "+
280                          "compatible with transferType " + transferType);
281         }
282         setupLUTs();
283     }
284
285     /**
286      * Constructs a <CODE>ComponentColorModel</CODE> from the specified
287      * parameters. Color components will be in the specified
288      * <CODE>ColorSpace</CODE>. The supported transfer types are
289      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
290      * <CODE>DataBuffer.TYPE_INT</CODE>,
291      * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
292      * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>. The number of significant
293      * bits per color and alpha component will be 8, 16, 32, 16, 32, or 64,
294      * respectively. The number of color components will be the
295      * number of components in the <CODE>ColorSpace</CODE>. There will be
296      * an alpha component if <CODE>hasAlpha</CODE> is <CODE>true</CODE>.
297      * If <CODE>hasAlpha</CODE> is true, then
298      * the boolean <CODE>isAlphaPremultiplied</CODE>
299      * specifies how to interpret color and alpha samples in pixel values.
300      * If the boolean is true, color samples are assumed to have been
301      * multiplied by the alpha sample. The <CODE>transparency</CODE>
302      * specifies what alpha values can be represented by this color model.
303      * The acceptable <code>transparency</code> values are
304      * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
305      * The <CODE>transferType</CODE> is the type of primitive array used
306      * to represent pixel values.
307      *
308      * @param colorSpace The <CODE>ColorSpace</CODE> associated
309      * with this color model.
310      * @param hasAlpha If true, this color model supports alpha.
311      * @param isAlphaPremultiplied If true, alpha is premultiplied.
312      * @param transparency Specifies what alpha values can be represented
313      * by this color model.
314      * @param transferType Specifies the type of primitive array used to
315      * represent pixel values.
316      *
317      * @throws IllegalArgumentException If transferType is not one of
318      * <CODE>DataBuffer.TYPE_BYTE</CODE>,
319      * <CODE>DataBuffer.TYPE_USHORT</CODE>,
320      * <CODE>DataBuffer.TYPE_INT</CODE>,
321      * <CODE>DataBuffer.TYPE_SHORT</CODE>,
322      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
323      * <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
324      *
325      * @see ColorSpace
326      * @see java.awt.Transparency
327      * @since 1.4
328      */

329     public ComponentColorModel (ColorSpace JavaDoc colorSpace,
330                                 boolean hasAlpha,
331                                 boolean isAlphaPremultiplied,
332                                 int transparency,
333                                 int transferType) {
334         this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
335              transparency, transferType);
336     }
337
338     private static int bitsHelper(int transferType,
339                                   ColorSpace JavaDoc colorSpace,
340                                   boolean hasAlpha) {
341         int numBits = DataBuffer.getDataTypeSize(transferType);
342         int numComponents = colorSpace.getNumComponents();
343         if (hasAlpha) {
344             ++numComponents;
345         }
346         return numBits * numComponents;
347     }
348
349     private static int[] bitsArrayHelper(int[] origBits,
350                                          int transferType,
351                                          ColorSpace JavaDoc colorSpace,
352                                          boolean hasAlpha) {
353         switch(transferType) {
354             case DataBuffer.TYPE_BYTE:
355             case DataBuffer.TYPE_USHORT:
356             case DataBuffer.TYPE_INT:
357                 if (origBits != null) {
358                     return origBits;
359                 }
360                 break;
361             default:
362                 break;
363         }
364         int numBits = DataBuffer.getDataTypeSize(transferType);
365         int numComponents = colorSpace.getNumComponents();
366         if (hasAlpha) {
367             ++numComponents;
368         }
369         int[] bits = new int[numComponents];
370         for (int i = 0; i < numComponents; i++) {
371             bits[i] = numBits;
372         }
373         return bits;
374     }
375
376     private void setupLUTs() {
377         // REMIND: there is potential to accelerate sRGB, LinearRGB,
378
// LinearGray, ICCGray, and non-ICC Gray spaces with non-standard
379
// scaling, if that becomes important
380
//
381
// NOTE: The is_xxx_stdScale and nonStdScale booleans are provisionally
382
// set here when this method is called at construction time. These
383
// variables may be set again when initScale is called later.
384
// When setupLUTs returns, nonStdScale is true if (the transferType
385
// is not float or double) AND (some minimum ColorSpace component
386
// value is not 0.0 OR some maximum ColorSpace component value
387
// is not 1.0). This is correct for the calls to
388
// getNormalizedComponents(Object, float[], int) from initScale().
389
// initScale() may change the value nonStdScale based on the
390
// return value of getNormalizedComponents() - this will only
391
// happen if getNormalizedComponents() has been overridden by a
392
// subclass to make the mapping of min/max pixel sample values
393
// something different from min/max color component values.
394
if (is_sRGB) {
395             is_sRGB_stdScale = true;
396             nonStdScale = false;
397         } else if (ColorModel.isLinearRGBspace(colorSpace)) {
398             // Note that the built-in Linear RGB space has a normalized
399
// range of 0.0 - 1.0 for each coordinate. Usage of these
400
// LUTs makes that assumption.
401
is_LinearRGB_stdScale = true;
402             nonStdScale = false;
403             if (transferType == DataBuffer.TYPE_BYTE) {
404                 tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
405                 fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
406             } else {
407                 tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
408                 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
409             }
410         } else if ((colorSpaceType == ColorSpace.TYPE_GRAY) &&
411                    (colorSpace instanceof ICC_ColorSpace JavaDoc) &&
412                    (colorSpace.getMinValue(0) == 0.0f) &&
413                    (colorSpace.getMaxValue(0) == 1.0f)) {
414             // Note that a normalized range of 0.0 - 1.0 for the gray
415
// component is required, because usage of these LUTs makes
416
// that assumption.
417
ICC_ColorSpace JavaDoc ics = (ICC_ColorSpace JavaDoc) colorSpace;
418             is_ICCGray_stdScale = true;
419             nonStdScale = false;
420             fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
421             if (ColorModel.isLinearGRAYspace(ics)) {
422                 is_LinearGray_stdScale = true;
423                 if (transferType == DataBuffer.TYPE_BYTE) {
424                     tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
425                 } else {
426                     tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
427                 }
428             } else {
429                 if (transferType == DataBuffer.TYPE_BYTE) {
430                     tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
431                     fromLinearGray16ToOtherGray8LUT =
432                         ColorModel.getLinearGray16ToOtherGray8LUT(ics);
433                 } else {
434                     tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
435                     fromLinearGray16ToOtherGray16LUT =
436                         ColorModel.getLinearGray16ToOtherGray16LUT(ics);
437                 }
438             }
439         } else if (needScaleInit) {
440             // if transferType is byte, ushort, int, or short and we
441
// don't already know the ColorSpace has minVlaue == 0.0f and
442
// maxValue == 1.0f for all components, we need to check that
443
// now and setup the min[] and diffMinMax[] arrays if necessary.
444
nonStdScale = false;
445             for (int i = 0; i < numColorComponents; i++) {
446                 if ((colorSpace.getMinValue(i) != 0.0f) ||
447                     (colorSpace.getMaxValue(i) != 1.0f)) {
448                     nonStdScale = true;
449                     break;
450                 }
451             }
452             if (nonStdScale) {
453                 min = new float[numColorComponents];
454                 diffMinMax = new float[numColorComponents];
455                 for (int i = 0; i < numColorComponents; i++) {
456                     min[i] = colorSpace.getMinValue(i);
457                     diffMinMax[i] = colorSpace.getMaxValue(i) - min[i];
458                 }
459             }
460         }
461     }
462
463     private void initScale() {
464         // This method is called the first time any method which uses
465
// pixel sample value to color component value scaling information
466
// is called if the transferType supports non-standard scaling
467
// as defined above (byte, ushort, int, and short), unless the
468
// method is getNormalizedComponents(Object, float[], int) (that
469
// method must be overridden to use non-standard scaling). This
470
// method also sets up the noUnnorm boolean variable for these
471
// transferTypes. After this method is called, the nonStdScale
472
// variable will be true if getNormalizedComponents() maps a
473
// sample value of 0 to anything other than 0.0f OR maps a
474
// sample value of 2^^n - 1 (2^^15 - 1 for short transferType)
475
// to anything other than 1.0f. Note that this can be independent
476
// of the colorSpace min/max component values, if the
477
// getNormalizedComponents() method has been overridden for some
478
// reason, e.g. to provide greater dynamic range in the sample
479
// values than in the color component values. Unfortunately,
480
// this method can't be called at construction time, since a
481
// subclass may still have uninitialized state that would cause
482
// getNormalizedComponents() to return an incorrect result.
483
needScaleInit = false; // only needs to called once
484
if (nonStdScale || signed) {
485             // The unnormalized form is only supported for unsigned
486
// transferTypes and when the ColorSpace min/max values
487
// are 0.0/1.0. When this method is called nonStdScale is
488
// true if the latter condition does not hold. In addition,
489
// the unnormalized form requires that the full range of
490
// the pixel sample values map to the full 0.0 - 1.0 range
491
// of color component values. That condition is checked
492
// later in this method.
493
noUnnorm = true;
494         } else {
495             noUnnorm = false;
496         }
497         float[] lowVal, highVal;
498         switch (transferType) {
499         case DataBuffer.TYPE_BYTE:
500             {
501                 byte[] bpixel = new byte[numComponents];
502                 for (int i = 0; i < numColorComponents; i++) {
503                     bpixel[i] = 0;
504                 }
505                 if (supportsAlpha) {
506                     bpixel[numColorComponents] =
507                         (byte) ((1 << nBits[numColorComponents]) - 1);
508                 }
509                 lowVal = getNormalizedComponents(bpixel, null, 0);
510                 for (int i = 0; i < numColorComponents; i++) {
511                     bpixel[i] = (byte) ((1 << nBits[i]) - 1);
512                 }
513                 highVal = getNormalizedComponents(bpixel, null, 0);
514             }
515             break;
516         case DataBuffer.TYPE_USHORT:
517             {
518                 short[] uspixel = new short[numComponents];
519                 for (int i = 0; i < numColorComponents; i++) {
520                     uspixel[i] = 0;
521                 }
522                 if (supportsAlpha) {
523                     uspixel[numColorComponents] =
524                         (short) ((1 << nBits[numColorComponents]) - 1);
525                 }
526                 lowVal = getNormalizedComponents(uspixel, null, 0);
527                 for (int i = 0; i < numColorComponents; i++) {
528                     uspixel[i] = (short) ((1 << nBits[i]) - 1);
529                 }
530                 highVal = getNormalizedComponents(uspixel, null, 0);
531             }
532             break;
533         case DataBuffer.TYPE_INT:
534             {
535                 int[] ipixel = new int[numComponents];
536                 for (int i = 0; i < numColorComponents; i++) {
537                     ipixel[i] = 0;
538                 }
539                 if (supportsAlpha) {
540                     ipixel[numColorComponents] =
541                         ((1 << nBits[numColorComponents]) - 1);
542                 }
543                 lowVal = getNormalizedComponents(ipixel, null, 0);
544                 for (int i = 0; i < numColorComponents; i++) {
545                     ipixel[i] = ((1 << nBits[i]) - 1);
546                 }
547                 highVal = getNormalizedComponents(ipixel, null, 0);
548             }
549             break;
550         case DataBuffer.TYPE_SHORT:
551             {
552                 short[] spixel = new short[numComponents];
553                 for (int i = 0; i < numColorComponents; i++) {
554                     spixel[i] = 0;
555                 }
556                 if (supportsAlpha) {
557                     spixel[numColorComponents] = 32767;
558                 }
559                 lowVal = getNormalizedComponents(spixel, null, 0);
560                 for (int i = 0; i < numColorComponents; i++) {
561                     spixel[i] = 32767;
562                 }
563                 highVal = getNormalizedComponents(spixel, null, 0);
564             }
565             break;
566         default:
567             lowVal = highVal = null; // to keep the compiler from complaining
568
break;
569         }
570         nonStdScale = false;
571         for (int i = 0; i < numColorComponents; i++) {
572             if ((lowVal[i] != 0.0f) || (highVal[i] != 1.0f)) {
573                 nonStdScale = true;
574                 break;
575             }
576         }
577         if (nonStdScale) {
578             noUnnorm = true;
579             is_sRGB_stdScale = false;
580             is_LinearRGB_stdScale = false;
581             is_LinearGray_stdScale = false;
582             is_ICCGray_stdScale = false;
583             compOffset = new float[numColorComponents];
584             compScale = new float[numColorComponents];
585             for (int i = 0; i < numColorComponents; i++) {
586                 compOffset[i] = lowVal[i];
587                 compScale[i] = 1.0f / (highVal[i] - lowVal[i]);
588             }
589         }
590     }
591
592     private int getRGBComponent(int pixel, int idx) {
593         if (numComponents > 1) {
594             throw new
595                 IllegalArgumentException JavaDoc("More than one component per pixel");
596         }
597         if (signed) {
598             throw new
599                 IllegalArgumentException JavaDoc("Component value is signed");
600         }
601         if (needScaleInit) {
602             initScale();
603         }
604         // Since there is only 1 component, there is no alpha
605

606         // Normalize the pixel in order to convert it
607
Object JavaDoc opixel = null;
608         switch (transferType) {
609         case DataBuffer.TYPE_BYTE:
610             {
611                 byte[] bpixel = { (byte) pixel };
612                 opixel = bpixel;
613             }
614             break;
615         case DataBuffer.TYPE_USHORT:
616             {
617                 short[] spixel = { (short) pixel };
618                 opixel = spixel;
619             }
620             break;
621         case DataBuffer.TYPE_INT:
622             {
623                 int[] ipixel = { pixel };
624                 opixel = ipixel;
625             }
626             break;
627         }
628         float[] norm = getNormalizedComponents(opixel, null, 0);
629         float[] rgb = colorSpace.toRGB(norm);
630
631         return (int) (rgb[idx] * 255.0f + 0.5f);
632     }
633
634     /**
635      * Returns the red color component for the specified pixel, scaled
636      * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
637      * is done if necessary. The pixel value is specified as an int.
638      * The returned value will be a non pre-multiplied value.
639      * If the alpha is premultiplied, this method divides
640      * it out before returning the value (if the alpha value is 0,
641      * the red value will be 0).
642      *
643      * @param pixel The pixel from which you want to get the red color component.
644      *
645      * @return The red color component for the specified pixel, as an int.
646      *
647      * @throws IllegalArgumentException If there is more than
648      * one component in this <CODE>ColorModel</CODE>.
649      * @throws IllegalArgumentException If the component value for this
650      * <CODE>ColorModel</CODE> is signed
651      */

652     public int getRed(int pixel) {
653         return getRGBComponent(pixel, 0);
654     }
655
656     /**
657      * Returns the green color component for the specified pixel, scaled
658      * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
659      * is done if necessary. The pixel value is specified as an int.
660      * The returned value will be a non
661      * pre-multiplied value. If the alpha is premultiplied, this method
662      * divides it out before returning the value (if the alpha value is 0,
663      * the green value will be 0).
664      *
665      * @param pixel The pixel from which you want to get the green color component.
666      *
667      * @return The green color component for the specified pixel, as an int.
668      *
669      * @throws IllegalArgumentException If there is more than
670      * one component in this <CODE>ColorModel</CODE>.
671      * @throws IllegalArgumentException If the component value for this
672      * <CODE>ColorModel</CODE> is signed
673      */

674     public int getGreen(int pixel) {
675         return getRGBComponent(pixel, 1);
676     }
677
678     /**
679      * Returns the blue color component for the specified pixel, scaled
680      * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
681      * is done if necessary. The pixel value is specified as an int.
682      * The returned value will be a non
683      * pre-multiplied value. If the alpha is premultiplied, this method
684      * divides it out before returning the value (if the alpha value is 0,
685      * the blue value will be 0).
686      *
687      * @param pixel The pixel from which you want to get the blue color component.
688      *
689      * @return The blue color component for the specified pixel, as an int.
690      *
691      * @throws IllegalArgumentException If there is more than
692      * one component in this <CODE>ColorModel</CODE>.
693      * @throws IllegalArgumentException If the component value for this
694      * <CODE>ColorModel</CODE> is signed
695      */

696     public int getBlue(int pixel) {
697         return getRGBComponent(pixel, 2);
698     }
699
700     /**
701      * Returns the alpha component for the specified pixel, scaled
702      * from 0 to 255. The pixel value is specified as an int.
703      *
704      * @param pixel The pixel from which you want to get the alpha component.
705      *
706      * @return The alpha component for the specified pixel, as an int.
707      *
708      * @throws IllegalArgumentException If there is more than
709      * one component in this <CODE>ColorModel</CODE>.
710      * @throws IllegalArgumentException If the component value for this
711      * <CODE>ColorModel</CODE> is signed
712      */

713     public int getAlpha(int pixel) {
714         if (supportsAlpha == false) {
715             return 255;
716         }
717         if (numComponents > 1) {
718             throw new
719                 IllegalArgumentException JavaDoc("More than one component per pixel");
720         }
721         if (signed) {
722             throw new
723                 IllegalArgumentException JavaDoc("Component value is signed");
724         }
725
726         return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f);
727     }
728
729     /**
730      * Returns the color/alpha components of the pixel in the default
731      * RGB color model format. A color conversion is done if necessary.
732      * The returned value will be in a non pre-multiplied format. If
733      * the alpha is premultiplied, this method divides it out of the
734      * color components (if the alpha value is 0, the color values will be 0).
735      *
736      * @param pixel The pixel from which you want to get the color/alpha components.
737      *
738      * @return The color/alpha components for the specified pixel, as an int.
739      *
740      * @throws IllegalArgumentException If there is more than
741      * one component in this <CODE>ColorModel</CODE>.
742      * @throws IllegalArgumentException If the component value for this
743      * <CODE>ColorModel</CODE> is signed
744      */

745     public int getRGB(int pixel) {
746         if (numComponents > 1) {
747             throw new
748                 IllegalArgumentException JavaDoc("More than one component per pixel");
749         }
750         if (signed) {
751             throw new
752                 IllegalArgumentException JavaDoc("Component value is signed");
753         }
754
755     return (getAlpha(pixel) << 24)
756         | (getRed(pixel) << 16)
757         | (getGreen(pixel) << 8)
758         | (getBlue(pixel) << 0);
759     }
760
761     private int extractComponent(Object JavaDoc inData, int idx, int precision) {
762         // Extract component idx from inData. The precision argument
763
// should be either 8 or 16. If it's 8, this method will return
764
// an 8-bit value. If it's 16, this method will return a 16-bit
765
// value for transferTypes other than TYPE_BYTE. For TYPE_BYTE,
766
// an 8-bit value will be returned.
767

768         // This method maps the input value corresponding to a
769
// normalized ColorSpace component value of 0.0 to 0, and the
770
// input value corresponding to a normalized ColorSpace
771
// component value of 1.0 to 2^n - 1 (where n is 8 or 16), so
772
// it is appropriate only for ColorSpaces with min/max component
773
// values of 0.0/1.0. This will be true for sRGB, the built-in
774
// Linear RGB and Linear Gray spaces, and any other ICC grayscale
775
// spaces for which we have precomputed LUTs.
776

777         boolean needAlpha = (supportsAlpha && isAlphaPremultiplied);
778         int alp = 0;
779         int comp;
780         int mask = (1 << nBits[idx]) - 1;
781
782         switch (transferType) {
783             // Note: we do no clamping of the pixel data here - we
784
// assume that the data is scaled properly
785
case DataBuffer.TYPE_SHORT: {
786                 short sdata[] = (short[]) inData;
787                 float scalefactor = (float) ((1 << precision) - 1);
788                 if (needAlpha) {
789                     short s = sdata[numColorComponents];
790                     if (s != (short) 0) {
791                         return (int) ((((float) sdata[idx]) /
792                                        ((float) s)) * scalefactor + 0.5f);
793                     } else {
794                         return 0;
795                     }
796                 } else {
797                     return (int) ((sdata[idx] / 32767.0f) * scalefactor + 0.5f);
798                 }
799             }
800             case DataBuffer.TYPE_FLOAT: {
801                 float fdata[] = (float[]) inData;
802                 float scalefactor = (float) ((1 << precision) - 1);
803                 if (needAlpha) {
804                     float f = fdata[numColorComponents];
805                     if (f != 0.0f) {
806                         return (int) (((fdata[idx] / f) * scalefactor) + 0.5f);
807                     } else {
808                         return 0;
809                     }
810                 } else {
811                     return (int) (fdata[idx] * scalefactor + 0.5f);
812                 }
813             }
814             case DataBuffer.TYPE_DOUBLE: {
815                 double ddata[] = (double[]) inData;
816                 double scalefactor = (double) ((1 << precision) - 1);
817                 if (needAlpha) {
818                     double d = ddata[numColorComponents];
819                     if (d != 0.0) {
820                         return (int) (((ddata[idx] / d) * scalefactor) + 0.5);
821                     } else {
822                         return 0;
823                     }
824