1 /*
2 * Copyright (c) 1995, 2013, 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.color.ColorSpace;
29 import java.awt.Transparency;
30
31 /**
32 * The {@code DirectColorModel} class is a {@code ColorModel}
33 * class that works with pixel values that represent RGB
34 * color and alpha information as separate samples and that pack all
35 * samples for a single pixel into a single int, short, or byte quantity.
36 * This class can be used only with ColorSpaces of type ColorSpace.TYPE_RGB.
37 * In addition, for each component of the ColorSpace, the minimum
38 * normalized component value obtained via the {@code getMinValue()}
39 * method of ColorSpace must be 0.0, and the maximum value obtained via
40 * the {@code getMaxValue()} method must be 1.0 (these min/max
41 * values are typical for RGB spaces).
42 * There must be three color samples in the pixel values and there can
43 * be a single alpha sample. For those methods that use a primitive array
44 * pixel representation of type {@code transferType}, the array
45 * length is always one. The transfer
46 * types supported are DataBuffer.TYPE_BYTE,
47 * DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
48 * Color and alpha samples are stored in the single
49 * element of the array in bits indicated by bit masks. Each bit mask
50 * must be contiguous and masks must not overlap. The same masks apply to
51 * the single int pixel representation used by other methods. The
52 * correspondence of masks and color/alpha samples is as follows:
53 * <ul>
54 * <li> Masks are identified by indices running from 0 through 2
55 * if no alpha is present, or 3 if an alpha is present.
56 * <li> The first three indices refer to color samples;
57 * index 0 corresponds to red, index 1 to green, and index 2 to blue.
58 * <li> Index 3 corresponds to the alpha sample, if present.
59 * </ul>
60 * <p>
61 * The translation from pixel values to color/alpha components for
62 * display or processing purposes is a one-to-one correspondence of
63 * samples to components. A {@code DirectColorModel} is
64 * typically used with image data which uses masks to define packed
65 * samples. For example, a {@code DirectColorModel} can be used in
66 * conjunction with a {@code SinglePixelPackedSampleModel} to
67 * construct a {@link BufferedImage}. Normally the masks used by the
68 * {@link SampleModel} and the {@code ColorModel} would be the
69 * same. However, if they are different, the color interpretation
70 * of pixel data will be done according to the masks of the
71 * {@code ColorModel}.
72 * <p>
73 * A single int pixel representation is valid for all objects of this
74 * class, since it is always possible to represent pixel values used with
75 * this class in a single int. Therefore, methods which use this
76 * representation will not throw an {@code IllegalArgumentException}
77 * due to an invalid pixel value.
78 * <p>
79 * This color model is similar to an X11 TrueColor visual.
80 * The default RGB ColorModel specified by the
81 * {@link ColorModel#getRGBdefault() getRGBdefault} method is a
82 * {@code DirectColorModel} with the following parameters:
83 * <pre>
84 * Number of bits: 32
85 * Red mask: 0x00ff0000
86 * Green mask: 0x0000ff00
87 * Blue mask: 0x000000ff
88 * Alpha mask: 0xff000000
89 * Color space: sRGB
90 * isAlphaPremultiplied: False
91 * Transparency: Transparency.TRANSLUCENT
92 * transferType: DataBuffer.TYPE_INT
93 * </pre>
94 * <p>
95 * Many of the methods in this class are final. This is because the
96 * underlying native graphics code makes assumptions about the layout
97 * and operation of this class and those assumptions are reflected in
98 * the implementations of the methods here that are marked final. You
99 * can subclass this class for other reasons, but you cannot override
100 * or modify the behavior of those methods.
101 *
102 * @see ColorModel
103 * @see ColorSpace
104 * @see SinglePixelPackedSampleModel
105 * @see BufferedImage
106 * @see ColorModel#getRGBdefault
107 *
108 */
109 public class DirectColorModel extends PackedColorModel {
110 private int red_mask;
111 private int green_mask;
112 private int blue_mask;
113 private int alpha_mask;
114 private int red_offset;
115 private int green_offset;
116 private int blue_offset;
117 private int alpha_offset;
118 private int red_scale;
119 private int green_scale;
120 private int blue_scale;
121 private int alpha_scale;
122 private boolean is_LinearRGB;
123 private int lRGBprecision;
124 private byte[] tosRGB8LUT;
125 private byte[] fromsRGB8LUT8;
126 private short[] fromsRGB8LUT16;
127
128 /**
129 * Constructs a {@code DirectColorModel} from the specified masks
130 * that indicate which bits in an {@code int} pixel representation
131 * contain the red, green and blue color samples. As pixel values do not
132 * contain alpha information, all pixels are treated as opaque, which
133 * means that alpha = 1.0. All of the bits
134 * in each mask must be contiguous and fit in the specified number
135 * of least significant bits of an {@code int} pixel representation.
136 * The {@code ColorSpace} is the default sRGB space. The
137 * transparency value is Transparency.OPAQUE. The transfer type
138 * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
139 * or DataBuffer.TYPE_INT that can hold a single pixel.
140 * @param bits the number of bits in the pixel values; for example,
141 * the sum of the number of bits in the masks.
142 * @param rmask specifies a mask indicating which bits in an
143 * integer pixel contain the red component
144 * @param gmask specifies a mask indicating which bits in an
145 * integer pixel contain the green component
146 * @param bmask specifies a mask indicating which bits in an
147 * integer pixel contain the blue component
148 *
149 */
150 public DirectColorModel(int bits,
151 int rmask, int gmask, int bmask) {
152 this(bits, rmask, gmask, bmask, 0);
153 }
154
155 /**
156 * Constructs a {@code DirectColorModel} from the specified masks
157 * that indicate which bits in an {@code int} pixel representation
158 * contain the red, green and blue color samples and the alpha sample,
159 * if present. If {@code amask} is 0, pixel values do not contain
160 * alpha information and all pixels are treated as opaque, which means
161 * that alpha = 1.0. All of the bits in each mask must
162 * be contiguous and fit in the specified number of least significant bits
163 * of an {@code int} pixel representation. Alpha, if present, is not
164 * premultiplied. The {@code ColorSpace} is the default sRGB space.
165 * The transparency value is Transparency.OPAQUE if no alpha is
166 * present, or Transparency.TRANSLUCENT otherwise. The transfer type
167 * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
168 * or DataBuffer.TYPE_INT that can hold a single pixel.
169 * @param bits the number of bits in the pixel values; for example,
170 * the sum of the number of bits in the masks.
171 * @param rmask specifies a mask indicating which bits in an
172 * integer pixel contain the red component
173 * @param gmask specifies a mask indicating which bits in an
174 * integer pixel contain the green component
175 * @param bmask specifies a mask indicating which bits in an
176 * integer pixel contain the blue component
177 * @param amask specifies a mask indicating which bits in an
178 * integer pixel contain the alpha component
179 */
180 public DirectColorModel(int bits, int rmask, int gmask,
181 int bmask, int amask) {
182 super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
183 bits, rmask, gmask, bmask, amask, false,
184 amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
185 ColorModel.getDefaultTransferType(bits));
186 setFields();
187 }
188
189 /**
190 * Constructs a {@code DirectColorModel} from the specified
191 * parameters. Color components are in the specified
192 * {@code ColorSpace}, which must be of type ColorSpace.TYPE_RGB
193 * and have minimum normalized component values which are all 0.0
194 * and maximum values which are all 1.0.
195 * The masks specify which bits in an {@code int} pixel
196 * representation contain the red, green and blue color samples and
197 * the alpha sample, if present. If {@code amask} is 0, pixel
198 * values do not contain alpha information and all pixels are treated
199 * as opaque, which means that alpha = 1.0. All of the
200 * bits in each mask must be contiguous and fit in the specified number
201 * of least significant bits of an {@code int} pixel
202 * representation. If there is alpha, the {@code boolean}
203 * {@code isAlphaPremultiplied} specifies how to interpret
204 * color and alpha samples in pixel values. If the {@code boolean}
205 * is {@code true}, color samples are assumed to have been
206 * multiplied by the alpha sample. The transparency value is
207 * Transparency.OPAQUE, if no alpha is present, or
208 * Transparency.TRANSLUCENT otherwise. The transfer type
209 * is the type of primitive array used to represent pixel values and
210 * must be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or
211 * DataBuffer.TYPE_INT.
212 * @param space the specified {@code ColorSpace}
213 * @param bits the number of bits in the pixel values; for example,
214 * the sum of the number of bits in the masks.
215 * @param rmask specifies a mask indicating which bits in an
216 * integer pixel contain the red component
217 * @param gmask specifies a mask indicating which bits in an
218 * integer pixel contain the green component
219 * @param bmask specifies a mask indicating which bits in an
220 * integer pixel contain the blue component
221 * @param amask specifies a mask indicating which bits in an
222 * integer pixel contain the alpha component
223 * @param isAlphaPremultiplied {@code true} if color samples are
224 * premultiplied by the alpha sample; {@code false} otherwise
225 * @param transferType the type of array used to represent pixel values
226 * @throws IllegalArgumentException if {@code space} is not a
227 * TYPE_RGB space or if the min/max normalized component
228 * values are not 0.0/1.0.
229 */
230 public DirectColorModel(ColorSpace space, int bits, int rmask,
231 int gmask, int bmask, int amask,
232 boolean isAlphaPremultiplied,
233 int transferType) {
234 super (space, bits, rmask, gmask, bmask, amask,
235 isAlphaPremultiplied,
236 amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
237 transferType);
238 if (ColorModel.isLinearRGBspace(colorSpace)) {
239 is_LinearRGB = true;
240 if (maxBits <= 8) {
241 lRGBprecision = 8;
242 tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
243 fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
244 } else {
245 lRGBprecision = 16;
246 tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
247 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
248 }
249 } else if (!is_sRGB) {
250 for (int i = 0; i < 3; i++) {
251 // super constructor checks that space is TYPE_RGB
252 // check here that min/max are all 0.0/1.0
253 if ((space.getMinValue(i) != 0.0f) ||
254 (space.getMaxValue(i) != 1.0f)) {
255 throw new IllegalArgumentException(
256 "Illegal min/max RGB component value");
257 }
258 }
259 }
260 setFields();
261 }
262
263 /**
264 * Returns the mask indicating which bits in an {@code int} pixel
265 * representation contain the red color component.
266 * @return the mask, which indicates which bits of the {@code int}
267 * pixel representation contain the red color sample.
268 */
269 public final int getRedMask() {
270 return maskArray[0];
271 }
272
273 /**
274 * Returns the mask indicating which bits in an {@code int} pixel
275 * representation contain the green color component.
276 * @return the mask, which indicates which bits of the {@code int}
277 * pixel representation contain the green color sample.
278 */
279 public final int getGreenMask() {
280 return maskArray[1];
281 }
282
283 /**
284 * Returns the mask indicating which bits in an {@code int} pixel
285 * representation contain the blue color component.
286 * @return the mask, which indicates which bits of the {@code int}
287 * pixel representation contain the blue color sample.
288 */
289 public final int getBlueMask() {
290 return maskArray[2];
291 }
292
293 /**
294 * Returns the mask indicating which bits in an {@code int} pixel
295 * representation contain the alpha component.
296 * @return the mask, which indicates which bits of the {@code int}
297 * pixel representation contain the alpha sample.
298 */
299 public final int getAlphaMask() {
300 if (supportsAlpha) {
301 return maskArray[3];
302 } else {
303 return 0;
304 }
305 }
306
307
308 /*
309 * Given an int pixel in this ColorModel's ColorSpace, converts
310 * it to the default sRGB ColorSpace and returns the R, G, and B
311 * components as float values between 0.0 and 1.0.
312 */
313 private float[] getDefaultRGBComponents(int pixel) {
314 int components[] = getComponents(pixel, null, 0);
315 float norm[] = getNormalizedComponents(components, 0, null, 0);
316 // Note that getNormalizedComponents returns non-premultiplied values
317 return colorSpace.toRGB(norm);
318 }
319
320
321 private int getsRGBComponentFromsRGB(int pixel, int idx) {
322 int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
323 if (isAlphaPremultiplied) {
324 int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
325 c = (a == 0) ? 0 :
326 (int) (((c * scaleFactors[idx]) * 255.0f /
327 (a * scaleFactors[3])) + 0.5f);
328 } else if (scaleFactors[idx] != 1.0f) {
329 c = (int) ((c * scaleFactors[idx]) + 0.5f);
330 }
331 return c;
332 }
333
334
335 private int getsRGBComponentFromLinearRGB(int pixel, int idx) {
336 int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
337 if (isAlphaPremultiplied) {
338 float factor = (float) ((1 << lRGBprecision) - 1);
339 int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
340 c = (a == 0) ? 0 :
341 (int) (((c * scaleFactors[idx]) * factor /
342 (a * scaleFactors[3])) + 0.5f);
343 } else if (nBits[idx] != lRGBprecision) {
344 if (lRGBprecision == 16) {
345 c = (int) ((c * scaleFactors[idx] * 257.0f) + 0.5f);
346 } else {
347 c = (int) ((c * scaleFactors[idx]) + 0.5f);
348 }
349 }
350 // now range of c is 0-255 or 0-65535, depending on lRGBprecision
351 return tosRGB8LUT[c] & 0xff;
352 }
353
354
355 /**
356 * Returns the red color component for the specified pixel, scaled
357 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A
358 * color conversion is done if necessary. The pixel value is specified
359 * as an {@code int}.
360 * The returned value is a non pre-multiplied value. Thus, if the
361 * alpha is premultiplied, this method divides it out before returning
362 * the value. If the alpha value is 0, for example, the red value
363 * is 0.
364 * @param pixel the specified pixel
365 * @return the red color component for the specified pixel, from
366 * 0 to 255 in the sRGB {@code ColorSpace}.
367 */
368 public final int getRed(int pixel) {
369 if (is_sRGB) {
370 return getsRGBComponentFromsRGB(pixel, 0);
371 } else if (is_LinearRGB) {
372 return getsRGBComponentFromLinearRGB(pixel, 0);
373 }
374 float rgb[] = getDefaultRGBComponents(pixel);
375 return (int) (rgb[0] * 255.0f + 0.5f);
376 }
377
378 /**
379 * Returns the green color component for the specified pixel, scaled
380 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A
381 * color conversion is done if necessary. The pixel value is specified
382 * as an {@code int}.
383 * The returned value is a non pre-multiplied value. Thus, if the
384 * alpha is premultiplied, this method divides it out before returning
385 * the value. If the alpha value is 0, for example, the green value
386 * is 0.
387 * @param pixel the specified pixel
388 * @return the green color component for the specified pixel, from
389 * 0 to 255 in the sRGB {@code ColorSpace}.
390 */
391 public final int getGreen(int pixel) {
392 if (is_sRGB) {
393 return getsRGBComponentFromsRGB(pixel, 1);
394 } else if (is_LinearRGB) {
395 return getsRGBComponentFromLinearRGB(pixel, 1);
396 }
397 float rgb[] = getDefaultRGBComponents(pixel);
398 return (int) (rgb[1] * 255.0f + 0.5f);
399 }
400
401 /**
402 * Returns the blue color component for the specified pixel, scaled
403 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A
404 * color conversion is done if necessary. The pixel value is specified
405 * as an {@code int}.
406 * The returned value is a non pre-multiplied value. Thus, if the
407 * alpha is premultiplied, this method divides it out before returning
408 * the value. If the alpha value is 0, for example, the blue value
409 * is 0.
410 * @param pixel the specified pixel
411 * @return the blue color component for the specified pixel, from
412 * 0 to 255 in the sRGB {@code ColorSpace}.
413 */
414 public final int getBlue(int pixel) {
415 if (is_sRGB) {
416 return getsRGBComponentFromsRGB(pixel, 2);
417 } else if (is_LinearRGB) {
418 return getsRGBComponentFromLinearRGB(pixel, 2);
419 }
420 float rgb[] = getDefaultRGBComponents(pixel);
421 return (int) (rgb[2] * 255.0f + 0.5f);
422 }
423
424 /**
425 * Returns the alpha component for the specified pixel, scaled
426 * from 0 to 255. The pixel value is specified as an {@code int}.
427 * @param pixel the specified pixel
428 * @return the value of the alpha component of {@code pixel}
429 * from 0 to 255.
430 */
431 public final int getAlpha(int pixel) {
432 if (!supportsAlpha) return 255;
433 int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
434 if (scaleFactors[3] != 1.0f) {
435 a = (int)(a * scaleFactors[3] + 0.5f);
436 }
437 return a;
438 }
439
440 /**
441 * Returns the color/alpha components of the pixel in the default
442 * RGB color model format. A color conversion is done if necessary.
443 * The pixel value is specified as an {@code int}.
444 * The returned value is in a non pre-multiplied format. Thus, if
445 * the alpha is premultiplied, this method divides it out of the
446 * color components. If the alpha value is 0, for example, the color
447 * values are each 0.
448 * @param pixel the specified pixel
449 * @return the RGB value of the color/alpha components of the specified
450 * pixel.
451 * @see ColorModel#getRGBdefault
452 */
453 public final int getRGB(int pixel) {
454 if (is_sRGB || is_LinearRGB) {
455 return (getAlpha(pixel) << 24)
456 | (getRed(pixel) << 16)
457 | (getGreen(pixel) << 8)
458 | (getBlue(pixel) << 0);
459 }
460 float rgb[] = getDefaultRGBComponents(pixel);
461 return (getAlpha(pixel) << 24)
462 | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
463 | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
464 | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
465 }
466
467 /**
468 * Returns the red color component for the specified pixel, scaled
469 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A
470 * color conversion is done if necessary. The pixel value is specified
471 * by an array of data elements of type {@code transferType} passed
472 * in as an object reference.
473 * The returned value is a non pre-multiplied value. Thus, if the
474 * alpha is premultiplied, this method divides it out before returning
475 * the value. If the alpha value is 0, for example, the red value
476 * is 0.
477 * If {@code inData} is not a primitive array of type
478 * {@code transferType}, a {@code ClassCastException} is
479 * thrown. An {@code ArrayIndexOutOfBoundsException} is
480 * thrown if {@code inData} is not large enough to hold a
481 * pixel value for this {@code ColorModel}. Since
482 * {@code DirectColorModel} can be subclassed, subclasses inherit
483 * the implementation of this method and if they don't override it
484 * then they throw an exception if they use an unsupported
485 * {@code transferType}.
486 * An {@code UnsupportedOperationException} is thrown if this
487 * {@code transferType} is not supported by this
488 * {@code ColorModel}.
489 * @param inData the array containing the pixel value
490 * @return the value of the red component of the specified pixel.
491 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
492 * large enough to hold a pixel value for this color model
493 * @throws ClassCastException if {@code inData} is not a
494 * primitive array of type {@code transferType}
495 * @throws UnsupportedOperationException if this {@code transferType}
496 * is not supported by this color model
497 */
498 public int getRed(Object inData) {
499 int pixel=0;
500 switch (transferType) {
501 case DataBuffer.TYPE_BYTE:
502 byte bdata[] = (byte[])inData;
503 pixel = bdata[0] & 0xff;
504 break;
505 case DataBuffer.TYPE_USHORT:
506 short sdata[] = (short[])inData;
507 pixel = sdata[0] & 0xffff;
508 break;
509 case DataBuffer.TYPE_INT:
510 int idata[] = (int[])inData;
511 pixel = idata[0];
512 break;
513 default:
514 throw new UnsupportedOperationException("This method has not been "+
515 "implemented for transferType " + transferType);
516 }
517 return getRed(pixel);
518 }
519
520
521 /**
522 * Returns the green color component for the specified pixel, scaled
523 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A
524 * color conversion is done if necessary. The pixel value is specified
525 * by an array of data elements of type {@code transferType} passed
526 * in as an object reference.
527 * The returned value is a non pre-multiplied value. Thus, if the
528 * alpha is premultiplied, this method divides it out before returning
529 * the value. If the alpha value is 0, for example, the green value
530 * is 0. If {@code inData} is not a primitive array of type
531 * {@code transferType}, a {@code ClassCastException} is thrown.
532 * An {@code ArrayIndexOutOfBoundsException} is
533 * thrown if {@code inData} is not large enough to hold a pixel
534 * value for this {@code ColorModel}. Since
535 * {@code DirectColorModel} can be subclassed, subclasses inherit
536 * the implementation of this method and if they don't override it
537 * then they throw an exception if they use an unsupported
538 * {@code transferType}.
539 * An {@code UnsupportedOperationException} is
540 * thrown if this {@code transferType} is not supported by this
541 * {@code ColorModel}.
542 * @param inData the array containing the pixel value
543 * @return the value of the green component of the specified pixel.
544 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
545 * large enough to hold a pixel value for this color model
546 * @throws ClassCastException if {@code inData} is not a
547 * primitive array of type {@code transferType}
548 * @throws UnsupportedOperationException if this {@code transferType}
549 * is not supported by this color model
550 */
551 public int getGreen(Object inData) {
552 int pixel=0;
553 switch (transferType) {
554 case DataBuffer.TYPE_BYTE:
555 byte bdata[] = (byte[])inData;
556 pixel = bdata[0] & 0xff;
557 break;
558 case DataBuffer.TYPE_USHORT:
559 short sdata[] = (short[])inData;
560 pixel = sdata[0] & 0xffff;
561 break;
562 case DataBuffer.TYPE_INT:
563 int idata[] = (int[])inData;
564 pixel = idata[0];
565 break;
566 default:
567 throw new UnsupportedOperationException("This method has not been "+
568 "implemented for transferType " + transferType);
569 }
570 return getGreen(pixel);
571 }
572
573
574 /**
575 * Returns the blue color component for the specified pixel, scaled
576 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A
577 * color conversion is done if necessary. The pixel value is specified
578 * by an array of data elements of type {@code transferType} passed
579 * in as an object reference.
580 * The returned value is a non pre-multiplied value. Thus, if the
581 * alpha is premultiplied, this method divides it out before returning
582 * the value. If the alpha value is 0, for example, the blue value
583 * is 0. If {@code inData} is not a primitive array of type
584 * {@code transferType}, a {@code ClassCastException} is thrown.
585 * An {@code ArrayIndexOutOfBoundsException} is
586 * thrown if {@code inData} is not large enough to hold a pixel
587 * value for this {@code ColorModel}. Since
588 * {@code DirectColorModel} can be subclassed, subclasses inherit
589 * the implementation of this method and if they don't override it
590 * then they throw an exception if they use an unsupported
591 * {@code transferType}.
592 * An {@code UnsupportedOperationException} is
593 * thrown if this {@code transferType} is not supported by this
594 * {@code ColorModel}.
595 * @param inData the array containing the pixel value
596 * @return the value of the blue component of the specified pixel.
597 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not
598 * large enough to hold a pixel value for this color model
599 * @throws ClassCastException if {@code inData} is not a
600 * primitive array of type {@code transferType}
601 * @throws UnsupportedOperationException if this {@code transferType}
602 * is not supported by this color model
603 */
604 public int getBlue(Object inData) {
605 int pixel=0;
606 switch (transferType) {
607 case DataBuffer.TYPE_BYTE:
608 byte bdata[] = (byte[])inData;
609 pixel = bdata[0] & 0xff;
610 break;
611 case DataBuffer.TYPE_USHORT:
612 short sdata[] = (short[])inData;
613 pixel = sdata[0] & 0xffff;
614 break;
615 case DataBuffer.TYPE_INT:
616 int idata[] = (int[])inData;
617 pixel = idata[0];
618 break;
619 default:
620 throw new UnsupportedOperationException("This method has not been "+
621 "implemented for transferType " + transferType);
622 }
623 return getBlue(pixel);
624 }
625
626 /**
627 * Returns the alpha component for the specified pixel, scaled
628 * from 0 to 255. The pixel value is specified by an array of data
629 * elements of type {@code transferType} passed in as an object
630 * reference.
631 * If {@code inData} is not a primitive array of type
632 * {@code transferType}, a {@code ClassCastException} is
633 * thrown. An {@code ArrayIndexOutOfBoundsException} is
634 * thrown if {@code inData} is not large enough to hold a pixel
635 * value for this {@code ColorModel}. Since
636 * {@code DirectColorModel} can be subclassed, subclasses inherit
637 * the implementation of this method and if they don't override it
638 * then they throw an exception if they use an unsupported
639 * {@code transferType}.
640 * If this {@code transferType} is not supported, an
641 * {@code UnsupportedOperationException} is thrown.
642 * @param inData the specified pixel
643 * @return the alpha component of the specified pixel, scaled from
644 * 0 to 255.
645 * @exception ClassCastException if {@code inData}
646 * is not a primitive array of type {@code transferType}
647 * @exception ArrayIndexOutOfBoundsException if
648 * {@code inData} is not large enough to hold a pixel value
649 * for this {@code ColorModel}
650 * @exception UnsupportedOperationException if this
651 * {@code tranferType} is not supported by this
652 * {@code ColorModel}
653 */
654 public int getAlpha(Object inData) {
655 int pixel=0;
656 switch (transferType) {
657 case DataBuffer.TYPE_BYTE:
658 byte bdata[] = (byte[])inData;
659 pixel = bdata[0] & 0xff;
660 break;
661 case DataBuffer.TYPE_USHORT:
662 short sdata[] = (short[])inData;
663 pixel = sdata[0] & 0xffff;
664 break;
665 case DataBuffer.TYPE_INT:
666 int idata[] = (int[])inData;
667 pixel = idata[0];
668 break;
669 default:
670 throw new UnsupportedOperationException("This method has not been "+
671 "implemented for transferType " + transferType);
672 }
673 return getAlpha(pixel);
674 }
675
676 /**
677 * Returns the color/alpha components for the specified pixel in the
678 * default RGB color model format. A color conversion is done if
679 * necessary. The pixel value is specified by an array of data
680 * elements of type {@code transferType} passed in as an object
681 * reference. If {@code inData} is not a primitive array of type
682 * {@code transferType}, a {@code ClassCastException} is
683 * thrown. An {@code ArrayIndexOutOfBoundsException} is
684 * thrown if {@code inData} is not large enough to hold a pixel
685 * value for this {@code ColorModel}.
686 * The returned value is in a non pre-multiplied format. Thus, if
687 * the alpha is premultiplied, this method divides it out of the
688 * color components. If the alpha value is 0, for example, the color
689 * values is 0. Since {@code DirectColorModel} can be
690 * subclassed, subclasses inherit the implementation of this method
691 * and if they don't override it then
692 * they throw an exception if they use an unsupported
693 * {@code transferType}.
694 *
695 * @param inData the specified pixel
696 * @return the color and alpha components of the specified pixel.
697 * @exception UnsupportedOperationException if this
698 * {@code transferType} is not supported by this
699 * {@code ColorModel}
700 * @see ColorModel#getRGBdefault
701 */
702 public int getRGB(Object inData) {
703 int pixel=0;
704 switch (transferType) {
705 case DataBuffer.TYPE_BYTE:
706 byte bdata[] = (byte[])inData;
707 pixel = bdata[0] & 0xff;
708 break;
709 case DataBuffer.TYPE_USHORT:
710 short sdata[] = (short[])inData;
711 pixel = sdata[0] & 0xffff;
712 break;
713 case DataBuffer.TYPE_INT:
714 int idata[] = (int[])inData;
715 pixel = idata[0];
716 break;
717 default:
718 throw new UnsupportedOperationException("This method has not been "+
719 "implemented for transferType " + transferType);
720 }
721 return getRGB(pixel);
722 }
723
724 /**
725 * Returns a data element array representation of a pixel in this
726 * {@code ColorModel}, given an integer pixel representation in the
727 * default RGB color model.
728 * This array can then be passed to the {@code setDataElements}
729 * method of a {@code WritableRaster} object. If the pixel variable
730 * is {@code null}, a new array is allocated. If {@code pixel}
731 * is not {@code null}, it must be a primitive array of type
732 * {@code transferType}; otherwise, a
733 * {@code ClassCastException} is thrown. An
734 * {@code ArrayIndexOutOfBoundsException} is
735 * thrown if {@code pixel} is not large enough to hold a pixel
736 * value for this {@code ColorModel}. The pixel array is returned.
737 * Since {@code DirectColorModel} can be subclassed, subclasses
738 * inherit the implementation of this method and if they don't
739 * override it then they throw an exception if they use an unsupported
740 * {@code transferType}.
741 *
742 * @param rgb the integer pixel representation in the default RGB
743 * color model
744 * @param pixel the specified pixel
745 * @return an array representation of the specified pixel in this
746 * {@code ColorModel}
747 * @exception ClassCastException if {@code pixel}
748 * is not a primitive array of type {@code transferType}
749 * @exception ArrayIndexOutOfBoundsException if
750 * {@code pixel} is not large enough to hold a pixel value
751 * for this {@code ColorModel}
752 * @exception UnsupportedOperationException if this
753 * {@code transferType} is not supported by this
754 * {@code ColorModel}
755 * @see WritableRaster#setDataElements
756 * @see SampleModel#setDataElements
757 */
758 public Object getDataElements(int rgb, Object pixel) {
759 //REMIND: maybe more efficient not to use int array for
760 //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
761 int intpixel[] = null;
762 if (transferType == DataBuffer.TYPE_INT &&
763 pixel != null) {
764 intpixel = (int[])pixel;
765 intpixel[0] = 0;
766 } else {
767 intpixel = new int[1];
768 }
769
770 ColorModel defaultCM = ColorModel.getRGBdefault();
771 if (this == defaultCM || equals(defaultCM)) {
772 intpixel[0] = rgb;
773 return intpixel;
774 }
775
776 int red, grn, blu, alp;
777 red = (rgb>>16) & 0xff;
778 grn = (rgb>>8) & 0xff;
779 blu = rgb & 0xff;
780 if (is_sRGB || is_LinearRGB) {
781 int precision;
782 float factor;
783 if (is_LinearRGB) {
784 if (lRGBprecision == 8) {
785 red = fromsRGB8LUT8[red] & 0xff;
786 grn = fromsRGB8LUT8[grn] & 0xff;
787 blu = fromsRGB8LUT8[blu] & 0xff;
788 precision = 8;
789 factor = 1.0f / 255.0f;
790 } else {
791 red = fromsRGB8LUT16[red] & 0xffff;
792 grn = fromsRGB8LUT16[grn] & 0xffff;
793 blu = fromsRGB8LUT16[blu] & 0xffff;
794 precision = 16;
795 factor = 1.0f / 65535.0f;
796 }
797 } else {
798 precision = 8;
799 factor = 1.0f / 255.0f;
800 }
801 if (supportsAlpha) {
802 alp = (rgb>>24) & 0xff;
803 if (isAlphaPremultiplied) {
804 factor *= (alp * (1.0f / 255.0f));
805 precision = -1; // force component calculations below
806 }
807 if (nBits[3] != 8) {
808 alp = (int)
809 ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
810 if (alp > ((1<<nBits[3]) - 1)) {
811 // fix 4412670 - see comment below
812 alp = (1<<nBits[3]) - 1;
813 }
814 }
815 intpixel[0] = alp << maskOffsets[3];
816 }
817 if (nBits[0] != precision) {
818 red = (int) ((red * factor * ((1<<nBits[0]) - 1)) + 0.5f);
819 }
820 if (nBits[1] != precision) {
821 grn = (int) ((grn * factor * ((1<<nBits[1]) - 1)) + 0.5f);
822 }
823 if (nBits[2] != precision) {
824 blu = (int) ((blu * factor * ((1<<nBits[2]) - 1)) + 0.5f);
825 }
826 } else {
827 // Need to convert the color
828 float[] norm = new float[3];
829 float factor = 1.0f / 255.0f;
830 norm[0] = red * factor;
831 norm[1] = grn * factor;
832 norm[2] = blu * factor;
833 norm = colorSpace.fromRGB(norm);
834 if (supportsAlpha) {
835 alp = (rgb>>24) & 0xff;
836 if (isAlphaPremultiplied) {
837 factor *= alp;
838 for (int i = 0; i < 3; i++) {
839 norm[i] *= factor;
840 }
841 }
842 if (nBits[3] != 8) {
843 alp = (int)
844 ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
845 if (alp > ((1<<nBits[3]) - 1)) {
846 // fix 4412670 - see comment below
847 alp = (1<<nBits[3]) - 1;
848 }
849 }
850 intpixel[0] = alp << maskOffsets[3];
851 }
852 red = (int) ((norm[0] * ((1<<nBits[0]) - 1)) + 0.5f);
853 grn = (int) ((norm[1] * ((1<<nBits[1]) - 1)) + 0.5f);
854 blu = (int) ((norm[2] * ((1<<nBits[2]) - 1)) + 0.5f);
855 }
856
857 if (maxBits > 23) {
858 // fix 4412670 - for components of 24 or more bits
859 // some calculations done above with float precision
860 // may lose enough precision that the integer result
861 // overflows nBits, so we need to clamp.
862 if (red > ((1<<nBits[0]) - 1)) {
863 red = (1<<nBits[0]) - 1;
864 }
865 if (grn > ((1<<nBits[1]) - 1)) {
866 grn = (1<<nBits[1]) - 1;
867 }
868 if (blu > ((1<<nBits[2]) - 1)) {
869 blu = (1<<nBits[2]) - 1;
870 }
871 }
872
873 intpixel[0] |= (red << maskOffsets[0]) |
874 (grn << maskOffsets[1]) |
875 (blu << maskOffsets[2]);
876
877 switch (transferType) {
878 case DataBuffer.TYPE_BYTE: {
879 byte bdata[];
880 if (pixel == null) {
881 bdata = new byte[1];
882 } else {
883 bdata = (byte[])pixel;
884 }
885 bdata[0] = (byte)(0xff&intpixel[0]);
886 return bdata;
887 }
888 case DataBuffer.TYPE_USHORT:{
889 short sdata[];
890 if (pixel == null) {
891 sdata = new short[1];
892 } else {
893 sdata = (short[])pixel;
894 }
895 sdata[0] = (short)(intpixel[0]&0xffff);
896 return sdata;
897 }
898 case DataBuffer.TYPE_INT:
899 return intpixel;
900 }
901 throw new UnsupportedOperationException("This method has not been "+
902 "implemented for transferType " + transferType);
903
904 }
905
906 /**
907 * Returns an array of unnormalized color/alpha components given a pixel
908 * in this {@code ColorModel}. The pixel value is specified as an
909 * {@code int}. If the {@code components} array is
910 * {@code null}, a new array is allocated. The
911 * {@code components} array is returned. Color/alpha components are
912 * stored in the {@code components} array starting at
913 * {@code offset}, even if the array is allocated by this method.
914 * An {@code ArrayIndexOutOfBoundsException} is thrown if the
915 * {@code components} array is not {@code null} and is not large
916 * enough to hold all the color and alpha components, starting at
917 * {@code offset}.
918 * @param pixel the specified pixel
919 * @param components the array to receive the color and alpha
920 * components of the specified pixel
921 * @param offset the offset into the {@code components} array at
922 * which to start storing the color and alpha components
923 * @return an array containing the color and alpha components of the
924 * specified pixel starting at the specified offset.
925 */
926 public final int[] getComponents(int pixel, int[] components, int offset) {
927 if (components == null) {
928 components = new int[offset+numComponents];
929 }
930
931 for (int i=0; i < numComponents; i++) {
932 components[offset+i] = (pixel & maskArray[i]) >>> maskOffsets[i];
933 }
934
935 return components;
936 }
937
938 /**
939 * Returns an array of unnormalized color/alpha components given a pixel
940 * in this {@code ColorModel}. The pixel value is specified by an
941 * array of data elements of type {@code transferType} passed in as
942 * an object reference. If {@code pixel} is not a primitive array
943 * of type {@code transferType}, a {@code ClassCastException}
944 * is thrown. An {@code ArrayIndexOutOfBoundsException} is
945 * thrown if {@code pixel} is not large enough to hold a
946 * pixel value for this {@code ColorModel}. If the
947 * {@code components} array is {@code null}, a new
948 * array is allocated. The {@code components} array is returned.
949 * Color/alpha components are stored in the {@code components} array
950 * starting at {@code offset}, even if the array is allocated by
951 * this method. An {@code ArrayIndexOutOfBoundsException}
952 * is thrown if the {@code components} array is not
953 * {@code null} and is not large enough to hold all the color and
954 * alpha components, starting at {@code offset}.
955 * Since {@code DirectColorModel} can be subclassed, subclasses
956 * inherit the implementation of this method and if they don't
957 * override it then they throw an exception if they use an unsupported
958 * {@code transferType}.
959 * @param pixel the specified pixel
960 * @param components the array to receive the color and alpha
961 * components of the specified pixel
962 * @param offset the offset into the {@code components} array at
963 * which to start storing the color and alpha components
964 * @return an array containing the color and alpha components of the
965 * specified pixel starting at the specified offset.
966 * @exception ClassCastException if {@code pixel}
967 * is not a primitive array of type {@code transferType}
968 * @exception ArrayIndexOutOfBoundsException if
969 * {@code pixel} is not large enough to hold a pixel value
970 * for this {@code ColorModel}, or if {@code components}
971 * is not {@code null} and is not large enough to hold all the
972 * color and alpha components, starting at {@code offset}
973 * @exception UnsupportedOperationException if this
974 * {@code transferType} is not supported by this
975 * color model
976 */
977 public final int[] getComponents(Object pixel, int[] components,
978 int offset) {
979 int intpixel=0;
980 switch (transferType) {
981 case DataBuffer.TYPE_BYTE:
982 byte bdata[] = (byte[])pixel;
983 intpixel = bdata[0] & 0xff;
984 break;
985 case DataBuffer.TYPE_USHORT:
986 short sdata[] = (short[])pixel;
987 intpixel = sdata[0] & 0xffff;
988 break;
989 case DataBuffer.TYPE_INT:
990 int idata[] = (int[])pixel;
991 intpixel = idata[0];
992 break;
993 default:
994 throw new UnsupportedOperationException("This method has not been "+
995 "implemented for transferType " + transferType);
996 }
997 return getComponents(intpixel, components, offset);
998 }
999
1000 /**
1001 * Creates a {@code WritableRaster} with the specified width and
1002 * height that has a data layout ({@code SampleModel}) compatible
1003 * with this {@code ColorModel}.
1004 * @param w the width to apply to the new {@code WritableRaster}
1005 * @param h the height to apply to the new {@code WritableRaster}
1006 * @return a {@code WritableRaster} object with the specified
1007 * width and height.
1008 * @throws IllegalArgumentException if {@code w} or {@code h}
1009 * is less than or equal to zero
1010 * @see WritableRaster
1011 * @see SampleModel
1012 */
1013 public final WritableRaster createCompatibleWritableRaster (int w,
1014 int h) {
1015 if ((w <= 0) || (h <= 0)) {
1016 throw new IllegalArgumentException("Width (" + w + ") and height (" + h +
1017 ") cannot be <= 0");
1018 }
1019 int[] bandmasks;
1020 if (supportsAlpha) {
1021 bandmasks = new int[4];
1022 bandmasks[3] = alpha_mask;
1023 }
1024 else {
1025 bandmasks = new int[3];
1026 }
1027 bandmasks[0] = red_mask;
1028 bandmasks[1] = green_mask;
1029 bandmasks[2] = blue_mask;
1030
1031 if (pixel_bits > 16) {
1032 return Raster.createPackedRaster(DataBuffer.TYPE_INT,
1033 w,h,bandmasks,null);
1034 }
1035 else if (pixel_bits > 8) {
1036 return Raster.createPackedRaster(DataBuffer.TYPE_USHORT,
1037 w,h,bandmasks,null);
1038 }
1039 else {
1040 return Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
1041 w,h,bandmasks,null);
1042 }
1043 }
1044
1045 /**
1046 * Returns a pixel value represented as an {@code int} in this
1047 * {@code ColorModel}, given an array of unnormalized color/alpha
1048 * components. An {@code ArrayIndexOutOfBoundsException} is
1049 * thrown if the {@code components} array is
1050 * not large enough to hold all the color and alpha components, starting
1051 * at {@code offset}.
1052 * @param components an array of unnormalized color and alpha
1053 * components
1054 * @param offset the index into {@code components} at which to
1055 * begin retrieving the color and alpha components
1056 * @return an {@code int} pixel value in this
1057 * {@code ColorModel} corresponding to the specified components.
1058 * @exception ArrayIndexOutOfBoundsException if
1059 * the {@code components} array is not large enough to
1060 * hold all of the color and alpha components starting at
1061 * {@code offset}
1062 */
1063 public int getDataElement(int[] components, int offset) {
1064 int pixel = 0;
1065 for (int i=0; i < numComponents; i++) {
1066 pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
1067 }
1068 return pixel;
1069 }
1070
1071 /**
1072 * Returns a data element array representation of a pixel in this
1073 * {@code ColorModel}, given an array of unnormalized color/alpha
1074 * components.
1075 * This array can then be passed to the {@code setDataElements}
1076 * method of a {@code WritableRaster} object.
1077 * An {@code ArrayIndexOutOfBoundsException} is thrown if the
1078 * {@code components} array
1079 * is not large enough to hold all the color and alpha components,
1080 * starting at offset. If the {@code obj} variable is
1081 * {@code null}, a new array is allocated. If {@code obj} is
1082 * not {@code null}, it must be a primitive array
1083 * of type {@code transferType}; otherwise, a
1084 * {@code ClassCastException} is thrown.
1085 * An {@code ArrayIndexOutOfBoundsException} is thrown if
1086 * {@code obj} is not large enough to hold a pixel value for this
1087 * {@code ColorModel}.
1088 * Since {@code DirectColorModel} can be subclassed, subclasses
1089 * inherit the implementation of this method and if they don't
1090 * override it then they throw an exception if they use an unsupported
1091 * {@code transferType}.
1092 * @param components an array of unnormalized color and alpha
1093 * components
1094 * @param offset the index into {@code components} at which to
1095 * begin retrieving color and alpha components
1096 * @param obj the {@code Object} representing an array of color
1097 * and alpha components
1098 * @return an {@code Object} representing an array of color and
1099 * alpha components.
1100 * @exception ClassCastException if {@code obj}
1101 * is not a primitive array of type {@code transferType}
1102 * @exception ArrayIndexOutOfBoundsException if
1103 * {@code obj} is not large enough to hold a pixel value
1104 * for this {@code ColorModel} or the {@code components}
1105 * array is not large enough to hold all of the color and alpha
1106 * components starting at {@code offset}
1107 * @exception UnsupportedOperationException if this
1108 * {@code transferType} is not supported by this
1109 * color model
1110 * @see WritableRaster#setDataElements
1111 * @see SampleModel#setDataElements
1112 */
1113 public Object getDataElements(int[] components, int offset, Object obj) {
1114 int pixel = 0;
1115 for (int i=0; i < numComponents; i++) {
1116 pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
1117 }
1118 switch (transferType) {
1119 case DataBuffer.TYPE_BYTE:
1120 if (obj instanceof byte[]) {
1121 byte bdata[] = (byte[])obj;
1122 bdata[0] = (byte)(pixel&0xff);
1123 return bdata;
1124 } else {
1125 byte bdata[] = {(byte)(pixel&0xff)};
1126 return bdata;
1127 }
1128 case DataBuffer.TYPE_USHORT:
1129 if (obj instanceof short[]) {
1130 short sdata[] = (short[])obj;
1131 sdata[0] = (short)(pixel&0xffff);
1132 return sdata;
1133 } else {
1134 short sdata[] = {(short)(pixel&0xffff)};
1135 return sdata;
1136 }
1137 case DataBuffer.TYPE_INT:
1138 if (obj instanceof int[]) {
1139 int idata[] = (int[])obj;
1140 idata[0] = pixel;
1141 return idata;
1142 } else {
1143 int idata[] = {pixel};
1144 return idata;
1145 }
1146 default:
1147 throw new ClassCastException("This method has not been "+
1148 "implemented for transferType " + transferType);
1149 }
1150 }
1151
1152 /**
1153 * Forces the raster data to match the state specified in the
1154 * {@code isAlphaPremultiplied} variable, assuming the data is
1155 * currently correctly described by this {@code ColorModel}. It
1156 * may multiply or divide the color raster data by alpha, or do
1157 * nothing if the data is in the correct state. If the data needs to
1158 * be coerced, this method will also return an instance of this
1159 * {@code ColorModel} with the {@code isAlphaPremultiplied}
1160 * flag set appropriately. This method will throw a
1161 * {@code UnsupportedOperationException} if this transferType is
1162 * not supported by this {@code ColorModel}. Since
1163 * {@code ColorModel} can be subclassed, subclasses inherit the
1164 * implementation of this method and if they don't override it then
1165 * they throw an exception if they use an unsupported transferType.
1166 *
1167 * @param raster the {@code WritableRaster} data
1168 * @param isAlphaPremultiplied {@code true} if the alpha is
1169 * premultiplied; {@code false} otherwise
1170 * @return a {@code ColorModel} object that represents the
1171 * coerced data.
1172 * @exception UnsupportedOperationException if this
1173 * {@code transferType} is not supported by this
1174 * color model
1175 */
1176 public final ColorModel coerceData (WritableRaster raster,
1177 boolean isAlphaPremultiplied)
1178 {
1179 if (!supportsAlpha ||
1180 this.isAlphaPremultiplied() == isAlphaPremultiplied) {
1181 return this;
1182 }
1183
1184 int w = raster.getWidth();
1185 int h = raster.getHeight();
1186 int aIdx = numColorComponents;
1187 float normAlpha;
1188 float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
1189
1190 int rminX = raster.getMinX();
1191 int rY = raster.getMinY();
1192 int rX;
1193 int pixel[] = null;
1194 int zpixel[] = null;
1195
1196 if (isAlphaPremultiplied) {
1197 // Must mean that we are currently not premultiplied so
1198 // multiply by alpha
1199 switch (transferType) {
1200 case DataBuffer.TYPE_BYTE: {
1201 for (int y = 0; y < h; y++, rY++) {
1202 rX = rminX;
1203 for (int x = 0; x < w; x++, rX++) {
1204 pixel = raster.getPixel(rX, rY, pixel);
1205 normAlpha = pixel[aIdx] * alphaScale;
1206 if (normAlpha != 0.f) {
1207 for (int c=0; c < aIdx; c++) {
1208 pixel[c] = (int) (pixel[c] * normAlpha +
1209 0.5f);
1210 }
1211 raster.setPixel(rX, rY, pixel);
1212 } else {
1213 if (zpixel == null) {
1214 zpixel = new int[numComponents];
1215 java.util.Arrays.fill(zpixel, 0);
1216 }
1217 raster.setPixel(rX, rY, zpixel);
1218 }
1219 }
1220 }
1221 }
1222 break;
1223 case DataBuffer.TYPE_USHORT: {
1224 for (int y = 0; y < h; y++, rY++) {
1225 rX = rminX;
1226 for (int x = 0; x < w; x++, rX++) {
1227 pixel = raster.getPixel(rX, rY, pixel);
1228 normAlpha = pixel[aIdx] * alphaScale;
1229 if (normAlpha != 0.f) {
1230 for (int c=0; c < aIdx; c++) {
1231 pixel[c] = (int) (pixel[c] * normAlpha +
1232 0.5f);
1233 }
1234 raster.setPixel(rX, rY, pixel);
1235 } else {
1236 if (zpixel == null) {
1237 zpixel = new int[numComponents];
1238 java.util.Arrays.fill(zpixel, 0);
1239 }
1240 raster.setPixel(rX, rY, zpixel);
1241 }
1242 }
1243 }
1244 }
1245 break;
1246 case DataBuffer.TYPE_INT: {
1247 for (int y = 0; y < h; y++, rY++) {
1248 rX = rminX;
1249 for (int x = 0; x < w; x++, rX++) {
1250 pixel = raster.getPixel(rX, rY, pixel);
1251 normAlpha = pixel[aIdx] * alphaScale;
1252 if (normAlpha != 0.f) {
1253 for (int c=0; c < aIdx; c++) {
1254 pixel[c] = (int) (pixel[c] * normAlpha +
1255 0.5f);
1256 }
1257 raster.setPixel(rX, rY, pixel);
1258 } else {
1259 if (zpixel == null) {
1260 zpixel = new int[numComponents];
1261 java.util.Arrays.fill(zpixel, 0);
1262 }
1263 raster.setPixel(rX, rY, zpixel);
1264 }
1265 }
1266 }
1267 }
1268 break;
1269 default:
1270 throw new UnsupportedOperationException("This method has not been "+
1271 "implemented for transferType " + transferType);
1272 }
1273 }
1274 else {
1275 // We are premultiplied and want to divide it out
1276 switch (transferType) {
1277 case DataBuffer.TYPE_BYTE: {
1278 for (int y = 0; y < h; y++, rY++) {
1279 rX = rminX;
1280 for (int x = 0; x < w; x++, rX++) {
1281 pixel = raster.getPixel(rX, rY, pixel);
1282 normAlpha = pixel[aIdx] * alphaScale;
1283 if (normAlpha != 0.0f) {
1284 float invAlpha = 1.0f / normAlpha;
1285 for (int c=0; c < aIdx; c++) {
1286 pixel[c] = (int) (pixel[c] * invAlpha +
1287 0.5f);
1288 }
1289 raster.setPixel(rX, rY, pixel);
1290 }
1291 }
1292 }
1293 }
1294 break;
1295 case DataBuffer.TYPE_USHORT: {
1296 for (int y = 0; y < h; y++, rY++) {
1297 rX = rminX;
1298 for (int x = 0; x < w; x++, rX++) {
1299 pixel = raster.getPixel(rX, rY, pixel);
1300 normAlpha = pixel[aIdx] * alphaScale;
1301 if (normAlpha != 0) {
1302 float invAlpha = 1.0f / normAlpha;
1303 for (int c=0; c < aIdx; c++) {
1304 pixel[c] = (int) (pixel[c] * invAlpha +
1305 0.5f);
1306 }
1307 raster.setPixel(rX, rY, pixel);
1308 }
1309 }
1310 }
1311 }
1312 break;
1313 case DataBuffer.TYPE_INT: {
1314 for (int y = 0; y < h; y++, rY++) {
1315 rX = rminX;
1316 for (int x = 0; x < w; x++, rX++) {
1317 pixel = raster.getPixel(rX, rY, pixel);
1318 normAlpha = pixel[aIdx] * alphaScale;
1319 if (normAlpha != 0) {
1320 float invAlpha = 1.0f / normAlpha;
1321 for (int c=0; c < aIdx; c++) {
1322 pixel[c] = (int) (pixel[c] * invAlpha +
1323 0.5f);
1324 }
1325 raster.setPixel(rX, rY, pixel);
1326 }
1327 }
1328 }
1329 }
1330 break;
1331 default:
1332 throw new UnsupportedOperationException("This method has not been "+
1333 "implemented for transferType " + transferType);
1334 }
1335 }
1336
1337 // Return a new color model
1338 return new DirectColorModel(colorSpace, pixel_bits, maskArray[0],
1339 maskArray[1], maskArray[2], maskArray[3],
1340 isAlphaPremultiplied,
1341 transferType);
1342
1343 }
1344
1345 /**
1346 * Returns {@code true} if {@code raster} is compatible
1347 * with this {@code ColorModel} and {@code false} if it is
1348 * not.
1349 * @param raster the {@link Raster} object to test for compatibility
1350 * @return {@code true} if {@code raster} is compatible
1351 * with this {@code ColorModel}; {@code false} otherwise.
1352 */
1353 public boolean isCompatibleRaster(Raster raster) {
1354 SampleModel sm = raster.getSampleModel();
1355 SinglePixelPackedSampleModel spsm;
1356 if (sm instanceof SinglePixelPackedSampleModel) {
1357 spsm = (SinglePixelPackedSampleModel) sm;
1358 }
1359 else {
1360 return false;
1361 }
1362 if (spsm.getNumBands() != getNumComponents()) {
1363 return false;
1364 }
1365
1366 int[] bitMasks = spsm.getBitMasks();
1367 for (int i=0; i<numComponents; i++) {
1368 if (bitMasks[i] != maskArray[i]) {
1369 return false;
1370 }
1371 }
1372
1373 return (raster.getTransferType() == transferType);
1374 }
1375
1376 private void setFields() {
1377 // Set the private fields
1378 // REMIND: Get rid of these from the native code
1379 red_mask = maskArray[0];
1380 red_offset = maskOffsets[0];
1381 green_mask = maskArray[1];
1382 green_offset = maskOffsets[1];
1383 blue_mask = maskArray[2];
1384 blue_offset = maskOffsets[2];
1385 if (nBits[0] < 8) {
1386 red_scale = (1 << nBits[0]) - 1;
1387 }
1388 if (nBits[1] < 8) {
1389 green_scale = (1 << nBits[1]) - 1;
1390 }
1391 if (nBits[2] < 8) {
1392 blue_scale = (1 << nBits[2]) - 1;
1393 }
1394 if (supportsAlpha) {
1395 alpha_mask = maskArray[3];
1396 alpha_offset = maskOffsets[3];
1397 if (nBits[3] < 8) {
1398 alpha_scale = (1 << nBits[3]) - 1;
1399 }
1400 }
1401 }
1402
1403 /**
1404 * Returns a {@code String} that represents this
1405 * {@code DirectColorModel}.
1406 * @return a {@code String} representing this
1407 * {@code DirectColorModel}.
1408 */
1409 public String toString() {
1410 return new String("DirectColorModel: rmask="
1411 +Integer.toHexString(red_mask)+" gmask="
1412 +Integer.toHexString(green_mask)+" bmask="
1413 +Integer.toHexString(blue_mask)+" amask="
1414 +Integer.toHexString(alpha_mask));
1415 }
1416 }
1417