|
1 /* |
|
2 * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 package java.awt.image; |
|
27 |
|
28 import java.awt.Transparency; |
|
29 import java.awt.color.ColorSpace; |
|
30 import java.math.BigInteger; |
|
31 import java.util.Arrays; |
|
32 |
|
33 /** |
|
34 * The {@code IndexColorModel} class is a {@code ColorModel} |
|
35 * class that works with pixel values consisting of a |
|
36 * single sample that is an index into a fixed colormap in the default |
|
37 * sRGB color space. The colormap specifies red, green, blue, and |
|
38 * optional alpha components corresponding to each index. All components |
|
39 * are represented in the colormap as 8-bit unsigned integral values. |
|
40 * Some constructors allow the caller to specify "holes" in the colormap |
|
41 * by indicating which colormap entries are valid and which represent |
|
42 * unusable colors via the bits set in a {@code BigInteger} object. |
|
43 * This color model is similar to an X11 PseudoColor visual. |
|
44 * <p> |
|
45 * Some constructors provide a means to specify an alpha component |
|
46 * for each pixel in the colormap, while others either provide no |
|
47 * such means or, in some cases, a flag to indicate whether the |
|
48 * colormap data contains alpha values. If no alpha is supplied to |
|
49 * the constructor, an opaque alpha component (alpha = 1.0) is |
|
50 * assumed for each entry. |
|
51 * An optional transparent pixel value can be supplied that indicates a |
|
52 * pixel to be made completely transparent, regardless of any alpha |
|
53 * component supplied or assumed for that pixel value. |
|
54 * Note that the color components in the colormap of an |
|
55 * {@code IndexColorModel} objects are never pre-multiplied with |
|
56 * the alpha components. |
|
57 * <p> |
|
58 * <a id="transparency"> |
|
59 * The transparency of an {@code IndexColorModel} object is |
|
60 * determined by examining the alpha components of the colors in the |
|
61 * colormap and choosing the most specific value after considering |
|
62 * the optional alpha values and any transparent index specified. |
|
63 * The transparency value is {@code Transparency.OPAQUE} |
|
64 * only if all valid colors in |
|
65 * the colormap are opaque and there is no valid transparent pixel. |
|
66 * If all valid colors |
|
67 * in the colormap are either completely opaque (alpha = 1.0) or |
|
68 * completely transparent (alpha = 0.0), which typically occurs when |
|
69 * a valid transparent pixel is specified, |
|
70 * the value is {@code Transparency.BITMASK}. |
|
71 * Otherwise, the value is {@code Transparency.TRANSLUCENT}, indicating |
|
72 * that some valid color has an alpha component that is |
|
73 * neither completely transparent nor completely opaque |
|
74 * (0.0 < alpha < 1.0). |
|
75 * </a> |
|
76 * |
|
77 * <p> |
|
78 * If an {@code IndexColorModel} object has |
|
79 * a transparency value of {@code Transparency.OPAQUE}, |
|
80 * then the {@code hasAlpha} |
|
81 * and {@code getNumComponents} methods |
|
82 * (both inherited from {@code ColorModel}) |
|
83 * return false and 3, respectively. |
|
84 * For any other transparency value, |
|
85 * {@code hasAlpha} returns true |
|
86 * and {@code getNumComponents} returns 4. |
|
87 * |
|
88 * <p> |
|
89 * <a id="index_values"> |
|
90 * The values used to index into the colormap are taken from the least |
|
91 * significant <em>n</em> bits of pixel representations where |
|
92 * <em>n</em> is based on the pixel size specified in the constructor. |
|
93 * For pixel sizes smaller than 8 bits, <em>n</em> is rounded up to a |
|
94 * power of two (3 becomes 4 and 5,6,7 become 8). |
|
95 * For pixel sizes between 8 and 16 bits, <em>n</em> is equal to the |
|
96 * pixel size. |
|
97 * Pixel sizes larger than 16 bits are not supported by this class. |
|
98 * Higher order bits beyond <em>n</em> are ignored in pixel representations. |
|
99 * Index values greater than or equal to the map size, but less than |
|
100 * 2<sup><em>n</em></sup>, are undefined and return 0 for all color and |
|
101 * alpha components. |
|
102 * </a> |
|
103 * <p> |
|
104 * For those methods that use a primitive array pixel representation of |
|
105 * type {@code transferType}, the array length is always one. |
|
106 * The transfer types supported are {@code DataBuffer.TYPE_BYTE} and |
|
107 * {@code DataBuffer.TYPE_USHORT}. A single int pixel |
|
108 * representation is valid for all objects of this class, since it is |
|
109 * always possible to represent pixel values used with this class in a |
|
110 * single int. Therefore, methods that use this representation do |
|
111 * not throw an {@code IllegalArgumentException} due to an invalid |
|
112 * pixel value. |
|
113 * <p> |
|
114 * Many of the methods in this class are final. The reason for |
|
115 * this is that the underlying native graphics code makes assumptions |
|
116 * about the layout and operation of this class and those assumptions |
|
117 * are reflected in the implementations of the methods here that are |
|
118 * marked final. You can subclass this class for other reasons, but |
|
119 * you cannot override or modify the behaviour of those methods. |
|
120 * |
|
121 * @see ColorModel |
|
122 * @see ColorSpace |
|
123 * @see DataBuffer |
|
124 * |
|
125 */ |
|
126 public class IndexColorModel extends ColorModel { |
|
127 private int rgb[]; |
|
128 private int map_size; |
|
129 private int pixel_mask; |
|
130 private int transparent_index = -1; |
|
131 private boolean allgrayopaque; |
|
132 private BigInteger validBits; |
|
133 private volatile int hashCode; |
|
134 |
|
135 private sun.awt.image.BufImgSurfaceData.ICMColorData colorData = null; |
|
136 |
|
137 private static int[] opaqueBits = {8, 8, 8}; |
|
138 private static int[] alphaBits = {8, 8, 8, 8}; |
|
139 |
|
140 private static native void initIDs(); |
|
141 static { |
|
142 ColorModel.loadLibraries(); |
|
143 initIDs(); |
|
144 } |
|
145 /** |
|
146 * Constructs an {@code IndexColorModel} from the specified |
|
147 * arrays of red, green, and blue components. Pixels described |
|
148 * by this color model all have alpha components of 255 |
|
149 * unnormalized (1.0 normalized), which means they |
|
150 * are fully opaque. All of the arrays specifying the color |
|
151 * components must have at least the specified number of entries. |
|
152 * The {@code ColorSpace} is the default sRGB space. |
|
153 * Since there is no alpha information in any of the arguments |
|
154 * to this constructor, the transparency value is always |
|
155 * {@code Transparency.OPAQUE}. |
|
156 * The transfer type is the smallest of {@code DataBuffer.TYPE_BYTE} |
|
157 * or {@code DataBuffer.TYPE_USHORT} that can hold a single pixel. |
|
158 * @param bits the number of bits each pixel occupies |
|
159 * @param size the size of the color component arrays |
|
160 * @param r the array of red color components |
|
161 * @param g the array of green color components |
|
162 * @param b the array of blue color components |
|
163 * @throws IllegalArgumentException if {@code bits} is less |
|
164 * than 1 or greater than 16 |
|
165 * @throws IllegalArgumentException if {@code size} is less |
|
166 * than 1 |
|
167 */ |
|
168 public IndexColorModel(int bits, int size, |
|
169 byte r[], byte g[], byte b[]) { |
|
170 super(bits, opaqueBits, |
|
171 ColorSpace.getInstance(ColorSpace.CS_sRGB), |
|
172 false, false, OPAQUE, |
|
173 ColorModel.getDefaultTransferType(bits)); |
|
174 if (bits < 1 || bits > 16) { |
|
175 throw new IllegalArgumentException("Number of bits must be between" |
|
176 +" 1 and 16."); |
|
177 } |
|
178 setRGBs(size, r, g, b, null); |
|
179 calculatePixelMask(); |
|
180 } |
|
181 |
|
182 /** |
|
183 * Constructs an {@code IndexColorModel} from the given arrays |
|
184 * of red, green, and blue components. Pixels described by this color |
|
185 * model all have alpha components of 255 unnormalized |
|
186 * (1.0 normalized), which means they are fully opaque, except |
|
187 * for the indicated pixel to be made transparent. All of the arrays |
|
188 * specifying the color components must have at least the specified |
|
189 * number of entries. |
|
190 * The {@code ColorSpace} is the default sRGB space. |
|
191 * The transparency value may be {@code Transparency.OPAQUE} or |
|
192 * {@code Transparency.BITMASK} depending on the arguments, as |
|
193 * specified in the <a href="#transparency">class description</a> above. |
|
194 * The transfer type is the smallest of {@code DataBuffer.TYPE_BYTE} |
|
195 * or {@code DataBuffer.TYPE_USHORT} that can hold a |
|
196 * single pixel. |
|
197 * @param bits the number of bits each pixel occupies |
|
198 * @param size the size of the color component arrays |
|
199 * @param r the array of red color components |
|
200 * @param g the array of green color components |
|
201 * @param b the array of blue color components |
|
202 * @param trans the index of the transparent pixel |
|
203 * @throws IllegalArgumentException if {@code bits} is less than |
|
204 * 1 or greater than 16 |
|
205 * @throws IllegalArgumentException if {@code size} is less than |
|
206 * 1 |
|
207 */ |
|
208 public IndexColorModel(int bits, int size, |
|
209 byte r[], byte g[], byte b[], int trans) { |
|
210 super(bits, opaqueBits, |
|
211 ColorSpace.getInstance(ColorSpace.CS_sRGB), |
|
212 false, false, OPAQUE, |
|
213 ColorModel.getDefaultTransferType(bits)); |
|
214 if (bits < 1 || bits > 16) { |
|
215 throw new IllegalArgumentException("Number of bits must be between" |
|
216 +" 1 and 16."); |
|
217 } |
|
218 setRGBs(size, r, g, b, null); |
|
219 setTransparentPixel(trans); |
|
220 calculatePixelMask(); |
|
221 } |
|
222 |
|
223 /** |
|
224 * Constructs an {@code IndexColorModel} from the given |
|
225 * arrays of red, green, blue and alpha components. All of the |
|
226 * arrays specifying the components must have at least the specified |
|
227 * number of entries. |
|
228 * The {@code ColorSpace} is the default sRGB space. |
|
229 * The transparency value may be any of {@code Transparency.OPAQUE}, |
|
230 * {@code Transparency.BITMASK}, |
|
231 * or {@code Transparency.TRANSLUCENT} |
|
232 * depending on the arguments, as specified |
|
233 * in the <a href="#transparency">class description</a> above. |
|
234 * The transfer type is the smallest of {@code DataBuffer.TYPE_BYTE} |
|
235 * or {@code DataBuffer.TYPE_USHORT} that can hold a single pixel. |
|
236 * @param bits the number of bits each pixel occupies |
|
237 * @param size the size of the color component arrays |
|
238 * @param r the array of red color components |
|
239 * @param g the array of green color components |
|
240 * @param b the array of blue color components |
|
241 * @param a the array of alpha value components |
|
242 * @throws IllegalArgumentException if {@code bits} is less |
|
243 * than 1 or greater than 16 |
|
244 * @throws IllegalArgumentException if {@code size} is less |
|
245 * than 1 |
|
246 */ |
|
247 public IndexColorModel(int bits, int size, |
|
248 byte r[], byte g[], byte b[], byte a[]) { |
|
249 super (bits, alphaBits, |
|
250 ColorSpace.getInstance(ColorSpace.CS_sRGB), |
|
251 true, false, TRANSLUCENT, |
|
252 ColorModel.getDefaultTransferType(bits)); |
|
253 if (bits < 1 || bits > 16) { |
|
254 throw new IllegalArgumentException("Number of bits must be between" |
|
255 +" 1 and 16."); |
|
256 } |
|
257 setRGBs (size, r, g, b, a); |
|
258 calculatePixelMask(); |
|
259 } |
|
260 |
|
261 /** |
|
262 * Constructs an {@code IndexColorModel} from a single |
|
263 * array of interleaved red, green, blue and optional alpha |
|
264 * components. The array must have enough values in it to |
|
265 * fill all of the needed component arrays of the specified |
|
266 * size. The {@code ColorSpace} is the default sRGB space. |
|
267 * The transparency value may be any of {@code Transparency.OPAQUE}, |
|
268 * {@code Transparency.BITMASK}, |
|
269 * or {@code Transparency.TRANSLUCENT} |
|
270 * depending on the arguments, as specified |
|
271 * in the <a href="#transparency">class description</a> above. |
|
272 * The transfer type is the smallest of |
|
273 * {@code DataBuffer.TYPE_BYTE} or {@code DataBuffer.TYPE_USHORT} |
|
274 * that can hold a single pixel. |
|
275 * |
|
276 * @param bits the number of bits each pixel occupies |
|
277 * @param size the size of the color component arrays |
|
278 * @param cmap the array of color components |
|
279 * @param start the starting offset of the first color component |
|
280 * @param hasalpha indicates whether alpha values are contained in |
|
281 * the {@code cmap} array |
|
282 * @throws IllegalArgumentException if {@code bits} is less |
|
283 * than 1 or greater than 16 |
|
284 * @throws IllegalArgumentException if {@code size} is less |
|
285 * than 1 |
|
286 */ |
|
287 public IndexColorModel(int bits, int size, byte cmap[], int start, |
|
288 boolean hasalpha) { |
|
289 this(bits, size, cmap, start, hasalpha, -1); |
|
290 if (bits < 1 || bits > 16) { |
|
291 throw new IllegalArgumentException("Number of bits must be between" |
|
292 +" 1 and 16."); |
|
293 } |
|
294 } |
|
295 |
|
296 /** |
|
297 * Constructs an {@code IndexColorModel} from a single array of |
|
298 * interleaved red, green, blue and optional alpha components. The |
|
299 * specified transparent index represents a pixel that is made |
|
300 * entirely transparent regardless of any alpha value specified |
|
301 * for it. The array must have enough values in it to fill all |
|
302 * of the needed component arrays of the specified size. |
|
303 * The {@code ColorSpace} is the default sRGB space. |
|
304 * The transparency value may be any of {@code Transparency.OPAQUE}, |
|
305 * {@code Transparency.BITMASK}, |
|
306 * or {@code Transparency.TRANSLUCENT} |
|
307 * depending on the arguments, as specified |
|
308 * in the <a href="#transparency">class description</a> above. |
|
309 * The transfer type is the smallest of |
|
310 * {@code DataBuffer.TYPE_BYTE} or {@code DataBuffer.TYPE_USHORT} |
|
311 * that can hold a single pixel. |
|
312 * @param bits the number of bits each pixel occupies |
|
313 * @param size the size of the color component arrays |
|
314 * @param cmap the array of color components |
|
315 * @param start the starting offset of the first color component |
|
316 * @param hasalpha indicates whether alpha values are contained in |
|
317 * the {@code cmap} array |
|
318 * @param trans the index of the fully transparent pixel |
|
319 * @throws IllegalArgumentException if {@code bits} is less than |
|
320 * 1 or greater than 16 |
|
321 * @throws IllegalArgumentException if {@code size} is less than |
|
322 * 1 |
|
323 */ |
|
324 public IndexColorModel(int bits, int size, byte cmap[], int start, |
|
325 boolean hasalpha, int trans) { |
|
326 // REMIND: This assumes the ordering: RGB[A] |
|
327 super(bits, opaqueBits, |
|
328 ColorSpace.getInstance(ColorSpace.CS_sRGB), |
|
329 false, false, OPAQUE, |
|
330 ColorModel.getDefaultTransferType(bits)); |
|
331 |
|
332 if (bits < 1 || bits > 16) { |
|
333 throw new IllegalArgumentException("Number of bits must be between" |
|
334 +" 1 and 16."); |
|
335 } |
|
336 if (size < 1) { |
|
337 throw new IllegalArgumentException("Map size ("+size+ |
|
338 ") must be >= 1"); |
|
339 } |
|
340 map_size = size; |
|
341 rgb = new int[calcRealMapSize(bits, size)]; |
|
342 int j = start; |
|
343 int alpha = 0xff; |
|
344 boolean allgray = true; |
|
345 int transparency = OPAQUE; |
|
346 for (int i = 0; i < size; i++) { |
|
347 int r = cmap[j++] & 0xff; |
|
348 int g = cmap[j++] & 0xff; |
|
349 int b = cmap[j++] & 0xff; |
|
350 allgray = allgray && (r == g) && (g == b); |
|
351 if (hasalpha) { |
|
352 alpha = cmap[j++] & 0xff; |
|
353 if (alpha != 0xff) { |
|
354 if (alpha == 0x00) { |
|
355 if (transparency == OPAQUE) { |
|
356 transparency = BITMASK; |
|
357 } |
|
358 if (transparent_index < 0) { |
|
359 transparent_index = i; |
|
360 } |
|
361 } else { |
|
362 transparency = TRANSLUCENT; |
|
363 } |
|
364 allgray = false; |
|
365 } |
|
366 } |
|
367 rgb[i] = (alpha << 24) | (r << 16) | (g << 8) | b; |
|
368 } |
|
369 this.allgrayopaque = allgray; |
|
370 setTransparency(transparency); |
|
371 setTransparentPixel(trans); |
|
372 calculatePixelMask(); |
|
373 } |
|
374 |
|
375 /** |
|
376 * Constructs an {@code IndexColorModel} from an array of |
|
377 * ints where each int is comprised of red, green, blue, and |
|
378 * optional alpha components in the default RGB color model format. |
|
379 * The specified transparent index represents a pixel that is made |
|
380 * entirely transparent regardless of any alpha value specified |
|
381 * for it. The array must have enough values in it to fill all |
|
382 * of the needed component arrays of the specified size. |
|
383 * The {@code ColorSpace} is the default sRGB space. |
|
384 * The transparency value may be any of {@code Transparency.OPAQUE}, |
|
385 * {@code Transparency.BITMASK}, |
|
386 * or {@code Transparency.TRANSLUCENT} |
|
387 * depending on the arguments, as specified |
|
388 * in the <a href="#transparency">class description</a> above. |
|
389 * @param bits the number of bits each pixel occupies |
|
390 * @param size the size of the color component arrays |
|
391 * @param cmap the array of color components |
|
392 * @param start the starting offset of the first color component |
|
393 * @param hasalpha indicates whether alpha values are contained in |
|
394 * the {@code cmap} array |
|
395 * @param trans the index of the fully transparent pixel |
|
396 * @param transferType the data type of the array used to represent |
|
397 * pixel values. The data type must be either |
|
398 * {@code DataBuffer.TYPE_BYTE} or |
|
399 * {@code DataBuffer.TYPE_USHORT}. |
|
400 * @throws IllegalArgumentException if {@code bits} is less |
|
401 * than 1 or greater than 16 |
|
402 * @throws IllegalArgumentException if {@code size} is less |
|
403 * than 1 |
|
404 * @throws IllegalArgumentException if {@code transferType} is not |
|
405 * one of {@code DataBuffer.TYPE_BYTE} or |
|
406 * {@code DataBuffer.TYPE_USHORT} |
|
407 */ |
|
408 public IndexColorModel(int bits, int size, |
|
409 int cmap[], int start, |
|
410 boolean hasalpha, int trans, int transferType) { |
|
411 // REMIND: This assumes the ordering: RGB[A] |
|
412 super(bits, opaqueBits, |
|
413 ColorSpace.getInstance(ColorSpace.CS_sRGB), |
|
414 false, false, OPAQUE, |
|
415 transferType); |
|
416 |
|
417 if (bits < 1 || bits > 16) { |
|
418 throw new IllegalArgumentException("Number of bits must be between" |
|
419 +" 1 and 16."); |
|
420 } |
|
421 if (size < 1) { |
|
422 throw new IllegalArgumentException("Map size ("+size+ |
|
423 ") must be >= 1"); |
|
424 } |
|
425 if ((transferType != DataBuffer.TYPE_BYTE) && |
|
426 (transferType != DataBuffer.TYPE_USHORT)) { |
|
427 throw new IllegalArgumentException("transferType must be either" + |
|
428 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); |
|
429 } |
|
430 |
|
431 setRGBs(size, cmap, start, hasalpha); |
|
432 setTransparentPixel(trans); |
|
433 calculatePixelMask(); |
|
434 } |
|
435 |
|
436 /** |
|
437 * Constructs an {@code IndexColorModel} from an |
|
438 * {@code int} array where each {@code int} is |
|
439 * comprised of red, green, blue, and alpha |
|
440 * components in the default RGB color model format. |
|
441 * The array must have enough values in it to fill all |
|
442 * of the needed component arrays of the specified size. |
|
443 * The {@code ColorSpace} is the default sRGB space. |
|
444 * The transparency value may be any of {@code Transparency.OPAQUE}, |
|
445 * {@code Transparency.BITMASK}, |
|
446 * or {@code Transparency.TRANSLUCENT} |
|
447 * depending on the arguments, as specified |
|
448 * in the <a href="#transparency">class description</a> above. |
|
449 * The transfer type must be one of {@code DataBuffer.TYPE_BYTE} |
|
450 * {@code DataBuffer.TYPE_USHORT}. |
|
451 * The {@code BigInteger} object specifies the valid/invalid pixels |
|
452 * in the {@code cmap} array. A pixel is valid if the |
|
453 * {@code BigInteger} value at that index is set, and is invalid |
|
454 * if the {@code BigInteger} bit at that index is not set. |
|
455 * @param bits the number of bits each pixel occupies |
|
456 * @param size the size of the color component array |
|
457 * @param cmap the array of color components |
|
458 * @param start the starting offset of the first color component |
|
459 * @param transferType the specified data type |
|
460 * @param validBits a {@code BigInteger} object. If a bit is |
|
461 * set in the BigInteger, the pixel at that index is valid. |
|
462 * If a bit is not set, the pixel at that index |
|
463 * is considered invalid. If null, all pixels are valid. |
|
464 * Only bits from 0 to the map size are considered. |
|
465 * @throws IllegalArgumentException if {@code bits} is less |
|
466 * than 1 or greater than 16 |
|
467 * @throws IllegalArgumentException if {@code size} is less |
|
468 * than 1 |
|
469 * @throws IllegalArgumentException if {@code transferType} is not |
|
470 * one of {@code DataBuffer.TYPE_BYTE} or |
|
471 * {@code DataBuffer.TYPE_USHORT} |
|
472 * |
|
473 * @since 1.3 |
|
474 */ |
|
475 public IndexColorModel(int bits, int size, int cmap[], int start, |
|
476 int transferType, BigInteger validBits) { |
|
477 super (bits, alphaBits, |
|
478 ColorSpace.getInstance(ColorSpace.CS_sRGB), |
|
479 true, false, TRANSLUCENT, |
|
480 transferType); |
|
481 |
|
482 if (bits < 1 || bits > 16) { |
|
483 throw new IllegalArgumentException("Number of bits must be between" |
|
484 +" 1 and 16."); |
|
485 } |
|
486 if (size < 1) { |
|
487 throw new IllegalArgumentException("Map size ("+size+ |
|
488 ") must be >= 1"); |
|
489 } |
|
490 if ((transferType != DataBuffer.TYPE_BYTE) && |
|
491 (transferType != DataBuffer.TYPE_USHORT)) { |
|
492 throw new IllegalArgumentException("transferType must be either" + |
|
493 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); |
|
494 } |
|
495 |
|
496 if (validBits != null) { |
|
497 // Check to see if it is all valid |
|
498 for (int i=0; i < size; i++) { |
|
499 if (!validBits.testBit(i)) { |
|
500 this.validBits = validBits; |
|
501 break; |
|
502 } |
|
503 } |
|
504 } |
|
505 |
|
506 setRGBs(size, cmap, start, true); |
|
507 calculatePixelMask(); |
|
508 } |
|
509 |
|
510 private void setRGBs(int size, byte r[], byte g[], byte b[], byte a[]) { |
|
511 if (size < 1) { |
|
512 throw new IllegalArgumentException("Map size ("+size+ |
|
513 ") must be >= 1"); |
|
514 } |
|
515 map_size = size; |
|
516 rgb = new int[calcRealMapSize(pixel_bits, size)]; |
|
517 int alpha = 0xff; |
|
518 int transparency = OPAQUE; |
|
519 boolean allgray = true; |
|
520 for (int i = 0; i < size; i++) { |
|
521 int rc = r[i] & 0xff; |
|
522 int gc = g[i] & 0xff; |
|
523 int bc = b[i] & 0xff; |
|
524 allgray = allgray && (rc == gc) && (gc == bc); |
|
525 if (a != null) { |
|
526 alpha = a[i] & 0xff; |
|
527 if (alpha != 0xff) { |
|
528 if (alpha == 0x00) { |
|
529 if (transparency == OPAQUE) { |
|
530 transparency = BITMASK; |
|
531 } |
|
532 if (transparent_index < 0) { |
|
533 transparent_index = i; |
|
534 } |
|
535 } else { |
|
536 transparency = TRANSLUCENT; |
|
537 } |
|
538 allgray = false; |
|
539 } |
|
540 } |
|
541 rgb[i] = (alpha << 24) | (rc << 16) | (gc << 8) | bc; |
|
542 } |
|
543 this.allgrayopaque = allgray; |
|
544 setTransparency(transparency); |
|
545 } |
|
546 |
|
547 private void setRGBs(int size, int cmap[], int start, boolean hasalpha) { |
|
548 map_size = size; |
|
549 rgb = new int[calcRealMapSize(pixel_bits, size)]; |
|
550 int j = start; |
|
551 int transparency = OPAQUE; |
|
552 boolean allgray = true; |
|
553 BigInteger validBits = this.validBits; |
|
554 for (int i = 0; i < size; i++, j++) { |
|
555 if (validBits != null && !validBits.testBit(i)) { |
|
556 continue; |
|
557 } |
|
558 int cmaprgb = cmap[j]; |
|
559 int r = (cmaprgb >> 16) & 0xff; |
|
560 int g = (cmaprgb >> 8) & 0xff; |
|
561 int b = (cmaprgb ) & 0xff; |
|
562 allgray = allgray && (r == g) && (g == b); |
|
563 if (hasalpha) { |
|
564 int alpha = cmaprgb >>> 24; |
|
565 if (alpha != 0xff) { |
|
566 if (alpha == 0x00) { |
|
567 if (transparency == OPAQUE) { |
|
568 transparency = BITMASK; |
|
569 } |
|
570 if (transparent_index < 0) { |
|
571 transparent_index = i; |
|
572 } |
|
573 } else { |
|
574 transparency = TRANSLUCENT; |
|
575 } |
|
576 allgray = false; |
|
577 } |
|
578 } else { |
|
579 cmaprgb |= 0xff000000; |
|
580 } |
|
581 rgb[i] = cmaprgb; |
|
582 } |
|
583 this.allgrayopaque = allgray; |
|
584 setTransparency(transparency); |
|
585 } |
|
586 |
|
587 private int calcRealMapSize(int bits, int size) { |
|
588 int newSize = Math.max(1 << bits, size); |
|
589 return Math.max(newSize, 256); |
|
590 } |
|
591 |
|
592 private BigInteger getAllValid() { |
|
593 int numbytes = (map_size+7)/8; |
|
594 byte[] valid = new byte[numbytes]; |
|
595 java.util.Arrays.fill(valid, (byte)0xff); |
|
596 valid[0] = (byte)(0xff >>> (numbytes*8 - map_size)); |
|
597 |
|
598 return new BigInteger(1, valid); |
|
599 } |
|
600 |
|
601 /** |
|
602 * Returns the transparency. Returns either OPAQUE, BITMASK, |
|
603 * or TRANSLUCENT |
|
604 * @return the transparency of this {@code IndexColorModel} |
|
605 * @see Transparency#OPAQUE |
|
606 * @see Transparency#BITMASK |
|
607 * @see Transparency#TRANSLUCENT |
|
608 */ |
|
609 public int getTransparency() { |
|
610 return transparency; |
|
611 } |
|
612 |
|
613 /** |
|
614 * Returns an array of the number of bits for each color/alpha component. |
|
615 * The array contains the color components in the order red, green, |
|
616 * blue, followed by the alpha component, if present. |
|
617 * @return an array containing the number of bits of each color |
|
618 * and alpha component of this {@code IndexColorModel} |
|
619 */ |
|
620 public int[] getComponentSize() { |
|
621 if (nBits == null) { |
|
622 if (supportsAlpha) { |
|
623 nBits = new int[4]; |
|
624 nBits[3] = 8; |
|
625 } |
|
626 else { |
|
627 nBits = new int[3]; |
|
628 } |
|
629 nBits[0] = nBits[1] = nBits[2] = 8; |
|
630 } |
|
631 return nBits.clone(); |
|
632 } |
|
633 |
|
634 /** |
|
635 * Returns the size of the color/alpha component arrays in this |
|
636 * {@code IndexColorModel}. |
|
637 * @return the size of the color and alpha component arrays. |
|
638 */ |
|
639 public final int getMapSize() { |
|
640 return map_size; |
|
641 } |
|
642 |
|
643 /** |
|
644 * Returns the index of a transparent pixel in this |
|
645 * {@code IndexColorModel} or -1 if there is no pixel |
|
646 * with an alpha value of 0. If a transparent pixel was |
|
647 * explicitly specified in one of the constructors by its |
|
648 * index, then that index will be preferred, otherwise, |
|
649 * the index of any pixel which happens to be fully transparent |
|
650 * may be returned. |
|
651 * @return the index of a transparent pixel in this |
|
652 * {@code IndexColorModel} object, or -1 if there |
|
653 * is no such pixel |
|
654 */ |
|
655 public final int getTransparentPixel() { |
|
656 return transparent_index; |
|
657 } |
|
658 |
|
659 /** |
|
660 * Copies the array of red color components into the specified array. |
|
661 * Only the initial entries of the array as specified by |
|
662 * {@link #getMapSize() getMapSize} are written. |
|
663 * @param r the specified array into which the elements of the |
|
664 * array of red color components are copied |
|
665 */ |
|
666 public final void getReds(byte r[]) { |
|
667 for (int i = 0; i < map_size; i++) { |
|
668 r[i] = (byte) (rgb[i] >> 16); |
|
669 } |
|
670 } |
|
671 |
|
672 /** |
|
673 * Copies the array of green color components into the specified array. |
|
674 * Only the initial entries of the array as specified by |
|
675 * {@code getMapSize} are written. |
|
676 * @param g the specified array into which the elements of the |
|
677 * array of green color components are copied |
|
678 */ |
|
679 public final void getGreens(byte g[]) { |
|
680 for (int i = 0; i < map_size; i++) { |
|
681 g[i] = (byte) (rgb[i] >> 8); |
|
682 } |
|
683 } |
|
684 |
|
685 /** |
|
686 * Copies the array of blue color components into the specified array. |
|
687 * Only the initial entries of the array as specified by |
|
688 * {@code getMapSize} are written. |
|
689 * @param b the specified array into which the elements of the |
|
690 * array of blue color components are copied |
|
691 */ |
|
692 public final void getBlues(byte b[]) { |
|
693 for (int i = 0; i < map_size; i++) { |
|
694 b[i] = (byte) rgb[i]; |
|
695 } |
|
696 } |
|
697 |
|
698 /** |
|
699 * Copies the array of alpha transparency components into the |
|
700 * specified array. Only the initial entries of the array as specified |
|
701 * by {@code getMapSize} are written. |
|
702 * @param a the specified array into which the elements of the |
|
703 * array of alpha components are copied |
|
704 */ |
|
705 public final void getAlphas(byte a[]) { |
|
706 for (int i = 0; i < map_size; i++) { |
|
707 a[i] = (byte) (rgb[i] >> 24); |
|
708 } |
|
709 } |
|
710 |
|
711 /** |
|
712 * Converts data for each index from the color and alpha component |
|
713 * arrays to an int in the default RGB ColorModel format and copies |
|
714 * the resulting 32-bit ARGB values into the specified array. Only |
|
715 * the initial entries of the array as specified by |
|
716 * {@code getMapSize} are |
|
717 * written. |
|
718 * @param rgb the specified array into which the converted ARGB |
|
719 * values from this array of color and alpha components |
|
720 * are copied. |
|
721 */ |
|
722 public final void getRGBs(int rgb[]) { |
|
723 System.arraycopy(this.rgb, 0, rgb, 0, map_size); |
|
724 } |
|
725 |
|
726 private void setTransparentPixel(int trans) { |
|
727 if (trans >= 0 && trans < map_size) { |
|
728 rgb[trans] &= 0x00ffffff; |
|
729 transparent_index = trans; |
|
730 allgrayopaque = false; |
|
731 if (this.transparency == OPAQUE) { |
|
732 setTransparency(BITMASK); |
|
733 } |
|
734 } |
|
735 } |
|
736 |
|
737 private void setTransparency(int transparency) { |
|
738 if (this.transparency != transparency) { |
|
739 this.transparency = transparency; |
|
740 if (transparency == OPAQUE) { |
|
741 supportsAlpha = false; |
|
742 numComponents = 3; |
|
743 nBits = opaqueBits; |
|
744 } else { |
|
745 supportsAlpha = true; |
|
746 numComponents = 4; |
|
747 nBits = alphaBits; |
|
748 } |
|
749 } |
|
750 } |
|
751 |
|
752 /** |
|
753 * This method is called from the constructors to set the pixel_mask |
|
754 * value, which is based on the value of pixel_bits. The pixel_mask |
|
755 * value is used to mask off the pixel parameters for methods such |
|
756 * as getRed(), getGreen(), getBlue(), getAlpha(), and getRGB(). |
|
757 */ |
|
758 private final void calculatePixelMask() { |
|
759 // Note that we adjust the mask so that our masking behavior here |
|
760 // is consistent with that of our native rendering loops. |
|
761 int maskbits = pixel_bits; |
|
762 if (maskbits == 3) { |
|
763 maskbits = 4; |
|
764 } else if (maskbits > 4 && maskbits < 8) { |
|
765 maskbits = 8; |
|
766 } |
|
767 pixel_mask = (1 << maskbits) - 1; |
|
768 } |
|
769 |
|
770 /** |
|
771 * Returns the red color component for the specified pixel, scaled |
|
772 * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value |
|
773 * is specified as an int. |
|
774 * Only the lower <em>n</em> bits of the pixel value, as specified in the |
|
775 * <a href="#index_values">class description</a> above, are used to |
|
776 * calculate the returned value. |
|
777 * The returned value is a non pre-multiplied value. |
|
778 * @param pixel the specified pixel |
|
779 * @return the value of the red color component for the specified pixel |
|
780 */ |
|
781 public final int getRed(int pixel) { |
|
782 return (rgb[pixel & pixel_mask] >> 16) & 0xff; |
|
783 } |
|
784 |
|
785 /** |
|
786 * Returns the green color component for the specified pixel, scaled |
|
787 * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value |
|
788 * is specified as an int. |
|
789 * Only the lower <em>n</em> bits of the pixel value, as specified in the |
|
790 * <a href="#index_values">class description</a> above, are used to |
|
791 * calculate the returned value. |
|
792 * The returned value is a non pre-multiplied value. |
|
793 * @param pixel the specified pixel |
|
794 * @return the value of the green color component for the specified pixel |
|
795 */ |
|
796 public final int getGreen(int pixel) { |
|
797 return (rgb[pixel & pixel_mask] >> 8) & 0xff; |
|
798 } |
|
799 |
|
800 /** |
|
801 * Returns the blue color component for the specified pixel, scaled |
|
802 * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value |
|
803 * is specified as an int. |
|
804 * Only the lower <em>n</em> bits of the pixel value, as specified in the |
|
805 * <a href="#index_values">class description</a> above, are used to |
|
806 * calculate the returned value. |
|
807 * The returned value is a non pre-multiplied value. |
|
808 * @param pixel the specified pixel |
|
809 * @return the value of the blue color component for the specified pixel |
|
810 */ |
|
811 public final int getBlue(int pixel) { |
|
812 return rgb[pixel & pixel_mask] & 0xff; |
|
813 } |
|
814 |
|
815 /** |
|
816 * Returns the alpha component for the specified pixel, scaled |
|
817 * from 0 to 255. The pixel value is specified as an int. |
|
818 * Only the lower <em>n</em> bits of the pixel value, as specified in the |
|
819 * <a href="#index_values">class description</a> above, are used to |
|
820 * calculate the returned value. |
|
821 * @param pixel the specified pixel |
|
822 * @return the value of the alpha component for the specified pixel |
|
823 */ |
|
824 public final int getAlpha(int pixel) { |
|
825 return (rgb[pixel & pixel_mask] >> 24) & 0xff; |
|
826 } |
|
827 |
|
828 /** |
|
829 * Returns the color/alpha components of the pixel in the default |
|
830 * RGB color model format. The pixel value is specified as an int. |
|
831 * Only the lower <em>n</em> bits of the pixel value, as specified in the |
|
832 * <a href="#index_values">class description</a> above, are used to |
|
833 * calculate the returned value. |
|
834 * The returned value is in a non pre-multiplied format. |
|
835 * @param pixel the specified pixel |
|
836 * @return the color and alpha components of the specified pixel |
|
837 * @see ColorModel#getRGBdefault |
|
838 */ |
|
839 public final int getRGB(int pixel) { |
|
840 return rgb[pixel & pixel_mask]; |
|
841 } |
|
842 |
|
843 private static final int CACHESIZE = 40; |
|
844 private int lookupcache[] = new int[CACHESIZE]; |
|
845 |
|
846 /** |
|
847 * Returns a data element array representation of a pixel in this |
|
848 * ColorModel, given an integer pixel representation in the |
|
849 * default RGB color model. This array can then be passed to the |
|
850 * {@link WritableRaster#setDataElements(int, int, java.lang.Object) setDataElements} |
|
851 * method of a {@link WritableRaster} object. If the pixel variable is |
|
852 * {@code null}, a new array is allocated. If {@code pixel} |
|
853 * is not {@code null}, it must be |
|
854 * a primitive array of type {@code transferType}; otherwise, a |
|
855 * {@code ClassCastException} is thrown. An |
|
856 * {@code ArrayIndexOutOfBoundsException} is |
|
857 * thrown if {@code pixel} is not large enough to hold a pixel |
|
858 * value for this {@code ColorModel}. The pixel array is returned. |
|
859 * <p> |
|
860 * Since {@code IndexColorModel} can be subclassed, subclasses |
|
861 * inherit the implementation of this method and if they don't |
|
862 * override it then they throw an exception if they use an |
|
863 * unsupported {@code transferType}. |
|
864 * |
|
865 * @param rgb the integer pixel representation in the default RGB |
|
866 * color model |
|
867 * @param pixel the specified pixel |
|
868 * @return an array representation of the specified pixel in this |
|
869 * {@code IndexColorModel}. |
|
870 * @throws ClassCastException if {@code pixel} |
|
871 * is not a primitive array of type {@code transferType} |
|
872 * @throws ArrayIndexOutOfBoundsException if |
|
873 * {@code pixel} is not large enough to hold a pixel value |
|
874 * for this {@code ColorModel} |
|
875 * @throws UnsupportedOperationException if {@code transferType} |
|
876 * is invalid |
|
877 * @see WritableRaster#setDataElements |
|
878 * @see SampleModel#setDataElements |
|
879 */ |
|
880 public synchronized Object getDataElements(int rgb, Object pixel) { |
|
881 int red = (rgb>>16) & 0xff; |
|
882 int green = (rgb>>8) & 0xff; |
|
883 int blue = rgb & 0xff; |
|
884 int alpha = (rgb>>>24); |
|
885 int pix = 0; |
|
886 |
|
887 // Note that pixels are stored at lookupcache[2*i] |
|
888 // and the rgb that was searched is stored at |
|
889 // lookupcache[2*i+1]. Also, the pixel is first |
|
890 // inverted using the unary complement operator |
|
891 // before storing in the cache so it can never be 0. |
|
892 for (int i = CACHESIZE - 2; i >= 0; i -= 2) { |
|
893 if ((pix = lookupcache[i]) == 0) { |
|
894 break; |
|
895 } |
|
896 if (rgb == lookupcache[i+1]) { |
|
897 return installpixel(pixel, ~pix); |
|
898 } |
|
899 } |
|
900 |
|
901 if (allgrayopaque) { |
|
902 // IndexColorModel objects are all tagged as |
|
903 // non-premultiplied so ignore the alpha value |
|
904 // of the incoming color, convert the |
|
905 // non-premultiplied color components to a |
|
906 // grayscale value and search for the closest |
|
907 // gray value in the palette. Since all colors |
|
908 // in the palette are gray, we only need compare |
|
909 // to one of the color components for a match |
|
910 // using a simple linear distance formula. |
|
911 |
|
912 int minDist = 256; |
|
913 int d; |
|
914 int gray = (red*77 + green*150 + blue*29 + 128)/256; |
|
915 |
|
916 for (int i = 0; i < map_size; i++) { |
|
917 if (this.rgb[i] == 0x0) { |
|
918 // For allgrayopaque colormaps, entries are 0 |
|
919 // iff they are an invalid color and should be |
|
920 // ignored during color searches. |
|
921 continue; |
|
922 } |
|
923 d = (this.rgb[i] & 0xff) - gray; |
|
924 if (d < 0) d = -d; |
|
925 if (d < minDist) { |
|
926 pix = i; |
|
927 if (d == 0) { |
|
928 break; |
|
929 } |
|
930 minDist = d; |
|
931 } |
|
932 } |
|
933 } else if (transparency == OPAQUE) { |
|
934 // IndexColorModel objects are all tagged as |
|
935 // non-premultiplied so ignore the alpha value |
|
936 // of the incoming color and search for closest |
|
937 // color match independently using a 3 component |
|
938 // Euclidean distance formula. |
|
939 // For opaque colormaps, palette entries are 0 |
|
940 // iff they are an invalid color and should be |
|
941 // ignored during color searches. |
|
942 // As an optimization, exact color searches are |
|
943 // likely to be fairly common in opaque colormaps |
|
944 // so first we will do a quick search for an |
|
945 // exact match. |
|
946 |
|
947 int smallestError = Integer.MAX_VALUE; |
|
948 int lut[] = this.rgb; |
|
949 int lutrgb; |
|
950 for (int i=0; i < map_size; i++) { |
|
951 lutrgb = lut[i]; |
|
952 if (lutrgb == rgb && lutrgb != 0) { |
|
953 pix = i; |
|
954 smallestError = 0; |
|
955 break; |
|
956 } |
|
957 } |
|
958 |
|
959 if (smallestError != 0) { |
|
960 for (int i=0; i < map_size; i++) { |
|
961 lutrgb = lut[i]; |
|
962 if (lutrgb == 0) { |
|
963 continue; |
|
964 } |
|
965 |
|
966 int tmp = ((lutrgb >> 16) & 0xff) - red; |
|
967 int currentError = tmp*tmp; |
|
968 if (currentError < smallestError) { |
|
969 tmp = ((lutrgb >> 8) & 0xff) - green; |
|
970 currentError += tmp * tmp; |
|
971 if (currentError < smallestError) { |
|
972 tmp = (lutrgb & 0xff) - blue; |
|
973 currentError += tmp * tmp; |
|
974 if (currentError < smallestError) { |
|
975 pix = i; |
|
976 smallestError = currentError; |
|
977 } |
|
978 } |
|
979 } |
|
980 } |
|
981 } |
|
982 } else if (alpha == 0 && transparent_index >= 0) { |
|
983 // Special case - transparent color maps to the |
|
984 // specified transparent pixel, if there is one |
|
985 |
|
986 pix = transparent_index; |
|
987 } else { |
|
988 // IndexColorModel objects are all tagged as |
|
989 // non-premultiplied so use non-premultiplied |
|
990 // color components in the distance calculations. |
|
991 // Look for closest match using a 4 component |
|
992 // Euclidean distance formula. |
|
993 |
|
994 int smallestError = Integer.MAX_VALUE; |
|
995 int lut[] = this.rgb; |
|
996 for (int i=0; i < map_size; i++) { |
|
997 int lutrgb = lut[i]; |
|
998 if (lutrgb == rgb) { |
|
999 if (validBits != null && !validBits.testBit(i)) { |
|
1000 continue; |
|
1001 } |
|
1002 pix = i; |
|
1003 break; |
|
1004 } |
|
1005 |
|
1006 int tmp = ((lutrgb >> 16) & 0xff) - red; |
|
1007 int currentError = tmp*tmp; |
|
1008 if (currentError < smallestError) { |
|
1009 tmp = ((lutrgb >> 8) & 0xff) - green; |
|
1010 currentError += tmp * tmp; |
|
1011 if (currentError < smallestError) { |
|
1012 tmp = (lutrgb & 0xff) - blue; |
|
1013 currentError += tmp * tmp; |
|
1014 if (currentError < smallestError) { |
|
1015 tmp = (lutrgb >>> 24) - alpha; |
|
1016 currentError += tmp * tmp; |
|
1017 if (currentError < smallestError && |
|
1018 (validBits == null || validBits.testBit(i))) |
|
1019 { |
|
1020 pix = i; |
|
1021 smallestError = currentError; |
|
1022 } |
|
1023 } |
|
1024 } |
|
1025 } |
|
1026 } |
|
1027 } |
|
1028 System.arraycopy(lookupcache, 2, lookupcache, 0, CACHESIZE - 2); |
|
1029 lookupcache[CACHESIZE - 1] = rgb; |
|
1030 lookupcache[CACHESIZE - 2] = ~pix; |
|
1031 return installpixel(pixel, pix); |
|
1032 } |
|
1033 |
|
1034 private Object installpixel(Object pixel, int pix) { |
|
1035 switch (transferType) { |
|
1036 case DataBuffer.TYPE_INT: |
|
1037 int[] intObj; |
|
1038 if (pixel == null) { |
|
1039 pixel = intObj = new int[1]; |
|
1040 } else { |
|
1041 intObj = (int[]) pixel; |
|
1042 } |
|
1043 intObj[0] = pix; |
|
1044 break; |
|
1045 case DataBuffer.TYPE_BYTE: |
|
1046 byte[] byteObj; |
|
1047 if (pixel == null) { |
|
1048 pixel = byteObj = new byte[1]; |
|
1049 } else { |
|
1050 byteObj = (byte[]) pixel; |
|
1051 } |
|
1052 byteObj[0] = (byte) pix; |
|
1053 break; |
|
1054 case DataBuffer.TYPE_USHORT: |
|
1055 short[] shortObj; |
|
1056 if (pixel == null) { |
|
1057 pixel = shortObj = new short[1]; |
|
1058 } else { |
|
1059 shortObj = (short[]) pixel; |
|
1060 } |
|
1061 shortObj[0] = (short) pix; |
|
1062 break; |
|
1063 default: |
|
1064 throw new UnsupportedOperationException("This method has not been "+ |
|
1065 "implemented for transferType " + transferType); |
|
1066 } |
|
1067 return pixel; |
|
1068 } |
|
1069 |
|
1070 /** |
|
1071 * Returns an array of unnormalized color/alpha components for a |
|
1072 * specified pixel in this {@code ColorModel}. The pixel value |
|
1073 * is specified as an int. If the {@code components} array is {@code null}, |
|
1074 * a new array is allocated that contains |
|
1075 * {@code offset + getNumComponents()} elements. |
|
1076 * The {@code components} array is returned, |
|
1077 * with the alpha component included |
|
1078 * only if {@code hasAlpha} returns true. |
|
1079 * Color/alpha components are stored in the {@code components} array starting |
|
1080 * at {@code offset} even if the array is allocated by this method. |
|
1081 * An {@code ArrayIndexOutOfBoundsException} |
|
1082 * is thrown if the {@code components} array is not {@code null} and is |
|
1083 * not large enough to hold all the color and alpha components |
|
1084 * starting at {@code offset}. |
|
1085 * @param pixel the specified pixel |
|
1086 * @param components the array to receive the color and alpha |
|
1087 * components of the specified pixel |
|
1088 * @param offset the offset into the {@code components} array at |
|
1089 * which to start storing the color and alpha components |
|
1090 * @return an array containing the color and alpha components of the |
|
1091 * specified pixel starting at the specified offset. |
|
1092 * @see ColorModel#hasAlpha |
|
1093 * @see ColorModel#getNumComponents |
|
1094 */ |
|
1095 public int[] getComponents(int pixel, int[] components, int offset) { |
|
1096 if (components == null) { |
|
1097 components = new int[offset+numComponents]; |
|
1098 } |
|
1099 |
|
1100 // REMIND: Needs to change if different color space |
|
1101 components[offset+0] = getRed(pixel); |
|
1102 components[offset+1] = getGreen(pixel); |
|
1103 components[offset+2] = getBlue(pixel); |
|
1104 if (supportsAlpha && (components.length-offset) > 3) { |
|
1105 components[offset+3] = getAlpha(pixel); |
|
1106 } |
|
1107 |
|
1108 return components; |
|
1109 } |
|
1110 |
|
1111 /** |
|
1112 * Returns an array of unnormalized color/alpha components for |
|
1113 * a specified pixel in this {@code ColorModel}. The pixel |
|
1114 * value is specified by an array of data elements of type |
|
1115 * {@code transferType} passed in as an object reference. |
|
1116 * If {@code pixel} is not a primitive array of type |
|
1117 * {@code transferType}, a {@code ClassCastException} |
|
1118 * is thrown. An {@code ArrayIndexOutOfBoundsException} |
|
1119 * is thrown if {@code pixel} is not large enough to hold |
|
1120 * a pixel value for this {@code ColorModel}. If the |
|
1121 * {@code components} array is {@code null}, a new array |
|
1122 * is allocated that contains |
|
1123 * {@code offset + getNumComponents()} elements. |
|
1124 * The {@code components} array is returned, |
|
1125 * with the alpha component included |
|
1126 * only if {@code hasAlpha} returns true. |
|
1127 * Color/alpha components are stored in the {@code components} |
|
1128 * array starting at {@code offset} even if the array is |
|
1129 * allocated by this method. An |
|
1130 * {@code ArrayIndexOutOfBoundsException} is also |
|
1131 * thrown if the {@code components} array is not |
|
1132 * {@code null} and is not large enough to hold all the color |
|
1133 * and alpha components starting at {@code offset}. |
|
1134 * <p> |
|
1135 * Since {@code IndexColorModel} can be subclassed, subclasses |
|
1136 * inherit the implementation of this method and if they don't |
|
1137 * override it then they throw an exception if they use an |
|
1138 * unsupported {@code transferType}. |
|
1139 * |
|
1140 * @param pixel the specified pixel |
|
1141 * @param components an array that receives the color and alpha |
|
1142 * components of the specified pixel |
|
1143 * @param offset the index into the {@code components} array at |
|
1144 * which to begin storing the color and alpha components of the |
|
1145 * specified pixel |
|
1146 * @return an array containing the color and alpha components of the |
|
1147 * specified pixel starting at the specified offset. |
|
1148 * @throws ArrayIndexOutOfBoundsException if {@code pixel} |
|
1149 * is not large enough to hold a pixel value for this |
|
1150 * {@code ColorModel} or if the |
|
1151 * {@code components} array is not {@code null} |
|
1152 * and is not large enough to hold all the color |
|
1153 * and alpha components starting at {@code offset} |
|
1154 * @throws ClassCastException if {@code pixel} is not a |
|
1155 * primitive array of type {@code transferType} |
|
1156 * @throws UnsupportedOperationException if {@code transferType} |
|
1157 * is not one of the supported transfer types |
|
1158 * @see ColorModel#hasAlpha |
|
1159 * @see ColorModel#getNumComponents |
|
1160 */ |
|
1161 public int[] getComponents(Object pixel, int[] components, int offset) { |
|
1162 int intpixel; |
|
1163 switch (transferType) { |
|
1164 case DataBuffer.TYPE_BYTE: |
|
1165 byte bdata[] = (byte[])pixel; |
|
1166 intpixel = bdata[0] & 0xff; |
|
1167 break; |
|
1168 case DataBuffer.TYPE_USHORT: |
|
1169 short sdata[] = (short[])pixel; |
|
1170 intpixel = sdata[0] & 0xffff; |
|
1171 break; |
|
1172 case DataBuffer.TYPE_INT: |
|
1173 int idata[] = (int[])pixel; |
|
1174 intpixel = idata[0]; |
|
1175 break; |
|
1176 default: |
|
1177 throw new UnsupportedOperationException("This method has not been "+ |
|
1178 "implemented for transferType " + transferType); |
|
1179 } |
|
1180 return getComponents(intpixel, components, offset); |
|
1181 } |
|
1182 |
|
1183 /** |
|
1184 * Returns a pixel value represented as an int in this |
|
1185 * {@code ColorModel} given an array of unnormalized |
|
1186 * color/alpha components. An |
|
1187 * {@code ArrayIndexOutOfBoundsException} |
|
1188 * is thrown if the {@code components} array is not large |
|
1189 * enough to hold all of the color and alpha components starting |
|
1190 * at {@code offset}. Since |
|
1191 * {@code ColorModel} can be subclassed, subclasses inherit the |
|
1192 * implementation of this method and if they don't override it then |
|
1193 * they throw an exception if they use an unsupported transferType. |
|
1194 * @param components an array of unnormalized color and alpha |
|
1195 * components |
|
1196 * @param offset the index into {@code components} at which to |
|
1197 * begin retrieving the color and alpha components |
|
1198 * @return an {@code int} pixel value in this |
|
1199 * {@code ColorModel} corresponding to the specified components. |
|
1200 * @throws ArrayIndexOutOfBoundsException if |
|
1201 * the {@code components} array is not large enough to |
|
1202 * hold all of the color and alpha components starting at |
|
1203 * {@code offset} |
|
1204 * @throws UnsupportedOperationException if {@code transferType} |
|
1205 * is invalid |
|
1206 */ |
|
1207 public int getDataElement(int[] components, int offset) { |
|
1208 int rgb = (components[offset+0]<<16) |
|
1209 | (components[offset+1]<<8) | (components[offset+2]); |
|
1210 if (supportsAlpha) { |
|
1211 rgb |= (components[offset+3]<<24); |
|
1212 } |
|
1213 else { |
|
1214 rgb |= 0xff000000; |
|
1215 } |
|
1216 Object inData = getDataElements(rgb, null); |
|
1217 int pixel; |
|
1218 switch (transferType) { |
|
1219 case DataBuffer.TYPE_BYTE: |
|
1220 byte bdata[] = (byte[])inData; |
|
1221 pixel = bdata[0] & 0xff; |
|
1222 break; |
|
1223 case DataBuffer.TYPE_USHORT: |
|
1224 short sdata[] = (short[])inData; |
|
1225 pixel = sdata[0]; |
|
1226 break; |
|
1227 case DataBuffer.TYPE_INT: |
|
1228 int idata[] = (int[])inData; |
|
1229 pixel = idata[0]; |
|
1230 break; |
|
1231 default: |
|
1232 throw new UnsupportedOperationException("This method has not been "+ |
|
1233 "implemented for transferType " + transferType); |
|
1234 } |
|
1235 return pixel; |
|
1236 } |
|
1237 |
|
1238 /** |
|
1239 * Returns a data element array representation of a pixel in this |
|
1240 * {@code ColorModel} given an array of unnormalized color/alpha |
|
1241 * components. This array can then be passed to the |
|
1242 * {@code setDataElements} method of a {@code WritableRaster} |
|
1243 * object. An {@code ArrayIndexOutOfBoundsException} is |
|
1244 * thrown if the |
|
1245 * {@code components} array is not large enough to hold all of the |
|
1246 * color and alpha components starting at {@code offset}. |
|
1247 * If the pixel variable is {@code null}, a new array |
|
1248 * is allocated. If {@code pixel} is not {@code null}, |
|
1249 * it must be a primitive array of type {@code transferType}; |
|
1250 * otherwise, a {@code ClassCastException} is thrown. |
|
1251 * An {@code ArrayIndexOutOfBoundsException} is thrown if pixel |
|
1252 * is not large enough to hold a pixel value for this |
|
1253 * {@code ColorModel}. |
|
1254 * <p> |
|
1255 * Since {@code IndexColorModel} can be subclassed, subclasses |
|
1256 * inherit the implementation of this method and if they don't |
|
1257 * override it then they throw an exception if they use an |
|
1258 * unsupported {@code transferType} |
|
1259 * |
|
1260 * @param components an array of unnormalized color and alpha |
|
1261 * components |
|
1262 * @param offset the index into {@code components} at which to |
|
1263 * begin retrieving color and alpha components |
|
1264 * @param pixel the {@code Object} representing an array of color |
|
1265 * and alpha components |
|
1266 * @return an {@code Object} representing an array of color and |
|
1267 * alpha components. |
|
1268 * @throws ClassCastException if {@code pixel} |
|
1269 * is not a primitive array of type {@code transferType} |
|
1270 * @throws ArrayIndexOutOfBoundsException if |
|
1271 * {@code pixel} is not large enough to hold a pixel value |
|
1272 * for this {@code ColorModel} or the {@code components} |
|
1273 * array is not large enough to hold all of the color and alpha |
|
1274 * components starting at {@code offset} |
|
1275 * @throws UnsupportedOperationException if {@code transferType} |
|
1276 * is not one of the supported transfer types |
|
1277 * @see WritableRaster#setDataElements |
|
1278 * @see SampleModel#setDataElements |
|
1279 */ |
|
1280 public Object getDataElements(int[] components, int offset, Object pixel) { |
|
1281 int rgb = (components[offset+0]<<16) | (components[offset+1]<<8) |
|
1282 | (components[offset+2]); |
|
1283 if (supportsAlpha) { |
|
1284 rgb |= (components[offset+3]<<24); |
|
1285 } |
|
1286 else { |
|
1287 rgb &= 0xff000000; |
|
1288 } |
|
1289 return getDataElements(rgb, pixel); |
|
1290 } |
|
1291 |
|
1292 /** |
|
1293 * Creates a {@code WritableRaster} with the specified width |
|
1294 * and height that has a data layout ({@code SampleModel}) |
|
1295 * compatible with this {@code ColorModel}. This method |
|
1296 * only works for color models with 16 or fewer bits per pixel. |
|
1297 * <p> |
|
1298 * Since {@code IndexColorModel} can be subclassed, any |
|
1299 * subclass that supports greater than 16 bits per pixel must |
|
1300 * override this method. |
|
1301 * |
|
1302 * @param w the width to apply to the new {@code WritableRaster} |
|
1303 * @param h the height to apply to the new {@code WritableRaster} |
|
1304 * @return a {@code WritableRaster} object with the specified |
|
1305 * width and height. |
|
1306 * @throws UnsupportedOperationException if the number of bits in a |
|
1307 * pixel is greater than 16 |
|
1308 * @see WritableRaster |
|
1309 * @see SampleModel |
|
1310 */ |
|
1311 public WritableRaster createCompatibleWritableRaster(int w, int h) { |
|
1312 WritableRaster raster; |
|
1313 |
|
1314 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) { |
|
1315 // TYPE_BINARY |
|
1316 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, |
|
1317 w, h, 1, pixel_bits, null); |
|
1318 } |
|
1319 else if (pixel_bits <= 8) { |
|
1320 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, |
|
1321 w,h,1,null); |
|
1322 } |
|
1323 else if (pixel_bits <= 16) { |
|
1324 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, |
|
1325 w,h,1,null); |
|
1326 } |
|
1327 else { |
|
1328 throw new |
|
1329 UnsupportedOperationException("This method is not supported "+ |
|
1330 " for pixel bits > 16."); |
|
1331 } |
|
1332 return raster; |
|
1333 } |
|
1334 |
|
1335 /** |
|
1336 * Returns {@code true} if {@code raster} is compatible |
|
1337 * with this {@code ColorModel} or {@code false} if it |
|
1338 * is not compatible with this {@code ColorModel}. |
|
1339 * @param raster the {@link Raster} object to test for compatibility |
|
1340 * @return {@code true} if {@code raster} is compatible |
|
1341 * with this {@code ColorModel}; {@code false} otherwise. |
|
1342 * |
|
1343 */ |
|
1344 public boolean isCompatibleRaster(Raster raster) { |
|
1345 |
|
1346 int size = raster.getSampleModel().getSampleSize(0); |
|
1347 return ((raster.getTransferType() == transferType) && |
|
1348 (raster.getNumBands() == 1) && ((1 << size) >= map_size)); |
|
1349 } |
|
1350 |
|
1351 /** |
|
1352 * Creates a {@code SampleModel} with the specified |
|
1353 * width and height that has a data layout compatible with |
|
1354 * this {@code ColorModel}. |
|
1355 * @param w the width to apply to the new {@code SampleModel} |
|
1356 * @param h the height to apply to the new {@code SampleModel} |
|
1357 * @return a {@code SampleModel} object with the specified |
|
1358 * width and height. |
|
1359 * @throws IllegalArgumentException if {@code w} or |
|
1360 * {@code h} is not greater than 0 |
|
1361 * @see SampleModel |
|
1362 */ |
|
1363 public SampleModel createCompatibleSampleModel(int w, int h) { |
|
1364 int[] off = new int[1]; |
|
1365 off[0] = 0; |
|
1366 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) { |
|
1367 return new MultiPixelPackedSampleModel(transferType, w, h, |
|
1368 pixel_bits); |
|
1369 } |
|
1370 else { |
|
1371 return new ComponentSampleModel(transferType, w, h, 1, w, |
|
1372 off); |
|
1373 } |
|
1374 } |
|
1375 |
|
1376 /** |
|
1377 * Checks if the specified {@code SampleModel} is compatible |
|
1378 * with this {@code ColorModel}. If {@code sm} is |
|
1379 * {@code null}, this method returns {@code false}. |
|
1380 * @param sm the specified {@code SampleModel}, |
|
1381 * or {@code null} |
|
1382 * @return {@code true} if the specified {@code SampleModel} |
|
1383 * is compatible with this {@code ColorModel}; {@code false} |
|
1384 * otherwise. |
|
1385 * @see SampleModel |
|
1386 */ |
|
1387 public boolean isCompatibleSampleModel(SampleModel sm) { |
|
1388 // fix 4238629 |
|
1389 if (! (sm instanceof ComponentSampleModel) && |
|
1390 ! (sm instanceof MultiPixelPackedSampleModel) ) { |
|
1391 return false; |
|
1392 } |
|
1393 |
|
1394 // Transfer type must be the same |
|
1395 if (sm.getTransferType() != transferType) { |
|
1396 return false; |
|
1397 } |
|
1398 |
|
1399 if (sm.getNumBands() != 1) { |
|
1400 return false; |
|
1401 } |
|
1402 |
|
1403 return true; |
|
1404 } |
|
1405 |
|
1406 /** |
|
1407 * Returns a new {@code BufferedImage} of TYPE_INT_ARGB or |
|
1408 * TYPE_INT_RGB that has a {@code Raster} with pixel data |
|
1409 * computed by expanding the indices in the source {@code Raster} |
|
1410 * using the color/alpha component arrays of this {@code ColorModel}. |
|
1411 * Only the lower <em>n</em> bits of each index value in the source |
|
1412 * {@code Raster}, as specified in the |
|
1413 * <a href="#index_values">class description</a> above, are used to |
|
1414 * compute the color/alpha values in the returned image. |
|
1415 * If {@code forceARGB} is {@code true}, a TYPE_INT_ARGB image is |
|
1416 * returned regardless of whether or not this {@code ColorModel} |
|
1417 * has an alpha component array or a transparent pixel. |
|
1418 * @param raster the specified {@code Raster} |
|
1419 * @param forceARGB if {@code true}, the returned |
|
1420 * {@code BufferedImage} is TYPE_INT_ARGB; otherwise it is |
|
1421 * TYPE_INT_RGB |
|
1422 * @return a {@code BufferedImage} created with the specified |
|
1423 * {@code Raster} |
|
1424 * @throws IllegalArgumentException if the raster argument is not |
|
1425 * compatible with this IndexColorModel |
|
1426 */ |
|
1427 public BufferedImage convertToIntDiscrete(Raster raster, |
|
1428 boolean forceARGB) { |
|
1429 ColorModel cm; |
|
1430 |
|
1431 if (!isCompatibleRaster(raster)) { |
|
1432 throw new IllegalArgumentException("This raster is not compatible" + |
|
1433 "with this IndexColorModel."); |
|
1434 } |
|
1435 if (forceARGB || transparency == TRANSLUCENT) { |
|
1436 cm = ColorModel.getRGBdefault(); |
|
1437 } |
|
1438 else if (transparency == BITMASK) { |
|
1439 cm = new DirectColorModel(25, 0xff0000, 0x00ff00, 0x0000ff, |
|
1440 0x1000000); |
|
1441 } |
|
1442 else { |
|
1443 cm = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff); |
|
1444 } |
|
1445 |
|
1446 int w = raster.getWidth(); |
|
1447 int h = raster.getHeight(); |
|
1448 WritableRaster discreteRaster = |
|
1449 cm.createCompatibleWritableRaster(w, h); |
|
1450 Object obj = null; |
|
1451 int[] data = null; |
|
1452 |
|
1453 int rX = raster.getMinX(); |
|
1454 int rY = raster.getMinY(); |
|
1455 |
|
1456 for (int y=0; y < h; y++, rY++) { |
|
1457 obj = raster.getDataElements(rX, rY, w, 1, obj); |
|
1458 if (obj instanceof int[]) { |
|
1459 data = (int[])obj; |
|
1460 } else { |
|
1461 data = DataBuffer.toIntArray(obj); |
|
1462 } |
|
1463 for (int x=0; x < w; x++) { |
|
1464 data[x] = rgb[data[x] & pixel_mask]; |
|
1465 } |
|
1466 discreteRaster.setDataElements(0, y, w, 1, data); |
|
1467 } |
|
1468 |
|
1469 return new BufferedImage(cm, discreteRaster, false, null); |
|
1470 } |
|
1471 |
|
1472 /** |
|
1473 * Returns whether or not the pixel is valid. |
|
1474 * @param pixel the specified pixel value |
|
1475 * @return {@code true} if {@code pixel} |
|
1476 * is valid; {@code false} otherwise. |
|
1477 * @since 1.3 |
|
1478 */ |
|
1479 public boolean isValid(int pixel) { |
|
1480 return ((pixel >= 0 && pixel < map_size) && |
|
1481 (validBits == null || validBits.testBit(pixel))); |
|
1482 } |
|
1483 |
|
1484 /** |
|
1485 * Returns whether or not all of the pixels are valid. |
|
1486 * @return {@code true} if all pixels are valid; |
|
1487 * {@code false} otherwise. |
|
1488 * @since 1.3 |
|
1489 */ |
|
1490 public boolean isValid() { |
|
1491 return (validBits == null); |
|
1492 } |
|
1493 |
|
1494 /** |
|
1495 * Returns a {@code BigInteger} that indicates the valid/invalid |
|
1496 * pixels in the colormap. A bit is valid if the |
|
1497 * {@code BigInteger} value at that index is set, and is invalid |
|
1498 * if the {@code BigInteger} value at that index is not set. |
|
1499 * The only valid ranges to query in the {@code BigInteger} are |
|
1500 * between 0 and the map size. |
|
1501 * @return a {@code BigInteger} indicating the valid/invalid pixels. |
|
1502 * @since 1.3 |
|
1503 */ |
|
1504 public BigInteger getValidPixels() { |
|
1505 if (validBits == null) { |
|
1506 return getAllValid(); |
|
1507 } |
|
1508 else { |
|
1509 return validBits; |
|
1510 } |
|
1511 } |
|
1512 |
|
1513 /** |
|
1514 * Disposes of system resources associated with this |
|
1515 * {@code ColorModel} once this {@code ColorModel} is no |
|
1516 * longer referenced. |
|
1517 * |
|
1518 * @deprecated The {@code finalize} method has been deprecated. |
|
1519 * Subclasses that override {@code finalize} in order to perform cleanup |
|
1520 * should be modified to use alternative cleanup mechanisms and |
|
1521 * to remove the overriding {@code finalize} method. |
|
1522 * When overriding the {@code finalize} method, its implementation must explicitly |
|
1523 * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. |
|
1524 * See the specification for {@link Object#finalize()} for further |
|
1525 * information about migration options. |
|
1526 */ |
|
1527 @Deprecated(since="9") |
|
1528 public void finalize() { |
|
1529 } |
|
1530 |
|
1531 /** |
|
1532 * Returns the {@code String} representation of the contents of |
|
1533 * this {@code ColorModel} object. |
|
1534 * @return a {@code String} representing the contents of this |
|
1535 * {@code ColorModel} object. |
|
1536 */ |
|
1537 public String toString() { |
|
1538 return new String("IndexColorModel: #pixelBits = "+pixel_bits |
|
1539 + " numComponents = "+numComponents |
|
1540 + " color space = "+colorSpace |
|
1541 + " transparency = "+transparency |
|
1542 + " transIndex = "+transparent_index |
|
1543 + " has alpha = "+supportsAlpha |
|
1544 + " isAlphaPre = "+isAlphaPremultiplied |
|
1545 ); |
|
1546 } |
|
1547 |
|
1548 /** |
|
1549 * Tests if the specified {@code Object} is an |
|
1550 * instance of {@code IndexColorModel} |
|
1551 * and if it equals this {@code IndexColorModel} |
|
1552 * @param obj the {@code Object} to test for equality |
|
1553 * @return {@code true} if the specified {@code Object} |
|
1554 * equals this {@code IndexColorModel}; {@code false} otherwise. |
|
1555 */ |
|
1556 @Override |
|
1557 public boolean equals(Object obj) { |
|
1558 |
|
1559 if (!(obj instanceof IndexColorModel)) { |
|
1560 return false; |
|
1561 } |
|
1562 |
|
1563 IndexColorModel cm = (IndexColorModel) obj; |
|
1564 if (supportsAlpha != cm.hasAlpha() || |
|
1565 isAlphaPremultiplied != cm.isAlphaPremultiplied() || |
|
1566 pixel_bits != cm.getPixelSize() || |
|
1567 transparency != cm.getTransparency() || |
|
1568 numComponents != cm.getNumComponents() || |
|
1569 (!(colorSpace.equals(cm.colorSpace))) || |
|
1570 transferType != cm.transferType || |
|
1571 map_size != cm.map_size || |
|
1572 transparent_index != cm.transparent_index) |
|
1573 { |
|
1574 return false; |
|
1575 } |
|
1576 |
|
1577 if (!(Arrays.equals(nBits, cm.getComponentSize()))) { |
|
1578 return false; |
|
1579 } |
|
1580 |
|
1581 // verify whether we have to check equality of all bits in validBits |
|
1582 boolean testValidBits; |
|
1583 if (validBits == cm.validBits) { |
|
1584 testValidBits = false; |
|
1585 } else if (validBits == null || cm.validBits == null) { |
|
1586 return false; |
|
1587 } else if (validBits.equals(cm.validBits)) { |
|
1588 testValidBits = false; |
|
1589 } else { |
|
1590 testValidBits = true; |
|
1591 } |
|
1592 |
|
1593 if (testValidBits) { |
|
1594 for (int i = 0; i < map_size; i++) { |
|
1595 if (rgb[i] != cm.rgb[i] || |
|
1596 validBits.testBit(i) != cm.validBits.testBit(i)) |
|
1597 { |
|
1598 return false; |
|
1599 } |
|
1600 } |
|
1601 } else { |
|
1602 for (int i = 0; i < map_size; i++) { |
|
1603 if (rgb[i] != cm.rgb[i]) { |
|
1604 return false; |
|
1605 } |
|
1606 } |
|
1607 } |
|
1608 return true; |
|
1609 } |
|
1610 |
|
1611 /** |
|
1612 * Returns the hash code for IndexColorModel. |
|
1613 * |
|
1614 * @return a hash code for IndexColorModel |
|
1615 */ |
|
1616 @Override |
|
1617 public int hashCode() { |
|
1618 int result = hashCode; |
|
1619 if (result == 0) { |
|
1620 /* |
|
1621 * We are intentionally not calculating hashCode for validBits, |
|
1622 * because it is only used for 8-bit indexed screens and they |
|
1623 * are very rare. It is very unlikely for 2 IndexColorModels |
|
1624 * to have different valiBits and have same value for all |
|
1625 * other properties. |
|
1626 */ |
|
1627 result = 7; |
|
1628 result = 89 * result + this.pixel_bits; |
|
1629 result = 89 * result + Arrays.hashCode(this.nBits); |
|
1630 result = 89 * result + this.transparency; |
|
1631 result = 89 * result + (this.supportsAlpha ? 1 : 0); |
|
1632 result = 89 * result + (this.isAlphaPremultiplied ? 1 : 0); |
|
1633 result = 89 * result + this.numComponents; |
|
1634 result = 89 * result + this.colorSpace.hashCode(); |
|
1635 result = 89 * result + this.transferType; |
|
1636 result = 89 * result + Arrays.hashCode(this.rgb); |
|
1637 result = 89 * result + this.map_size; |
|
1638 result = 89 * result + this.transparent_index; |
|
1639 hashCode = result; |
|
1640 } |
|
1641 return result; |
|
1642 } |
|
1643 } |