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                 } else {
825                     return (int) (ddata[idx] * scalefactor + 0.5);
826                 }
827             }
828             case DataBuffer.TYPE_BYTE:
829                byte bdata[] = (byte[])inData;
830                comp = bdata[idx] & mask;
831                precision = 8;
832                if (needAlpha) {
833                    alp = bdata[numColorComponents] & mask;
834                }
835             break;
836             case DataBuffer.TYPE_USHORT:
837                short usdata[] = (short[])inData;
838                comp = usdata[idx] & mask;
839                if (needAlpha) {
840                    alp = usdata[numColorComponents] & mask;
841                }
842             break;
843             case DataBuffer.TYPE_INT:
844                int idata[] = (int[])inData;
845                comp = idata[idx];
846                if (needAlpha) {
847                    alp = idata[numColorComponents];
848                }
849             break;
850             default:
851                throw new
852                    UnsupportedOperationException JavaDoc("This method has not "+
853                    "been implemented for transferType " + transferType);
854         }
855         if (needAlpha) {
856             if (alp != 0) {
857                 float scalefactor = (float) ((1 << precision) - 1);
858                 float fcomp = ((float) comp) / ((float)mask);
859                 float invalp = ((float) ((1<<nBits[numColorComponents]) - 1)) /
860                                ((float) alp);
861                 return (int) (fcomp * invalp * scalefactor + 0.5f);
862             } else {
863                 return 0;
864             }
865         } else {
866             if (nBits[idx] != precision) {
867                 float scalefactor = (float) ((1 << precision) - 1);
868                 float fcomp = ((float) comp) / ((float)mask);
869                 return (int) (fcomp * scalefactor + 0.5f);
870             }
871             return comp;
872         }
873     }
874
875     private int getRGBComponent(Object JavaDoc inData, int idx) {
876         if (needScaleInit) {
877             initScale();
878         }
879         if (is_sRGB_stdScale) {
880             return extractComponent(inData, idx, 8);
881         } else if (is_LinearRGB_stdScale) {
882             int lutidx = extractComponent(inData, idx, 16);
883             return tosRGB8LUT[lutidx] & 0xff;
884         } else if (is_ICCGray_stdScale) {
885             int lutidx = extractComponent(inData, 0, 16);
886             return tosRGB8LUT[lutidx] & 0xff;
887         }
888
889         // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace
890
float[] norm = getNormalizedComponents(inData, null, 0);
891         // Note that getNormalizedComponents returns non-premultiplied values
892
float[] rgb = colorSpace.toRGB(norm);
893         return (int) (rgb[idx] * 255.0f + 0.5f);
894     }
895    
896     /**
897      * Returns the red color component for the specified pixel, scaled
898      * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
899      * is done if necessary. The <CODE>pixel</CODE> value is specified by an array
900      * of data elements of type <CODE>transferType</CODE> passed in as an object
901      * reference. The returned value will be a non pre-multiplied value. If the
902      * alpha is premultiplied, this method divides it out before returning
903      * the value (if the alpha value is 0, the red value will be 0). Since
904      * <code>ComponentColorModel</code> can be subclassed, subclasses
905      * inherit the implementation of this method and if they don't override
906      * it then they throw an exception if they use an unsupported
907      * <code>transferType</code>.
908      *
909      * @param inData The pixel from which you want to get the red color component,
910      * specified by an array of data elements of type <CODE>transferType</CODE>.
911      *
912      * @return The red color component for the specified pixel, as an int.
913      *
914      * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
915      * of type <CODE>transferType</CODE>.
916      * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
917      * large enough to hold a pixel value for this
918      * <CODE>ColorModel</CODE>.
919      * @throws UnsupportedOperationException If the transfer type of
920      * this <CODE>ComponentColorModel</CODE>
921      * is not one of the supported transfer types:
922      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
923      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
924      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
925      */

926     public int getRed(Object JavaDoc inData) {
927         return getRGBComponent(inData, 0);
928     }
929    
930
931     /**
932      * Returns the green color component for the specified pixel, scaled
933      * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
934      * A color conversion is done if necessary. The <CODE>pixel</CODE> value
935      * is specified by an array of data elements of type <CODE>transferType</CODE>
936      * passed in as an object reference. The returned value is a non pre-multiplied
937      * value. If the alpha is premultiplied, this method divides it out before
938      * returning the value (if the alpha value is 0, the green value will be 0).
939      * Since <code>ComponentColorModel</code> can be subclassed,
940      * subclasses inherit the implementation of this method and if they
941      * don't override it then they throw an exception if they use an
942      * unsupported <code>transferType</code>.
943      *
944      * @param inData The pixel from which you want to get the green color component,
945      * specified by an array of data elements of type <CODE>transferType</CODE>.
946      *
947      * @return The green color component for the specified pixel, as an int.
948      *
949      * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
950      * of type <CODE>transferType</CODE>.
951      * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
952      * large enough to hold a pixel value for this
953      * <CODE>ColorModel</CODE>.
954      * @throws UnsupportedOperationException If the transfer type of
955      * this <CODE>ComponentColorModel</CODE>
956      * is not one of the supported transfer types:
957      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
958      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
959      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
960      */

961     public int getGreen(Object JavaDoc inData) {
962         return getRGBComponent(inData, 1);
963     }
964    
965
966     /**
967      * Returns the blue color component for the specified pixel, scaled
968      * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
969      * A color conversion is done if necessary. The <CODE>pixel</CODE> value is
970      * specified by an array of data elements of type <CODE>transferType</CODE>
971      * passed in as an object reference. The returned value is a non pre-multiplied
972      * value. If the alpha is premultiplied, this method divides it out before
973      * returning the value (if the alpha value is 0, the blue value will be 0).
974      * Since <code>ComponentColorModel</code> can be subclassed,
975      * subclasses inherit the implementation of this method and if they
976      * don't override it then they throw an exception if they use an
977      * unsupported <code>transferType</code>.
978      *
979      * @param inData The pixel from which you want to get the blue color component,
980      * specified by an array of data elements of type <CODE>transferType</CODE>.
981      *
982      * @return The blue color component for the specified pixel, as an int.
983      *
984      * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
985      * of type <CODE>transferType</CODE>.
986      * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
987      * large enough to hold a pixel value for this
988      * <CODE>ColorModel</CODE>.
989      * @throws UnsupportedOperationException If the transfer type of
990      * this <CODE>ComponentColorModel</CODE>
991      * is not one of the supported transfer types:
992      * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
993      * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
994      * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
995      */

996     public int getBlue(Object JavaDoc inData) {
997         return getRGBComponent(inData, 2);
998     }
999
1000    /**
1001     * Returns the alpha component for the specified pixel, scaled from
1002     * 0 to 255. The pixel value is specified by an array of data
1003     * elements of type <CODE>transferType</CODE> passed in as an
1004     * object reference. Since <code>ComponentColorModel</code> can be
1005     * subclassed, subclasses inherit the
1006     * implementation of this method and if they don't override it then
1007     * they throw an exception if they use an unsupported
1008     * <code>transferType</code>.
1009     *
1010     * @param inData The pixel from which you want to get the alpha component,
1011     * specified by an array of data elements of type <CODE>transferType</CODE>.
1012     *
1013     * @return The alpha component for the specified pixel, as an int.
1014     *
1015     * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1016     * of type <CODE>transferType</CODE>.
1017     * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1018     * large enough to hold a pixel value for this
1019     * <CODE>ColorModel</CODE>.
1020     * @throws UnsupportedOperationException If the transfer type of
1021     * this <CODE>ComponentColorModel</CODE>
1022     * is not one of the supported transfer types:
1023     * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1024     * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1025     * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1026     */

1027    public int getAlpha(Object JavaDoc inData) {
1028        if (supportsAlpha == false) {
1029            return 255;
1030        }
1031
1032        int alpha = 0;
1033        int aIdx = numColorComponents;
1034        int mask = (1 << nBits[aIdx]) - 1;
1035
1036        switch (transferType) {
1037            case DataBuffer.TYPE_SHORT:
1038                short sdata[] = (short[])inData;
1039                alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f);
1040                return alpha;
1041            case DataBuffer.TYPE_FLOAT:
1042                float fdata[] = (float[])inData;
1043                alpha = (int) (fdata[aIdx] * 255.0f + 0.5f);
1044                return alpha;
1045            case DataBuffer.TYPE_DOUBLE:
1046                double ddata[] = (double[])inData;
1047                alpha = (int) (ddata[aIdx] * 255.0 + 0.5);
1048                return alpha;
1049            case DataBuffer.TYPE_BYTE:
1050               byte bdata[] = (byte[])inData;
1051               alpha = bdata[aIdx] & mask;
1052            break;
1053            case DataBuffer.TYPE_USHORT:
1054               short usdata[] = (short[])inData;
1055               alpha = usdata[aIdx] & mask;
1056            break;
1057            case DataBuffer.TYPE_INT:
1058               int idata[] = (int[])inData;
1059               alpha = idata[aIdx];
1060            break;
1061            default:
1062               throw new
1063                   UnsupportedOperationException JavaDoc("This method has not "+
1064                   "been implemented for transferType " + transferType);
1065        }
1066
1067        if (nBits[aIdx] == 8) {
1068            return alpha;
1069        } else {
1070            return (int)
1071                ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) *
1072                 255.0f + 0.5f);
1073        }
1074    }
1075
1076    /**
1077     * Returns the color/alpha components for the specified pixel in the
1078     * default RGB color model format. A color conversion is done if
1079     * necessary. The pixel value is specified by an
1080     * array of data elements of type <CODE>transferType</CODE> passed
1081     * in as an object reference.
1082     * The returned value is in a non pre-multiplied format. If
1083     * the alpha is premultiplied, this method divides it out of the
1084     * color components (if the alpha value is 0, the color values will be 0).
1085     * Since <code>ComponentColorModel</code> can be subclassed,
1086     * subclasses inherit the implementation of this method and if they
1087     * don't override it then they throw an exception if they use an
1088     * unsupported <code>transferType</code>.
1089     *
1090     * @param inData The pixel from which you want to get the color/alpha components,
1091     * specified by an array of data elements of type <CODE>transferType</CODE>.
1092     *
1093     * @return The color/alpha components for the specified pixel, as an int.
1094     *
1095     * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1096     * of type <CODE>transferType</CODE>.
1097     * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1098     * large enough to hold a pixel value for this
1099     * <CODE>ColorModel</CODE>.
1100     * @throws UnsupportedOperationException If the transfer type of
1101     * this <CODE>ComponentColorModel</CODE>
1102     * is not one of the supported transfer types:
1103     * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1104     * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1105     * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1106     * @see ColorModel#getRGBdefault
1107     */

