1 |
/* IndexColorModel.java -- Java class for interpreting Pixel objects |
/* IndexColorModel.java -- Java class for interpreting Pixel objects |
2 |
Copyright (C) 1999 Free Software Foundation, Inc. |
Copyright (C) 1999, 2005 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
35 |
obligated to do so. If you do not wish to do so, delete this |
obligated to do so. If you do not wish to do so, delete this |
36 |
exception statement from your version. */ |
exception statement from your version. */ |
37 |
|
|
|
|
|
38 |
package java.awt.image; |
package java.awt.image; |
39 |
|
|
40 |
|
import gnu.java.awt.Buffers; |
41 |
|
|
42 |
import java.awt.color.ColorSpace; |
import java.awt.color.ColorSpace; |
43 |
import java.math.BigInteger; |
import java.math.BigInteger; |
44 |
|
|
45 |
/** |
/** |
46 |
* Color model similar to pseudo visual in X11. |
* Color model similar to pseudo visual in X11. |
47 |
* |
* <br><br> |
48 |
* This color model maps linear pixel values to actual RGB and alpha colors. |
* This color model maps linear pixel values to actual RGB and alpha colors. |
49 |
* Thus, pixel values are indexes into the color map. Each color component is |
* Thus, pixel values are indexes into the color map. Each color component is |
50 |
* an 8-bit unsigned value. |
* an 8-bit unsigned value. |
51 |
* |
* <br><br> |
52 |
* The IndexColorModel supports a map of valid pixels, allowing the |
* The <code>IndexColorModel</code> supports a map of valid pixels, allowing |
53 |
* representation of holes in the the color map. The valid map is represented |
* the representation of holes in the the color map. The valid map is |
54 |
* as a BigInteger where each bit indicates the validity of the map entry with |
* represented as a {@link BigInteger} where each bit indicates the validity |
55 |
* the same index. |
* of the map entry with the same index. |
56 |
* |
* <br><br> |
57 |
* Colors can have alpha components for transparency support. If alpha |
* Colors can have alpha components for transparency support. If alpha |
58 |
* component values aren't given, color values are opaque. The model also |
* component values aren't given, color values are opaque. The model also |
59 |
* supports a reserved pixel value to represent completely transparent colors, |
* supports a reserved pixel value to represent completely transparent colors, |
60 |
* no matter what the actual color component values are. |
* no matter what the actual color component values are. |
61 |
* |
* <br><br> |
62 |
* IndexColorModel supports anywhere from 1 to 16 bit index values. The |
* <code>IndexColorModel</code> supports anywhere from 1 to 16 bit index |
63 |
* allowed transfer types are DataBuffer.TYPE_BYTE and DataBuffer.TYPE_USHORT. |
* values. The allowed transfer types are {@link DataBuffer#TYPE_BYTE} and |
64 |
|
* {@link DataBuffer#TYPE_USHORT}. |
65 |
* |
* |
66 |
* @author C. Brian Jones (cbj@gnu.org) |
* @author C. Brian Jones (cbj@gnu.org) |
67 |
*/ |
*/ |
68 |
public class IndexColorModel extends ColorModel |
public class IndexColorModel extends ColorModel |
69 |
{ |
{ |
70 |
private int map_size; |
private int map_size; |
71 |
private boolean opaque; |
private boolean opaque; // no alpha, but doesn't account for trans |
72 |
private int trans = -1; |
private int trans = -1; |
73 |
private int[] rgb; |
private int[] rgb; |
74 |
private BigInteger validBits = BigInteger.ZERO; |
private BigInteger validBits = BigInteger.ZERO; |
75 |
|
|
76 |
/** |
/** |
77 |
* Each array much contain <code>size</code> elements. For each |
* Creates a new indexed color model for <code>size</code> color elements |
78 |
* array, the i-th color is described by reds[i], greens[i], |
* with no alpha component. Each array must contain at least |
79 |
* blues[i], alphas[i], unless alphas is not specified, then all the |
* <code>size</code> elements. For each array, the i-th color is described |
80 |
* colors are opaque except for the transparent color. |
* by reds[i], greens[i] and blues[i]. |
81 |
* |
* |
82 |
* @param bits the number of bits needed to represent <code>size</code> colors |
* @param bits the number of bits needed to represent <code>size</code> |
83 |
* @param size the number of colors in the color map |
* colors. |
84 |
* @param reds the red component of all colors |
* @param size the number of colors in the color map. |
85 |
* @param greens the green component of all colors |
* @param reds the red component of all colors. |
86 |
* @param blues the blue component of all colors |
* @param greens the green component of all colors. |
87 |
|
* @param blues the blue component of all colors. |
88 |
|
* |
89 |
|
* @throws IllegalArgumentException if <code>bits</code> < 1 or |
90 |
|
* <code>bits</code> > 16. |
91 |
|
* @throws NullPointerException if any of the arrays is <code>null</code>. |
92 |
|
* @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater |
93 |
|
* than the length of the component arrays. |
94 |
*/ |
*/ |
95 |
public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, |
public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, |
96 |
byte[] blues) |
byte[] blues) |
97 |
{ |
{ |
98 |
this (bits, size, reds, greens, blues, (byte[]) null); |
this(bits, size, reds, greens, blues, (byte[]) null); |
99 |
} |
} |
100 |
|
|
101 |
/** |
/** |
102 |
* Each array much contain <code>size</code> elements. For each |
* Creates a new indexed color model for <code>size</code> color elements. |
103 |
* array, the i-th color is described by reds[i], greens[i], |
* Each array must contain at least <code>size</code> elements. For each |
104 |
* blues[i], alphas[i], unless alphas is not specified, then all the |
* array, the i-th color is described by reds[i], greens[i] and blues[i]. |
105 |
* colors are opaque except for the transparent color. |
* All the colors are opaque except for the transparent color. |
106 |
* |
* |
107 |
* @param bits the number of bits needed to represent <code>size</code> colors |
* @param bits the number of bits needed to represent <code>size</code> |
108 |
|
* colors |
109 |
* @param size the number of colors in the color map |
* @param size the number of colors in the color map |
110 |
* @param reds the red component of all colors |
* @param reds the red component of all colors |
111 |
* @param greens the green component of all colors |
* @param greens the green component of all colors |
112 |
* @param blues the blue component of all colors |
* @param blues the blue component of all colors |
113 |
* @param trans the index of the transparent color |
* @param trans the index of the transparent color (use -1 for no |
114 |
|
* transparent color). |
115 |
|
* |
116 |
|
* @throws IllegalArgumentException if <code>bits</code> < 1 or |
117 |
|
* <code>bits</code> > 16. |
118 |
|
* @throws NullPointerException if any of the arrays is <code>null</code>. |
119 |
|
* @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater |
120 |
|
* than the length of the component arrays. |
121 |
*/ |
*/ |
122 |
public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, |
public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, |
123 |
byte[] blues, int trans) |
byte[] blues, int trans) |
124 |
{ |
{ |
125 |
this (bits, size, reds, greens, blues, (byte[]) null); |
super(bits, nArray(8, (0 <= trans && trans < size) ? 4 : 3), |
126 |
this.trans = trans; |
ColorSpace.getInstance(ColorSpace.CS_sRGB), |
127 |
|
(0 <= trans && trans < size), // hasAlpha |
128 |
|
false, OPAQUE, |
129 |
|
Buffers.smallestAppropriateTransferType(bits)); |
130 |
|
if (bits < 1) |
131 |
|
throw new IllegalArgumentException("bits < 1"); |
132 |
|
if (bits > 16) |
133 |
|
throw new IllegalArgumentException("bits > 16"); |
134 |
|
if (size < 1) |
135 |
|
throw new IllegalArgumentException("size < 1"); |
136 |
|
map_size = size; |
137 |
|
if (0 <= trans && trans < size) { |
138 |
|
this.trans = trans; |
139 |
|
transparency = BITMASK; |
140 |
|
} |
141 |
|
rgb = new int[size]; |
142 |
|
for (int i = 0; i < size; i++) |
143 |
|
{ |
144 |
|
rgb[i] = (0xff000000 |
145 |
|
| ((reds[i] & 0xff) << 16) |
146 |
|
| ((greens[i] & 0xff) << 8) |
147 |
|
| (blues[i] & 0xff)); |
148 |
|
} |
149 |
|
// Generate a bigint with 1's for every pixel |
150 |
|
validBits = validBits.setBit(size).subtract(BigInteger.ONE); |
151 |
} |
} |
152 |
|
|
153 |
/** |
/** |
154 |
* Each array much contain <code>size</code> elements. For each |
* Creates a new indexed color model for <code>size</code> color elements |
155 |
* array, the i-th color is described by reds[i], greens[i], |
* including alpha. Each array must contain at least <code>size</code> |
156 |
* blues[i], alphas[i], unless alphas is not specified, then all the |
* elements. For each array, the i-th color is described |
157 |
* colors are opaque except for the transparent color. |
* by reds[i], greens[i], blues[i] and alphas[i]. |
158 |
* |
* |
159 |
* @param bits the number of bits needed to represent <code>size</code> colors |
* @param bits the number of bits needed to represent <code>size</code> |
160 |
* @param size the number of colors in the color map |
* colors. |
161 |
* @param reds the red component of all colors |
* @param size the number of colors in the color map. |
162 |
* @param greens the green component of all colors |
* @param reds the red component of all colors. |
163 |
* @param blues the blue component of all colors |
* @param greens the green component of all colors. |
164 |
* @param alphas the alpha component of all colors |
* @param blues the blue component of all colors. |
165 |
|
* @param alphas the alpha component of all colors (<code>null</code> |
166 |
|
* permitted). |
167 |
|
* |
168 |
|
* @throws IllegalArgumentException if <code>bits</code> < 1 or |
169 |
|
* <code>bits</code> > 16. |
170 |
|
* @throws NullPointerException if <code>reds</code>, <code>greens</code> or |
171 |
|
* <code>blues</code> is <code>null</code>. |
172 |
|
* @throws ArrayIndexOutOfBoundsException if <code>size</code> is greater |
173 |
|
* than the length of the component arrays. |
174 |
*/ |
*/ |
175 |
public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, |
public IndexColorModel(int bits, int size, byte[] reds, byte[] greens, |
176 |
byte[] blues, byte[] alphas) |
byte[] blues, byte[] alphas) |
177 |
{ |
{ |
178 |
// FIXME: This super() constructor should not be used since it can give |
super(bits, nArray(8, (alphas == null ? 3 : 4)), |
179 |
// the wrong value for hasAlpha() which is final and cannot be overloaded |
ColorSpace.getInstance(ColorSpace.CS_sRGB), |
180 |
super(bits); |
(alphas != null), false, TRANSLUCENT, |
181 |
|
Buffers.smallestAppropriateTransferType(bits)); |
182 |
|
if (bits < 1) |
183 |
|
throw new IllegalArgumentException("bits < 1"); |
184 |
|
if (bits > 16) |
185 |
|
throw new IllegalArgumentException("bits > 16"); |
186 |
|
if (size < 1) |
187 |
|
throw new IllegalArgumentException("size < 1"); |
188 |
map_size = size; |
map_size = size; |
189 |
opaque = (alphas == null); |
opaque = (alphas == null); |
190 |
|
|
198 |
| ((greens[i] & 0xff) << 8) |
| ((greens[i] & 0xff) << 8) |
199 |
| (blues[i] & 0xff)); |
| (blues[i] & 0xff)); |
200 |
} |
} |
201 |
|
transparency = OPAQUE; |
202 |
} |
} |
203 |
else |
else |
204 |
{ |
{ |
205 |
|
byte alphaZero = (byte) 0x00; |
206 |
|
byte alphaOne = (byte) 0xFF; |
207 |
for (int i = 0; i < size; i++) |
for (int i = 0; i < size; i++) |
208 |
{ |
{ |
209 |
|
alphaZero = (byte) (alphaZero | alphas[i]); |
210 |
|
alphaOne = (byte) (alphaOne & alphas[i]); |
211 |
rgb[i] = ((alphas[i] & 0xff) << 24 |
rgb[i] = ((alphas[i] & 0xff) << 24 |
212 |
| ((reds[i] & 0xff) << 16) |
| ((reds[i] & 0xff) << 16) |
213 |
| ((greens[i] & 0xff) << 8) |
| ((greens[i] & 0xff) << 8) |
214 |
| (blues[i] & 0xff)); |
| (blues[i] & 0xff)); |
215 |
} |
} |
216 |
|
if ((alphaZero == (byte) 0x00) || (alphaOne == (byte) 0xFF)) |
217 |
|
transparency = BITMASK; |
218 |
|
else |
219 |
|
transparency = TRANSLUCENT; |
220 |
} |
} |
221 |
|
|
222 |
// Generate a bigint with 1's for every pixel |
// Generate a bigint with 1's for every pixel |
224 |
} |
} |
225 |
|
|
226 |
/** |
/** |
227 |
* Each array much contain <code>size</code> elements. For each |
* Creates a new indexed color model using the color components in |
228 |
* array, the i-th color is described by reds[i], greens[i], |
* <code>cmap</code>. If <code>hasAlpha</code> is <code>true</code> then |
229 |
* blues[i], alphas[i], unless alphas is not specified, then all the |
* <code>cmap</code> contains an alpha component after each of the red, green |
230 |
* colors are opaque except for the transparent color. |
* and blue components. |
231 |
* |
* |
232 |
* @param bits the number of bits needed to represent <code>size</code> colors |
* @param bits the number of bits needed to represent <code>size</code> |
233 |
|
* colors |
234 |
* @param size the number of colors in the color map |
* @param size the number of colors in the color map |
235 |
* @param cmap packed color components |
* @param cmap packed color components |
236 |
* @param start the offset of the first color component in <code>cmap</code> |
* @param start the offset of the first color component in <code>cmap</code> |
237 |
* @param hasAlpha <code>cmap</code> has alpha values |
* @param hasAlpha <code>cmap</code> has alpha values |
238 |
* @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1. |
* @throws IllegalArgumentException if bits < 1, bits > 16, or size |
239 |
|
* < 1. |
240 |
|
* @throws NullPointerException if <code>cmap</code> is <code>null</code>. |
241 |
*/ |
*/ |
242 |
public IndexColorModel (int bits, int size, byte[] cmap, int start, |
public IndexColorModel(int bits, int size, byte[] cmap, int start, |
243 |
boolean hasAlpha) |
boolean hasAlpha) |
244 |
{ |
{ |
245 |
this (bits, size, cmap, start, hasAlpha, -1); |
this(bits, size, cmap, start, hasAlpha, -1); |
246 |
} |
} |
247 |
|
|
248 |
/** |
/** |
249 |
* Construct an IndexColorModel from an array of red, green, blue, and |
* Construct an IndexColorModel from an array of red, green, blue, and |
250 |
* optional alpha components. The component values are interleaved as RGB(A). |
* optional alpha components. The component values are interleaved as RGB(A). |
251 |
* |
* |
252 |
* @param bits the number of bits needed to represent <code>size</code> colors |
* @param bits the number of bits needed to represent <code>size</code> |
253 |
|
* colors |
254 |
* @param size the number of colors in the color map |
* @param size the number of colors in the color map |
255 |
* @param cmap interleaved color components |
* @param cmap interleaved color components |
256 |
* @param start the offset of the first color component in <code>cmap</code> |
* @param start the offset of the first color component in <code>cmap</code> |
257 |
* @param hasAlpha <code>cmap</code> has alpha values |
* @param hasAlpha <code>cmap</code> has alpha values |
258 |
* @param trans the index of the transparent color |
* @param trans the index of the transparent color |
259 |
* @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1. |
* @throws IllegalArgumentException if bits < 1, bits > 16, or size |
260 |
*/ |
* < 1. |
261 |
public IndexColorModel (int bits, int size, byte[] cmap, int start, |
* @throws NullPointerException if <code>cmap</code> is <code>null</code>. |
262 |
boolean hasAlpha, int trans) |
*/ |
263 |
{ |
public IndexColorModel(int bits, int size, byte[] cmap, int start, |
264 |
super (bits); |
boolean hasAlpha, int trans) |
265 |
|
{ |
266 |
|
super(bits, nArray(8, hasAlpha || (0 <= trans && trans < size) ? 4 : 3), |
267 |
|
ColorSpace.getInstance(ColorSpace.CS_sRGB), |
268 |
|
hasAlpha || (0 <= trans && trans < size), false, OPAQUE, |
269 |
|
Buffers.smallestAppropriateTransferType(bits)); |
270 |
|
if (bits < 1) |
271 |
|
throw new IllegalArgumentException("bits < 1"); |
272 |
if (bits > 16) |
if (bits > 16) |
273 |
throw new IllegalArgumentException("bits > 16"); |
throw new IllegalArgumentException("bits > 16"); |
274 |
if (size < 1) |
if (size < 1) |
275 |
throw new IllegalArgumentException("size < 1"); |
throw new IllegalArgumentException("size < 1"); |
276 |
map_size = size; |
map_size = size; |
277 |
opaque = !hasAlpha; |
opaque = !hasAlpha; |
278 |
this.trans = trans; |
if (0 <= trans && trans < size) |
279 |
|
this.trans = trans; |
280 |
|
|
281 |
rgb = new int[size]; |
rgb = new int[size]; |
282 |
if (hasAlpha) |
if (hasAlpha) |
283 |
{ |
{ |
284 |
for (int i = 0; i < size; i++) |
int alpha; |
285 |
|
int alphaZero = 0x00; // use to detect all zeros |
286 |
|
int alphaOne = 0xff; // use to detect all ones |
287 |
|
for (int i = 0; i < size; i++) { |
288 |
|
alpha = cmap[4 * i + 3 + start] & 0xff; |
289 |
|
alphaZero = alphaZero | alpha; |
290 |
|
alphaOne = alphaOne & alpha; |
291 |
rgb[i] = |
rgb[i] = |
292 |
// alpha |
( alpha << 24 |
|
((cmap[4 * i + 3 + start] & 0xff) << 24 |
|
293 |
// red |
// red |
294 |
| ((cmap[4 * i + start] & 0xff) << 16) |
| ((cmap[4 * i + start] & 0xff) << 16) |
295 |
// green |
// green |
296 |
| ((cmap[4 * i + 1 + start] & 0xff) << 8) |
| ((cmap[4 * i + 1 + start] & 0xff) << 8) |
297 |
// blue |
// blue |
298 |
| (cmap[4 * i + 2 + start] & 0xff)); |
| (cmap[4 * i + 2 + start] & 0xff)); |
299 |
|
} |
300 |
|
if (alphaZero == 0) |
301 |
|
transparency = BITMASK; |
302 |
|
else if (alphaOne == 255) |
303 |
|
transparency = (trans != -1 ? BITMASK : OPAQUE); |
304 |
|
else |
305 |
|
transparency = TRANSLUCENT; |
306 |
} |
} |
307 |
else |
else |
308 |
{ |
{ |
314 |
| ((cmap[3 * i + 1 + start] & 0xff) << 8) |
| ((cmap[3 * i + 1 + start] & 0xff) << 8) |
315 |
// blue |
// blue |
316 |
| (cmap[3 * i + 2 + start] & 0xff)); |
| (cmap[3 * i + 2 + start] & 0xff)); |
317 |
|
if (trans != -1) |
318 |
|
transparency = BITMASK; |
319 |
} |
} |
320 |
|
|
321 |
// Generate a bigint with 1's for every pixel |
// Generate a bigint with 1's for every pixel |
328 |
* alpha values packed in order. If hasAlpha is false, then all the colors |
* alpha values packed in order. If hasAlpha is false, then all the colors |
329 |
* are opaque except for the transparent color. |
* are opaque except for the transparent color. |
330 |
* |
* |
331 |
* @param bits the number of bits needed to represent <code>size</code> colors |
* @param bits the number of bits needed to represent <code>size</code> |
332 |
|
* colors |
333 |
* @param size the number of colors in the color map |
* @param size the number of colors in the color map |
334 |
* @param cmap packed color components |
* @param cmap packed color components |
335 |
* @param start the offset of the first color component in <code>cmap</code> |
* @param start the offset of the first color component in <code>cmap</code> |
336 |
* @param hasAlpha <code>cmap</code> has alpha values |
* @param hasAlpha <code>cmap</code> has alpha values |
337 |
* @param trans the index of the transparent color |
* @param trans the index of the transparent color |
338 |
* @param transferType DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT |
* @param transferType {@link DataBuffer#TYPE_BYTE} or |
339 |
* @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1. |
{@link DataBuffer#TYPE_USHORT}. |
340 |
* @throws IllegalArgumentException if transferType is something other than |
* @throws IllegalArgumentException if bits < 1, bits > 16, or size |
341 |
* TYPE_BYTE or TYPE_USHORT. |
* < 1. |
342 |
|
* @throws IllegalArgumentException if <code>transferType</code> is something |
343 |
|
* other than {@link DataBuffer#TYPE_BYTE} or |
344 |
|
* {@link DataBuffer#TYPE_USHORT}. |
345 |
*/ |
*/ |
346 |
public IndexColorModel (int bits, int size, int[] cmap, int start, |
public IndexColorModel(int bits, int size, int[] cmap, int start, |
347 |
boolean hasAlpha, int trans, int transferType) |
boolean hasAlpha, int trans, int transferType) |
348 |
{ |
{ |
349 |
super(bits * 4, // total bits, sRGB, four channels |
super(bits, |
350 |
nArray(bits, 4), // bits for each channel |
nArray(8, 4), // bits for each channel |
351 |
ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB |
ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB |
352 |
true, // has alpha |
true, // has alpha |
353 |
false, // not premultiplied |
false, // not premultiplied |
361 |
throw new IllegalArgumentException("size < 1"); |
throw new IllegalArgumentException("size < 1"); |
362 |
map_size = size; |
map_size = size; |
363 |
opaque = !hasAlpha; |
opaque = !hasAlpha; |
364 |
this.trans = trans; |
if (0 <= trans && trans < size) |
365 |
|
this.trans = trans; |
366 |
|
|
367 |
rgb = new int[size]; |
rgb = new int[size]; |
368 |
if (!hasAlpha) |
if (!hasAlpha) |
377 |
|
|
378 |
/** |
/** |
379 |
* Construct an IndexColorModel using a colormap with holes. |
* Construct an IndexColorModel using a colormap with holes. |
380 |
* |
* <br><br> |
381 |
* The IndexColorModel is built from the array of ints defining the |
* The IndexColorModel is built from the array of ints defining the |
382 |
* colormap. Each element contains red, green, blue, and alpha |
* colormap. Each element contains red, green, blue, and alpha |
383 |
* components. The ColorSpace is sRGB. The transparency value is |
* components. The ColorSpace is sRGB. The transparency value is |
384 |
* automatically determined. |
* automatically determined. |
385 |
* |
* <br><br> |
386 |
* This constructor permits indicating which colormap entries are valid, |
* This constructor permits indicating which colormap entries are valid, |
387 |
* using the validBits argument. Each entry in cmap is valid if the |
* using the validBits argument. Each entry in cmap is valid if the |
388 |
* corresponding bit in validBits is set. |
* corresponding bit in validBits is set. |
389 |
* |
* |
390 |
* @param bits the number of bits needed to represent <code>size</code> colors |
* @param bits the number of bits needed to represent <code>size</code> |
391 |
* @param size the number of colors in the color map |
* colors. |
392 |
* @param cmap packed color components |
* @param size the number of colors in the color map. |
393 |
* @param start the offset of the first color component in <code>cmap</code> |
* @param cmap packed color components. |
394 |
* @param transferType DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT |
* @param start the offset of the first color component in <code>cmap</code>. |
395 |
* @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1. |
* @param transferType {@link DataBuffer#TYPE_BYTE} or |
396 |
|
* {@link DataBuffer#TYPE_USHORT}. |
397 |
|
* @param validBits a map of the valid entries in <code>cmap</code>. |
398 |
|
* @throws IllegalArgumentException if bits < 1, bits > 16, or size |
399 |
|
* < 1. |
400 |
* @throws IllegalArgumentException if transferType is something other than |
* @throws IllegalArgumentException if transferType is something other than |
401 |
* TYPE_BYTE or TYPE_USHORT. |
* {@link DataBuffer#TYPE_BYTE} or {@link DataBuffer#TYPE_USHORT}. |
402 |
*/ |
*/ |
403 |
public IndexColorModel (int bits, int size, int[] cmap, int start, |
public IndexColorModel(int bits, int size, int[] cmap, int start, |
404 |
int transferType, BigInteger validBits) |
int transferType, BigInteger validBits) |
405 |
{ |
{ |
406 |
super(bits * 4, // total bits, sRGB, four channels |
super(bits, // total bits, sRGB, four channels |
407 |
nArray(bits, 4), // bits for each channel |
nArray(8, 4), // bits for each channel |
408 |
ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB |
ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB |
409 |
true, // has alpha |
true, // has alpha |
410 |
false, // not premultiplied |
false, // not premultiplied |
429 |
System.arraycopy(cmap, start, rgb, 0, size); |
System.arraycopy(cmap, start, rgb, 0, size); |
430 |
} |
} |
431 |
|
|
432 |
public final int getMapSize () |
/** |
433 |
|
* Returns the size of the color lookup table. |
434 |
|
* |
435 |
|
* @return The size of the color lookup table. |
436 |
|
*/ |
437 |
|
public final int getMapSize() |
438 |
{ |
{ |
439 |
return map_size; |
return map_size; |
440 |
} |
} |
441 |
|
|
442 |
/** |
/** |
443 |
* Get the index of the transparent color in this color model |
* Get the index of the transparent color in this color model. |
444 |
|
* |
445 |
|
* @return The index of the color that is considered transparent, or -1 if |
446 |
|
* there is no transparent color. |
447 |
*/ |
*/ |
448 |
public final int getTransparentPixel () |
public final int getTransparentPixel() |
449 |
{ |
{ |
450 |
return trans; |
return trans; |
451 |
} |
} |
452 |
|
|
453 |
/** |
/** |
454 |
* <br> |
* Fills the supplied array with the red component of each color in the |
455 |
|
* lookup table. |
456 |
|
* |
457 |
|
* @param r an array that is at least as large as {@link #getMapSize()}. |
458 |
|
* @throws NullPointerException if <code>r</code> is <code>null</code>. |
459 |
|
* @throws ArrayIndexOutOfBoundsException if <code>r</code> has less |
460 |
|
* than {@link #getMapSize()} elements. |
461 |
*/ |
*/ |
462 |
public final void getReds (byte[] r) |
public final void getReds(byte[] r) |
463 |
{ |
{ |
464 |
getComponents (r, 2); |
int i; |
465 |
|
for (i = 0; i < map_size; i++) |
466 |
|
r[i] = (byte) ((0x00FF0000 & rgb[i]) >> 16); |
467 |
} |
} |
468 |
|
|
469 |
/** |
/** |
470 |
* <br> |
* Fills the supplied array with the green component of each color in the |
471 |
|
* lookup table. |
472 |
|
* |
473 |
|
* @param g an array that is at least as large as {@link #getMapSize()}. |
474 |
|
* @throws NullPointerException if <code>g</code> is <code>null</code>. |
475 |
|
* @throws ArrayIndexOutOfBoundsException if <code>g</code> has less |
476 |
|
* than {@link #getMapSize()} elements. |
477 |
*/ |
*/ |
478 |
public final void getGreens (byte[] g) |
public final void getGreens(byte[] g) |
479 |
{ |
{ |
480 |
getComponents (g, 1); |
int i; |
481 |
|
for (i = 0; i < map_size; i++) |
482 |
|
g[i] = (byte) ((0x0000FF00 & rgb[i]) >> 8); |
483 |
} |
} |
484 |
|
|
485 |
/** |
/** |
486 |
* <br> |
* Fills the supplied array with the blue component of each color in the |
487 |
|
* lookup table. |
488 |
|
* |
489 |
|
* @param b an array that is at least as large as {@link #getMapSize()}. |
490 |
|
* @throws NullPointerException if <code>b</code> is <code>null</code>. |
491 |
|
* @throws ArrayIndexOutOfBoundsException if <code>b</code> has less |
492 |
|
* than {@link #getMapSize()} elements. |
493 |
*/ |
*/ |
494 |
public final void getBlues (byte[] b) |
public final void getBlues(byte[] b) |
495 |
{ |
{ |
496 |
getComponents (b, 0); |
int i; |
497 |
|
for (i = 0; i < map_size; i++) |
498 |
|
b[i] = (byte) (0x000000FF & rgb[i]); |
499 |
} |
} |
500 |
|
|
501 |
/** |
/** |
502 |
* <br> |
* Fills the supplied array with the alpha component of each color in the |
503 |
|
* lookup table. If the model has a transparent pixel specified, the alpha |
504 |
|
* for that pixel will be 0. |
505 |
|
* |
506 |
|
* @param a an array that is at least as large as {@link #getMapSize()}. |
507 |
|
* @throws NullPointerException if <code>a</code> is <code>null</code>. |
508 |
|
* @throws ArrayIndexOutOfBoundsException if <code>a</code> has less |
509 |
|
* than {@link #getMapSize()} elements. |
510 |
*/ |
*/ |
511 |
public final void getAlphas (byte[] a) |
public final void getAlphas(byte[] a) |
512 |
{ |
{ |
513 |
getComponents (a, 3); |
int i; |
514 |
|
for (i = 0; i < map_size; i++) |
515 |
|
if (i == trans) |
516 |
|
a[i] = (byte) 0; |
517 |
|
else |
518 |
|
a[i] = (byte) ((0xFF000000 & rgb[i]) >> 24); |
519 |
} |
} |
520 |
|
|
|
private void getComponents (byte[] c, int ci) |
|
|
{ |
|
|
int i, max = (map_size < c.length) ? map_size : c.length; |
|
|
for (i = 0; i < max; i++) |
|
|
c[i] = (byte) ((generateMask (ci) & rgb[i]) >> (ci * pixel_bits)); |
|
|
} |
|
|
|
|
521 |
/** |
/** |
522 |
* Get the red component of the given pixel. |
* Returns the red component of the color in the lookup table for the |
523 |
|
* given pixel value. |
524 |
|
* |
525 |
|
* @param pixel the pixel lookup value. |
526 |
|
* |
527 |
|
* @return The red component of the color in the lookup table. |
528 |
|
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. |
529 |
*/ |
*/ |
530 |
public final int getRed (int pixel) |
public final int getRed(int pixel) |
531 |
{ |
{ |
532 |
if (pixel < map_size) |
if (pixel < map_size) |
533 |
return (int) ((generateMask (2) & rgb[pixel]) >> (2 * pixel_bits)); |
return (0x00FF0000 & rgb[pixel]) >> 16; |
534 |
|
|
535 |
return 0; |
return 0; |
536 |
} |
} |
537 |
|
|
538 |
/** |
/** |
539 |
* Get the green component of the given pixel. |
* Returns the green component of the color in the lookup table for the |
540 |
|
* given pixel value. |
541 |
|
* |
542 |
|
* @param pixel the pixel lookup value. |
543 |
|
* |
544 |
|
* @return The green component of the color in the lookup table. |
545 |
|
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. |
546 |
*/ |
*/ |
547 |
public final int getGreen (int pixel) |
public final int getGreen(int pixel) |
548 |
{ |
{ |
549 |
if (pixel < map_size) |
if (pixel < map_size) |
550 |
return (int) ((generateMask (1) & rgb[pixel]) >> (1 * pixel_bits)); |
return (0x0000FF00 & rgb[pixel]) >> 8; |
551 |
|
|
552 |
return 0; |
return 0; |
553 |
} |
} |
554 |
|
|
555 |
/** |
/** |
556 |
* Get the blue component of the given pixel. |
* Returns the blue component of the color in the lookup table for the |
557 |
|
* given pixel value. |
558 |
|
* |
559 |
|
* @param pixel the pixel lookup value. |
560 |
|
* |
561 |
|
* @return The blue component of the color in the lookup table. |
562 |
|
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. |
563 |
*/ |
*/ |
564 |
public final int getBlue (int pixel) |
public final int getBlue(int pixel) |
565 |
{ |
{ |
566 |
if (pixel < map_size) |
if (pixel < map_size) |
567 |
return (int) (generateMask (0) & rgb[pixel]); |
return 0x000000FF & rgb[pixel]; |
568 |
|
|
569 |
return 0; |
return 0; |
570 |
} |
} |
571 |
|
|
572 |
/** |
/** |
573 |
* Get the alpha component of the given pixel. |
* Returns the alpha component of the color in the lookup table for the |
574 |
|
* given pixel value. If no alpha channel was specified when the color model |
575 |
|
* was created, then 255 is returned for all pixels except the transparent |
576 |
|
* pixel (if one is defined - see {@link #getTransparentPixel()}) which |
577 |
|
* returns an alpha of 0. |
578 |
|
* |
579 |
|
* @param pixel the pixel lookup value. |
580 |
|
* |
581 |
|
* @return The alpha component of the color in the lookup table (in the |
582 |
|
* range 0 to 255). |
583 |
|
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. |
584 |
*/ |
*/ |
585 |
public final int getAlpha (int pixel) |
public final int getAlpha(int pixel) |
586 |
{ |
{ |
587 |
if (opaque || pixel >= map_size) |
if (opaque && pixel != trans) |
588 |
return 255; |
return 255; |
589 |
|
if ((pixel == trans && trans != -1) || pixel >= map_size) |
590 |
|
return 0; |
591 |
|
|
592 |
return (int) ((generateMask (3) & rgb[pixel]) >> (3 * pixel_bits)); |
return (0xFF000000 & rgb[pixel]) >> 24; |
593 |
} |
} |
594 |
|
|
595 |
/** |
/** |
596 |
* Get the RGB color value of the given pixel using the default |
* Get the RGB color value of the given pixel using the default |
597 |
* RGB color model. |
* RGB color model. |
598 |
* |
* |
599 |
* @param pixel a pixel value |
* @param pixel the pixel lookup value. |
600 |
|
* @return The RGB color value. |
601 |
|
* @throws ArrayIndexOutOfBoundsException if <code>pixel</code> is negative. |
602 |
*/ |
*/ |
603 |
public final int getRGB (int pixel) |
public final int getRGB(int pixel) |
604 |
{ |
{ |
605 |
if (pixel >= 0 && pixel < map_size) |
if (pixel >= 0 && pixel < map_size) |
606 |
return rgb[pixel]; |
return rgb[pixel]; |
607 |
|
|
608 |
return 0; |
return 0; |
609 |
} |
} |
614 |
* |
* |
615 |
* @param rgb The destination array. |
* @param rgb The destination array. |
616 |
*/ |
*/ |
617 |
public final void getRGBs (int[] rgb) |
public final void getRGBs(int[] rgb) |
618 |
{ |
{ |
619 |
System.arraycopy(this.rgb, 0, rgb, 0, map_size); |
System.arraycopy(this.rgb, 0, rgb, 0, map_size); |
620 |
} |
} |
621 |
|
|
622 |
//pixel_bits is number of bits to be in generated mask |
/** |
623 |
private int generateMask (int offset) |
* Return <code>true</code> if the lookup table contains valid data for |
624 |
{ |
* <code>pixel</code>, and <code>false</code> otherwise. |
625 |
return (((2 << pixel_bits ) - 1) << (pixel_bits * offset)); |
* |
626 |
} |
* @param pixel the pixel value used to index the color lookup table. |
627 |
|
* @return <code>true</code> if <code>pixel</code> is valid, |
628 |
/** Return true if pixel is valid, false otherwise. */ |
* <code>false</code> otherwise. |
629 |
|
*/ |
630 |
public boolean isValid(int pixel) |
public boolean isValid(int pixel) |
631 |
{ |
{ |
632 |
return validBits.testBit(pixel); |
if (pixel >= 0) |
633 |
|
return validBits.testBit(pixel); |
634 |
|
return false; |
635 |
} |
} |
636 |
|
|
637 |
/** Return true if all pixels are valid, false otherwise. */ |
/** |
638 |
|
* Return <code>true</code> if all pixels are valid, <code>false</code> |
639 |
|
* otherwise. |
640 |
|
* |
641 |
|
* @return <code>true</code> if all pixels are valid, <code>false</code> |
642 |
|
* otherwise. |
643 |
|
*/ |
644 |
public boolean isValid() |
public boolean isValid() |
645 |
{ |
{ |
646 |
// Generate a bigint with 1's for every pixel |
// Generate a bigint with 1's for every pixel |
647 |
BigInteger allbits = new BigInteger("0"); |
BigInteger allbits = new BigInteger("0"); |
648 |
allbits.setBit(map_size); |
allbits = allbits.setBit(map_size); |
649 |
allbits.subtract(new BigInteger("1")); |
allbits = allbits.subtract(new BigInteger("1")); |
650 |
return allbits.equals(validBits); |
return allbits.equals(validBits); |
651 |
} |
} |
652 |
|
|
653 |
/** |
/** |
654 |
* Returns a BigInteger where each bit represents an entry in the color |
* Returns a binary value ({@link BigInteger}) where each bit represents an |
655 |
* model. If the bit is on, the entry is valid. |
* entry in the color lookup table. If the bit is on, the entry is valid. |
656 |
|
* |
657 |
|
* @return The binary value. |
658 |
*/ |
*/ |
659 |
public BigInteger getValidPixels() |
public BigInteger getValidPixels() |
660 |
{ |
{ |
662 |
} |
} |
663 |
|
|
664 |
/** |
/** |
665 |
* Construct a BufferedImage with rgb pixel values from a Raster. |
* Construct a {@link BufferedImage} with rgb pixel values from a |
666 |
|
* {@link Raster}. |
667 |
* |
* |
668 |
* Constructs a new BufferedImage in which each pixel is an RGBA int from |
* Constructs a new BufferedImage in which each pixel is an RGBA int from |
669 |
* a Raster with index-valued pixels. If this model has no alpha component |
* a Raster with index-valued pixels. If this model has no alpha component |
695 |
return im; |
return im; |
696 |
} |
} |
697 |
} |
} |
|
|
|