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
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
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;
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 }
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) {
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;
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 *
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) {
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;
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.
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},
|
1 /*
2 * Copyright (c) 1995, 2018, 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
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
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;
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 }
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) {
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;
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 *
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) {
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;
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.
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},
|