1108    public int getRGB(Object JavaDoc inData) {
1109        if (needScaleInit) {
1110            initScale();
1111        }
1112        if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1113            return (getAlpha(inData) << 24)
1114                | (getRed(inData) << 16)
1115                | (getGreen(inData) << 8)
1116                | (getBlue(inData));
1117        } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
1118            int gray = getRed(inData); // Red sRGB component should equal
1119
// green and blue components
1120
return (getAlpha(inData) << 24)
1121                | (gray << 16)
1122                | (gray << 8)
1123                | gray;
1124        }
1125        float[] norm = getNormalizedComponents(inData, null, 0);
1126        // Note that getNormalizedComponents returns non-premult values
1127
float[] rgb = colorSpace.toRGB(norm);
1128        return (getAlpha(inData) << 24)
1129            | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
1130            | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
1131            | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
1132    }
1133
1134    /**
1135     * Returns a data element array representation of a pixel in this
1136     * <CODE>ColorModel</CODE>, given an integer pixel representation
1137     * in the default RGB color model.
1138     * This array can then be passed to the <CODE>setDataElements</CODE>
1139     * method of a <CODE>WritableRaster</CODE> object. If the
1140     * <CODE>pixel</CODE>
1141     * parameter is null, a new array is allocated. Since
1142     * <code>ComponentColorModel</code> can be subclassed, subclasses
1143     * inherit the implementation of this method and if they don't
1144     * override it then
1145     * they throw an exception if they use an unsupported
1146     * <code>transferType</code>.
1147     *
1148     * @param rgb the integer representation of the pixel in the RGB
1149     * color model
1150     * @param pixel the specified pixel
1151     * @return The data element array representation of a pixel
1152     * in this <CODE>ColorModel</CODE>.
1153     * @throws ClassCastException If <CODE>pixel</CODE> is not null and
1154     * is not a primitive array of type <CODE>transferType</CODE>.
1155     * @throws ArrayIndexOutOfBoundsException If <CODE>pixel</CODE> is
1156     * not large enough to hold a pixel value for this
1157     * <CODE>ColorModel</CODE>.
1158     * @throws UnsupportedOperationException If the transfer type of
1159     * this <CODE>ComponentColorModel</CODE>
1160     * is not one of the supported transfer types:
1161     * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1162     * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1163     * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1164     *
1165     * @see WritableRaster#setDataElements
1166     * @see SampleModel#setDataElements
1167     */

