Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / java / awt / image / ComponentColorModel.java
blob2b065328ee0b433a821bd71c77db7688c90b5915
1 /* ComponentColorModel.java --
2 Copyright (C) 2000, 2002, 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.color.ColorSpace;
46 public class ComponentColorModel extends ColorModel
48 private static int sum(int[] values)
50 int sum = 0;
51 for (int i=0; i<values.length; i++)
52 sum += values[i];
53 return sum;
56 public ComponentColorModel(ColorSpace colorSpace, int[] bits,
57 boolean hasAlpha,
58 boolean isAlphaPremultiplied,
59 int transparency, int transferType)
61 super(sum(bits), bits, colorSpace, hasAlpha, isAlphaPremultiplied,
62 transparency, transferType);
65 /**
66 * Construct a new ComponentColorModel.
68 * This constructor makes all bits of each sample significant, so for a
69 * transferType of DataBuffer.BYTE, the bits per sample is 8, etc. If
70 * both hasAlpha and isAlphaPremultiplied are true, color samples are
71 * assumed to be premultiplied by the alpha component. Transparency may be
72 * one of OPAQUE, BITMASK, or TRANSLUCENT.
74 * @param colorSpace The colorspace for this color model.
75 * @param hasAlpha True if there is an alpha component.
76 * @param isAlphaPremultiplied True if colors are already multiplied by
77 * alpha.
78 * @param transparency The type of alpha values.
79 * @param transferType Data type of pixel sample values.
80 * @since 1.4
82 public ComponentColorModel(ColorSpace colorSpace,
83 boolean hasAlpha,
84 boolean isAlphaPremultiplied,
85 int transparency, int transferType)
87 this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
88 transparency, transferType);
91 public int getRed(int pixel)
93 if (getNumComponents()>1) throw new IllegalArgumentException();
94 return (int) getRGBFloat(pixel)[0];
97 public int getGreen(int pixel)
99 if (getNumComponents()>1) throw new IllegalArgumentException();
100 return (int) getRGBFloat(pixel)[0];
103 public int getBlue(int pixel)
105 if (getNumComponents()>1) throw new IllegalArgumentException();
106 return (int) getRGBFloat(pixel)[0];
109 public int getAlpha(int pixel)
111 if (getNumComponents()>1) throw new IllegalArgumentException();
112 int shift = 8 - getComponentSize(getNumColorComponents());
113 if (shift >= 0) return pixel << shift;
114 return pixel >> (-shift);
117 public int getRGB(int pixel)
119 float[] rgb = getRGBFloat(pixel);
120 int ret = getRGB(rgb);
121 if (hasAlpha()) ret |= getAlpha(pixel) << 24;
122 return ret;
126 /* Note, it's OK to pass a to large array to toRGB(). Extra
127 elements are ignored. */
129 private float[] getRGBFloat(int pixel)
131 float[] data = { pixel };
132 return cspace.toRGB(data);
135 private float[] getRGBFloat(Object inData)
137 DataBuffer buffer =
138 Buffers.createBufferFromData(transferType, inData,
139 getNumComponents());
140 int colors = getNumColorComponents();
141 float[] data = new float[colors];
143 // FIXME: unpremultiply data that is premultiplied
144 for (int i=0; i<colors; i++)
146 float maxValue = (1<<getComponentSize(i))-1;
147 data[i] = buffer.getElemFloat(i)/maxValue;
149 float[] rgb = cspace.toRGB(data);
150 return rgb;
153 public int getRed(Object inData)
155 return (int) getRGBFloat(inData)[0]*255;
158 public int getGreen(Object inData)
160 return (int) getRGBFloat(inData)[1]*255;
163 public int getBlue(Object inData)
165 return (int) getRGBFloat(inData)[2]*255;
168 public int getAlpha(Object inData)
170 DataBuffer buffer =
171 Buffers.createBufferFromData(transferType, inData,
172 getNumComponents());
173 int shift = 8 - getComponentSize(getNumColorComponents());
174 int alpha = buffer.getElem(getNumColorComponents());
175 if (shift >= 0) return alpha << shift;
176 return alpha >> (-shift);
179 private int getRGB(float[] rgb)
181 /* NOTE: We could cast to byte instead of int here. This would
182 avoid bits spilling over from one bit field to
183 another. But, if we assume that floats are in the [0.0,
184 1.0] range, this will never happen anyway. */
186 /* Remember to multiply BEFORE casting to int, otherwise, decimal
187 point data will be lost. */
188 int ret =
189 (((int) (rgb[0]*255F)) << 16) |
190 (((int) (rgb[1]*255F)) << 8) |
191 (((int) (rgb[2]*255F)) << 0);
192 return ret;
196 * @param inData pixel data of transferType, as returned by the
197 * getDataElements method in SampleModel.
199 public int getRGB(Object inData)
201 float[] rgb = getRGBFloat(inData);
202 int ret = getRGB(rgb);
203 if (hasAlpha()) ret |= getAlpha(inData) << 24;
204 return ret;
207 public Object getDataElements(int rgb, Object pixel)
209 // Convert rgb to [0.0, 1.0] sRGB values.
210 float[] rgbFloats = {
211 ((rgb >> 16)&0xff)/255.0F,
212 ((rgb >> 8)&0xff)/255.0F,
213 ((rgb >> 0)&0xff)/255.0F
216 // Convert from rgb to color space components.
217 float[] data = cspace.fromRGB(rgbFloats);
218 DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
219 getNumComponents());
220 int numColors = getNumColorComponents();
222 if (hasAlpha())
224 float alpha = ((rgb >> 24)&0xff)/255.0F;
226 /* If color model has alpha and should be premultiplied, multiply
227 color space components with alpha value. */
228 if (isAlphaPremultiplied()) {
229 for (int i=0; i<numColors; i++)
230 data[i] *= alpha;
232 // Scale the alpha sample to the correct number of bits.
233 alpha *= (1<<(bits[numColors]-1));
234 // Arrange the alpha sample in the output array.
235 buffer.setElemFloat(numColors, alpha);
237 for (int i=0; i<numColors; i++)
239 // Scale the color samples to the correct number of bits.
240 float value = data[i]*(1<<(bits[i]-1));
241 // Arrange the color samples in the output array.
242 buffer.setElemFloat(i, value);
244 return Buffers.getData(buffer);
247 public int[] getComponents(int pixel, int[] components, int offset)
249 if (getNumComponents()>1) throw new IllegalArgumentException();
250 if (components == null)
251 components = new int[getNumComponents() + offset];
252 components[offset] = pixel;
253 return components;
256 public int[] getComponents(Object pixel, int[] components, int offset)
258 DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
259 getNumComponents());
260 int numComponents = getNumComponents();
262 if (components == null)
263 components = new int[numComponents + offset];
265 for (int i=0; i<numComponents; i++)
266 components[offset++] = buffer.getElem(i);
268 return components;
271 public int getDataElement(int[] components, int offset)
273 if (getNumComponents()>1) throw new IllegalArgumentException();
274 return components[offset];
277 public Object getDataElements(int[] components, int offset, Object obj)
279 DataBuffer buffer = Buffers.createBuffer(transferType, obj,
280 getNumComponents());
281 int numComponents = getNumComponents();
283 for (int i=0; i<numComponents; i++)
284 buffer.setElem(i, components[offset++]);
286 return Buffers.getData(buffer);
289 public ColorModel coerceData(WritableRaster raster,
290 boolean isAlphaPremultiplied) {
291 if (this.isAlphaPremultiplied == isAlphaPremultiplied)
292 return this;
294 /* TODO: provide better implementation based on the
295 assumptions we can make due to the specific type of the
296 color model. */
297 super.coerceData(raster, isAlphaPremultiplied);
299 return new ComponentColorModel(cspace, bits, hasAlpha(),
300 isAlphaPremultiplied, // argument
301 transparency, transferType);
304 public boolean isCompatibleRaster(Raster raster)
306 return super.isCompatibleRaster(raster);
307 // FIXME: Should we test something more here? (Why override?)
310 public WritableRaster createCompatibleWritableRaster(int w, int h)
312 SampleModel sm = createCompatibleSampleModel(w, h);
313 Point origin = new Point(0, 0);
314 return Raster.createWritableRaster(sm, origin);
319 * Creates a <code>SampleModel</code> whose arrangement of pixel
320 * data is compatible to this <code>ColorModel</code>.
322 * @param w the number of pixels in the horizontal direction.
323 * @param h the number of pixels in the vertical direction.
325 public SampleModel createCompatibleSampleModel(int w, int h)
327 int pixelStride, scanlineStride;
328 int[] bandOffsets;
330 pixelStride = getNumComponents();
331 scanlineStride = pixelStride * w;
333 /* We might be able to re-use the same bandOffsets array among
334 * multiple calls to this method. However, this optimization does
335 * not seem worthwile because setting up descriptive data
336 * structures (such as SampleModels) is neglectible in comparision
337 * to shuffling around masses of pixel data.
339 bandOffsets = new int[pixelStride];
340 for (int i = 0; i < pixelStride; i++)
341 bandOffsets[i] = i;
343 /* FIXME: Think about whether it would make sense to return the
344 * possibly more efficient PixelInterleavedSampleModel for other
345 * transferTypes as well. It seems unlikely that this would break
346 * any user applications, so the Mauve tests on this method
347 * might be too restrictive.
349 switch (transferType)
351 case DataBuffer.TYPE_BYTE:
352 case DataBuffer.TYPE_USHORT:
353 return new PixelInterleavedSampleModel(transferType, w, h,
354 pixelStride,
355 scanlineStride,
356 bandOffsets);
358 default:
359 return new ComponentSampleModel(transferType, w, h,
360 pixelStride,
361 scanlineStride,
362 bandOffsets);
367 public boolean isCompatibleSampleModel(SampleModel sm)
369 return
370 (sm instanceof ComponentSampleModel) &&
371 super.isCompatibleSampleModel(sm);
374 public WritableRaster getAlphaRaster(WritableRaster raster)
376 if (!hasAlpha()) return null;
378 SampleModel sm = raster.getSampleModel();
379 int[] alphaBand = { sm.getNumBands() - 1 };
380 SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
381 DataBuffer buffer = raster.getDataBuffer();
382 Point origin = new Point(0, 0);
383 return Raster.createWritableRaster(alphaModel, buffer, origin);
386 public boolean equals(Object obj)
388 if (!(obj instanceof ComponentColorModel)) return false;
389 return super.equals(obj);