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)
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
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
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
;
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
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
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
,
101 super(cspace
, pixelBits
,
102 rmask
, gmask
, bmask
, amask
, isAlphaPremultiplied
,
103 ((amask
== 0) ? Transparency
.OPAQUE
: Transparency
.TRANSLUCENT
),
107 public final int getRedMask()
112 public final int getGreenMask()
117 public final int getBlueMask()
122 public final int getAlphaMask()
124 return hasAlpha() ?
getMask(3) : 0;
128 * Get the red component of the given pixel.
131 public final int getRed(int pixel
)
133 return extractAndNormalizeSample(pixel
, 0);
137 * Get the green component of the given pixel.
140 public final int getGreen(int pixel
)
142 return extractAndNormalizeSample(pixel
, 1);
146 * Get the blue component of the given pixel.
149 public final int getBlue(int pixel
)
151 return extractAndNormalizeSample(pixel
, 2);
155 * Get the alpha component of the given pixel.
158 public final int getAlpha(int pixel
)
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
);
173 private final int extractAndScaleSample(int pixel
, int component
)
175 int field
= pixel
& getMask(component
);
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
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
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
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
249 a
= (rgb
>>> 24) & 0xff;
250 pixelValue
= valueToField(a
, 3, 8);
253 if (hasAlpha() && isAlphaPremultiplied())
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
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;
274 valueToField(r
, 0, 16) | // Red
275 valueToField(g
, 1, 16) | // Green
276 valueToField(b
, 2, 16); // Blue
281 // using 8 bit values
282 r
= (rgb
>>> 16) & 0xff;
283 g
= (rgb
>>> 8) & 0xff;
284 b
= (rgb
>>> 0) & 0xff;
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
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
306 private final int valueToField(int val
, int component
, int highBit
)
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
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
];
344 public final int[] getComponents(Object pixel
, int[] components
,
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();
362 for (int c
=0; c
<numComponents
; c
++)
363 pixelValue
|= (components
[offset
++] << shifts
[c
]) & getMask(c
);
368 public Object
getDataElements(int[] components
, int offset
, Object obj
)
370 /* In this color model, the whole pixel fits in the first element
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
)
385 /* TODO: provide better implementation based on the
386 assumptions we can make due to the specific type of the
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
400 return super.isCompatibleRaster(raster
);
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();