1168    public Object JavaDoc getDataElements(int rgb, Object JavaDoc pixel) {
1169        // REMIND: Use rendering hints?
1170

1171        int red, grn, blu, alp;
1172        red = (rgb>>16) & 0xff;
1173        grn = (rgb>>8) & 0xff;
1174        blu = rgb & 0xff;
1175
1176        if (needScaleInit) {
1177            initScale();
1178        }
1179    if (signed) {
1180            // Handle SHORT, FLOAT, & DOUBLE here
1181

1182            switch(transferType) {
1183            case DataBuffer.TYPE_SHORT:
1184                {
1185                    short sdata[];
1186                    if (pixel == null) {
1187                        sdata = new short[numComponents];
1188                    } else {
1189                        sdata = (short[])pixel;
1190                    }
1191                    float factor;
1192                    if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1193                        factor = 32767.0f / 255.0f;
1194                        if (is_LinearRGB_stdScale) {
1195                            red = fromsRGB8LUT16[red] & 0xffff;
1196                            grn = fromsRGB8LUT16[grn] & 0xffff;
1197                            blu = fromsRGB8LUT16[blu] & 0xffff;
1198                            factor = 32767.0f / 65535.0f;
1199                        }
1200                        if (supportsAlpha) {
1201                            alp = (rgb>>24) & 0xff;
1202                            sdata[3] =
1203                                (short) (alp * (32767.0f / 255.0f) + 0.5f);
1204                            if (isAlphaPremultiplied) {
1205                                factor = alp * factor * (1.0f / 255.0f);
1206                            }
1207                        }
1208                        sdata[0] = (short) (red * factor + 0.5f);
1209                        sdata[1] = (short) (grn * factor + 0.5f);
1210                        sdata[2] = (short) (blu * factor + 0.5f);
1211                    } else if (is_LinearGray_stdScale) {
1212                        red = fromsRGB8LUT16[red] & 0xffff;
1213                        grn = fromsRGB8LUT16[grn] & 0xffff;
1214                        blu = fromsRGB8LUT16[blu] & 0xffff;
1215                        float gray = ((0.2125f * red) +
1216                                      (0.7154f * grn) +
1217                                      (0.0721f * blu)) / 65535.0f;
1218                        factor = 32767.0f;
1219                        if (supportsAlpha) {
1220                            alp = (rgb>>24) & 0xff;
1221                            sdata[1] =
1222                                (short) (alp * (32767.0f / 255.0f) + 0.5f);
1223                            if (isAlphaPremultiplied) {
1224                                factor = alp * factor * (1.0f / 255.0f);
1225                            }
1226                        }
1227                        sdata[0] = (short) (gray * factor + 0.5f);
1228                    } else if (is_ICCGray_stdScale) {
1229                        red = fromsRGB8LUT16[red] & 0xffff;
1230                        grn = fromsRGB8LUT16[grn] & 0xffff;
1231                        blu = fromsRGB8LUT16[blu] & 0xffff;
1232                        int gray = (int) ((0.2125f * red) +
1233                                          (0.7154f * grn) +
1234                                          (0.0721f * blu) + 0.5f);
1235                        gray = fromLinearGray16ToOtherGray16LUT[gray] & 0xffff;
1236                        factor = 32767.0f / 65535.0f;
1237                        if (supportsAlpha) {
1238                            alp = (rgb>>24) & 0xff;
1239                            sdata[1] =
1240                                (short) (alp * (32767.0f / 255.0f) + 0.5f);
1241                            if (isAlphaPremultiplied) {
1242                                factor = alp * factor * (1.0f / 255.0f);
1243                            }
1244                        }
1245                        sdata[0] = (short) (gray * factor + 0.5f);
1246                    } else {
1247                        factor = 1.0f / 255.0f;
1248                        float norm[] = new float[3];
1249                        norm[0] = red * factor;
1250                        norm[1] = grn * factor;
1251                        norm[2] = blu * factor;
1252                        norm = colorSpace.fromRGB(norm);
1253                        if (nonStdScale) {
1254                            for (int i = 0; i < numColorComponents; i++) {
1255                                norm[i] = (norm[i] - compOffset[i]) *
1256                                          compScale[i];
1257                                // REMIND: need to analyze whether this
1258
// clamping is necessary
1259
if (norm[i] < 0.0f) {
1260                                    norm[i] = 0.0f;
1261                                }
1262                                if (norm[i] > 1.0f) {
1263                                    norm[i] = 1.0f;
1264                                }
1265                            }
1266                        }
1267                        factor = 32767.0f;
1268                        if (supportsAlpha) {
1269                            alp = (rgb>>24) & 0xff;
1270                            sdata[numColorComponents] =
1271                                (short) (alp * (32767.0f / 255.0f) + 0.5f);
1272                            if (isAlphaPremultiplied) {
1273                                factor *= alp * (1.0f / 255.0f);
1274                            }
1275                        }
1276                        for (int i = 0; i < numColorComponents; i++) {
1277                            sdata[i] = (short) (norm[i] * factor + 0.5f);
1278                        }
1279                    }
1280                    return sdata;
1281                }
1282            case DataBuffer.TYPE_FLOAT:
1283                {
1284                    float fdata[];
1285                    if (pixel == null) {
1286                        fdata = new float[numComponents];
1287                    } else {
1288                        fdata = (float[])pixel;
1289                    }
1290                    float factor;
1291                    if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1292                        if (is_LinearRGB_stdScale) {
1293                            red = fromsRGB8LUT16[red] & 0xffff;
1294                            grn = fromsRGB8LUT16[grn] & 0xffff;
1295                            blu = fromsRGB8LUT16[blu] & 0xffff;
1296                            factor = 1.0f / 65535.0f;
1297                        } else {
1298                            factor = 1.0f / 255.0f;
1299                        }
1300                        if (supportsAlpha) {
1301                            alp = (rgb>>24) & 0xff;
1302                            fdata[3] = alp * (1.0f / 255.0f);
1303                            if (isAlphaPremultiplied) {
1304                                factor *= fdata[3];
1305                            }
1306                        }
1307                        fdata[0] = red * factor;
1308                        fdata[1] = grn * factor;
1309                        fdata[2] = blu * factor;
1310                    } else if (is_LinearGray_stdScale) {
1311                        red = fromsRGB8LUT16[red] & 0xffff;
1312                        grn = fromsRGB8LUT16[grn] & 0xffff;
1313                        blu = fromsRGB8LUT16[blu] & 0xffff;
1314                        fdata[0] = ((0.2125f * red) +
1315                                    (0.7154f * grn) +
1316                                    (0.0721f * blu)) / 65535.0f;
1317                        if (supportsAlpha) {
1318                            alp = (rgb>>24) & 0xff;
1319                            fdata[1] = alp * (1.0f / 255.0f);
1320                            if (isAlphaPremultiplied) {
1321                                fdata[0] *= fdata[1];
1322                            }
1323                        }
1324                    } else if (is_ICCGray_stdScale) {
1325                        red = fromsRGB8LUT16[red] & 0xffff;
1326                        grn = fromsRGB8LUT16[grn] & 0xffff;
1327                        blu = fromsRGB8LUT16[blu] & 0xffff;
1328                        int gray = (int) ((0.2125f * red) +
1329                                          (0.7154f * grn) +
1330                                          (0.0721f * blu) + 0.5f);
1331                        fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
1332                                    0xffff) / 65535.0f;
1333                        if (supportsAlpha) {
1334                            alp = (rgb>>24) & 0xff;
1335                            fdata[1] = alp * (1.0f / 255.0f);
1336                            if (isAlphaPremultiplied) {
1337                                fdata[0] *= fdata[1];
1338                            }
1339                        }
1340                    } else {
1341                        float norm[] = new float[3];
1342                        factor = 1.0f / 255.0f;
1343                        norm[0] = red * factor;
1344                        norm[1] = grn * factor;
1345                        norm[2] = blu * factor;
1346                        norm = colorSpace.fromRGB(norm);
1347                        if (supportsAlpha) {
1348                            alp = (rgb>>24) & 0xff;
1349                            fdata[numColorComponents] = alp * factor;
1350                            if (isAlphaPremultiplied) {
1351                                factor *= alp;
1352                                for (int i = 0; i < numColorComponents; i++) {
1353                                    norm[i] *= factor;
1354                                }
1355                            }
1356                        }
1357                        for (int i = 0; i < numColorComponents; i++) {
1358                            fdata[i] = norm[i];
1359                        }
1360                    }
1361                    return fdata;
1362                }
1363            case DataBuffer.TYPE_DOUBLE:
1364                {
1365                    double ddata[];
1366                    if (pixel == null) {
1367                        ddata = new double[numComponents];
1368                    } else {
1369                        ddata = (double[])pixel;
1370                    }
1371                    if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1372                        double factor;
1373                        if (is_LinearRGB_stdScale) {
1374                            red = fromsRGB8LUT16[red] & 0xffff;
1375                            grn = fromsRGB8LUT16[grn] & 0xffff;
1376                            blu = fromsRGB8LUT16[blu] & 0xffff;
1377                            factor = 1.0 / 65535.0;
1378                        } else {
1379                            factor = 1.0 / 255.0;
1380                        }
1381                        if (supportsAlpha) {
1382                            alp = (rgb>>24) & 0xff;
1383                            ddata[3] = alp * (1.0 / 255.0);
1384                            if (isAlphaPremultiplied) {
1385                                factor *= ddata[3];
1386                            }
1387                        }
1388                        ddata[0] = red * factor;
1389                        ddata[1] = grn * factor;
1390                        ddata[2] = blu * factor;
1391                    } else if (is_LinearGray_stdScale) {
1392                        red = fromsRGB8LUT16[red] & 0xffff;
1393                        grn = fromsRGB8LUT16[grn] & 0xffff;
1394                        blu = fromsRGB8LUT16[blu] & 0xffff;
1395                        ddata[0] = ((0.2125 * red) +
1396                                    (0.7154 * grn) +
1397                                    (0.0721 * blu)) / 65535.0;
1398                        if (supportsAlpha) {
1399                            alp = (rgb>>24) & 0xff;
1400                            ddata[1] = alp * (1.0 / 255.0);
1401                            if (isAlphaPremultiplied) {
1402                                ddata[0] *= ddata[1];
1403                            }
1404                        }
1405                    } else if (is_ICCGray_stdScale) {
1406                        red = fromsRGB8LUT16[red] & 0xffff;
1407                        grn = fromsRGB8LUT16[grn] & 0xffff;
1408                        blu = fromsRGB8LUT16[blu] & 0xffff;
1409                        int gray = (int) ((0.2125f * red) +
1410                                          (0.7154f * grn) +
1411                                          (0.0721f * blu) + 0.5f);
1412                        ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
1413                                    0xffff) / 65535.0;
1414                        if (supportsAlpha) {
1415                            alp = (rgb>>24) & 0xff;
1416                            ddata[1] = alp * (1.0 / 255.0);
1417                            if (isAlphaPremultiplied) {
1418                                ddata[0] *= ddata[1];
1419                            }
1420                        }
1421                    } else {
1422                        float factor = 1.0f / 255.0f;
1423                        float norm[] = new float[3];
1424                        norm[0] = red * factor;
1425                        norm[1] = grn * factor;
1426                        norm[2] = blu * factor;
1427                        norm = colorSpace.fromRGB(norm);
1428                        if (supportsAlpha) {
1429                            alp = (rgb>>24) & 0xff;
1430                            ddata[numColorComponents] = alp * (1.0 / 255.0);
1431                            if (isAlphaPremultiplied) {
1432                                factor *= alp;
1433                                for (int i = 0; i < numColorComponents; i++) {
1434                                    norm[i] *= factor;
1435                                }
1436                            }
1437                        }
1438                        for (int i = 0; i < numColorComponents; i++) {
1439                            ddata[i] = norm[i];
1440                        }
1441                    }
1442                    return ddata;
1443                }
1444            }
1445        }
1446
1447        // Handle BYTE, USHORT, & INT here
1448
//REMIND: maybe more efficient not to use int array for
1449
//DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
1450
int intpixel[];
1451        if (transferType == DataBuffer.TYPE_INT &&
1452            pixel != null) {
1453           intpixel = (int[])pixel;
1454        } else {
1455            intpixel = new int[numComponents];
1456        }
1457
1458        if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1459            int precision;
1460            float factor;
1461            if (is_LinearRGB_stdScale) {
1462                if (transferType == DataBuffer.TYPE_BYTE) {
1463                    red = fromsRGB8LUT8[red] & 0xff;
1464                    grn = fromsRGB8LUT8[grn] & 0xff;
1465                    blu = fromsRGB8LUT8[blu] & 0xff;
1466                    precision = 8;
1467                    factor = 1.0f / 255.0f;
1468                } else {
1469                    red = fromsRGB8LUT16[red] & 0xffff;
1470                    grn = fromsRGB8LUT16[grn] & 0xffff;
1471                    blu = fromsRGB8LUT16[blu] & 0xffff;
1472                    precision = 16;
1473                    factor = 1.0f / 65535.0f;
1474                }
1475            } else {
1476                precision = 8;
1477                factor = 1.0f / 255.0f;
1478            }
1479            if (supportsAlpha) {
1480                alp = (rgb>>24)&0xff;
1481                if (nBits[3] == 8) {
1482                    intpixel[3] = alp;
1483                }
1484                else {
1485                    intpixel[3] = (int)
1486                        (alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1) + 0.5f);
1487                }
1488                if (isAlphaPremultiplied) {
1489                    factor *= (alp * (1.0f / 255.0f));
1490                    precision = -1; // force component calculations below
1491
}
1492            }
1493            if (nBits[0] == precision) {
1494                intpixel[0] = red;
1495            }
1496            else {
1497                intpixel[0] = (int) (red * factor * ((1<<nBits[0]) - 1) + 0.5f);
1498            }
1499            if (nBits[1] == precision) {
1500                intpixel[1] = (int)(grn);
1501            }
1502            else {
1503                intpixel[1] = (int) (grn * factor * ((1<<nBits[1]) - 1) + 0.5f);
1504            }
1505            if (nBits[2] == precision) {
1506                intpixel[2] = (int)(blu);
1507            }
1508            else {
1509                intpixel[2] = (int) (blu * factor * ((1<<nBits[2]) - 1) + 0.5f);
1510            }
1511        } else if (is_LinearGray_stdScale) {
1512            red = fromsRGB8LUT16[red] & 0xffff;
1513            grn = fromsRGB8LUT16[grn] & 0xffff;
1514            blu = fromsRGB8LUT16[blu] & 0xffff;
1515            float gray = ((0.2125f * red) +
1516                          (0.7154f * grn) +
1517                          (0.0721f * blu)) / 65535.0f;
1518            if (supportsAlpha) {
1519                alp = (rgb>>24) & 0xff;
1520                if (nBits[1] == 8) {
1521                    intpixel[1] = alp;
1522                } else {
1523                    intpixel[1] = (int) (alp * (1.0f / 255.0f) *
1524                                         ((1 << nBits[1]) - 1) + 0.5f);
1525                }
1526                if (isAlphaPremultiplied) {
1527                    gray *= (alp * (1.0f / 255.0f));
1528                }
1529            }
1530            intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
1531        } else if (is_ICCGray_stdScale) {
1532            red = fromsRGB8LUT16[red] & 0xffff;
1533            grn = fromsRGB8LUT16[grn] & 0xffff;
1534            blu = fromsRGB8LUT16[blu] & 0xffff;
1535            int gray16 = (int) ((0.2125f * red) +
1536                                (0.7154f * grn) +
1537                                (0.0721f * blu) + 0.5f);
1538            float gray = (fromLinearGray16ToOtherGray16LUT[gray16] &
1539                          0xffff) / 65535.0f;
1540            if (supportsAlpha) {
1541                alp = (rgb>>24) & 0xff;
1542                if (nBits[1] == 8) {
1543                    intpixel[1] = alp;
1544                } else {
1545                    intpixel[1] = (int) (alp * (1.0f / 255.0f) *
1546                                         ((1 << nBits[1]) - 1) + 0.5f);
1547                }
1548                if (isAlphaPremultiplied) {
1549                    gray *= (alp * (1.0f / 255.0f));
1550                }
1551            }
1552            intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f);
1553        } else {
1554            // Need to convert the color
1555
float[] norm = new float[3];
1556            float factor = 1.0f / 255.0f;
1557            norm[0] = red * factor;
1558            norm[1] = grn * factor;
1559            norm[2] = blu * factor;
1560            norm = colorSpace.fromRGB(norm);
1561            if (nonStdScale) {
1562                for (int i = 0; i < numColorComponents; i++) {
1563                    norm[i] = (norm[i] - compOffset[i]) *
1564                              compScale[i];
1565                    // REMIND: need to analyze whether this
1566
// clamping is necessary
1567
if (norm[i] < 0.0f) {
1568                        norm[i] = 0.0f;
1569                    }
1570                    if (norm[i] > 1.0f) {
1571                        norm[i] = 1.0f;
1572                    }
1573                }
1574            }
1575            if (supportsAlpha) {
1576                alp = (rgb>>24) & 0xff;
1577                if (nBits[numColorComponents] == 8) {
1578                    intpixel[numColorComponents] = alp;
1579                }
1580                else {
1581                    intpixel[numColorComponents] =
1582                        (int) (alp * factor *
1583                               ((1<<nBits[numColorComponents]) - 1) + 0.5f);
1584                }
1585                if (isAlphaPremultiplied) {
1586                    factor *= alp;
1587                    for (int i = 0; i < numColorComponents; i++) {
1588                        norm[i] *= factor;
1589                    }
1590                }
1591            }
1592            for (int i = 0; i < numColorComponents; i++) {
1593                intpixel[i] = (int) (norm[i] * ((1<<nBits[i]) - 1) + 0.5f);
1594            }
1595        }
1596
1597        switch (transferType) {
1598            case DataBuffer.TYPE_BYTE: {
1599               byte bdata[];
1600               if (pixel == null) {
1601                   bdata = new byte[numComponents];
1602               } else {
1603                   bdata = (byte[])pixel;
1604               }
1605               for (int i = 0; i < numComponents; i++) {
1606                   bdata[i] = (byte)(0xff&intpixel[i]);
1607               }
1608               return bdata;
1609            }
1610            case DataBuffer.TYPE_USHORT:{
1611               short sdata[];
1612               if (pixel == null) {
1613                   sdata = new short[numComponents];
1614               } else {
1615                   sdata = (short[])pixel;
1616               }
1617               for (int i = 0; i < numComponents; i++) {
1618                   sdata[i] = (short)(intpixel[i]&0xffff);
1619               }
1620               return sdata;
1621            }
1622            case DataBuffer.TYPE_INT:
1623                if (maxBits > 23) {
1624                    // fix 4412670 - for components of 24 or more bits
1625
// some calculations done above with float precision
1626
// may lose enough precision that the integer result
1627
// overflows nBits, so we need to clamp.
1628
for (int i = 0; i < numComponents; i++) {
1629                        if (intpixel[i] > ((1<<nBits[i]) - 1)) {
1630                            intpixel[i] = (1<<nBits[i]) - 1;
1631                        }
1632                    }
1633                }
1634                return intpixel;
1635        }
1636        throw new IllegalArgumentException JavaDoc("This method has not been "+
1637                 "implemented for transferType " + transferType);
1638    }
1639    
1640   /** Returns an array of unnormalized color/alpha components given a pixel
1641     * in this <CODE>ColorModel</CODE>.
1642     * An IllegalArgumentException is thrown if the component value for this
1643     * <CODE>ColorModel</CODE> is not conveniently representable in the
1644     * unnormalized form. Color/alpha components are stored
1645     * in the <CODE>components</CODE> array starting at <CODE>offset</CODE>
1646     * (even if the array is allocated by this method).
1647     *
1648     * @param pixel The pixel value specified as an integer.
1649     * @param components An integer array in which to store the unnormalized
1650     * color/alpha components. If the <CODE>components</CODE> array is null,
1651     * a new array is allocated.
1652     * @param offset An offset into the <CODE>components</CODE> array.
1653     *
1654     * @return The components array.
1655     *
1656     * @throws IllegalArgumentException If there is more than one
1657     * component in this <CODE>ColorModel</CODE>.
1658     * @throws IllegalArgumentException If this
1659     * <CODE>ColorModel</CODE> does not support the unnormalized form
1660     * @throws ArrayIndexOutOfBoundsException If the <CODE>components</CODE>
1661     * array is not null and is not large enough to hold all the color and
1662     * alpha components (starting at offset).
1663     */

