1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17/**
18 * @author Igor V. Stolyarov
19 * @version $Revision$
20 */
21
22package java.awt.image;
23
24import java.awt.Transparency;
25import java.awt.color.ColorSpace;
26import java.util.Arrays;
27
28import org.apache.harmony.awt.internal.nls.Messages;
29
30/**
31 * The class ColorModel.
32 *
33 * @since Android 1.0
34 */
35public abstract class ColorModel implements Transparency {
36
37    /**
38     * The pixel_bits.
39     */
40    protected int pixel_bits; // Pixel length in bits
41
42    /**
43     * The transfer type.
44     */
45    protected int transferType;
46
47    /**
48     * The cs.
49     */
50    ColorSpace cs;
51
52    /**
53     * The has alpha.
54     */
55    boolean hasAlpha;
56
57    /**
58     * The is alpha premultiplied.
59     */
60    boolean isAlphaPremultiplied;
61
62    /**
63     * The transparency.
64     */
65    int transparency;
66
67    /**
68     * The num color components.
69     */
70    int numColorComponents;
71
72    /**
73     * The num components.
74     */
75    int numComponents;
76
77    /**
78     * The bits.
79     */
80    int[] bits; // Array of components masks
81
82    /**
83     * The max values.
84     */
85    int[] maxValues = null; // Max values that may be represent by color
86
87    // components
88
89    /**
90     * The max bit length.
91     */
92    int maxBitLength; // Max length color components in bits
93
94    /**
95     * The RG bdefault.
96     */
97    private static ColorModel RGBdefault;
98
99    /**
100     * Instantiates a new color model with the specified values.
101     *
102     * @param pixel_bits
103     *            the pixel length in bits.
104     * @param bits
105     *            the array of component masks.
106     * @param cspace
107     *            the color space.
108     * @param hasAlpha
109     *            whether the color model has alpha.
110     * @param isAlphaPremultiplied
111     *            whether the alpha is pre-multiplied.
112     * @param transparency
113     *            the transparency strategy, @see java.awt.Transparency.
114     * @param transferType
115     *            the transfer type (primitive java type to use for the
116     *            components).
117     */
118    protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace, boolean hasAlpha,
119            boolean isAlphaPremultiplied, int transparency, int transferType) {
120
121        if (pixel_bits < 1) {
122            // awt.26B=The number of bits in the pixel values is less than 1
123            throw new IllegalArgumentException(Messages.getString("awt.26B")); //$NON-NLS-1$
124        }
125
126        if (bits == null) {
127            // awt.26C=bits is null
128            throw new NullPointerException(Messages.getString("awt.26C")); //$NON-NLS-1$
129        }
130
131        int sum = 0;
132        for (int element : bits) {
133            if (element < 0) {
134                // awt.26D=The elements in bits is less than 0
135                throw new IllegalArgumentException(Messages.getString("awt.26D")); //$NON-NLS-1$
136            }
137            sum += element;
138        }
139
140        if (sum < 1) {
141            // awt.26E=The sum of the number of bits in bits is less than 1
142            throw new NullPointerException(Messages.getString("awt.26E")); //$NON-NLS-1$
143        }
144
145        if (cspace == null) {
146            // awt.26F=The cspace is null
147            throw new IllegalArgumentException(Messages.getString("awt.26F")); //$NON-NLS-1$
148        }
149
150        if (transparency < Transparency.OPAQUE || transparency > Transparency.TRANSLUCENT) {
151            // awt.270=The transparency is not a valid value
152            throw new IllegalArgumentException(Messages.getString("awt.270")); //$NON-NLS-1$
153        }
154
155        this.pixel_bits = pixel_bits;
156        this.bits = bits.clone();
157
158        maxValues = new int[bits.length];
159        maxBitLength = 0;
160        for (int i = 0; i < maxValues.length; i++) {
161            maxValues[i] = (1 << bits[i]) - 1;
162            if (bits[i] > maxBitLength) {
163                maxBitLength = bits[i];
164            }
165        }
166
167        cs = cspace;
168        this.hasAlpha = hasAlpha;
169        this.isAlphaPremultiplied = isAlphaPremultiplied;
170        numColorComponents = cs.getNumComponents();
171
172        if (hasAlpha) {
173            numComponents = numColorComponents + 1;
174        } else {
175            numComponents = numColorComponents;
176        }
177
178        this.transparency = transparency;
179        this.transferType = transferType;
180
181    }
182
183    /**
184     * Instantiates a new color model with the specified pixel bit depth. The
185     * transferType is chosen based on the pixel bits, and the other data fields
186     * are given default values.
187     *
188     * @param bits
189     *            the array of component masks.
190     */
191    public ColorModel(int bits) {
192
193        if (bits < 1) {
194            // awt.271=The number of bits in bits is less than 1
195            throw new IllegalArgumentException(Messages.getString("awt.271")); //$NON-NLS-1$
196        }
197
198        pixel_bits = bits;
199        transferType = getTransferType(bits);
200        cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
201        hasAlpha = true;
202        isAlphaPremultiplied = false;
203        transparency = Transparency.TRANSLUCENT;
204
205        numColorComponents = 3;
206        numComponents = 4;
207
208        this.bits = null;
209    }
210
211    /**
212     * Gets the data elements from the specified component array, transforming
213     * them according to rules of the color model.
214     *
215     * @param components
216     *            the components.
217     * @param offset
218     *            the offset in the normComponents array.
219     * @param obj
220     *            the array that the result is written to: an array of values
221     *            whose length must be the number of components used by the
222     *            color model and whose type depends on the transfer type (based
223     *            on the pixel bit depth), or null to have the appropriate array
224     *            created.
225     * @return the array of data elements.
226     */
227    public Object getDataElements(int[] components, int offset, Object obj) {
228        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
229                "supported by this ColorModel"); //$NON-NLS-1$
230    }
231
232    /**
233     * Gets the data elements from the specified array of normalized components.
234     *
235     * @param normComponents
236     *            the array normalized components.
237     * @param normOffset
238     *            the offset in the normComponents array.
239     * @param obj
240     *            the array that the result is written to: an array of values
241     *            whose length must be the number of components used by the
242     *            color model and whose type depends on the transfer type (based
243     *            on the pixel bit depth), or null to have the appropriate array
244     *            created.
245     * @return the array of data elements.
246     */
247    public Object getDataElements(float[] normComponents, int normOffset, Object obj) {
248        int unnormComponents[] = getUnnormalizedComponents(normComponents, normOffset, null, 0);
249        return getDataElements(unnormComponents, 0, obj);
250    }
251
252    /**
253     * Gets the data elements corresponding to the pixel determined by the RGB
254     * data.
255     *
256     * @param rgb
257     *            the RGB integer value that defines the pixel.
258     * @param pixel
259     *            the array that the result is written to: an array of values
260     *            whose length must be the number of components used by the
261     *            color model and whose type depends on the transfer type (based
262     *            on the pixel bit depth), or null to have the appropriate array
263     *            created.
264     * @return the array of data elements.
265     */
266    public Object getDataElements(int rgb, Object pixel) {
267        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
268                "supported by this ColorModel"); //$NON-NLS-1$
269    }
270
271    /**
272     * Gets the child raster corresponding to the alpha channel of the specified
273     * writable raster, or null if alpha is not supported.
274     *
275     * @param raster
276     *            the raster.
277     * @return the alpha raster.
278     */
279    public WritableRaster getAlphaRaster(WritableRaster raster) {
280        return null;
281    }
282
283    /**
284     * Creates a new color model by coercing the data in the writable raster in
285     * accordance with the alpha strategy of this color model.
286     *
287     * @param raster
288     *            the raster.
289     * @param isAlphaPremultiplied
290     *            whether the alpha is pre-multiplied in this color model
291     * @return the new color model.
292     */
293    public ColorModel coerceData(WritableRaster raster, boolean isAlphaPremultiplied) {
294        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
295                "supported by this ColorModel"); //$NON-NLS-1$
296    }
297
298    @Override
299    public String toString() {
300        // The output format based on 1.5 release behavior.
301        // It could be reveled such way:
302        // ColorModel cm = new
303        // ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB,
304        // false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
305        // System.out.println(cm.toString());
306        return "ColorModel: Color Space = " + cs.toString() + "; has alpha = " //$NON-NLS-1$ //$NON-NLS-2$
307                + hasAlpha + "; is alpha premultipied = " //$NON-NLS-1$
308                + isAlphaPremultiplied + "; transparency = " + transparency //$NON-NLS-1$
309                + "; number color components = " + numColorComponents //$NON-NLS-1$
310                + "; pixel bits = " + pixel_bits + "; transfer type = " //$NON-NLS-1$ //$NON-NLS-2$
311                + transferType;
312    }
313
314    /**
315     * Gets the components of the pixel determined by the data array.
316     *
317     * @param pixel
318     *            the data array that defines the pixel (whose primitive type
319     *            corresponds to the pixel length in bits.
320     * @see ColorModel#getTransferType()
321     * @param components
322     *            the the array where the resulting components are written (or
323     *            null to prompt the method to create the return array).
324     * @param offset
325     *            the offset that tells where the results should be written in
326     *            the return array.
327     * @return the array of components.
328     */
329    public int[] getComponents(Object pixel, int[] components, int offset) {
330        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
331                "supported by this ColorModel"); //$NON-NLS-1$
332    }
333
334    /**
335     * Gets the normalized components of the pixel determined by the data array.
336     *
337     * @param pixel
338     *            the data array that defines the pixel (whose primitive type
339     *            corresponds to the pixel length in bits.
340     * @see ColorModel#getTransferType()
341     * @param normComponents
342     *            the array where the resulting normalized components are
343     *            written (or null to prompt the method to create the return
344     *            array).
345     * @param normOffset
346     *            the offset that tells where the results should be written in
347     *            the return array.
348     * @return the array of normalized components.
349     */
350    public float[] getNormalizedComponents(Object pixel, float[] normComponents, int normOffset) {
351
352        if (pixel == null) {
353            // awt.294=pixel is null
354            throw new NullPointerException(Messages.getString("awt.294")); //$NON-NLS-1$
355        }
356
357        int unnormComponents[] = getComponents(pixel, null, 0);
358        return getNormalizedComponents(unnormComponents, 0, normComponents, normOffset);
359    }
360
361    @Override
362    public boolean equals(Object obj) {
363        if (!(obj instanceof ColorModel)) {
364            return false;
365        }
366        ColorModel cm = (ColorModel)obj;
367
368        return (pixel_bits == cm.getPixelSize() && transferType == cm.getTransferType()
369                && cs.getType() == cm.getColorSpace().getType() && hasAlpha == cm.hasAlpha()
370                && isAlphaPremultiplied == cm.isAlphaPremultiplied()
371                && transparency == cm.getTransparency()
372                && numColorComponents == cm.getNumColorComponents()
373                && numComponents == cm.getNumComponents() && Arrays.equals(bits, cm
374                .getComponentSize()));
375    }
376
377    /**
378     * Gets the red component of the pixel determined by the data array.
379     *
380     * @param inData
381     *            the data array that defines the pixel (whose primitive type
382     *            corresponds to the pixel length in bits.
383     * @see ColorModel#getTransferType()
384     * @return the red.
385     */
386    public int getRed(Object inData) {
387        return getRed(constructPixel(inData));
388    }
389
390    /**
391     * Gets the RGB integer value corresponding to the pixel defined by the data
392     * array.
393     *
394     * @param inData
395     *            the data array that defines the pixel (whose primitive type
396     *            corresponds to the pixel length in bits.
397     * @see ColorModel#getTransferType()
398     * @return the integer value that gives the pixel's colors in RGB format.
399     */
400    public int getRGB(Object inData) {
401        return (getAlpha(inData) << 24 | getRed(inData) << 16 | getGreen(inData) << 8 | getBlue(inData));
402    }
403
404    /**
405     * Gets the green component of the pixel defined by the data array.
406     *
407     * @param inData
408     *            the data array that defines the pixel (whose primitive type
409     *            corresponds to the pixel length in bits.
410     * @see ColorModel#getTransferType()
411     * @return the green.
412     */
413    public int getGreen(Object inData) {
414        return getGreen(constructPixel(inData));
415    }
416
417    /**
418     * Gets the blue component of the pixel defined by the data array.
419     *
420     * @param inData
421     *            the data array that defines the pixel (whose primitive type
422     *            corresponds to the pixel length in bits.
423     * @see ColorModel#getTransferType()
424     * @return the blue.
425     */
426    public int getBlue(Object inData) {
427        return getBlue(constructPixel(inData));
428    }
429
430    /**
431     * Gets the alpha component of the pixel defined by the data array.
432     *
433     * @param inData
434     *            the data array that defines the pixel (whose primitive type
435     *            corresponds to the pixel length in bits.
436     * @see ColorModel#getTransferType()
437     * @return the alpha.
438     */
439    public int getAlpha(Object inData) {
440        return getAlpha(constructPixel(inData));
441    }
442
443    /**
444     * Creates a compatible writable raster.
445     *
446     * @param w
447     *            the width of the desired writable raster.
448     * @param h
449     *            the height of the desired writable raster.
450     * @return the writable raster.
451     */
452    public WritableRaster createCompatibleWritableRaster(int w, int h) {
453        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
454                "supported by this ColorModel"); //$NON-NLS-1$
455    }
456
457    /**
458     * Checks if the sample model is compatible with this color model.
459     *
460     * @param sm
461     *            the sample model.
462     * @return true, if the sample model is compatible with this color model.
463     */
464    public boolean isCompatibleSampleModel(SampleModel sm) {
465        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
466                "supported by this ColorModel"); //$NON-NLS-1$
467    }
468
469    /**
470     * Creates the compatible sample model.
471     *
472     * @param w
473     *            the width of the desired sample model.
474     * @param h
475     *            the height of the desired sample model.
476     * @return the sample model.
477     */
478    public SampleModel createCompatibleSampleModel(int w, int h) {
479        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
480                "supported by this ColorModel"); //$NON-NLS-1$
481    }
482
483    /**
484     * Checks if the specified raster is compatible with this color model.
485     *
486     * @param raster
487     *            the raster to inspect.
488     * @return true, if the raster is compatible with this color model.
489     */
490    public boolean isCompatibleRaster(Raster raster) {
491        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
492                "supported by this ColorModel"); //$NON-NLS-1$
493    }
494
495    /**
496     * Gets the color space of this color model.
497     *
498     * @return the color space.
499     */
500    public final ColorSpace getColorSpace() {
501        return cs;
502    }
503
504    /**
505     * Gets the normalized components corresponding to the specified
506     * unnormalized components.
507     *
508     * @param components
509     *            the array of unnormalized components.
510     * @param offset
511     *            the offset where the components should be read from the array
512     *            of unnormalized components.
513     * @param normComponents
514     *            the array where the resulting normalized components are
515     *            written (or null to prompt the method to create the return
516     *            array).
517     * @param normOffset
518     *            the offset that tells where the results should be written in
519     *            the return array.
520     * @return the normalized components.
521     */
522    public float[] getNormalizedComponents(int[] components, int offset, float normComponents[],
523            int normOffset) {
524        if (bits == null) {
525            // awt.26C=bits is null
526            throw new UnsupportedOperationException(Messages.getString("awt.26C")); //$NON-NLS-1$
527        }
528
529        if (normComponents == null) {
530            normComponents = new float[numComponents + normOffset];
531        }
532
533        if (hasAlpha && isAlphaPremultiplied) {
534            float normAlpha = (float)components[offset + numColorComponents]
535                    / maxValues[numColorComponents];
536            if (normAlpha != 0.0f) {
537                for (int i = 0; i < numColorComponents; i++) {
538                    normComponents[normOffset + i] = components[offset + i]
539                            / (normAlpha * maxValues[i]);
540                }
541                normComponents[normOffset + numColorComponents] = normAlpha;
542            } else {
543                for (int i = 0; i < numComponents; i++) {
544                    normComponents[normOffset + i] = 0.0f;
545                }
546            }
547        } else {
548            for (int i = 0; i < numComponents; i++) {
549                normComponents[normOffset + i] = (float)components[offset + i] / maxValues[i];
550            }
551        }
552
553        return normComponents;
554    }
555
556    /**
557     * Gets the data element corresponding to the unnormalized components.
558     *
559     * @param components
560     *            the components.
561     * @param offset
562     *            the offset to start reading the components from the array of
563     *            components.
564     * @return the data element.
565     */
566    public int getDataElement(int[] components, int offset) {
567        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
568                "supported by this ColorModel"); //$NON-NLS-1$
569    }
570
571    /**
572     * Gets the unnormalized components corresponding to the specified
573     * normalized components.
574     *
575     * @param normComponents
576     *            the array of normalized components.
577     * @param normOffset
578     *            the offset where the components should be read from the array
579     *            of normalized components.
580     * @param components
581     *            the array where the resulting unnormalized components are
582     *            written (or null to prompt the method to create the return
583     *            array).
584     * @param offset
585     *            the offset that tells where the results should be written in
586     *            the return array.
587     * @return the unnormalized components.
588     */
589    public int[] getUnnormalizedComponents(float normComponents[], int normOffset,
590            int components[], int offset) {
591
592        if (bits == null) {
593            // awt.26C=bits is null
594            throw new UnsupportedOperationException(Messages.getString("awt.26C")); //$NON-NLS-1$
595        }
596
597        if (normComponents.length - normOffset < numComponents) {
598            // awt.273=The length of normComponents minus normOffset is less
599            // than numComponents
600            throw new IllegalArgumentException(Messages.getString("awt.273")); //$NON-NLS-1$
601        }
602
603        if (components == null) {
604            components = new int[numComponents + offset];
605        } else {
606            if (components.length - offset < numComponents) {
607                // awt.272=The length of components minus offset is less than
608                // numComponents
609                throw new IllegalArgumentException(Messages.getString("awt.272")); //$NON-NLS-1$
610            }
611        }
612
613        if (hasAlpha && isAlphaPremultiplied) {
614            float alpha = normComponents[normOffset + numColorComponents];
615            for (int i = 0; i < numColorComponents; i++) {
616                components[offset + i] = (int)(normComponents[normOffset + i] * maxValues[i]
617                        * alpha + 0.5f);
618            }
619            components[offset + numColorComponents] = (int)(normComponents[normOffset
620                    + numColorComponents]
621                    * maxValues[numColorComponents] + 0.5f);
622        } else {
623            for (int i = 0; i < numComponents; i++) {
624                components[offset + i] = (int)(normComponents[normOffset + i] * maxValues[i] + 0.5f);
625            }
626        }
627
628        return components;
629    }
630
631    /**
632     * Gets the data element corresponding to the normalized components.
633     *
634     * @param normComponents
635     *            the normalized components.
636     * @param normOffset
637     *            the offset where the normalized components should be read from
638     *            the normalized component array.
639     * @return the data element.
640     */
641    public int getDataElement(float normComponents[], int normOffset) {
642        int unnormComponents[] = getUnnormalizedComponents(normComponents, normOffset, null, 0);
643        return getDataElement(unnormComponents, 0);
644    }
645
646    /**
647     * Takes a pixel whose data is defined by an integer, and writes the
648     * corresponding components into the components array, starting from the
649     * index offset.
650     *
651     * @param pixel
652     *            the pixel data.
653     * @param components
654     *            the data array to write the components to (or null to have the
655     *            method create the return array).
656     * @param offset
657     *            the offset that determines where the results are written in
658     *            the components array.
659     * @return the array of components corresponding to the pixel.
660     */
661    public int[] getComponents(int pixel, int components[], int offset) {
662        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
663                "supported by this ColorModel"); //$NON-NLS-1$
664    }
665
666    /**
667     * Gets the red component of the pixel determined by the pixel data.
668     *
669     * @param pixel
670     *            the pixel.
671     * @return the red component of the given pixel.
672     */
673    public abstract int getRed(int pixel);
674
675    /**
676     * Takes the pixel data and returns the integer value corresponding to the
677     * pixel's color in RGB format.
678     *
679     * @param pixel
680     *            the pixel data.
681     * @return the corresponding RGB integer value.
682     */
683    public int getRGB(int pixel) {
684        return (getAlpha(pixel) << 24 | getRed(pixel) << 16 | getGreen(pixel) << 8 | getBlue(pixel));
685    }
686
687    /**
688     * Gets the green component of the pixel determined by the pixel data.
689     *
690     * @param pixel
691     *            the pixel.
692     * @return the green component of the given pixel.
693     */
694    public abstract int getGreen(int pixel);
695
696    /**
697     * Gets the size of the desired component of this color model.
698     *
699     * @param componentIdx
700     *            the index that determines which component size to get.
701     * @return the component size corresponding to the index.
702     * @throws NullPointerException
703     *             if this color model doesn't support an array of separate
704     *             components.
705     * @throws ArrayIndexOutOfBoundsException
706     *             if the index is negative or greater than or equal to the
707     *             number of components.
708     */
709    public int getComponentSize(int componentIdx) {
710        if (bits == null) {
711            // awt.26C=bits is null
712            throw new NullPointerException(Messages.getString("awt.26C")); //$NON-NLS-1$
713        }
714
715        if (componentIdx < 0 || componentIdx >= bits.length) {
716            // awt.274=componentIdx is greater than the number of components or
717            // less than zero
718            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.274")); //$NON-NLS-1$
719        }
720
721        return bits[componentIdx];
722    }
723
724    /**
725     * Gets the blue component of the pixel determined by the pixel data.
726     *
727     * @param pixel
728     *            the pixel.
729     * @return the blue component of the given pixel.
730     */
731    public abstract int getBlue(int pixel);
732
733    /**
734     * Gets the alpha component of the pixel determined by the pixel data.
735     *
736     * @param pixel
737     *            the pixel.
738     * @return the alpha component of the given pixel.
739     */
740    public abstract int getAlpha(int pixel);
741
742    /**
743     * Gets the array of sizes of the different components.
744     *
745     * @return the array of sizes of the different components.
746     */
747    public int[] getComponentSize() {
748        if (bits != null) {
749            return bits.clone();
750        }
751        return null;
752    }
753
754    /**
755     * Checks if the alpha component is pre-multiplied.
756     *
757     * @return true, if the alpha component is pre-multiplied.
758     */
759    public final boolean isAlphaPremultiplied() {
760        return isAlphaPremultiplied;
761    }
762
763    /**
764     * Checks whether this color model supports alpha.
765     *
766     * @return true, if this color model has alpha.
767     */
768    public final boolean hasAlpha() {
769        return hasAlpha;
770    }
771
772    @Override
773    public int hashCode() {
774        int hash = 0;
775        int tmp;
776
777        if (hasAlpha) {
778            hash ^= 1;
779            hash <<= 8;
780        }
781        if (isAlphaPremultiplied) {
782            hash ^= 1;
783            hash <<= 8;
784        }
785
786        tmp = hash >>> 24;
787        hash ^= numColorComponents;
788        hash <<= 8;
789        hash |= tmp;
790
791        tmp = hash >>> 24;
792        hash ^= transparency;
793        hash <<= 8;
794        hash |= tmp;
795
796        tmp = hash >>> 24;
797        hash ^= cs.getType();
798        hash <<= 8;
799        hash |= tmp;
800
801        tmp = hash >>> 24;
802        hash ^= pixel_bits;
803        hash <<= 8;
804        hash |= tmp;
805
806        tmp = hash >>> 24;
807        hash ^= transferType;
808        hash <<= 8;
809        hash |= tmp;
810
811        if (bits != null) {
812
813            for (int element : bits) {
814                tmp = hash >>> 24;
815                hash ^= element;
816                hash <<= 8;
817                hash |= tmp;
818            }
819
820        }
821
822        return hash;
823    }
824
825    public int getTransparency() {
826        return transparency;
827    }
828
829    /**
830     * Gets the transfer type, which is the type of Java primitive value that
831     * corresponds to the bit length per pixel: either
832     * {@link DataBuffer#TYPE_BYTE}, {@link DataBuffer#TYPE_USHORT},
833     * {@link DataBuffer#TYPE_INT}, or {@link DataBuffer#TYPE_UNDEFINED}.
834     *
835     * @return the transfer type.
836     */
837    public final int getTransferType() {
838        return transferType;
839    }
840
841    /**
842     * Gets the pixel size in bits.
843     *
844     * @return the pixel size.
845     */
846    public int getPixelSize() {
847        return pixel_bits;
848    }
849
850    /**
851     * Gets the number of components of this color model.
852     *
853     * @return the number of components.
854     */
855    public int getNumComponents() {
856        return numComponents;
857    }
858
859    /**
860     * Gets the number of color components of this color model.
861     *
862     * @return the number color components.
863     */
864    public int getNumColorComponents() {
865        return numColorComponents;
866    }
867
868    /**
869     * Gets the default RGB color model.
870     *
871     * @return the default RGB color model.
872     */
873    public static ColorModel getRGBdefault() {
874        if (RGBdefault == null) {
875            RGBdefault = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
876        }
877        return RGBdefault;
878    }
879
880    /*
881     * Construct INT pixel representation from Object
882     * @param obj
883     * @return
884     */
885    /**
886     * Construct pixel.
887     *
888     * @param obj
889     *            the obj.
890     * @return the int.
891     */
892    private int constructPixel(Object obj) {
893        int pixel = 0;
894
895        switch (getTransferType()) {
896
897            case DataBuffer.TYPE_BYTE:
898                byte[] bPixel = (byte[])obj;
899                if (bPixel.length > 1) {
900                    // awt.275=This pixel representation is not suuported by tis
901                    // Color Model
902                    throw new UnsupportedOperationException(Messages.getString("awt.275")); //$NON-NLS-1$
903                }
904                pixel = bPixel[0] & 0xff;
905                break;
906
907            case DataBuffer.TYPE_USHORT:
908                short[] sPixel = (short[])obj;
909                if (sPixel.length > 1) {
910                    // awt.275=This pixel representation is not suuported by tis
911                    // Color Model
912                    throw new UnsupportedOperationException(Messages.getString("awt.275")); //$NON-NLS-1$
913                }
914                pixel = sPixel[0] & 0xffff;
915                break;
916
917            case DataBuffer.TYPE_INT:
918                int[] iPixel = (int[])obj;
919                if (iPixel.length > 1) {
920                    // awt.275=This pixel representation is not suuported by tis
921                    // Color Model
922                    throw new UnsupportedOperationException(Messages.getString("awt.275")); //$NON-NLS-1$
923                }
924                pixel = iPixel[0];
925                break;
926
927            default:
928                // awt.22D=This transferType ( {0} ) is not supported by this
929                // color model
930                throw new UnsupportedOperationException(Messages.getString("awt.22D", //$NON-NLS-1$
931                        transferType));
932
933        }
934        return pixel;
935    }
936
937    /**
938     * Gets the transfer type, which is the type of Java primitive value that
939     * corresponds to the bit length per pixel: either
940     * {@link DataBuffer#TYPE_BYTE}, {@link DataBuffer#TYPE_USHORT},
941     * {@link DataBuffer#TYPE_INT}, or {@link DataBuffer#TYPE_UNDEFINED}.
942     *
943     * @param bits
944     *            the array of component masks.
945     * @return the transfer type.
946     */
947    static int getTransferType(int bits) {
948        if (bits <= 8) {
949            return DataBuffer.TYPE_BYTE;
950        } else if (bits <= 16) {
951            return DataBuffer.TYPE_USHORT;
952        } else if (bits <= 32) {
953            return DataBuffer.TYPE_INT;
954        } else {
955            return DataBuffer.TYPE_UNDEFINED;
956        }
957    }
958
959    @Override
960    public void finalize() {
961        // This method is added for the API compatibility
962        // Don't need to call super since Object's finalize is always empty
963    }
964}
965