Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / java / awt / image / ColorModel.java
blob11615fdadfbdd62f22c6fa1fe6de95e830d307c5
1 /* ColorModel.java --
2 Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.awt.image;
41 import gnu.java.awt.Buffers;
43 import java.awt.Point;
44 import java.awt.Transparency;
45 import java.awt.color.ColorSpace;
46 import java.lang.reflect.Constructor;
47 import java.util.Arrays;
49 /**
50 * A color model operates with colors in several formats:
52 * <ul>
53 * <li>normalized: component samples are in range [0.0, 1.0].</li>
55 * <li>color model pixel value: all the color component samples for a
56 * sigle pixel packed/encoded in a way natural for the color
57 * model.</li>
59 * <li>color model pixel int value: only makes sense if the natural
60 * encoding of a single pixel can fit in a single int value.</li>
62 * <li>array of transferType containing a single pixel: the pixel is
63 * encoded in the natural way of the color model, taking up as many
64 * array elements as needed.</li>
66 * <li>sRGB pixel int value: a pixel in sRGB color space, encoded in
67 * default 0xAARRGGBB format, assumed not alpha premultiplied.</li>
69 * <li>single [0, 255] scaled int samples from default sRGB color
70 * space. These are always assumed to be alpha non-premultiplied.</li>
72 * <li>arrays of unnormalized component samples of single pixel: these
73 * samples are scaled and multiplied according to the color model, but
74 * is otherwise not packed or encoded. Each element of the array is one
75 * separate component sample. The color model only operate on the
76 * components from one pixel at a time, but using offsets, allows
77 * manipulation of arrays that contain the components of more than one
78 * pixel.</li>
80 * </ul>
82 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
83 * @author C. Brian Jones (cbj@gnu.org)
85 public abstract class ColorModel implements Transparency
87 protected int pixel_bits;
88 protected int transferType;
90 int[] bits;
91 ColorSpace cspace;
92 int transparency;
93 boolean hasAlpha;
94 boolean isAlphaPremultiplied;
96 static int[] nArray(int value, int times)
98 int[] array = new int[times];
99 java.util.Arrays.fill(array, value);
100 return array;
103 static byte[] nArray(byte value, int times)
105 byte[] array = new byte[times];
106 java.util.Arrays.fill(array, value);
107 return array;
111 * Constructs the default color model. The default color model
112 * can be obtained by calling <code>getRGBdefault</code> of this
113 * class.
114 * @param bits the number of bits wide used for bit size of pixel values
116 public ColorModel(int bits)
118 this(bits * 4, // total bits, sRGB, four channels
119 nArray(bits, 4), // bits for each channel
120 ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
121 true, // has alpha
122 false, // not premultiplied
123 TRANSLUCENT,
124 Buffers.smallestAppropriateTransferType(bits * 4));
128 * Constructs a ColorModel that translates pixel values to
129 * color/alpha components.
131 * @exception IllegalArgumentException If the length of the bit array is less
132 * than the number of color or alpha components in this ColorModel, or if the
133 * transparency is not a valid value, or if the sum of the number of bits in
134 * bits is less than 1 or if any of the elements in bits is less than 0.
136 protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
137 boolean hasAlpha, boolean isAlphaPremultiplied,
138 int transparency, int transferType)
140 int bits_sum = 0;
141 for (int i = 0; i < bits.length; i++)
143 if (bits [i] < 0)
144 throw new IllegalArgumentException ();
146 bits_sum |= bits [i];
149 if ((bits.length < cspace.getNumComponents())
150 || (bits_sum < 1))
151 throw new IllegalArgumentException ();
153 this.pixel_bits = pixel_bits;
154 this.bits = bits;
155 this.cspace = cspace;
156 this.hasAlpha = hasAlpha;
157 this.isAlphaPremultiplied = isAlphaPremultiplied;
158 this.transparency = transparency;
159 this.transferType = transferType;
162 // This is a hook for ColorConvertOp to create a colormodel with
163 // a new colorspace
164 ColorModel cloneColorModel(ColorSpace cspace)
166 Class cls = this.getClass();
167 ColorModel cm;
168 try {
169 // This constructor will exist.
170 Constructor ctor =
171 cls.getConstructor(new Class[]{int.class, int[].class,
172 ColorSpace.class, boolean.class,
173 boolean.class, int.class, int.class});
174 cm = (ColorModel)ctor.
175 newInstance(new Object[]{new Integer(pixel_bits),
176 bits, cspace, Boolean.valueOf(hasAlpha),
177 Boolean.valueOf(isAlphaPremultiplied),
178 new Integer(transparency),
179 new Integer(transferType)});
181 catch (Exception e)
183 throw new IllegalArgumentException();
185 return cm;
188 public void finalize()
190 // Do nothing here.
194 * Returns the default color model which in Sun's case is an instance
195 * of <code>DirectColorModel</code>.
197 public static ColorModel getRGBdefault()
199 return new DirectColorModel(32, 0xff0000, 0xff00, 0xff, 0xff000000);
202 public final boolean hasAlpha()
204 return hasAlpha;
207 public final boolean isAlphaPremultiplied()
209 return isAlphaPremultiplied;
213 * Get get number of bits wide used for the bit size of pixel values
215 public int getPixelSize()
217 return pixel_bits;
220 public int getComponentSize(int componentIdx)
222 return bits[componentIdx];
225 public int[] getComponentSize()
227 return bits;
230 public int getTransparency()
232 return transparency;
235 public int getNumComponents()
237 return getNumColorComponents() + (hasAlpha ? 1 : 0);
240 public int getNumColorComponents()
242 return cspace.getNumComponents();
246 * Converts pixel value to sRGB and extract red int sample scaled
247 * to range [0, 255].
249 * @param pixel pixel value that will be interpreted according to
250 * the color model, (assumed alpha premultiplied if color model says
251 * so.)
253 * @return red sample scaled to range [0, 255], from default color
254 * space sRGB, alpha non-premultiplied.
256 public abstract int getRed(int pixel);
259 * Converts pixel value to sRGB and extract green int sample
260 * scaled to range [0, 255].
262 * @see #getRed(int)
264 public abstract int getGreen(int pixel);
267 * Converts pixel value to sRGB and extract blue int sample
268 * scaled to range [0, 255].
270 * @see #getRed(int)
272 public abstract int getBlue(int pixel);
275 * Extract alpha int sample from pixel value, scaled to [0, 255].
277 * @param pixel pixel value that will be interpreted according to
278 * the color model.
280 * @return alpha sample, scaled to range [0, 255].
282 public abstract int getAlpha(int pixel);
285 * Converts a pixel int value of the color space of the color
286 * model to a sRGB pixel int value.
288 * This method is typically overriden in subclasses to provide a
289 * more efficient implementation.
291 * @param pixel pixel value that will be interpreted according to
292 * the color model.
294 * @return a pixel in sRGB color space, encoded in default
295 * 0xAARRGGBB format. */
296 public int getRGB(int pixel)
298 return
299 ((getAlpha(pixel) & 0xff) << 24) |
300 (( getRed(pixel) & 0xff) << 16) |
301 ((getGreen(pixel) & 0xff) << 8) |
302 (( getBlue(pixel) & 0xff) << 0);
307 * In this color model we know that the whole pixel value will
308 * always be contained within the first element of the pixel
309 * array.
311 final int getPixelFromArray(Object inData) {
312 DataBuffer data =
313 Buffers.createBufferFromData(transferType, inData, 1);
314 Object da = Buffers.getData(data);
316 return data.getElem(0);
319 /**
320 * Converts pixel in the given array to sRGB and extract blue int
321 * sample scaled to range [0-255].
323 * This method is typically overriden in subclasses to provide a
324 * more efficient implementation.
326 * @param inData array of transferType containing a single pixel. The
327 * pixel should be encoded in the natural way of the color model.
329 public int getRed(Object inData)
331 return getRed(getPixelFromArray(inData));
335 * @see #getRed(Object)
337 public int getGreen(Object inData)
339 return getGreen(getPixelFromArray(inData));
343 * @see #getRed(Object)
345 public int getBlue(Object inData) {
346 return getBlue(getPixelFromArray(inData));
350 * @see #getRed(Object)
352 public int getAlpha(Object inData) {
353 return getAlpha(getPixelFromArray(inData));
357 * Converts a pixel in the given array of the color space of the
358 * color model to an sRGB pixel int value.
360 * <p>This method performs the inverse function of
361 * <code>getDataElements(int rgb, Object pixel)</code>.
362 * I.e. <code>(rgb == cm.getRGB(cm.getDataElements(rgb,
363 * null)))</code>.
365 * @param inData array of transferType containing a single pixel. The
366 * pixel should be encoded in the natural way of the color model.
368 * @return a pixel in sRGB color space, encoded in default
369 * 0xAARRGGBB format.
371 * @see #getDataElements(int, Object)
373 public int getRGB(Object inData)
375 return
376 ((getAlpha(inData) & 0xff) << 24) |
377 (( getRed(inData) & 0xff) << 16) |
378 ((getGreen(inData) & 0xff) << 8) |
379 (( getBlue(inData) & 0xff) << 0);
383 * Converts an sRGB pixel int value to an array containing a
384 * single pixel of the color space of the color model.
386 * <p>This method performs the inverse function of
387 * <code>getRGB(Object inData)</code>.
389 * Outline of conversion process:
391 * <ol>
393 * <li>Convert rgb to normalized [0.0, 1.0] sRGB values.</li>
395 * <li>Convert to color space components using fromRGB in
396 * ColorSpace.</li>
398 * <li>If color model has alpha and should be premultiplied,
399 * multiply color space components with alpha value</li>
401 * <li>Scale the components to the correct number of bits.</li>
403 * <li>Arrange the components in the output array</li>
405 * </ol>
407 * @param rgb The color to be converted to dataElements. A pixel
408 * in sRGB color space, encoded in default 0xAARRGGBB format,
409 * assumed not alpha premultiplied.
411 * @param pixel to avoid needless creation of arrays, an array to
412 * use to return the pixel can be given. If null, a suitable array
413 * will be created.
415 * @return An array of transferType values representing the color,
416 * in the color model format. The color model defines whether the
418 * @see #getRGB(Object)
420 public Object getDataElements(int rgb, Object pixel)
422 // subclasses has to implement this method.
423 throw new UnsupportedOperationException();
427 * Fills an array with the unnormalized component samples from a
428 * pixel value. I.e. decompose the pixel, but not perform any
429 * color conversion.
431 * This method is typically overriden in subclasses to provide a
432 * more efficient implementation.
434 * @param pixel pixel value encoded according to the color model.
436 * @return arrays of unnormalized component samples of single
437 * pixel. The scale and multiplication state of the samples are
438 * according to the color model. Each component sample is stored
439 * as a separate element in the array.
441 public int[] getComponents(int pixel, int[] components, int offset)
443 // subclasses has to implement this method.
444 throw new UnsupportedOperationException();
448 * Fills an array with the unnormalized component samples from an
449 * array of transferType containing a single pixel. I.e. decompose
450 * the pixel, but not perform any color conversion.
452 * This method is typically overriden in subclasses to provide a
453 * more efficient implementation.
455 * @param array of transferType containing a single pixel. The
456 * pixel should be encoded in the natural way of the color model.
458 * @return arrays of unnormalized component samples of single
459 * pixel. The scale and multiplication state of the samples are
460 * according to the color model. Each component sample is stored
461 * as a separate element in the array.
463 public int[] getComponents(Object pixel, int[] components, int offset)
465 // subclasses has to implement this method.
466 throw new UnsupportedOperationException();
470 * Convert normalized components to unnormalized components.
472 public int[] getUnnormalizedComponents(float[] normComponents,
473 int normOffset,
474 int[] components,
475 int offset)
477 int numComponents = getNumComponents();
478 if (components == null)
480 components = new int[offset + numComponents];
483 for (int i=0; i<numComponents; i++)
485 float in = normComponents[normOffset++];
486 int out = (int) (in * ((1<<getComponentSize(i)) - 1));
487 components[offset++] = out;
489 return components;
493 * Convert unnormalized components to normalized components.
495 public float[] getNormalizedComponents(int[] components,
496 int offset,
497 float[] normComponents,
498 int normOffset)
500 int numComponents = getNumComponents();
501 if (normComponents == null)
503 normComponents = new float[normOffset + numComponents];
506 for (int i=0; i<numComponents; i++)
508 float in = components[offset++];
509 float out = in / ((1<<getComponentSize(i)) - 1);
510 normComponents[normOffset++] = out;
512 return normComponents;
516 * Convert unnormalized components to normalized components.
518 * @since 1.4
520 public float[] getNormalizedComponents (Object pixel,
521 float[] normComponents,
522 int normOffset)
524 // subclasses has to implement this method.
525 throw new UnsupportedOperationException();
529 * Converts the unnormalized component samples from an array to a
530 * pixel value. I.e. composes the pixel from component samples, but
531 * does not perform any color conversion or scaling of the samples.
533 * This method performs the inverse function of
534 * <code>getComponents(int pixel, int[] components,
535 * int offset)</code>. I.e.
537 * <code>(pixel == cm.getDataElement(cm.getComponents(pixel, null,
538 * 0), 0))</code>.
540 * This method is overriden in subclasses since this abstract class throws
541 * UnsupportedOperationException().
543 * @param components Array of unnormalized component samples of single
544 * pixel. The scale and multiplication state of the samples are according
545 * to the color model. Each component sample is stored as a separate element
546 * in the array.
547 * @param offset Position of the first value of the pixel in components.
549 * @return pixel value encoded according to the color model.
551 public int getDataElement(int[] components, int offset)
553 // subclasses have to implement this method.
554 throw new UnsupportedOperationException();
558 * Converts the normalized component samples from an array to a pixel
559 * value. I.e. composes the pixel from component samples, but does not
560 * perform any color conversion or scaling of the samples.
562 * This method is typically overriden in subclasses to provide a
563 * more efficient implementation. The method provided by this abstract
564 * class converts the components to unnormalized form and returns
565 * getDataElement(int[], int).
567 * @param components Array of normalized component samples of single pixel.
568 * The scale and multiplication state of the samples are according to the
569 * color model. Each component sample is stored as a separate element in the
570 * array.
571 * @param offset Position of the first value of the pixel in components.
573 * @return pixel value encoded according to the color model.
574 * @since 1.4
576 public int getDataElement (float[] components, int offset)
578 return
579 getDataElement(getUnnormalizedComponents(components, offset, null, 0),
583 public Object getDataElements(int[] components, int offset, Object obj)
585 // subclasses have to implement this method.
586 throw new UnsupportedOperationException();
590 * Converts the normalized component samples from an array to an array of
591 * TransferType values. I.e. composes the pixel from component samples, but
592 * does not perform any color conversion or scaling of the samples.
594 * If obj is null, a new array of TransferType is allocated and returned.
595 * Otherwise the results are stored in obj and obj is returned. If obj is
596 * not long enough, ArrayIndexOutOfBounds is thrown. If obj is not an array
597 * of primitives, ClassCastException is thrown.
599 * This method is typically overriden in subclasses to provide a
600 * more efficient implementation. The method provided by this abstract
601 * class converts the components to unnormalized form and returns
602 * getDataElement(int[], int, Object).
604 * @param components Array of normalized component samples of single pixel.
605 * The scale and multiplication state of the samples are according to the
606 * color model. Each component sample is stored as a separate element in the
607 * array.
608 * @param offset Position of the first value of the pixel in components.
609 * @param obj Array of TransferType or null.
611 * @return pixel value encoded according to the color model.
612 * @throws ArrayIndexOutOfBounds
613 * @throws ClassCastException
614 * @since 1.4
616 public Object getDataElements(float[] components, int offset, Object obj)
618 return
619 getDataElements(getUnnormalizedComponents(components, offset, null, 0),
620 0, obj);
623 public boolean equals(Object obj)
625 if (!(obj instanceof ColorModel)) return false;
627 ColorModel o = (ColorModel) obj;
628 return
629 (pixel_bits == o.pixel_bits) &&
630 (transferType == o.transferType) &&
631 (transparency == o.transparency) &&
632 (hasAlpha == o.hasAlpha) &&
633 (isAlphaPremultiplied == o.isAlphaPremultiplied) &&
634 Arrays.equals(bits, o.bits) &&
635 (cspace.equals(o.cspace));
638 public final ColorSpace getColorSpace()
640 return cspace;
643 // Typically overridden
644 public ColorModel coerceData(WritableRaster raster,
645 boolean isAlphaPremultiplied)
647 if (this.isAlphaPremultiplied == isAlphaPremultiplied)
648 return this;
650 int w = raster.getWidth();
651 int h = raster.getHeight();
652 int x = raster.getMinX();
653 int y = raster.getMinY();
654 int size = w*h;
655 int numColors = getNumColorComponents();
656 int numComponents = getNumComponents();
657 int alphaScale = (1<<getComponentSize(numColors)) - 1;
658 double[] pixels = raster.getPixels(x, y, w, h, (double[]) null);
660 for (int i=0; i<size; i++)
662 double alpha = pixels[i*numComponents+numColors]*alphaScale;
663 for (int c=0; c<numColors; c++)
665 int offset = i*numComponents+c;
666 if (isAlphaPremultiplied)
667 pixels[offset] = pixels[offset]/alpha;
668 else
669 pixels[offset] = pixels[offset]*alpha;
673 raster.setPixels(0, 0, w, h, pixels);
675 // FIXME: what can we return?
676 return null;
680 * Checks if the given raster has a compatible data-layout (SampleModel).
681 * @param raster The Raster to test.
682 * @return true if raster is compatible.
684 public boolean isCompatibleRaster(Raster raster)
686 SampleModel sampleModel = raster.getSampleModel();
687 return isCompatibleSampleModel(sampleModel);
690 // Typically overridden
691 public WritableRaster createCompatibleWritableRaster(int w, int h)
693 return new WritableRaster(createCompatibleSampleModel(w, h),
694 new Point(0, 0));
697 // Typically overridden
698 public SampleModel createCompatibleSampleModel(int w, int h)
700 throw new UnsupportedOperationException();
703 // Typically overridden
704 public boolean isCompatibleSampleModel(SampleModel sm)
706 return sm.getTransferType() == transferType;
709 public final int getTransferType ()
711 return transferType;
715 * Subclasses must override this method if it is possible for the
716 * color model to have an alpha channel.
718 * @return null, as per JDK 1.3 doc. Subclasses will only return
719 * null if no alpha raster exists.
721 public WritableRaster getAlphaRaster(WritableRaster raster)
723 return null;
725 /* It is a mystery to me why we couldn't use the following code...
728 if (!hasAlpha()) return null;
730 SampleModel sm = raster.getSampleModel();
731 int[] alphaBand = { sm.getNumBands() - 1 };
732 SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
733 DataBuffer buffer = raster.getDataBuffer();
734 Point origin = new Point(0, 0);
735 return Raster.createWritableRaster(alphaModel, buffer, origin);
738 ...here, and avoided overriding the method in subclasses,
739 but the Sun docs state that this method always will return
740 null, and that overriding is required. Oh, well.
744 String stringParam()
746 return "pixel_bits=" + pixel_bits +
747 ", cspace=" + cspace +
748 ", transferType=" + transferType +
749 ", transparency=" + transparency +
750 ", hasAlpha=" + hasAlpha +
751 ", isAlphaPremultiplied=" + isAlphaPremultiplied;
754 public String toString()
756 return getClass().getName() + "[" + stringParam() + "]";