1664    public int[] getComponents(int pixel, int[] components, int offset) {
1665        if (numComponents > 1) {
1666            throw new
1667                IllegalArgumentException JavaDoc("More than one component per pixel");
1668        }
1669        if (needScaleInit) {
1670            initScale();
1671        }
1672        if (noUnnorm) {
1673            throw new
1674                IllegalArgumentException JavaDoc(
1675                    "This ColorModel does not support the unnormalized form");
1676        }
1677        if (components == null) {
1678            components = new int[offset+1];
1679        }
1680
1681        components[offset+0] = (pixel & ((1<<nBits[0]) - 1));
1682        return components;
1683    }
1684    
1685    /**
1686     * Returns an array of unnormalized color/alpha components given a pixel
1687     * in this <CODE>ColorModel</CODE>. The pixel value is specified by an
1688     * array of data elements of type <CODE>transferType</CODE> passed in as
1689     * an object reference.
1690     * An IllegalArgumentException is thrown if the component values for this
1691     * <CODE>ColorModel</CODE> are not conveniently representable in the
1692     * unnormalized form.
1693     * Color/alpha components are stored in the <CODE>components</CODE> array
1694     * starting at <CODE>offset</CODE> (even if the array is allocated by
1695     * this method). Since <code>ComponentColorModel</code> can be
1696     * subclassed, subclasses inherit the
1697     * implementation of this method and if they don't override it then
1698     * this method might throw an exception if they use an unsupported
1699     * <code>transferType</code>.
1700     *
1701     * @param pixel A pixel value specified by an array of data elements of
1702     * type <CODE>transferType</CODE>.
1703     * @param components An integer array in which to store the unnormalized
1704     * color/alpha components. If the <CODE>components</CODE> array is null,
1705     * a new array is allocated.
1706     * @param offset An offset into the <CODE>components</CODE> array.
1707     *
1708     * @return The <CODE>components</CODE> array.
1709     *
1710     * @throws IllegalArgumentException If this
1711     * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1712     * @throws UnsupportedOperationException in some cases iff the
1713     * transfer type of this <CODE>ComponentColorModel</CODE>
1714     * is not one of the following transfer types:
1715     * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1716     * or <CODE>DataBuffer.TYPE_INT</CODE>.
1717     * @throws ClassCastException If <CODE>pixel</CODE> is not a primitive
1718     * array of type <CODE>transferType</CODE>.
1719     * @throws IllegalArgumentException If the <CODE>components</CODE> array is
1720     * not null and is not large enough to hold all the color and alpha
1721     * components (starting at offset), or if <CODE>pixel</CODE> is not large
1722     * enough to hold a pixel value for this ColorModel.
1723     */

1724    public int[] getComponents(Object JavaDoc pixel, int[] components, int offset) {
1725        int intpixel[];
1726        if (needScaleInit) {
1727            initScale();
1728        }
1729        if (noUnnorm) {
1730            throw new
1731                IllegalArgumentException JavaDoc(
1732                    "This ColorModel does not support the unnormalized form");
1733        }
1734        if (pixel instanceof int[]) {
1735            intpixel = (int[])pixel;
1736        } else {
1737            intpixel = DataBuffer.toIntArray(pixel);
1738            if (intpixel == null) {
1739               throw new UnsupportedOperationException JavaDoc("This method has not been "+
1740                   "implemented for transferType " + transferType);
1741            }
1742        }
1743        if (intpixel.length < numComponents) {
1744            throw new IllegalArgumentException JavaDoc
1745                ("Length of pixel array < number of components in model");
1746        }
1747        if (components == null) {
1748            components = new int[offset+numComponents];
1749        }
1750        else if ((components.length-offset) < numComponents) {
1751            throw new IllegalArgumentException JavaDoc
1752                ("Length of components array < number of components in model");
1753        }
1754        System.arraycopy(intpixel, 0, components, offset, numComponents);
1755
1756        return components;
1757    }
1758
1759    /**
1760     * Returns an array of all of the color/alpha components in unnormalized
1761     * form, given a normalized component array. Unnormalized components
1762     * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1763     * n is the number of bits for a particular component. Normalized
1764     * components are float values between a per component minimum and
1765     * maximum specified by the <code>ColorSpace</code> object for this
1766     * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
1767     * will be thrown if color component values for this
1768     * <code>ColorModel</code> are not conveniently representable in the
1769     * unnormalized form. If the
1770     * <code>components</code> array is <code>null</code>, a new array
1771     * will be allocated. The <code>components</code> array will
1772     * be returned. Color/alpha components are stored in the
1773     * <code>components</code> array starting at <code>offset</code> (even
1774     * if the array is allocated by this method). An
1775     * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1776     * <code>components</code> array is not <code>null</code> and is not
1777     * large enough to hold all the color and alpha
1778     * components (starting at <code>offset</code>). An
1779     * <code>IllegalArgumentException</code> is thrown if the
1780     * <code>normComponents</code> array is not large enough to hold
1781     * all the color and alpha components starting at
1782     * <code>normOffset</code>.
1783     * @param normComponents an array containing normalized components
1784     * @param normOffset the offset into the <code>normComponents</code>
1785     * array at which to start retrieving normalized components
1786     * @param components an array that receives the components from
1787     * <code>normComponents</code>
1788     * @param offset the index into <code>components</code> at which to
1789     * begin storing normalized components from
1790     * <code>normComponents</code>
1791     * @return an array containing unnormalized color and alpha
1792     * components.
1793     * @throws IllegalArgumentException If this
1794     * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1795     * @throws IllegalArgumentException if the length of
1796     * <code>normComponents</code> minus <code>normOffset</code>
1797     * is less than <code>numComponents</code>
1798     */

1799    public int[] getUnnormalizedComponents(float[] normComponents,
1800                                           int normOffset,
1801                                           int[] components, int offset) {
1802        if (needScaleInit) {
1803            initScale();
1804        }
1805        if (noUnnorm) {
1806            throw new
1807                IllegalArgumentException JavaDoc(
1808                    "This ColorModel does not support the unnormalized form");
1809        }
1810        return super.getUnnormalizedComponents(normComponents, normOffset,
1811                                               components, offset);
1812    }
1813    
1814    /**
1815     * Returns an array of all of the color/alpha components in normalized
1816     * form, given an unnormalized component array. Unnormalized components
1817     * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1818     * n is the number of bits for a particular component. Normalized
1819     * components are float values between a per component minimum and
1820     * maximum specified by the <code>ColorSpace</code> object for this
1821     * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
1822     * will be thrown if color component values for this
1823     * <code>ColorModel</code> are not conveniently representable in the
1824     * unnormalized form. If the
1825     * <code>normComponents</code> array is <code>null</code>, a new array
1826     * will be allocated. The <code>normComponents</code> array
1827     * will be returned. Color/alpha components are stored in the
1828     * <code>normComponents</code> array starting at
1829     * <code>normOffset</code> (even if the array is allocated by this
1830     * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
1831     * if the <code>normComponents</code> array is not <code>null</code>
1832     * and is not large enough to hold all the color and alpha components
1833     * (starting at <code>normOffset</code>). An
1834     * <code>IllegalArgumentException</code> is thrown if the
1835     * <code>components</code> array is not large enough to hold all the
1836     * color and alpha components starting at <code>offset</code>.
1837     * @param components an array containing unnormalized components
1838     * @param offset the offset into the <code>components</code> array at
1839     * which to start retrieving unnormalized components
1840     * @param normComponents an array that receives the normalized components
1841     * @param normOffset the index into <code>normComponents</code> at
1842     * which to begin storing normalized components
1843     * @return an array containing normalized color and alpha
1844     * components.
1845     * @throws IllegalArgumentException If this
1846     * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1847     */

1848    public float[] getNormalizedComponents(int[] components, int offset,
1849                                           float[] normComponents,
1850                                           int normOffset) {
1851        if (needScaleInit) {
1852            initScale();
1853        }
1854        if (noUnnorm) {
1855            throw new
1856                IllegalArgumentException JavaDoc(
1857                    "This ColorModel does not support the unnormalized form");
1858        }
1859        return super.getNormalizedComponents(components, offset,
1860                                             normComponents, normOffset);
1861    }
1862
1863    /**
1864     * Returns a pixel value represented as an int in this <CODE>ColorModel</CODE>,
1865     * given an array of unnormalized color/alpha components.
1866     *
1867     * @param components An array of unnormalized color/alpha components.
1868     * @param offset An offset into the <CODE>components</CODE> array.
1869     *
1870     * @return A pixel value represented as an int.
1871     *
1872     * @throws IllegalArgumentException If there is more than one component
1873     * in this <CODE>ColorModel</CODE>.
1874     * @throws IllegalArgumentException If this
1875     * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1876     */

