001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Igor V. Stolyarov
019: * @version $Revision$
020: */package java.awt.image;
021:
022: import java.awt.Transparency;
023: import java.awt.color.ColorSpace;
024: import java.util.Arrays;
025:
026: import org.apache.harmony.awt.internal.nls.Messages;
027:
028: public abstract class ColorModel implements Transparency {
029:
030: protected int pixel_bits; // Pixel length in bits
031:
032: protected int transferType;
033:
034: ColorSpace cs;
035:
036: boolean hasAlpha;
037:
038: boolean isAlphaPremultiplied;
039:
040: int transparency;
041:
042: int numColorComponents;
043:
044: int numComponents;
045:
046: int[] bits; // Array of components masks
047:
048: int[] maxValues = null; // Max values that may be represent by color
049: // components
050:
051: int maxBitLength; // Max length color components in bits
052:
053: private static ColorModel RGBdefault;
054:
055: protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
056: boolean hasAlpha, boolean isAlphaPremultiplied,
057: int transparency, int transferType) {
058:
059: if (pixel_bits < 1) {
060: // awt.26B=The number of bits in the pixel values is less than 1
061: throw new IllegalArgumentException(Messages
062: .getString("awt.26B")); //$NON-NLS-1$
063: }
064:
065: if (bits == null) {
066: // awt.26C=bits is null
067: throw new NullPointerException(Messages
068: .getString("awt.26C")); //$NON-NLS-1$
069: }
070:
071: int sum = 0;
072: for (int element : bits) {
073: if (element < 0) {
074: // awt.26D=The elements in bits is less than 0
075: throw new IllegalArgumentException(Messages
076: .getString("awt.26D")); //$NON-NLS-1$
077: }
078: sum += element;
079: }
080:
081: if (sum < 1) {
082: // awt.26E=The sum of the number of bits in bits is less than 1
083: throw new NullPointerException(Messages
084: .getString("awt.26E")); //$NON-NLS-1$
085: }
086:
087: if (cspace == null) {
088: // awt.26F=The cspace is null
089: throw new IllegalArgumentException(Messages
090: .getString("awt.26F")); //$NON-NLS-1$
091: }
092:
093: if (transparency < Transparency.OPAQUE
094: || transparency > Transparency.TRANSLUCENT) {
095: // awt.270=The transparency is not a valid value
096: throw new IllegalArgumentException(Messages
097: .getString("awt.270")); //$NON-NLS-1$
098: }
099:
100: this .pixel_bits = pixel_bits;
101: this .bits = bits.clone();
102:
103: maxValues = new int[bits.length];
104: maxBitLength = 0;
105: for (int i = 0; i < maxValues.length; i++) {
106: maxValues[i] = (1 << bits[i]) - 1;
107: if (bits[i] > maxBitLength) {
108: maxBitLength = bits[i];
109: }
110: }
111:
112: cs = cspace;
113: this .hasAlpha = hasAlpha;
114: this .isAlphaPremultiplied = isAlphaPremultiplied;
115: numColorComponents = cs.getNumComponents();
116:
117: if (hasAlpha) {
118: numComponents = numColorComponents + 1;
119: } else {
120: numComponents = numColorComponents;
121: }
122:
123: this .transparency = transparency;
124: this .transferType = transferType;
125:
126: }
127:
128: public ColorModel(int bits) {
129:
130: if (bits < 1) {
131: // awt.271=The number of bits in bits is less than 1
132: throw new IllegalArgumentException(Messages
133: .getString("awt.271")); //$NON-NLS-1$
134: }
135:
136: pixel_bits = bits;
137: transferType = getTransferType(bits);
138: cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
139: hasAlpha = true;
140: isAlphaPremultiplied = false;
141: transparency = Transparency.TRANSLUCENT;
142:
143: numColorComponents = 3;
144: numComponents = 4;
145:
146: this .bits = null;
147: }
148:
149: public Object getDataElements(int[] components, int offset,
150: Object obj) {
151: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
152: "supported by this ColorModel"); //$NON-NLS-1$
153: }
154:
155: public Object getDataElements(float[] normComponents,
156: int normOffset, Object obj) {
157: int unnormComponents[] = getUnnormalizedComponents(
158: normComponents, normOffset, null, 0);
159: return getDataElements(unnormComponents, 0, obj);
160: }
161:
162: public Object getDataElements(int rgb, Object pixel) {
163: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
164: "supported by this ColorModel"); //$NON-NLS-1$
165: }
166:
167: public WritableRaster getAlphaRaster(WritableRaster raster) {
168: return null;
169: }
170:
171: public ColorModel coerceData(WritableRaster raster,
172: boolean isAlphaPremultiplied) {
173: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
174: "supported by this ColorModel"); //$NON-NLS-1$
175: }
176:
177: @Override
178: public String toString() {
179: // The output format based on 1.5 release behaviour.
180: // It could be reveled such way:
181: // ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB,
182: // false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
183: // System.out.println(cm.toString());
184: return "ColorModel: Color Space = " + cs.toString() + "; has alpha = " //$NON-NLS-1$ //$NON-NLS-2$
185: + hasAlpha
186: + "; is alpha premultipied = " //$NON-NLS-1$
187: + isAlphaPremultiplied
188: + "; transparency = " + transparency //$NON-NLS-1$
189: + "; number color components = " + numColorComponents //$NON-NLS-1$
190: + "; pixel bits = " + pixel_bits + "; transfer type = " //$NON-NLS-1$ //$NON-NLS-2$
191: + transferType;
192: }
193:
194: public int[] getComponents(Object pixel, int[] components,
195: int offset) {
196: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
197: "supported by this ColorModel"); //$NON-NLS-1$
198: }
199:
200: public float[] getNormalizedComponents(Object pixel,
201: float[] normComponents, int normOffset) {
202:
203: if (pixel == null) {
204: // awt.294=pixel is null
205: throw new NullPointerException(Messages
206: .getString("awt.294")); //$NON-NLS-1$
207: }
208:
209: int unnormComponents[] = getComponents(pixel, null, 0);
210: return getNormalizedComponents(unnormComponents, 0,
211: normComponents, normOffset);
212: }
213:
214: @Override
215: public boolean equals(Object obj) {
216: if (!(obj instanceof ColorModel)) {
217: return false;
218: }
219: ColorModel cm = (ColorModel) obj;
220:
221: return (pixel_bits == cm.getPixelSize()
222: && transferType == cm.getTransferType()
223: && cs.getType() == cm.getColorSpace().getType()
224: && hasAlpha == cm.hasAlpha()
225: && isAlphaPremultiplied == cm.isAlphaPremultiplied()
226: && transparency == cm.getTransparency()
227: && numColorComponents == cm.getNumColorComponents()
228: && numComponents == cm.getNumComponents() && Arrays
229: .equals(bits, cm.getComponentSize()));
230: }
231:
232: public int getRed(Object inData) {
233: return getRed(constructPixel(inData));
234: }
235:
236: public int getRGB(Object inData) {
237: return (getAlpha(inData) << 24 | getRed(inData) << 16
238: | getGreen(inData) << 8 | getBlue(inData));
239: }
240:
241: public int getGreen(Object inData) {
242: return getGreen(constructPixel(inData));
243: }
244:
245: public int getBlue(Object inData) {
246: return getBlue(constructPixel(inData));
247: }
248:
249: public int getAlpha(Object inData) {
250: return getAlpha(constructPixel(inData));
251: }
252:
253: public WritableRaster createCompatibleWritableRaster(int w, int h) {
254: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
255: "supported by this ColorModel"); //$NON-NLS-1$
256: }
257:
258: public boolean isCompatibleSampleModel(SampleModel sm) {
259: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
260: "supported by this ColorModel"); //$NON-NLS-1$
261: }
262:
263: public SampleModel createCompatibleSampleModel(int w, int h) {
264: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
265: "supported by this ColorModel"); //$NON-NLS-1$
266: }
267:
268: public boolean isCompatibleRaster(Raster raster) {
269: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
270: "supported by this ColorModel"); //$NON-NLS-1$
271: }
272:
273: public final ColorSpace getColorSpace() {
274: return cs;
275: }
276:
277: public float[] getNormalizedComponents(int[] components,
278: int offset, float normComponents[], int normOffset) {
279: if (bits == null) {
280: // awt.26C=bits is null
281: throw new UnsupportedOperationException(Messages
282: .getString("awt.26C")); //$NON-NLS-1$
283: }
284:
285: if (normComponents == null) {
286: normComponents = new float[numComponents + normOffset];
287: }
288:
289: if (hasAlpha && isAlphaPremultiplied) {
290: float normAlpha = (float) components[offset
291: + numColorComponents]
292: / maxValues[numColorComponents];
293: if (normAlpha != 0.0f) {
294: for (int i = 0; i < numColorComponents; i++) {
295: normComponents[normOffset + i] = components[offset
296: + i]
297: / (normAlpha * maxValues[i]);
298: }
299: normComponents[normOffset + numColorComponents] = normAlpha;
300: } else {
301: for (int i = 0; i < numComponents; i++) {
302: normComponents[normOffset + i] = 0.0f;
303: }
304: }
305: } else {
306: for (int i = 0; i < numComponents; i++) {
307: normComponents[normOffset + i] = (float) components[offset
308: + i]
309: / maxValues[i];
310: }
311: }
312:
313: return normComponents;
314: }
315:
316: public int getDataElement(int[] components, int offset) {
317: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
318: "supported by this ColorModel"); //$NON-NLS-1$
319: }
320:
321: public int[] getUnnormalizedComponents(float normComponents[],
322: int normOffset, int components[], int offset) {
323:
324: if (bits == null) {
325: // awt.26C=bits is null
326: throw new UnsupportedOperationException(Messages
327: .getString("awt.26C")); //$NON-NLS-1$
328: }
329:
330: if (normComponents.length - normOffset < numComponents) {
331: // awt.273=The length of normComponents minus normOffset is less than numComponents
332: throw new IllegalArgumentException(Messages
333: .getString("awt.273")); //$NON-NLS-1$
334: }
335:
336: if (components == null) {
337: components = new int[numComponents + offset];
338: } else {
339: if (components.length - offset < numComponents) {
340: // awt.272=The length of components minus offset is less than numComponents
341: throw new IllegalArgumentException(Messages
342: .getString("awt.272")); //$NON-NLS-1$
343: }
344: }
345:
346: if (hasAlpha && isAlphaPremultiplied) {
347: float alpha = normComponents[normOffset
348: + numColorComponents];
349: for (int i = 0; i < numColorComponents; i++) {
350: components[offset + i] = (int) (normComponents[normOffset
351: + i]
352: * maxValues[i] * alpha + 0.5f);
353: }
354: components[offset + numColorComponents] = (int) (normComponents[normOffset
355: + numColorComponents]
356: * maxValues[numColorComponents] + 0.5f);
357: } else {
358: for (int i = 0; i < numComponents; i++) {
359: components[offset + i] = (int) (normComponents[normOffset
360: + i]
361: * maxValues[i] + 0.5f);
362: }
363: }
364:
365: return components;
366: }
367:
368: public int getDataElement(float normComponents[], int normOffset) {
369: int unnormComponents[] = getUnnormalizedComponents(
370: normComponents, normOffset, null, 0);
371: return getDataElement(unnormComponents, 0);
372: }
373:
374: public int[] getComponents(int pixel, int components[], int offset) {
375: throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
376: "supported by this ColorModel"); //$NON-NLS-1$
377: }
378:
379: public abstract int getRed(int pixel);
380:
381: public int getRGB(int pixel) {
382: return (getAlpha(pixel) << 24 | getRed(pixel) << 16
383: | getGreen(pixel) << 8 | getBlue(pixel));
384: }
385:
386: public abstract int getGreen(int pixel);
387:
388: public int getComponentSize(int componentIdx) {
389: if (bits == null) {
390: // awt.26C=bits is null
391: throw new NullPointerException(Messages
392: .getString("awt.26C")); //$NON-NLS-1$
393: }
394:
395: if (componentIdx < 0 || componentIdx >= bits.length) {
396: // awt.274=componentIdx is greater than the number of components or less than zero
397: throw new ArrayIndexOutOfBoundsException(Messages
398: .getString("awt.274")); //$NON-NLS-1$
399: }
400:
401: return bits[componentIdx];
402: }
403:
404: public abstract int getBlue(int pixel);
405:
406: public abstract int getAlpha(int pixel);
407:
408: public int[] getComponentSize() {
409: if (bits != null) {
410: return bits.clone();
411: }
412: return null;
413: }
414:
415: public final boolean isAlphaPremultiplied() {
416: return isAlphaPremultiplied;
417: }
418:
419: public final boolean hasAlpha() {
420: return hasAlpha;
421: }
422:
423: @Override
424: public int hashCode() {
425: int hash = 0;
426: int tmp;
427:
428: if (hasAlpha) {
429: hash ^= 1;
430: hash <<= 8;
431: }
432: if (isAlphaPremultiplied) {
433: hash ^= 1;
434: hash <<= 8;
435: }
436:
437: tmp = hash >>> 24;
438: hash ^= numColorComponents;
439: hash <<= 8;
440: hash |= tmp;
441:
442: tmp = hash >>> 24;
443: hash ^= transparency;
444: hash <<= 8;
445: hash |= tmp;
446:
447: tmp = hash >>> 24;
448: hash ^= cs.getType();
449: hash <<= 8;
450: hash |= tmp;
451:
452: tmp = hash >>> 24;
453: hash ^= pixel_bits;
454: hash <<= 8;
455: hash |= tmp;
456:
457: tmp = hash >>> 24;
458: hash ^= transferType;
459: hash <<= 8;
460: hash |= tmp;
461:
462: if (bits != null) {
463:
464: for (int element : bits) {
465: tmp = hash >>> 24;
466: hash ^= element;
467: hash <<= 8;
468: hash |= tmp;
469: }
470:
471: }
472:
473: return hash;
474: }
475:
476: public int getTransparency() {
477: return transparency;
478: }
479:
480: public final int getTransferType() {
481: return transferType;
482: }
483:
484: public int getPixelSize() {
485: return pixel_bits;
486: }
487:
488: public int getNumComponents() {
489: return numComponents;
490: }
491:
492: public int getNumColorComponents() {
493: return numColorComponents;
494: }
495:
496: public static ColorModel getRGBdefault() {
497: if (RGBdefault == null) {
498: RGBdefault = new DirectColorModel(32, 0x00ff0000,
499: 0x0000ff00, 0x000000ff, 0xff000000);
500: }
501: return RGBdefault;
502: }
503:
504: /*
505: * Construct INT pixel representation from Object
506: * @param obj
507: *
508: * @return
509: */
510: private int constructPixel(Object obj) {
511: int pixel = 0;
512:
513: switch (getTransferType()) {
514:
515: case DataBuffer.TYPE_BYTE:
516: byte[] bPixel = (byte[]) obj;
517: if (bPixel.length > 1) {
518: // awt.275=This pixel representation is not suuported by tis Color Model
519: throw new UnsupportedOperationException(Messages
520: .getString("awt.275")); //$NON-NLS-1$
521: }
522: pixel = bPixel[0] & 0xff;
523: break;
524:
525: case DataBuffer.TYPE_USHORT:
526: short[] sPixel = (short[]) obj;
527: if (sPixel.length > 1) {
528: // awt.275=This pixel representation is not suuported by tis Color Model
529: throw new UnsupportedOperationException(Messages
530: .getString("awt.275")); //$NON-NLS-1$
531: }
532: pixel = sPixel[0] & 0xffff;
533: break;
534:
535: case DataBuffer.TYPE_INT:
536: int[] iPixel = (int[]) obj;
537: if (iPixel.length > 1) {
538: // awt.275=This pixel representation is not suuported by tis Color Model
539: throw new UnsupportedOperationException(Messages
540: .getString("awt.275")); //$NON-NLS-1$
541: }
542: pixel = iPixel[0];
543: break;
544:
545: default:
546: // awt.22D=This transferType ( {0} ) is not supported by this color model
547: throw new UnsupportedOperationException(Messages.getString(
548: "awt.22D", //$NON-NLS-1$
549: transferType));
550:
551: }
552: return pixel;
553: }
554:
555: static int getTransferType(int bits) {
556: if (bits <= 8) {
557: return DataBuffer.TYPE_BYTE;
558: } else if (bits <= 16) {
559: return DataBuffer.TYPE_USHORT;
560: } else if (bits <= 32) {
561: return DataBuffer.TYPE_INT;
562: } else {
563: return DataBuffer.TYPE_UNDEFINED;
564: }
565: }
566:
567: @Override
568: public void finalize() {
569: // This method is added for the API compatibility
570: // Don't need to call super since Object's finalize is always empty
571: }
572: }
|