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 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 */ DirectColorModel(int bits, int rmask, int gmask, int bmask)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 */ DirectColorModel(int bits, int rmask, int gmask, int bmask, int amask)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 */ DirectColorModel(ColorSpace space, int bits, int rmask, int gmask, int bmask, int amask, boolean isAlphaPremultiplied, int transferType)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 */ getRedMask()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 */ getGreenMask()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 */ getBlueMask()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 */ getAlphaMask()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 */ getDefaultRGBComponents(int pixel)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 getsRGBComponentFromsRGB(int pixel, int idx)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 getsRGBComponentFromLinearRGB(int pixel, int idx)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 */ getRed(int pixel)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 */ getGreen(int pixel)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 */ getBlue(int pixel)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 */ getAlpha(int pixel)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 */ getRGB(int pixel)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 */ getRed(Object inData)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 */ getGreen(Object inData)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 */ getBlue(Object inData)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 */ getAlpha(Object inData)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 */ getRGB(Object inData)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 */ getDataElements(int rgb, Object pixel)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 */ getComponents(int pixel, int[] components, int offset)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 */ getComponents(Object pixel, int[] components, int offset)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 */ createCompatibleWritableRaster(int w, int h)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 */ getDataElement(int[] components, int offset)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 */ getDataElements(int[] components, int offset, Object obj)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 */ coerceData(WritableRaster raster, boolean isAlphaPremultiplied)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 */ isCompatibleRaster(Raster raster)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 setFields()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 */ toString()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