1877    public int getDataElement(int[] components, int offset) {
1878        if (needScaleInit) {
1879            initScale();
1880        }
1881        if (numComponents == 1) {
1882            if (noUnnorm) {
1883                throw new
1884                    IllegalArgumentException JavaDoc(
1885                    "This ColorModel does not support the unnormalized form");
1886            }
1887            return components[offset+0];
1888        }
1889        throw new IllegalArgumentException JavaDoc("This model returns "+
1890                                           numComponents+
1891                                           " elements in the pixel array.");
1892    }
1893    
1894    /**
1895     * Returns a data element array representation of a pixel in this
1896     * <CODE>ColorModel</CODE>, given an array of unnormalized color/alpha
1897     * components. This array can then be passed to the <CODE>setDataElements</CODE>
1898     * method of a <CODE>WritableRaster</CODE> object.
1899     *
1900     * @param components An array of unnormalized color/alpha components.
1901     * @param offset The integer offset into the <CODE>components</CODE> array.
1902     * @param obj The object in which to store the data element array
1903     * representation of the pixel. If <CODE>obj</CODE> variable is null,
1904     * a new array is allocated. If <CODE>obj</CODE> is not null, it must
1905     * be a primitive array of type <CODE>transferType</CODE>. An
1906     * <CODE>ArrayIndexOutOfBoundsException</CODE> is thrown if
1907     * <CODE>obj</CODE> is not large enough to hold a pixel value
1908     * for this <CODE>ColorModel</CODE>. Since
1909     * <code>ComponentColorModel</code> can be subclassed, subclasses
1910     * inherit the implementation of this method and if they don't
1911     * override it then they throw an exception if they use an
1912     * unsupported <code>transferType</code>.
1913     *
1914     * @return The data element array representation of a pixel
1915     * in this <CODE>ColorModel</CODE>.
1916     *
1917     * @throws IllegalArgumentException If the components array
1918     * is not large enough to hold all the color and alpha components
1919     * (starting at offset).
1920     * @throws ClassCastException If <CODE>obj</CODE> is not null and is not a
1921     * primitive array of type <CODE>transferType</CODE>.
1922     * @throws ArrayIndexOutOfBoundsException If <CODE>obj</CODE> is not large
1923     * enough to hold a pixel value for this <CODE>ColorModel</CODE>.
1924     * @throws IllegalArgumentException If this
1925     * <CODE>ComponentColorModel</CODE> does not support the unnormalized form
1926     * @throws UnsupportedOperationException If the transfer type of
1927     * this <CODE>ComponentColorModel</CODE>
1928     * is not one of the following transfer types:
1929     * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1930     * or <CODE>DataBuffer.TYPE_INT</CODE>.
1931     *
1932     * @see WritableRaster#setDataElements
1933     * @see SampleModel#setDataElements
1934     */

1935    public Object JavaDoc getDataElements(int[] components, int offset, Object JavaDoc obj) {
1936        if (needScaleInit) {
1937            initScale();
1938        }
1939        if (noUnnorm) {
1940            throw new
1941                IllegalArgumentException JavaDoc(
1942                    "This ColorModel does not support the unnormalized form");
1943        }
1944        if ((components.length-offset) < numComponents) {
1945            throw new IllegalArgumentException JavaDoc("Component array too small"+
1946                                               " (should be "+numComponents);
1947        }
1948        switch(transferType) {
1949        case DataBuffer.TYPE_INT:
1950            {
1951                int[] pixel;
1952                if (obj == null) {
1953                    pixel = new int[numComponents];
1954                }
1955                else {
1956                    pixel = (int[]) obj;
1957                }
1958                System.arraycopy(components, offset, pixel, 0,
1959                                 numComponents);
1960                return pixel;
1961            }
1962        
1963        case DataBuffer.TYPE_BYTE:
1964            {
1965                byte[] pixel;
1966                if (obj == null) {
1967                    pixel = new byte[numComponents];
1968                }
1969                else {
1970                    pixel = (byte[]) obj;
1971                }
1972                for (int i=0; i < numComponents; i++) {
1973                    pixel[i] = (byte) (components[offset+i]&0xff);
1974                }
1975                return pixel;
1976            }
1977        
1978        case DataBuffer.TYPE_USHORT:
1979            {
1980                short[] pixel;
1981                if (obj == null) {
1982                    pixel = new short[numComponents];
1983                }
1984                else {
1985                    pixel = (short[]) obj;
1986                }
1987                for (int i=0; i < numComponents; i++) {
1988                    pixel[i] = (short) (components[offset+i]&0xffff);
1989                }
1990                return pixel;
1991            }
1992        
1993        default:
1994            throw new UnsupportedOperationException JavaDoc("This method has not been "+
1995                                        "implemented for transferType " +
1996                                        transferType);
1997        }
1998    }
1999
2000    /**
2001     * Returns a pixel value represented as an <code>int</code> in this
2002     * <code>ColorModel</code>, given an array of normalized color/alpha
2003     * components. This method will throw an
2004     * <code>IllegalArgumentException</code> if pixel values for this
2005     * <code>ColorModel</code> are not conveniently representable as a
2006     * single <code>int</code>. An
2007     * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
2008     * <code>normComponents</code> array is not large enough to hold all the
2009     * color and alpha components (starting at <code>normOffset</code>).
2010     * @param normComponents an array of normalized color and alpha
2011     * components
2012     * @param normOffset the index into <code>normComponents</code> at which to
2013     * begin retrieving the color and alpha components
2014     * @return an <code>int</code> pixel value in this
2015     * <code>ColorModel</code> corresponding to the specified components.
2016     * @throws IllegalArgumentException if
2017     * pixel values for this <code>ColorModel</code> are not
2018     * conveniently representable as a single <code>int</code>
2019     * @throws ArrayIndexOutOfBoundsException if
2020     * the <code>normComponents</code> array is not large enough to
2021     * hold all of the color and alpha components starting at
2022     * <code>normOffset</code>
2023     * @since 1.4
2024     */

2025    public int getDataElement(float[] normComponents, int normOffset) {
2026        if (numComponents > 1) {
2027            throw new
2028                IllegalArgumentException JavaDoc("More than one component per pixel");
2029        }
2030        if (signed) {
2031            throw new
2032                IllegalArgumentException JavaDoc("Component value is signed");
2033        }
2034        if (needScaleInit) {
2035            initScale();
2036        }
2037        Object JavaDoc pixel = getDataElements(normComponents, normOffset, null);
2038        switch (transferType) {
2039        case DataBuffer.TYPE_BYTE:
2040            {
2041                byte bpixel[] = (byte[]) pixel;
2042                return bpixel[0] & 0xff;
2043            }
2044        case DataBuffer.TYPE_USHORT:
2045            {
2046                short[] uspixel = (short[]) pixel;
2047                return uspixel[0] & 0xffff;
2048            }
2049        case DataBuffer.TYPE_INT:
2050            {
2051                int[] ipixel = (int[]) pixel;
2052                return ipixel[0];
2053            }
2054        default:
2055            throw new UnsupportedOperationException JavaDoc("This method has not been "
2056                + "implemented for transferType " + transferType);
2057        }
2058    }
2059
2060    /**
2061     * Returns a data element array representation of a pixel in this
2062     * <code>ColorModel</code>, given an array of normalized color/alpha
2063     * components. This array can then be passed to the
2064     * <code>setDataElements</code> method of a <code>WritableRaster</code>
2065     * object. An <code>ArrayIndexOutOfBoundsException</code> is thrown
2066     * if the <code>normComponents</code> array is not large enough to hold
2067     * all the color and alpha components (starting at
2068     * <code>normOffset</code>). If the <code>obj</code> variable is
2069     * <code>null</code>, a new array will be allocated. If
2070     * <code>obj</code> is not <code>null</code>, it must be a primitive
2071     * array of type transferType; otherwise, a
2072     * <code>ClassCastException</code> is thrown. An
2073     * <code>ArrayIndexOutOfBoundsException</code> is thrown if
2074     * <code>obj</code> is not large enough to hold a pixel value for this
2075     * <code>ColorModel</code>.
2076     * @param normComponents an array of normalized color and alpha
2077     * components
2078     * @param normOffset the index into <code>normComponents</code> at which to
2079     * begin retrieving color and alpha components
2080     * @param obj a primitive data array to hold the returned pixel
2081     * @return an <code>Object</code> which is a primitive data array
2082     * representation of a pixel
2083     * @throws ClassCastException if <code>obj</code>
2084     * is not a primitive array of type <code>transferType</code>
2085     * @throws ArrayIndexOutOfBoundsException if
2086     * <code>obj</code> is not large enough to hold a pixel value
2087     * for this <code>ColorModel</code> or the <code>normComponents</code>
2088     * array is not large enough to hold all of the color and alpha
2089     * components starting at <code>normOffset</code>
2090     * @see WritableRaster#setDataElements
2091     * @see SampleModel#setDataElements
2092     * @since 1.4
2093     */

