001: /*
002: * @(#)ColorModel.java 1.38 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.awt.image;
029:
030: import java.awt.Transparency;
031: import java.awt.color.ColorSpace;
032:
033: /**
034: * A class that encapsulates the methods for translating from pixel values
035: * to alpha, red, green, and blue color components for an image. This
036: * class is abstract.
037: *
038: * @see IndexColorModel
039: * @see DirectColorModel
040: *
041: * @version 1.22 02/20/02
042: * @author Jim Graham
043: */
044: public abstract class ColorModel implements Transparency {
045: private int pData;
046: protected int pixel_bits;
047: int transparency = Transparency.TRANSLUCENT;
048: int nBits[];
049: boolean supportsAlpha = true;
050: boolean isAlphaPremultiplied = false;
051: int numComponents = -1;
052: int numColorComponents = -1;
053: ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
054: /**
055: * Data type of the array used to represent pixel values.
056: */
057: private int transferType;
058: private static ColorModel RGBdefault;
059:
060: /**
061: * Return a ColorModel which describes the default format for
062: * integer RGB values used throughout the AWT image interfaces.
063: * The format for the RGB values is an integer with 8 bits
064: * each of alpha, red, green, and blue color components ordered
065: * correspondingly from the most significant byte to the least
066: * significant byte, as in: 0xAARRGGBB
067: */
068: public static ColorModel getRGBdefault() {
069: if (RGBdefault == null) {
070: RGBdefault = new DirectColorModel(32, 0x00ff0000, // Red
071: 0x0000ff00, // Green
072: 0x000000ff, // Blue
073: 0xff000000 // Alpha
074: );
075: }
076: return RGBdefault;
077: }
078:
079: /**
080: * Returns whether or not alpha is supported in this
081: * <code>ColorModel</code>.
082: * @return <code>true</code> if alpha is supported in this
083: * <code>ColorModel</code>; <code>false</code> otherwise.
084: */
085: final public boolean hasAlpha() {
086: return supportsAlpha;
087: }
088:
089: /**
090: * Returns whether or not the alpha has been premultiplied in the
091: * pixel values to be translated by this <code>ColorModel</code>.
092: * If the boolean is <code>true</code>, this <code>ColorModel</code>
093: * is to be used to interpret pixel values in which color and alpha
094: * information are represented as separate spatial bands, and color
095: * samples are assumed to have been multiplied by the
096: * alpha sample.
097: * @return <code>true</code> if the alpha values are premultiplied
098: * in the pixel values to be translated by this
099: * <code>ColorModel</code>; <code>false</code> otherwise.
100: */
101: final public boolean isAlphaPremultiplied() {
102: return isAlphaPremultiplied;
103: }
104:
105: /**
106: * Constructs a ColorModel which describes a pixel of the specified
107: * number of bits.
108: */
109: public ColorModel(int bits) {
110: pixel_bits = bits;
111: if (bits < 1) {
112: throw new IllegalArgumentException(
113: "Number of bits must be > 0");
114: }
115: numComponents = 4;
116: numColorComponents = 3;
117: //maxBits = bits;
118: // TODO: make sure transferType is set correctly
119: transferType = ColorModel.getDefaultTransferType(bits);
120: }
121:
122: /**
123: * Constructs a <code>ColorModel</code> that translates pixel values
124: * to color/alpha components. Color components will be in the
125: * specified <code>ColorSpace</code>. <code>pixel_bits</code> is the
126: * number of bits in the pixel values. The bits array
127: * specifies the number of significant bits per color and alpha component.
128: * Its length should be the number of components in the
129: * <code>ColorSpace</code> if there is no alpha information in the
130: * pixel values, or one more than this number if there is alpha
131: * information. <code>hasAlpha</code> indicates whether or not alpha
132: * information is present. The <code>boolean</code>
133: * <code>isAlphaPremultiplied</code> specifies how to interpret pixel
134: * values in which color and alpha information are represented as
135: * separate spatial bands. If the <code>boolean</code>
136: * is <code>true</code>, color samples are assumed to have been
137: * multiplied by the alpha sample. The <code>transparency</code>
138: * specifies what alpha values can be represented by this color model.
139: * The transfer type is the type of primitive array used to represent
140: * pixel values. Note that the bits array contains the number of
141: * significant bits per color/alpha component after the translation
142: * from pixel values. For example, for an
143: * <code>IndexColorModel</code> with <code>pixel_bits</code> equal to
144: * 16, the bits array might have four elements with each element set
145: * to 8.
146: * @param pixel_bits the number of bits in the pixel values
147: * @param bits array that specifies the number of significant bits
148: * per color and alpha component
149: * @param cspace the specified <code>ColorSpace</code>
150: * @param hasAlpha <code>true</code> if alpha information is present;
151: * <code>false</code> otherwise
152: * @param isAlphaPremultiplied <code>true</code> if color samples are
153: * assumed to be premultiplied by the alpha samples;
154: * <code>false</code> otherwise
155: * @param transparency what alpha values can be represented by this
156: * color model
157: * @param transferType the type of the array used to represent pixel
158: * values
159: * @throws IllegalArgumentException if the length of
160: * the bit array is less than the number of color or alpha
161: * components in this <code>ColorModel</code>, or if the
162: * transparency is not a valid value.
163: * @throws IllegalArgumentException if the sum of the number
164: * of bits in <code>bits</code> is less than 1 or if
165: * any of the elements in <code>bits</code> is less than 0.
166: * @see java.awt.Transparency
167: */
168: protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
169: boolean hasAlpha, boolean isAlphaPremultiplied,
170: int transparency, int transferType) {
171: colorSpace = cspace;
172: numColorComponents = cspace.getNumComponents();
173: numComponents = numColorComponents + (hasAlpha ? 1 : 0);
174: supportsAlpha = hasAlpha;
175: if (bits.length < numComponents) {
176: throw new IllegalArgumentException("Number of color/alpha "
177: + "components should be " + numComponents
178: + " but length of bits array is " + bits.length);
179: }
180: // 4186669
181: if (transparency < Transparency.OPAQUE
182: || transparency > Transparency.TRANSLUCENT) {
183: throw new IllegalArgumentException("Unknown transparency: "
184: + transparency);
185: }
186: if (supportsAlpha == false) {
187: this .isAlphaPremultiplied = false;
188: this .transparency = Transparency.OPAQUE;
189: } else {
190: this .isAlphaPremultiplied = isAlphaPremultiplied;
191: this .transparency = transparency;
192: }
193: nBits = (int[]) bits.clone();
194: this .pixel_bits = pixel_bits;
195: if (pixel_bits <= 0) {
196: throw new IllegalArgumentException(
197: "Number of pixel bits must " + "be > 0");
198: }
199: // Check for bits < 0
200: //maxBits = 0;
201: int maxBits = 0;
202: for (int i = 0; i < bits.length; i++) {
203: // bug 4304697
204: if (bits[i] < 0) {
205: throw new IllegalArgumentException(
206: "Number of bits must be >= 0");
207: }
208: if (maxBits < bits[i]) {
209: maxBits = bits[i];
210: }
211: }
212: // Make sure that we don't have all 0-bit components
213: if (maxBits == 0) {
214: throw new IllegalArgumentException(
215: "There must be at least "
216: + "one component with > 0 " + "pixel bits.");
217: }
218: // Save the transfer type
219: this .transferType = transferType;
220: }
221:
222: /**
223: * Returns the number of bits per pixel described by this ColorModel.
224: */
225: public int getPixelSize() {
226: return pixel_bits;
227: }
228:
229: /**
230: * The subclass must provide a function which provides the red
231: * color compoment for the specified pixel.
232: * @return The red color component ranging from 0 to 255
233: */
234: public abstract int getRed(int pixel);
235:
236: /**
237: * The subclass must provide a function which provides the green
238: * color compoment for the specified pixel.
239: * @return The green color component ranging from 0 to 255
240: */
241: public abstract int getGreen(int pixel);
242:
243: /**
244: * The subclass must provide a function which provides the blue
245: * color compoment for the specified pixel.
246: * @return The blue color component ranging from 0 to 255
247: */
248: public abstract int getBlue(int pixel);
249:
250: /**
251: * The subclass must provide a function which provides the alpha
252: * color compoment for the specified pixel.
253: * @return The alpha transparency value ranging from 0 to 255
254: */
255: public abstract int getAlpha(int pixel);
256:
257: /**
258: * Returns the color of the pixel in the default RGB color model.
259: * @see ColorModel#getRGBdefault
260: */
261: public int getRGB(int pixel) {
262: return (getAlpha(pixel) << 24) | (getRed(pixel) << 16)
263: | (getGreen(pixel) << 8) | (getBlue(pixel) << 0);
264: }
265:
266: /**
267: * Tests if the specified <code>Object</code> is an instance of
268: * <code>ColorModel</code> and if it equals this
269: * <code>ColorModel</code>.
270: * @param obj the <code>Object</code> to test for equality
271: * @return <code>true</code> if the specified <code>Object</code>
272: * is an instance of <code>ColorModel</code> and equals this
273: * <code>ColorModel</code>; <code>false</code> otherwise.
274: */
275: public boolean equals(Object obj) {
276: if (!(obj instanceof ColorModel)) {
277: return false;
278: }
279: ColorModel cm = (ColorModel) obj;
280: if (this == cm) {
281: return true;
282: }
283: if (supportsAlpha != cm.hasAlpha()
284: || isAlphaPremultiplied != cm.isAlphaPremultiplied()
285: || transparency != cm.getTransparency()
286: || pixel_bits != cm.getPixelSize()) {
287: return false;
288: }
289: return true;
290: }
291:
292: /**
293: * Disposes of system resources associated with this
294: * <code>ColorModel</code> once this <code>ColorModel</code> is no
295: * longer referenced.
296: */
297: public void finalize() {
298: }
299:
300: /**
301: * Returns the hash code for this ColorModel.
302: *
303: * @return a hash code for this ColorModel.
304: */
305: public int hashCode() {
306: int result = 0;
307: result = (supportsAlpha ? 2 : 3)
308: + (isAlphaPremultiplied ? 4 : 5) + pixel_bits * 6
309: + transparency * 7;
310: return result;
311: }
312:
313: /**
314: * Returns the <code>ColorSpace</code> associated with this
315: * <code>ColorModel</code>.
316: * @return the <code>ColorSpace</code> of this
317: * <code>ColorModel</code>.
318: */
319: final public ColorSpace getColorSpace() {
320: return colorSpace;
321: }
322:
323: /**
324: * Returns the transparency. Returns either OPAQUE, BITMASK,
325: * or TRANSLUCENT.
326: * @return the transparency of this <code>ColorModel</code>.
327: * @see Transparency#OPAQUE
328: * @see Transparency#BITMASK
329: * @see Transparency#TRANSLUCENT
330: */
331: public int getTransparency() {
332: return transparency;
333: }
334:
335: /**
336: * Returns the number of bits for the specified color/alpha component.
337: * Color components are indexed in the order specified by the
338: * <code>ColorSpace</code>. Typically, this order reflects the name
339: * of the color space type. For example, for TYPE_RGB, index 0
340: * corresponds to red, index 1 to green, and index 2
341: * to blue. If this <code>ColorModel</code> supports alpha, the alpha
342: * component corresponds to the index following the last color
343: * component.
344: * @param componentIdx the index of the color/alpha component
345: * @return the number of bits for the color/alpha component at the
346: * specified index.
347: * @throws ArrayIndexOutOfBoundsException if <code>componentIdx</code>
348: * is greater than the number of components or
349: * less than zero
350: * @throws NullPointerException if the number of bits array is
351: * <code>null</code>
352: */
353: public int getComponentSize(int componentIdx) {
354: // NOTE
355: if (nBits == null) {
356: throw new NullPointerException(
357: "Number of bits array is null.");
358: }
359: return nBits[componentIdx];
360: }
361:
362: /**
363: * Returns an array of the number of bits per color/alpha component.
364: * The array contains the color components in the order specified by the
365: * <code>ColorSpace</code>, followed by the alpha component, if
366: * present.
367: * @return an array of the number of bits per color/alpha component
368: */
369: public int[] getComponentSize() {
370: if (nBits != null) {
371: return (int[]) nBits.clone();
372: }
373: return null;
374: }
375:
376: /**
377: * Returns the number of components, including alpha, in this
378: * <code>ColorModel</code>. This is equal to the number of color
379: * components, optionally plus one, if there is an alpha component.
380: * @return the number of components in this <code>ColorModel</code>
381: */
382: public int getNumComponents() {
383: return numComponents;
384: }
385:
386: /**
387: * Returns the number of color components in this
388: * <code>ColorModel</code>.
389: * This is the number of components returned by
390: * {@link ColorSpace#getNumComponents}.
391: * @return the number of color components in this
392: * <code>ColorModel</code>.
393: * @see ColorSpace#getNumComponents
394: */
395: public int getNumColorComponents() {
396: return numColorComponents;
397: }
398:
399: /**
400: * Returns the transfer type of this <code>ColorModel</code>.
401: * The transfer type is the type of primitive array used to represent
402: * pixel values as arrays.
403: * @return the transfer type.
404: */
405: public final int getTransferType() {
406: return transferType;
407: }
408:
409: static final int getDefaultTransferType(int pixel_bits) {
410: if (pixel_bits <= 8) {
411: return DataBuffer.TYPE_BYTE;
412: } else if (pixel_bits <= 16) {
413: return DataBuffer.TYPE_USHORT;
414: } else if (pixel_bits <= 32) {
415: return DataBuffer.TYPE_INT;
416: } else {
417: return DataBuffer.TYPE_UNDEFINED;
418: }
419: }
420:
421: /**
422: * Returns the <code>String</code> representation of the contents of
423: * this <code>ColorModel</code>object.
424: * @return a <code>String</code> representing the contents of this
425: * <code>ColorModel</code> object.
426: */
427: public String toString() {
428: return new String("ColorModel: #pixelBits = " + pixel_bits
429: + " numComponents = " + numComponents
430: + " color space = " + colorSpace + " transparency = "
431: + transparency + " has alpha = " + supportsAlpha
432: + " isAlphaPre = " + isAlphaPremultiplied);
433: }
434:
435: }
|