2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / awt / image / DirectColorModel.java
blob9444e831f8351d76cfb9f2e0104f4cc1f65e6094
1 /* Copyright (C) 1999, 2000, 2002 Free Software Foundation
3 This file is part of GNU Classpath.
5 GNU Classpath is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 GNU Classpath is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNU Classpath; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA.
20 Linking this library statically or dynamically with other modules is
21 making a combined work based on this library. Thus, the terms and
22 conditions of the GNU General Public License cover the whole
23 combination.
25 As a special exception, the copyright holders of this library give you
26 permission to link this library with independent modules to produce an
27 executable, regardless of the license terms of these independent
28 modules, and to copy and distribute the resulting executable under
29 terms of your choice, provided that you also meet, for each linked
30 independent module, the terms and conditions of the license of that
31 module. An independent module is a module which is not derived from
32 or based on this library. If you modify this library, you may extend
33 this exception to your version of the library, but you are not
34 obligated to do so. If you do not wish to do so, delete this
35 exception statement from your version. */
38 package java.awt.image;
40 import java.awt.Point;
41 import java.awt.Transparency;
42 import java.awt.color.ColorSpace;
43 import gnu.java.awt.Buffers;
45 /**
46 * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
47 * @author C. Brian Jones (cbj@gnu.org)
48 * @author Mark Benvenuto (mcb54@columbia.edu)
50 public class DirectColorModel extends PackedColorModel
52 /**
53 * For the color model created with this constructor the pixels
54 * will have fully opaque alpha components with a value of 255.
55 * Each mask should describe a fully contiguous set of bits in the
56 * most likely order of alpha, red, green, blue from the most significant
57 * byte to the least significant byte.
59 * @param bits the number of bits wide used for bit size of pixel values
60 * @param rmask the bits describing the red component of a pixel
61 * @param gmask the bits describing the green component of a pixel
62 * @param bmask the bits describing the blue component of a pixel
63 * @param amask the bits describing the alpha component of a pixel
65 public DirectColorModel(int pixelBits, int rmask, int gmask, int bmask)
67 this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
68 rmask, gmask, bmask, 0,
69 false, // not alpha premultiplied
70 Buffers.smallestAppropriateTransferType(pixelBits) // find type
74 /**
75 * For the color model created with this constructor the pixels
76 * will have fully opaque alpha components with a value of 255.
77 * Each mask should describe a fully contiguous set of bits in the
78 * most likely order of red, green, blue from the most significant
79 * byte to the least significant byte.
81 * @param bits the number of bits wide used for bit size of pixel values
82 * @param rmask the bits describing the red component of a pixel
83 * @param gmask the bits describing the green component of a pixel
84 * @param bmask the bits describing the blue component of a pixel
86 public DirectColorModel(int pixelBits,
87 int rmask, int gmask, int bmask, int amask)
89 this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
90 rmask, gmask, bmask, amask,
91 false, // not alpha premultiplied
92 Buffers.smallestAppropriateTransferType(pixelBits) // find type
96 public DirectColorModel(ColorSpace cspace, int pixelBits,
97 int rmask, int gmask, int bmask, int amask,
98 boolean isAlphaPremultiplied,
99 int transferType)
101 super(cspace, pixelBits,
102 rmask, gmask, bmask, amask, isAlphaPremultiplied,
103 ((amask == 0) ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
104 transferType);
107 public final int getRedMask()
109 return getMask(0);
112 public final int getGreenMask()
114 return getMask(1);
117 public final int getBlueMask()
119 return getMask(2);
122 public final int getAlphaMask()
124 return hasAlpha() ? getMask(3) : 0;
128 * Get the red component of the given pixel.
129 * <br>
131 public final int getRed(int pixel)
133 return extractAndNormalizeSample(pixel, 0);
137 * Get the green component of the given pixel.
138 * <br>
140 public final int getGreen(int pixel)
142 return extractAndNormalizeSample(pixel, 1);
146 * Get the blue component of the given pixel.
147 * <br>
149 public final int getBlue(int pixel)
151 return extractAndNormalizeSample(pixel, 2);
155 * Get the alpha component of the given pixel.
156 * <br>
158 public final int getAlpha(int pixel)
160 if (!hasAlpha())
161 return 0;
162 return extractAndScaleSample(pixel, 3);
165 private final int extractAndNormalizeSample(int pixel, int component)
167 int value = extractAndScaleSample(pixel, component);
168 if (hasAlpha() && isAlphaPremultiplied())
169 value = value*255/getAlpha(pixel);
170 return value;
173 private final int extractAndScaleSample(int pixel, int component)
175 int field = pixel & getMask(component);
176 int to8BitShift =
177 8 - shifts[component] - getComponentSize(component);
178 return (to8BitShift>0) ?
179 (field << to8BitShift) :
180 (field >>> (-to8BitShift));
184 * Get the RGB color value of the given pixel using the default
185 * RGB color model.
186 * <br>
188 * @param pixel a pixel value
190 public final int getRGB(int pixel)
192 /* FIXME: The Sun docs show that this method is overridden, but I
193 don't see any way to improve on the superclass
194 implementation. */
195 return super.getRGB(pixel);
198 public int getRed(Object inData)
200 return getRed(getPixelFromArray(inData));
203 public int getGreen(Object inData)
205 return getGreen(getPixelFromArray(inData));
208 public int getBlue(Object inData)
210 return getBlue(getPixelFromArray(inData));
213 public int getAlpha(Object inData)
215 return getAlpha(getPixelFromArray(inData));
218 public int getRGB(Object inData)
220 return getRGB(getPixelFromArray(inData));
224 * Converts a normalized pixel int value in the sRGB color
225 * space to an array containing a single pixel of the color space
226 * of the color model.
228 * <p>This method performs the inverse function of
229 * <code>getRGB(Object inData)</code>.
231 * @param rgb pixel as a normalized sRGB, 0xAARRGGBB value.
233 * @param pixel to avoid needless creation of arrays, an array to
234 * use to return the pixel can be given. If null, a suitable array
235 * will be created.
237 * @return array of transferType containing a single pixel. The
238 * pixel should be encoded in the natural way of the color model.
240 * @see #getRGB(Object)
242 public Object getDataElements(int rgb, Object pixel)
244 // FIXME: handle alpha multiply
246 int pixelValue = 0;
247 int a = 0;
248 if (hasAlpha()) {
249 a = (rgb >>> 24) & 0xff;
250 pixelValue = valueToField(a, 3, 8);
253 if (hasAlpha() && isAlphaPremultiplied())
255 int r, g, b;
256 /* if r=0xff and a=0xff, then resulting
257 value will be (r*a)>>>8 == 0xfe... This seems wrong.
258 We should divide by 255 rather than shifting >>>8 after
259 multiplying.
261 Too bad, shifting is probably less expensive.
262 r = ((rgb >>> 16) & 0xff)*a;
263 g = ((rgb >>> 8) & 0xff)*a;
264 b = ((rgb >>> 0) & 0xff)*a; */
265 /* The r, g, b values we calculate are 16 bit. This allows
266 us to avoid discarding the lower 8 bits obtained if
267 multiplying with the alpha band. */
269 // using 16 bit values
270 r = ((rgb >>> 8) & 0xff00)*a/255;
271 g = ((rgb >>> 0) & 0xff00)*a/255;
272 b = ((rgb << 8) & 0xff00)*a/255;
273 pixelValue |=
274 valueToField(r, 0, 16) | // Red
275 valueToField(g, 1, 16) | // Green
276 valueToField(b, 2, 16); // Blue
278 else
280 int r, g, b;
281 // using 8 bit values
282 r = (rgb >>> 16) & 0xff;
283 g = (rgb >>> 8) & 0xff;
284 b = (rgb >>> 0) & 0xff;
286 pixelValue |=
287 valueToField(r, 0, 8) | // Red
288 valueToField(g, 1, 8) | // Green
289 valueToField(b, 2, 8); // Blue
292 /* In this color model, the whole pixel fits in the first element
293 of the array. */
294 DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
295 buffer.setElem(0, pixelValue);
296 return Buffers.getData(buffer);
300 * Converts a value to the correct field bits based on the
301 * information derived from the field masks.
303 * @param highBit the position of the most significant bit in the
304 * val parameter.
306 private final int valueToField(int val, int component, int highBit)
308 int toFieldShift =
309 getComponentSize(component) + shifts[component] - highBit;
310 int ret = (toFieldShift>0) ?
311 (val << toFieldShift) :
312 (val >>> (-toFieldShift));
313 return ret & getMask(component);
317 * Converts a 16 bit value to the correct field bits based on the
318 * information derived from the field masks.
320 private final int value16ToField(int val, int component)
322 int toFieldShift = getComponentSize(component) + shifts[component] - 16;
323 return (toFieldShift>0) ?
324 (val << toFieldShift) :
325 (val >>> (-toFieldShift));
329 * Fills an array with the unnormalized component samples from a
330 * pixel value. I.e. decompose the pixel, but not perform any
331 * color conversion.
333 public final int[] getComponents(int pixel, int[] components, int offset)
335 int numComponents = getNumComponents();
336 if (components == null) components = new int[offset + numComponents];
338 for (int b=0; b<numComponents; b++)
339 components[offset++] = (pixel&getMask(b)) >>> shifts[b];
341 return components;
344 public final int[] getComponents(Object pixel, int[] components,
345 int offset)
347 return getComponents(getPixelFromArray(pixel), components, offset);
350 public final WritableRaster createCompatibleWritableRaster(int w, int h)
352 SampleModel sm = createCompatibleSampleModel(w, h);
353 Point origin = new Point(0, 0);
354 return Raster.createWritableRaster(sm, origin);
357 public int getDataElement(int[] components, int offset)
359 int numComponents = getNumComponents();
360 int pixelValue = 0;
362 for (int c=0; c<numComponents; c++)
363 pixelValue |= (components[offset++] << shifts[c]) & getMask(c);
365 return pixelValue;
368 public Object getDataElements(int[] components, int offset, Object obj)
370 /* In this color model, the whole pixel fits in the first element
371 of the array. */
372 int pixelValue = getDataElement(components, offset);
374 DataBuffer buffer = Buffers.createBuffer(transferType, obj, 1);
375 buffer.setElem(0, pixelValue);
376 return Buffers.getData(buffer);
379 public final ColorModel coerceData (WritableRaster raster,
380 boolean isAlphaPremultiplied)
382 if (this.isAlphaPremultiplied == isAlphaPremultiplied)
383 return this;
385 /* TODO: provide better implementation based on the
386 assumptions we can make due to the specific type of the
387 color model. */
388 super.coerceData(raster, isAlphaPremultiplied);
390 return new ComponentColorModel(cspace, bits, hasAlpha(),
391 isAlphaPremultiplied, // argument
392 transparency, transferType);
395 public boolean isCompatibleRaster(Raster raster)
397 /* FIXME: the Sun docs say this method is overridden here,
398 but I don't see any way to improve upon the implementation
399 in ColorModel. */
400 return super.isCompatibleRaster(raster);
403 String stringParam()
405 return super.stringParam() +
406 ", redMask=" + Integer.toHexString(getRedMask()) +
407 ", greenMask=" + Integer.toHexString(getGreenMask()) +
408 ", blueMask=" + Integer.toHexString(getBlueMask()) +
409 ", alphaMask=" + Integer.toHexString(getAlphaMask());
412 public String toString()
414 /* FIXME: Again, docs say override, but how do we improve upon the
415 superclass implementation? */
416 return super.toString();