2094    public Object JavaDoc getDataElements(float[] normComponents, int normOffset,
2095                                  Object JavaDoc obj) {
2096        boolean needAlpha = supportsAlpha && isAlphaPremultiplied;
2097        float[] stdNormComponents;
2098        if (needScaleInit) {
2099            initScale();
2100        }
2101        if (nonStdScale) {
2102            stdNormComponents = new float[numComponents];
2103            for (int c = 0, nc = normOffset; c < numColorComponents;
2104                 c++, nc++) {
2105                stdNormComponents[c] = (normComponents[nc] - compOffset[c]) *
2106                                       compScale[c];
2107                // REMIND: need to analyze whether this
2108
// clamping is necessary
2109
if (stdNormComponents[c] < 0.0f) {
2110                    stdNormComponents[c] = 0.0f;
2111                }
2112                if (stdNormComponents[c] > 1.0f) {
2113                    stdNormComponents[c] = 1.0f;
2114                }
2115            }
2116            if (supportsAlpha) {
2117                stdNormComponents[numColorComponents] =
2118                    normComponents[numColorComponents + normOffset];
2119            }
2120            normOffset = 0;
2121        } else {
2122            stdNormComponents = normComponents;
2123        }
2124        switch (transferType) {
2125        case DataBuffer.TYPE_BYTE:
2126            byte[] bpixel;
2127            if (obj == null) {
2128                bpixel = new byte[numComponents];
2129            } else {
2130                bpixel = (byte[]) obj;
2131            }
2132            if (needAlpha) {
2133                float alpha =
2134                    stdNormComponents[numColorComponents + normOffset];
2135                for (int c = 0, nc = normOffset; c < numColorComponents;
2136                     c++, nc++) {
2137                    bpixel[c] = (byte) ((stdNormComponents[nc] * alpha) *
2138                                        ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2139                }
2140                bpixel[numColorComponents] =
2141                    (byte) (alpha *
2142                            ((float) ((1 << nBits[numColorComponents]) - 1)) +
2143                            0.5f);
2144            } else {
2145                for (int c = 0, nc = normOffset; c < numComponents;
2146                     c++, nc++) {
2147                    bpixel[c] = (byte) (stdNormComponents[nc] *
2148                                        ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2149                }
2150            }
2151            return bpixel;
2152        case DataBuffer.TYPE_USHORT:
2153            short[] uspixel;
2154            if (obj == null) {
2155                uspixel = new short[numComponents];
2156            } else {
2157                uspixel = (short[]) obj;
2158            }
2159            if (needAlpha) {
2160                float alpha =
2161                    stdNormComponents[numColorComponents + normOffset];
2162                for (int c = 0, nc = normOffset; c < numColorComponents;
2163                     c++, nc++) {
2164                    uspixel[c] = (short) ((stdNormComponents[nc] * alpha) *
2165                                          ((float) ((1 << nBits[c]) - 1)) +
2166                                          0.5f);
2167                }
2168                uspixel[numColorComponents] =
2169                    (short) (alpha *
2170                             ((float) ((1 << nBits[numColorComponents]) - 1)) +
2171                             0.5f);
2172            } else {
2173                for (int c = 0, nc = normOffset; c < numComponents;
2174                     c++, nc++) {
2175                    uspixel[c] = (short) (stdNormComponents[nc] *
2176                                          ((float) ((1 << nBits[c]) - 1)) +
2177                                          0.5f);
2178                }
2179            }
2180            return uspixel;
2181        case DataBuffer.TYPE_INT:
2182            int[] ipixel;
2183            if (obj == null) {
2184                ipixel = new int[numComponents];
2185            } else {
2186                ipixel = (int[]) obj;
2187            }
2188            if (needAlpha) {
2189                float alpha =
2190                    stdNormComponents[numColorComponents + normOffset];
2191                for (int c = 0, nc = normOffset; c < numColorComponents;
2192                     c++, nc++) {
2193                    ipixel[c] = (int) ((stdNormComponents[nc] * alpha) *
2194                                       ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2195                }
2196                ipixel[numColorComponents] =
2197                    (int) (alpha *
2198                           ((float) ((1 << nBits[numColorComponents]) - 1)) +
2199                           0.5f);
2200            } else {
2201                for (int c = 0, nc = normOffset; c < numComponents;
2202                     c++, nc++) {
2203                    ipixel[c] = (int) (stdNormComponents[nc] *
2204                                       ((float) ((1 << nBits[c]) - 1)) + 0.5f);
2205                }
2206            }
2207            return ipixel;
2208        case DataBuffer.TYPE_SHORT:
2209            short[] spixel;
2210            if (obj == null) {
2211                spixel = new short[numComponents];
2212            } else {
2213                spixel = (short[]) obj;
2214            }
2215            if (needAlpha) {
2216                float alpha =
2217                    stdNormComponents[numColorComponents + normOffset];
2218                for (int c = 0, nc = normOffset; c < numColorComponents;
2219                     c++, nc++) {
2220                    spixel[c] = (short)
2221                        (stdNormComponents[nc] * alpha * 32767.0f + 0.5f);
2222                }
2223                spixel[numColorComponents] = (short) (alpha * 32767.0f + 0.5f);
2224            } else {
2225                for (int c = 0, nc = normOffset; c < numComponents;
2226                     c++, nc++) {
2227                    spixel[c] = (short)
2228                        (stdNormComponents[nc] * 32767.0f + 0.5f);
2229                }
2230            }
2231            return spixel;
2232        case DataBuffer.TYPE_FLOAT:
2233            float[] fpixel;
2234            if (obj == null) {
2235                fpixel = new float[numComponents];
2236            } else {
2237                fpixel = (float[]) obj;
2238            }
2239            if (needAlpha) {
2240                float alpha = normComponents[numColorComponents + normOffset];
2241                for (int c = 0, nc = normOffset; c < numColorComponents;
2242                     c++, nc++) {
2243                    fpixel[c] = normComponents[nc] * alpha;
2244                }
2245                fpixel[numColorComponents] = alpha;
2246            } else {
2247                for (int c = 0, nc = normOffset; c < numComponents;
2248                     c++, nc++) {
2249                    fpixel[c] = normComponents[nc];
2250                }
2251            }
2252            return fpixel;
2253        case DataBuffer.TYPE_DOUBLE:
2254            double[] dpixel;
2255            if (obj == null) {
2256                dpixel = new double[numComponents];
2257            } else {
2258                dpixel = (double[]) obj;
2259            }
2260            if (needAlpha) {
2261                double alpha =
2262                    (double) (normComponents[numColorComponents + normOffset]);
2263                for (int c = 0, nc = normOffset; c < numColorComponents;
2264                     c++, nc++) {
2265                    dpixel[c] = normComponents[nc] * alpha;
2266                }
2267                dpixel[numColorComponents] = alpha;
2268            } else {
2269                for (int c = 0, nc = normOffset; c < numComponents;
2270                     c++, nc++) {
2271                    dpixel[c] = (double) normComponents[nc];
2272                }
2273            }
2274            return dpixel;
2275        default:
2276            throw new UnsupportedOperationException JavaDoc("This method has not been "+
2277                                        "implemented for transferType " +
2278                                        transferType);
2279        }
2280    }
2281
2282    /**
2283     * Returns an array of all of the color/alpha components in normalized
2284     * form, given a pixel in this <code>ColorModel</code>. The pixel
2285     * value is specified by an array of data elements of type transferType
2286     * passed in as an object reference. If pixel is not a primitive array
2287     * of type transferType, a <code>ClassCastException</code> is thrown.
2288     * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
2289     * <code>pixel</code> is not large enough to hold a pixel value for this
2290     * <code>ColorModel</code>.
2291     * Normalized components are float values between a per component minimum
2292     * and maximum specified by the <code>ColorSpace</code> object for this
2293     * <code>ColorModel</code>. If the
2294     * <code>normComponents</code> array is <code>null</code>, a new array
2295     * will be allocated. The <code>normComponents</code> array
2296     * will be returned. Color/alpha components are stored in the
2297     * <code>normComponents</code> array starting at
2298     * <code>normOffset</code> (even if the array is allocated by this
2299     * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
2300     * if the <code>normComponents</code> array is not <code>null</code>
2301     * and is not large enough to hold all the color and alpha components
2302     * (starting at <code>normOffset</code>).
2303     * <p>
2304     * This method must be overrridden by a subclass if that subclass
2305     * is designed to translate pixel sample values to color component values
2306     * in a non-default way. The default translations implemented by this
2307     * class is described in the class comments. Any subclass implementing
2308     * a non-default translation must follow the constraints on allowable
2309     * translations defined there.
2310     * @param pixel the specified pixel
2311     * @param normComponents an array to receive the normalized components
2312     * @param normOffset the offset into the <code>normComponents</code>
2313     * array at which to start storing normalized components
2314     * @return an array containing normalized color and alpha
2315     * components.
2316     * @throws ClassCastException if <code>pixel</code> is not a primitive
2317     * array of type transferType
2318     * @throws ArrayIndexOutOfBoundsException if
2319     * <code>normComponents</code> is not large enough to hold all
2320     * color and alpha components starting at <code>normOffset</code>
2321     * @throws ArrayIndexOutOfBoundsException if
2322     * <code>pixel</code> is not large enough to hold a pixel
2323     * value for this <code>ColorModel</code>.
2324     * @since 1.4
2325     */

2326    public float[] getNormalizedComponents(Object JavaDoc pixel,
2327                                           float[] normComponents,
2328                                           int normOffset) {
2329        if (normComponents == null) {
2330            normComponents = new float[numComponents+normOffset];
2331        }
2332        switch (transferType) {
2333        case DataBuffer.TYPE_BYTE:
2334            byte[] bpixel = (byte[]) pixel;
2335            for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2336                normComponents[nc] = ((float) (bpixel[c] & 0xff)) /
2337                                     ((float) ((1 << nBits[c]) - 1));
2338            }
2339            break;
2340        case DataBuffer.TYPE_USHORT:
2341            short[] uspixel = (short[]) pixel;
2342            for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2343                normComponents[nc] = ((float) (uspixel[c] & 0xffff)) /
2344                                     ((float) ((1 << nBits[c]) - 1));
2345            }
2346            break;
2347        case DataBuffer.TYPE_INT:
2348            int[] ipixel = (int[]) pixel;
2349            for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2350                normComponents[nc] = ((float) ipixel[c]) /
2351                                     ((float) ((1 << nBits[c]) - 1));
2352            }
2353            break;
2354        case DataBuffer.TYPE_SHORT:
2355            short[] spixel = (short[]) pixel;
2356            for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2357                normComponents[nc] = ((float) spixel[c]) / 32767.0f;
2358            }
2359            break;
2360        case DataBuffer.TYPE_FLOAT:
2361            float[] fpixel = (float[]) pixel;
2362            for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2363                normComponents[nc] = fpixel[c];
2364            }
2365            break;
2366        case DataBuffer.TYPE_DOUBLE:
2367            double[] dpixel = (double[]) pixel;
2368            for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
2369                normComponents[nc] = (float) dpixel[c];
2370            }
2371            break;
2372        default:
2373            throw new UnsupportedOperationException JavaDoc("This method has not been "+
2374                                        "implemented for transferType " +
2375                                        transferType);
2376        }
2377
2378        if (supportsAlpha && isAlphaPremultiplied) {
2379            float alpha = normComponents[numColorComponents + normOffset];
2380            if (alpha != 0.0f) {
2381                float invAlpha = 1.0f / alpha;
2382                for (int c = normOffset; c < numColorComponents + normOffset;
2383                     c++) {
2384                    normComponents[c] *= invAlpha;
2385                }
2386            }
2387        }
2388        if (min != null) {
2389            // Normally (i.e. when this class is not subclassed to override
2390
// this method), the test (min != null) will be equivalent to
2391
// the test (nonStdScale). However, there is an unlikely, but
2392
// possible case, in which this method is overridden, nonStdScale
2393
// is set true by initScale(), the subclass method for some
2394
// reason calls this superclass method, but the min and
2395
// diffMinMax arrays were never initialized by setupLUTs(). In
2396
// that case, the right thing to do is follow the intended
2397
// semantics of this method, and rescale the color components
2398
// only if the ColorSpace min/max were detected to be other
2399
// than 0.0/1.0 by setupLUTs(). Note that this implies the
2400
// transferType is byte, ushort, int, or short - i.e. components
2401
// derived from float and double pixel data are never rescaled.
2402
for (int c = 0; c < numColorComponents; c++) {
2403                normComponents[c + normOffset] = min[c] +
2404                    diffMinMax[c] * normComponents[c + normOffset];
2405            }
2406        }
2407        return normComponents;
2408    }
2409
2410    /**
2411     * Forces the raster data to match the state specified in the
2412     * <CODE>isAlphaPremultiplied</CODE> variable, assuming the data
2413     * is currently correctly described by this <CODE>ColorModel</CODE>.
2414     * It may multiply or divide the color raster data by alpha, or
2415     * do nothing if the data is in the correct state. If the data needs
2416     * to be coerced, this method also returns an instance of
2417     * this <CODE>ColorModel</CODE> with
2418     * the <CODE>isAlphaPremultiplied</CODE> flag set appropriately.
2419     * Since <code>ColorModel</code> can be subclassed, subclasses inherit
2420     * the implementation of this method and if they don't override it
2421     * then they throw an exception if they use an unsupported
2422     * <code>transferType</code>.
2423     *
2424     * @throws NullPointerException if <code>raster</code> is
2425     * <code>null</code> and data coercion is required.
2426     * @throws UnsupportedOperationException if the transfer type of
2427     * this <CODE>ComponentColorModel</CODE>
2428     * is not one of the supported transfer types:
2429     * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
2430     * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
2431     * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
2432     */

2433    public ColorModel JavaDoc coerceData (WritableRaster JavaDoc raster,
2434                                  boolean isAlphaPremultiplied) {
2435        if ((supportsAlpha == false) ||
2436            (this.isAlphaPremultiplied == isAlphaPremultiplied))
2437        {
2438            // Nothing to do
2439
return this;
2440        }
2441        
2442        int w = raster.getWidth();
2443        int h = raster.getHeight();
2444        int aIdx = raster.getNumBands() - 1;
2445        float normAlpha;
2446        int rminX = raster.getMinX();
2447        int rY = raster.getMinY();
2448        int rX;
2449        if (isAlphaPremultiplied) {
2450            switch (transferType) {
2451                case DataBuffer.TYPE_BYTE: {
2452                    byte pixel[] = null;
2453                    byte zpixel[] = null;
2454                    float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
2455                    for (int y = 0; y < h; y++, rY++) {
2456                        rX = rminX;
2457                        for (int x = 0; x < w; x++, rX++) {
2458                            pixel = (byte[])raster.getDataElements(rX, rY,
2459                                                                   pixel);
2460                            normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
2461                            if (normAlpha != 0.0f) {
2462                                for (int c=0; c < aIdx; c++) {
2463                                    pixel[c] = (byte)((pixel[c] & 0xff) *
2464                                                      normAlpha + 0.5f);
2465                                }
2466                                raster.setDataElements(rX, rY, pixel);
2467                            } else {
2468                                if (zpixel == null) {
2469                                    zpixel = new byte[numComponents];
2470                                    java.util.Arrays.fill(zpixel, (byte) 0);
2471                                }
2472                                raster.setDataElements(rX, rY, zpixel);
2473                            }
2474                        }
2475                    }
2476                }
2477                break;
2478                case DataBuffer.TYPE_USHORT: {
2479                    short pixel[] = null;
2480                    short zpixel[] = null;
2481                    float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
2482                    for (int y = 0; y < h; y++, rY++) {
2483                        rX = rminX;
2484                        for (int x = 0; x < w; x++, rX++) {
2485                            pixel = (short[])raster.getDataElements(rX, rY,
2486                                                                    pixel);
2487                            normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
2488                            if (normAlpha != 0.0f) {
2489                                for (int c=0; c < aIdx; c++) {
2490                                    pixel[c] = (short)
2491                                        ((pixel[c] & 0xffff) * normAlpha +
2492                                         0.5f);
2493                                }
2494                                raster.setDataElements(rX, rY, pixel);
2495                            } else {
2496                                if (zpixel == null) {
2497                                    zpixel = new short[numComponents];
2498                                    java.util.Arrays.fill(zpixel, (short) 0);
2499                                }
2500                                raster.setDataElements(rX, rY, zpixel);
2501                            }
2502                        }
2503                    }
2504                }
2505                break;
2506                case DataBuffer.TYPE_INT: {
2507                    int pixel[] = null;
2508                    int zpixel[] = null;
2509                    float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
2510                    for (int y = 0; y < h; y++, rY++) {
2511                        rX = rminX;
2512                        for (int x = 0; x < w; x++, rX++) {
2513                            pixel = (int[])raster.getDataElements(rX, rY,
2514                                                                  pixel);
2515                            normAlpha = pixel[aIdx] * alphaScale;
2516                            if (normAlpha != 0.0f) {
2517                                for (int c=0; c < aIdx; c++) {
2518                                    pixel[c] = (int) (pixel[c] * normAlpha +
2519                                                      0.5f);
2520                                }
2521                                raster.setDataElements(rX, rY, pixel);
2522                            } else {
2523                                if (zpixel == null) {
2524                                    zpixel = new int[numComponents];
2525                                    java.util.Arrays.fill(zpixel, 0);
2526                                }
2527                                raster.setDataElements(rX, rY, zpixel);
2528                            }
2529                        }
2530                    }
2531                }
2532                break;
2533                case DataBuffer.TYPE_SHORT: {
2534                    short pixel[] = null;
2535                    short zpixel[] = null;
2536                    float alphaScale = 1.0f / 32767.0f;
2537                    for (int y = 0; y < h; y++, rY++) {
2538                        rX = rminX;
2539                        for (int x = 0; x < w; x++, rX++) {
2540                            pixel = (short[]) raster.getDataElements(rX, rY,
2541                                                                     pixel);
2542                            normAlpha = pixel[aIdx] * alphaScale;
2543                            if (normAlpha != 0.0f) {
2544                                for (int c=0; c < aIdx; c++) {
2545                                    pixel[c] = (short) (pixel[c] * normAlpha +
2546                                                        0.5f);
2547                                }
2548                                raster.setDataElements(rX, rY, pixel);
2549                            } else {
2550                                if (zpixel == null) {
2551                                    zpixel = new short[numComponents];
2552                                    java.util.Arrays.fill(zpixel, (short) 0);
2553                                }
2554                                raster.setDataElements(rX, rY, zpixel);
2555                            }
2556                        }
2557                    }
2558                }
2559                break;
2560                case DataBuffer.TYPE_FLOAT: {
2561                    float pixel[] = null;
2562                    float zpixel[] = null;
2563                    for (int y = 0; y < h; y++, rY++) {
2564                        rX = rminX;
2565                        for (int x = 0; x < w; x++, rX++) {
2566                            pixel = (float[]) raster.getDataElements(rX, rY,
2567                                                                     pixel);
2568                            normAlpha = pixel[aIdx];
2569                            if (normAlpha != 0.0f) {
2570                                for (int c=0; c < aIdx; c++) {
2571                                    pixel[c] *= normAlpha;
2572                                }
2573                                raster.setDataElements(rX, rY, pixel);
2574                            } else {
2575                                if (zpixel == null) {
2576                                    zpixel = new float[numComponents];
2577                                    java.util.Arrays.fill(zpixel, 0.0f);
2578                                }
2579                                raster.setDataElements(rX, rY, zpixel);
2580                            }
2581                        }
2582                    }
2583                }
2584                break;
2585                case DataBuffer.TYPE_DOUBLE: {
2586                    double pixel[] = null;
2587                    double zpixel[] = null;
2588                    for (int y = 0; y < h; y++, rY++) {
2589                        rX = rminX;
2590                        for (int x = 0; x < w; x++, rX++) {
2591                            pixel = (double[]) raster.getDataElements(rX, rY,
2592                                                                      pixel);
2593                            double dnormAlpha = pixel[aIdx];
2594                            if (dnormAlpha != 0.0) {
2595                                for (int c=0; c < aIdx; c++) {
2596                                    pixel[c] *= dnormAlpha;
2597                                }
2598                                raster.setDataElements(rX, rY, pixel);
2599                            } else {
2600                                if (zpixel == null) {
2601                                    zpixel = new double[numComponents];
2602                                    java.util.Arrays.fill(zpixel, 0.0);
2603                                }
2604                                raster.setDataElements(rX, rY, zpixel);
2605                            }
2606                        }
2607                    }
2608                }
2609                break;
2610                default:
2611                    throw new UnsupportedOperationException JavaDoc("This method has not been "+
2612                         "implemented for transferType " + transferType);
2613            }
2614        }
2615        else {
2616            // We are premultiplied and want to divide it out
2617
switch (transferType) {
2618                case DataBuffer.TYPE_BYTE: {
2619                    byte pixel[] = null;
2620                    float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
2621                    for (int y = 0; y < h; y++, rY++) {
2622                        rX = rminX;
2623                        for (int x = 0; x < w; x++, rX++) {
2624                            pixel = (byte[])raster.getDataElements(rX, rY,
2625                                                                   pixel);
2626                            normAlpha = (pixel[aIdx] & 0xff) * alphaScale;
2627                            if (normAlpha != 0.0f) {
2628                                float invAlpha = 1.0f / normAlpha;
2629                                for (int c=0; c < aIdx; c++) {
2630                                    pixel[c] = (byte)
2631                                        ((pixel[c] & 0xff) * invAlpha + 0.5f);
2632                                }
2633                                raster.setDataElements(rX, rY, pixel);
2634                            }
2635                        }
2636                    }
2637                }
2638                break;
2639                case DataBuffer.TYPE_USHORT: {
2640                    short pixel[] = null;
2641                    float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
2642                    for (int y = 0; y < h; y++, rY++) {
2643                        rX = rminX;
2644                        for (int x = 0; x < w; x++, rX++) {
2645                            pixel = (short[])raster.getDataElements(rX, rY,
2646                                                                    pixel);
2647                            normAlpha = (pixel[aIdx] & 0xffff) * alphaScale;
2648                            if (normAlpha != 0.0f) {
2649                                float invAlpha = 1.0f / normAlpha;
2650                                for (int c=0; c < aIdx; c++) {
2651                                    pixel[c] = (short)
2652                                        ((pixel[c] & 0xffff) * invAlpha + 0.5f);
2653                                }
2654                                raster.setDataElements(rX, rY, pixel);
2655                            }
2656                        }
2657                    }
2658                }
2659                break;
2660                case DataBuffer.TYPE_INT: {
2661                    int pixel[] = null;
2662                    float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1));
2663                    for (int y = 0; y < h; y++, rY++) {
2664                        rX = rminX;
2665                        for (int x = 0; x < w; x++, rX++) {
2666                            pixel = (int[])raster.getDataElements(rX, rY,
2667                                                                  pixel);
2668                            normAlpha = pixel[aIdx] * alphaScale;
2669                            if (normAlpha != 0.0f) {
2670                                float invAlpha = 1.0f / normAlpha;
2671                                for (int c=0; c < aIdx; c++) {
2672                                    pixel[c] = (int)
2673                                        (pixel[c] * invAlpha + 0.5f);
2674                                }
2675                                raster.setDataElements(rX, rY, pixel);
2676                            }
2677                        }
2678                    }
2679                }
2680                break;
2681                case DataBuffer.TYPE_SHORT: {
2682                    short pixel[] = null;
2683                    float alphaScale = 1.0f / 32767.0f;
2684                    for (int y = 0; y < h; y++, rY++) {
2685                        rX = rminX;
2686                        for (int x = 0; x < w; x++, rX++) {
2687                            pixel = (short[])raster.getDataElements(rX, rY,
2688                                                                    pixel);
2689                            normAlpha = pixel[aIdx] * alphaScale;
2690                            if (normAlpha != 0.0f) {
2691                                float invAlpha = 1.0f / normAlpha;
2692                                for (int c=0; c < aIdx; c++) {
2693                                    pixel[c] = (short)
2694                                        (pixel[c] * invAlpha + 0.5f);
2695                                }
2696                                raster.setDataElements(rX, rY, pixel);
2697                            }
2698                        }
2699                    }
2700                }
2701                break;
2702                case DataBuffer.TYPE_FLOAT: {
2703                    float pixel[] = null;
2704                    for (int y = 0; y < h; y++, rY++) {
2705                        rX = rminX;
2706                        for (int x = 0; x < w; x++, rX++) {
2707                            pixel = (float[])raster.getDataElements(rX, rY,
2708                                                                    pixel);
2709                            normAlpha = pixel[aIdx];
2710                            if (normAlpha != 0.0f) {
2711                                float invAlpha = 1.0f / normAlpha;
2712                                for (int c=0; c < aIdx; c++) {
2713                                    pixel[c] *= invAlpha;
2714                                }
2715                                raster.setDataElements(rX, rY, pixel);
2716                            }
2717                        }
2718                    }
2719                }
2720                break;
2721                case DataBuffer.TYPE_DOUBLE: {
2722                    double pixel[] = null;
2723                    for (int y = 0; y < h; y++, rY++) {
2724                        rX = rminX;
2725                        for (int x = 0; x < w; x++, rX++) {
2726                            pixel = (double[])raster.getDataElements(rX, rY,
2727                                                                     pixel);
2728                            double dnormAlpha = pixel[aIdx];
2729                            if (dnormAlpha != 0.0) {
2730                                double invAlpha = 1.0 / dnormAlpha;
2731                                for (int c=0; c < aIdx; c++) {
2732                                    pixel[c] *= invAlpha;
2733                                }
2734                                raster.setDataElements(rX, rY, pixel);
2735                            }
2736                        }
2737                    }
2738                }
2739                break;
2740                default:
2741                    throw new UnsupportedOperationException JavaDoc("This method has not been "+
2742                         "implemented for transferType " + transferType);
2743            }
2744        }
2745
2746        // Return a new color model
2747
if (!signed) {
2748            return new ComponentColorModel JavaDoc(colorSpace, nBits, supportsAlpha,
2749                                           isAlphaPremultiplied, transparency,
2750                                           transferType);
2751        } else {
2752            return new ComponentColorModel JavaDoc(colorSpace, supportsAlpha,
2753                                           isAlphaPremultiplied, transparency,
2754                                           transferType);
2755        }
2756
2757    }
2758
2759    /**
2760      * Returns true if <CODE>raster</CODE> is compatible with this
2761      * <CODE>ColorModel</CODE>; false if it is not.
2762      *
2763      * @param raster The <CODE>Raster</CODE> object to test for compatibility.
2764      *
2765      * @return <CODE>true</CODE> if <CODE>raster</CODE> is compatible with this
2766      * <CODE>ColorModel</CODE>, <CODE>false</CODE> if it is not.
2767      */

2768    public boolean isCompatibleRaster(Raster JavaDoc raster) {
2769
2770        SampleModel JavaDoc sm = raster.getSampleModel();
2771
2772        if (sm instanceof ComponentSampleModel JavaDoc) {
2773            if (sm.getNumBands() != getNumComponents()) {
2774                return false;
2775            }
2776            for (int i=0; i<nBits.length; i++) {
2777                if (sm.getSampleSize(i) < nBits[i]) {
2778                    return false;
2779                }
2780            }
2781            return (raster.getTransferType() == transferType);
2782        }
2783        else {
2784            return false;
2785        }
2786    }
2787    
2788    /**
2789     * Creates a <CODE>WritableRaster</CODE> with the specified width and height,
2790     * that has a data layout (<CODE>SampleModel</CODE>) compatible with
2791     * this <CODE>ColorModel</CODE>.
2792     *
2793     * @param w The width of the <CODE>WritableRaster</CODE> you want to create.
2794     * @param h The height of the <CODE>WritableRaster</CODE> you want to create.
2795     *
2796     * @return A <CODE>WritableRaster</CODE> that is compatible with
2797     * this <CODE>ColorModel</CODE>.
2798     * @see WritableRaster
2799     * @see SampleModel
2800     */

2801    public WritableRaster JavaDoc createCompatibleWritableRaster (int w, int h) {
2802        int dataSize = w*h*numComponents;
2803        WritableRaster JavaDoc raster = null;
2804
2805        switch (transferType) {
2806        case DataBuffer.TYPE_BYTE:
2807        case DataBuffer.TYPE_USHORT:
2808            raster = Raster.createInterleavedRaster(transferType,
2809                                                    w, h,
2810                                                    numComponents, null);
2811            break;
2812        default:
2813            SampleModel JavaDoc sm = createCompatibleSampleModel(w, h);
2814            DataBuffer JavaDoc db = sm.createDataBuffer();
2815            raster = Raster.createWritableRaster(sm, db, null);
2816        }
2817
2818        return raster;
2819    }
2820
2821    /**
2822     * Creates a <CODE>SampleModel</CODE> with the specified width and height,
2823     * that has a data layout compatible with this <CODE>ColorModel</CODE>.
2824     *
2825     * @param w The width of the <CODE>SampleModel</CODE> you want to create.
2826     * @param h The height of the <CODE>SampleModel</CODE> you want to create.
2827     *
2828     * @return A <CODE>SampleModel</CODE> that is compatible with this
2829     * <CODE>ColorModel</CODE>.
2830     *
2831     * @see SampleModel
2832     */

2833    public SampleModel JavaDoc createCompatibleSampleModel(int w, int h) {
2834        int[] bandOffsets = new int[numComponents];
2835        for (int i=0; i < numComponents; i++) {
2836            bandOffsets[i] = i;
2837        }
2838        switch (transferType) {
2839        case DataBuffer.TYPE_BYTE:
2840        case DataBuffer.TYPE_USHORT:
2841            return new PixelInterleavedSampleModel JavaDoc(transferType, w, h,
2842                                                   numComponents,
2843                                                   w*numComponents,
2844                                                   bandOffsets);
2845        default:
2846            return new ComponentSampleModel JavaDoc(transferType, w, h,
2847                                            numComponents,
2848                                            w*numComponents,
2849                                            bandOffsets);
2850        }
2851    }
2852    
2853    /**
2854     * Checks whether or not the specified <CODE>SampleModel</CODE>
2855     * is compatible with this <CODE>ColorModel</CODE>.
2856     *
2857     * @param sm The <CODE>SampleModel</CODE> to test for compatibility.
2858     *
2859     * @return <CODE>true</CODE> if the <CODE>SampleModel</CODE> is
2860     * compatible with this <CODE>ColorModel</CODE>, <CODE>false</CODE>
2861     * if it is not.
2862     *
2863     * @see SampleModel
2864     */

2865    public boolean isCompatibleSampleModel(SampleModel JavaDoc sm) {
2866        if (!(sm instanceof ComponentSampleModel JavaDoc)) {
2867            return false;
2868        }
2869
2870        // Must have the same number of components
2871
if (numComponents != sm.getNumBands()) {
2872            return false;
2873        }
2874        
2875        if (sm.getTransferType() != transferType) {
2876            return false;
2877        }
2878        
2879        return true;
2880    }
2881    
2882    /**
2883     * Returns a <CODE>Raster</CODE> representing the alpha channel of an image,
2884     * extracted from the input <CODE>Raster</CODE>.
2885     * This method assumes that <CODE>Raster</CODE> objects associated with
2886     * this <CODE>ColorModel</CODE> store the alpha band, if present, as
2887     * the last band of image data. Returns null if there is no separate spatial
2888     * alpha channel associated with this <CODE>ColorModel</CODE>.
2889     * This method creates a new <CODE>Raster</CODE>, but will share the data
2890     * array.
2891     *
2892     * @param raster The <CODE>WritableRaster</CODE> from which to extract the
2893     * alpha channel.
2894     *
2895     * @return A <CODE>WritableRaster</CODE> containing the image's alpha channel.
2896     *
2897     */

2898    public WritableRaster JavaDoc getAlphaRaster(WritableRaster JavaDoc raster) {
2899        if (hasAlpha() == false) {
2900            return null;
2901        }
2902        
2903        int x = raster.getMinX();
2904        int y = raster.getMinY();
2905        int[] band = new int[1];
2906        band[0] = raster.getNumBands() - 1;
2907        return raster.createWritableChild(x, y, raster.getWidth(),
2908                                          raster.getHeight(), x, y,
2909                                          band);
2910    }
2911    
2912    /**
2913     * Compares this color model with another for equality.
2914     *
2915     * @param obj The object to compare with this color model.
2916     * @return <CODE>true</CODE> if the color model objects are equal,
2917     * <CODE>false</CODE> if they are not.
2918     */

2919    public boolean equals(Object JavaDoc obj) {
2920        if (!super.equals(obj)) {
2921            return false;
2922        }
2923
2924        if (obj.getClass() != getClass()) {
2925            return false;
2926        }
2927        
2928        return true;
2929    }
2930
2931}
2932
2933
Popular Tags