1 /* 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt.image; 27 28 import java.awt.color.ColorSpace; 29 import java.awt.color.ICC_ColorSpace; 30 import java.util.Arrays; 31 32 /** 33 * A {@code ColorModel} class that works with pixel values that 34 * represent color and alpha information as separate samples and that 35 * store each sample in a separate data element. This class can be 36 * used with an arbitrary {@code ColorSpace}. The number of 37 * color samples in the pixel values must be same as the number of 38 * color components in the {@code ColorSpace}. There may be a 39 * single alpha sample. 40 * <p> 41 * For those methods that use 42 * a primitive array pixel representation of type {@code transferType}, 43 * the array length is the same as the number of color and alpha samples. 44 * Color samples are stored first in the array followed by the alpha 45 * sample, if present. The order of the color samples is specified 46 * by the {@code ColorSpace}. Typically, this order reflects the 47 * name of the color space type. For example, for {@code TYPE_RGB}, 48 * index 0 corresponds to red, index 1 to green, and index 2 to blue. 49 * <p> 50 * The translation from pixel sample values to color/alpha components for 51 * display or processing purposes is based on a one-to-one correspondence of 52 * samples to components. 53 * Depending on the transfer type used to create an instance of 54 * {@code ComponentColorModel}, the pixel sample values 55 * represented by that instance may be signed or unsigned and may 56 * be of integral type or float or double (see below for details). 57 * The translation from sample values to normalized color/alpha components 58 * must follow certain rules. For float and double samples, the translation 59 * is an identity, i.e. normalized component values are equal to the 60 * corresponding sample values. For integral samples, the translation 61 * should be only a simple scale and offset, where the scale and offset 62 * constants may be different for each component. The result of 63 * applying the scale and offset constants is a set of color/alpha 64 * component values, which are guaranteed to fall within a certain 65 * range. Typically, the range for a color component will be the range 66 * defined by the {@code getMinValue} and {@code getMaxValue} 67 * methods of the {@code ColorSpace} class. The range for an 68 * alpha component should be 0.0 to 1.0. 69 * <p> 70 * Instances of {@code ComponentColorModel} created with transfer types 71 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 72 * and {@code DataBuffer.TYPE_INT} have pixel sample values which 73 * are treated as unsigned integral values. 74 * The number of bits in a color or alpha sample of a pixel value might not 75 * be the same as the number of bits for the corresponding color or alpha 76 * sample passed to the 77 * {@code ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)} 78 * constructor. In 79 * that case, this class assumes that the least significant n bits of a sample 80 * value hold the component value, where n is the number of significant bits 81 * for the component passed to the constructor. It also assumes that 82 * any higher-order bits in a sample value are zero. Thus, sample values 83 * range from 0 to 2<sup>n</sup> - 1. This class maps these sample values 84 * to normalized color component values such that 0 maps to the value 85 * obtained from the {@code ColorSpace's getMinValue} 86 * method for each component and 2<sup>n</sup> - 1 maps to the value 87 * obtained from {@code getMaxValue}. To create a 88 * {@code ComponentColorModel} with a different color sample mapping 89 * requires subclassing this class and overriding the 90 * {@code getNormalizedComponents(Object, float[], int)} method. 91 * The mapping for an alpha sample always maps 0 to 0.0 and 92 * 2<sup>n</sup> - 1 to 1.0. 93 * <p> 94 * For instances with unsigned sample values, 95 * the unnormalized color/alpha component representation is only 96 * supported if two conditions hold. First, sample value 0 must 97 * map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1 98 * to 1.0. Second the min/max range of all color components of the 99 * {@code ColorSpace} must be 0.0 to 1.0. In this case, the 100 * component representation is the n least 101 * significant bits of the corresponding sample. Thus each component is 102 * an unsigned integral value between 0 and 2<sup>n</sup> - 1, where 103 * n is the number of significant bits for a particular component. 104 * If these conditions are not met, any method taking an unnormalized 105 * component argument will throw an {@code IllegalArgumentException}. 106 * <p> 107 * Instances of {@code ComponentColorModel} created with transfer types 108 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, and 109 * {@code DataBuffer.TYPE_DOUBLE} have pixel sample values which 110 * are treated as signed short, float, or double values. 111 * Such instances do not support the unnormalized color/alpha component 112 * representation, so any methods taking such a representation as an argument 113 * will throw an {@code IllegalArgumentException} when called on one 114 * of these instances. The normalized component values of instances 115 * of this class have a range which depends on the transfer 116 * type as follows: for float samples, the full range of the float data 117 * type; for double samples, the full range of the float data type 118 * (resulting from casting double to float); for short samples, 119 * from approximately -maxVal to +maxVal, where maxVal is the per 120 * component maximum value for the {@code ColorSpace} 121 * (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps 122 * to +maxVal). A subclass may override the scaling for short sample 123 * values to normalized component values by overriding the 124 * {@code getNormalizedComponents(Object, float[], int)} method. 125 * For float and double samples, the normalized component values are 126 * taken to be equal to the corresponding sample values, and subclasses 127 * should not attempt to add any non-identity scaling for these transfer 128 * types. 129 * <p> 130 * Instances of {@code ComponentColorModel} created with transfer types 131 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, and 132 * {@code DataBuffer.TYPE_DOUBLE} 133 * use all the bits of all sample values. Thus all color/alpha components 134 * have 16 bits when using {@code DataBuffer.TYPE_SHORT}, 32 bits when 135 * using {@code DataBuffer.TYPE_FLOAT}, and 64 bits when using 136 * {@code DataBuffer.TYPE_DOUBLE}. When the 137 * {@code ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)} 138 * form of constructor is used with one of these transfer types, the 139 * bits array argument is ignored. 140 * <p> 141 * It is possible to have color/alpha sample values 142 * which cannot be reasonably interpreted as component values for rendering. 143 * This can happen when {@code ComponentColorModel} is subclassed to 144 * override the mapping of unsigned sample values to normalized color 145 * component values or when signed sample values outside a certain range 146 * are used. (As an example, specifying an alpha component as a signed 147 * short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can 148 * lead to unexpected results.) It is the 149 * responsibility of applications to appropriately scale pixel data before 150 * rendering such that color components fall within the normalized range 151 * of the {@code ColorSpace} (obtained using the {@code getMinValue} 152 * and {@code getMaxValue} methods of the {@code ColorSpace} class) 153 * and the alpha component is between 0.0 and 1.0. If color or alpha 154 * component values fall outside these ranges, rendering results are 155 * indeterminate. 156 * <p> 157 * Methods that use a single int pixel representation throw 158 * an {@code IllegalArgumentException}, unless the number of components 159 * for the {@code ComponentColorModel} is one and the component 160 * value is unsigned -- in other words, a single color component using 161 * a transfer type of {@code DataBuffer.TYPE_BYTE}, 162 * {@code DataBuffer.TYPE_USHORT}, or {@code DataBuffer.TYPE_INT} 163 * and no alpha. 164 * <p> 165 * A {@code ComponentColorModel} can be used in conjunction with a 166 * {@code ComponentSampleModel}, a {@code BandedSampleModel}, 167 * or a {@code PixelInterleavedSampleModel} to construct a 168 * {@code BufferedImage}. 169 * 170 * @see ColorModel 171 * @see ColorSpace 172 * @see ComponentSampleModel 173 * @see BandedSampleModel 174 * @see PixelInterleavedSampleModel 175 * @see BufferedImage 176 * 177 */ 178 public class ComponentColorModel extends ColorModel { 179 180 /** 181 * {@code signed} is {@code true} for {@code short}, 182 * {@code float}, and {@code double} transfer types; it 183 * is {@code false} for {@code byte}, {@code ushort}, 184 * and {@code int} transfer types. 185 */ 186 private boolean signed; // true for transfer types short, float, double 187 // false for byte, ushort, int 188 private boolean is_sRGB_stdScale; 189 private boolean is_LinearRGB_stdScale; 190 private boolean is_LinearGray_stdScale; 191 private boolean is_ICCGray_stdScale; 192 private byte[] tosRGB8LUT; 193 private byte[] fromsRGB8LUT8; 194 private short[] fromsRGB8LUT16; 195 private byte[] fromLinearGray16ToOtherGray8LUT; 196 private short[] fromLinearGray16ToOtherGray16LUT; 197 private boolean needScaleInit; 198 private boolean noUnnorm; 199 private boolean nonStdScale; 200 private float[] min; 201 private float[] diffMinMax; 202 private float[] compOffset; 203 private float[] compScale; 204 private volatile int hashCode; 205 206 /** 207 * Constructs a {@code ComponentColorModel} from the specified 208 * parameters. Color components will be in the specified 209 * {@code ColorSpace}. The supported transfer types are 210 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 211 * {@code DataBuffer.TYPE_INT}, 212 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, 213 * and {@code DataBuffer.TYPE_DOUBLE}. 214 * If not null, the {@code bits} array specifies the 215 * number of significant bits per color and alpha component and its 216 * length should be at least the number of components in the 217 * {@code ColorSpace} if there is no alpha 218 * information in the pixel values, or one more than this number if 219 * there is alpha information. When the {@code transferType} is 220 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, 221 * or {@code DataBuffer.TYPE_DOUBLE} the {@code bits} array 222 * argument is ignored. {@code hasAlpha} indicates whether alpha 223 * information is present. If {@code hasAlpha} is true, then 224 * the boolean {@code isAlphaPremultiplied} 225 * specifies how to interpret color and alpha samples in pixel values. 226 * If the boolean is true, color samples are assumed to have been 227 * multiplied by the alpha sample. The {@code transparency} 228 * specifies what alpha values can be represented by this color model. 229 * The acceptable {@code transparency} values are 230 * {@code OPAQUE}, {@code BITMASK} or {@code TRANSLUCENT}. 231 * The {@code transferType} is the type of primitive array used 232 * to represent pixel values. 233 * 234 * @param colorSpace The {@code ColorSpace} associated 235 * with this color model. 236 * @param bits The number of significant bits per component. 237 * May be null, in which case all bits of all 238 * component samples will be significant. 239 * Ignored if transferType is one of 240 * {@code DataBuffer.TYPE_SHORT}, 241 * {@code DataBuffer.TYPE_FLOAT}, or 242 * {@code DataBuffer.TYPE_DOUBLE}, 243 * in which case all bits of all component 244 * samples will be significant. 245 * @param hasAlpha If true, this color model supports alpha. 246 * @param isAlphaPremultiplied If true, alpha is premultiplied. 247 * @param transparency Specifies what alpha values can be represented 248 * by this color model. 249 * @param transferType Specifies the type of primitive array used to 250 * represent pixel values. 251 * 252 * @throws IllegalArgumentException If the {@code bits} array 253 * argument is not null, its length is less than the number of 254 * color and alpha components, and transferType is one of 255 * {@code DataBuffer.TYPE_BYTE}, 256 * {@code DataBuffer.TYPE_USHORT}, or 257 * {@code DataBuffer.TYPE_INT}. 258 * @throws IllegalArgumentException If transferType is not one of 259 * {@code DataBuffer.TYPE_BYTE}, 260 * {@code DataBuffer.TYPE_USHORT}, 261 * {@code DataBuffer.TYPE_INT}, 262 * {@code DataBuffer.TYPE_SHORT}, 263 * {@code DataBuffer.TYPE_FLOAT}, or 264 * {@code DataBuffer.TYPE_DOUBLE}. 265 * 266 * @see ColorSpace 267 * @see java.awt.Transparency 268 */ 269 public ComponentColorModel (ColorSpace colorSpace, 270 int[] bits, 271 boolean hasAlpha, 272 boolean isAlphaPremultiplied, 273 int transparency, 274 int transferType) { 275 super (bitsHelper(transferType, colorSpace, hasAlpha), 276 bitsArrayHelper(bits, transferType, colorSpace, hasAlpha), 277 colorSpace, hasAlpha, isAlphaPremultiplied, transparency, 278 transferType); 279 switch(transferType) { 280 case DataBuffer.TYPE_BYTE: 281 case DataBuffer.TYPE_USHORT: 282 case DataBuffer.TYPE_INT: 283 signed = false; 284 needScaleInit = true; 285 break; 286 case DataBuffer.TYPE_SHORT: 287 signed = true; 288 needScaleInit = true; 289 break; 290 case DataBuffer.TYPE_FLOAT: 291 case DataBuffer.TYPE_DOUBLE: 292 signed = true; 293 needScaleInit = false; 294 noUnnorm = true; 295 nonStdScale = false; 296 break; 297 default: 298 throw new IllegalArgumentException("This constructor is not "+ 299 "compatible with transferType " + transferType); 300 } 301 setupLUTs(); 302 } 303 304 /** 305 * Constructs a {@code ComponentColorModel} from the specified 306 * parameters. Color components will be in the specified 307 * {@code ColorSpace}. The supported transfer types are 308 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 309 * {@code DataBuffer.TYPE_INT}, 310 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, 311 * and {@code DataBuffer.TYPE_DOUBLE}. The number of significant 312 * bits per color and alpha component will be 8, 16, 32, 16, 32, or 64, 313 * respectively. The number of color components will be the 314 * number of components in the {@code ColorSpace}. There will be 315 * an alpha component if {@code hasAlpha} is {@code true}. 316 * If {@code hasAlpha} is true, then 317 * the boolean {@code isAlphaPremultiplied} 318 * specifies how to interpret color and alpha samples in pixel values. 319 * If the boolean is true, color samples are assumed to have been 320 * multiplied by the alpha sample. The {@code transparency} 321 * specifies what alpha values can be represented by this color model. 322 * The acceptable {@code transparency} values are 323 * {@code OPAQUE}, {@code BITMASK} or {@code TRANSLUCENT}. 324 * The {@code transferType} is the type of primitive array used 325 * to represent pixel values. 326 * 327 * @param colorSpace The {@code ColorSpace} associated 328 * with this color model. 329 * @param hasAlpha If true, this color model supports alpha. 330 * @param isAlphaPremultiplied If true, alpha is premultiplied. 331 * @param transparency Specifies what alpha values can be represented 332 * by this color model. 333 * @param transferType Specifies the type of primitive array used to 334 * represent pixel values. 335 * 336 * @throws IllegalArgumentException If transferType is not one of 337 * {@code DataBuffer.TYPE_BYTE}, 338 * {@code DataBuffer.TYPE_USHORT}, 339 * {@code DataBuffer.TYPE_INT}, 340 * {@code DataBuffer.TYPE_SHORT}, 341 * {@code DataBuffer.TYPE_FLOAT}, or 342 * {@code DataBuffer.TYPE_DOUBLE}. 343 * 344 * @see ColorSpace 345 * @see java.awt.Transparency 346 * @since 1.4 347 */ 348 public ComponentColorModel (ColorSpace colorSpace, 349 boolean hasAlpha, 350 boolean isAlphaPremultiplied, 351 int transparency, 352 int transferType) { 353 this(colorSpace, null, hasAlpha, isAlphaPremultiplied, 354 transparency, transferType); 355 } 356 357 private static int bitsHelper(int transferType, 358 ColorSpace colorSpace, 359 boolean hasAlpha) { 360 int numBits = DataBuffer.getDataTypeSize(transferType); 361 int numComponents = colorSpace.getNumComponents(); 362 if (hasAlpha) { 363 ++numComponents; 364 } 365 return numBits * numComponents; 366 } 367 368 private static int[] bitsArrayHelper(int[] origBits, 369 int transferType, 370 ColorSpace colorSpace, 371 boolean hasAlpha) { 372 switch(transferType) { 373 case DataBuffer.TYPE_BYTE: 374 case DataBuffer.TYPE_USHORT: 375 case DataBuffer.TYPE_INT: 376 if (origBits != null) { 377 return origBits; 378 } 379 break; 380 default: 381 break; 382 } 383 int numBits = DataBuffer.getDataTypeSize(transferType); 384 int numComponents = colorSpace.getNumComponents(); 385 if (hasAlpha) { 386 ++numComponents; 387 } 388 int[] bits = new int[numComponents]; 389 for (int i = 0; i < numComponents; i++) { 390 bits[i] = numBits; 391 } 392 return bits; 393 } 394 395 private void setupLUTs() { 396 // REMIND: there is potential to accelerate sRGB, LinearRGB, 397 // LinearGray, ICCGray, and non-ICC Gray spaces with non-standard 398 // scaling, if that becomes important 399 // 400 // NOTE: The is_xxx_stdScale and nonStdScale booleans are provisionally 401 // set here when this method is called at construction time. These 402 // variables may be set again when initScale is called later. 403 // When setupLUTs returns, nonStdScale is true if (the transferType 404 // is not float or double) AND (some minimum ColorSpace component 405 // value is not 0.0 OR some maximum ColorSpace component value 406 // is not 1.0). This is correct for the calls to 407 // getNormalizedComponents(Object, float[], int) from initScale(). 408 // initScale() may change the value nonStdScale based on the 409 // return value of getNormalizedComponents() - this will only 410 // happen if getNormalizedComponents() has been overridden by a 411 // subclass to make the mapping of min/max pixel sample values 412 // something different from min/max color component values. 413 if (is_sRGB) { 414 is_sRGB_stdScale = true; 415 nonStdScale = false; 416 } else if (ColorModel.isLinearRGBspace(colorSpace)) { 417 // Note that the built-in Linear RGB space has a normalized 418 // range of 0.0 - 1.0 for each coordinate. Usage of these 419 // LUTs makes that assumption. 420 is_LinearRGB_stdScale = true; 421 nonStdScale = false; 422 if (transferType == DataBuffer.TYPE_BYTE) { 423 tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT(); 424 fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT(); 425 } else { 426 tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT(); 427 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT(); 428 } 429 } else if ((colorSpaceType == ColorSpace.TYPE_GRAY) && 430 (colorSpace instanceof ICC_ColorSpace) && 431 (colorSpace.getMinValue(0) == 0.0f) && 432 (colorSpace.getMaxValue(0) == 1.0f)) { 433 // Note that a normalized range of 0.0 - 1.0 for the gray 434 // component is required, because usage of these LUTs makes 435 // that assumption. 436 ICC_ColorSpace ics = (ICC_ColorSpace) colorSpace; 437 is_ICCGray_stdScale = true; 438 nonStdScale = false; 439 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT(); 440 if (ColorModel.isLinearGRAYspace(ics)) { 441 is_LinearGray_stdScale = true; 442 if (transferType == DataBuffer.TYPE_BYTE) { 443 tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics); 444 } else { 445 tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics); 446 } 447 } else { 448 if (transferType == DataBuffer.TYPE_BYTE) { 449 tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics); 450 fromLinearGray16ToOtherGray8LUT = 451 ColorModel.getLinearGray16ToOtherGray8LUT(ics); 452 } else { 453 tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics); 454 fromLinearGray16ToOtherGray16LUT = 455 ColorModel.getLinearGray16ToOtherGray16LUT(ics); 456 } 457 } 458 } else if (needScaleInit) { 459 // if transferType is byte, ushort, int, or short and we 460 // don't already know the ColorSpace has minVlaue == 0.0f and 461 // maxValue == 1.0f for all components, we need to check that 462 // now and setup the min[] and diffMinMax[] arrays if necessary. 463 nonStdScale = false; 464 for (int i = 0; i < numColorComponents; i++) { 465 if ((colorSpace.getMinValue(i) != 0.0f) || 466 (colorSpace.getMaxValue(i) != 1.0f)) { 467 nonStdScale = true; 468 break; 469 } 470 } 471 if (nonStdScale) { 472 min = new float[numColorComponents]; 473 diffMinMax = new float[numColorComponents]; 474 for (int i = 0; i < numColorComponents; i++) { 475 min[i] = colorSpace.getMinValue(i); 476 diffMinMax[i] = colorSpace.getMaxValue(i) - min[i]; 477 } 478 } 479 } 480 } 481 482 private void initScale() { 483 // This method is called the first time any method which uses 484 // pixel sample value to color component value scaling information 485 // is called if the transferType supports non-standard scaling 486 // as defined above (byte, ushort, int, and short), unless the 487 // method is getNormalizedComponents(Object, float[], int) (that 488 // method must be overridden to use non-standard scaling). This 489 // method also sets up the noUnnorm boolean variable for these 490 // transferTypes. After this method is called, the nonStdScale 491 // variable will be true if getNormalizedComponents() maps a 492 // sample value of 0 to anything other than 0.0f OR maps a 493 // sample value of 2^^n - 1 (2^^15 - 1 for short transferType) 494 // to anything other than 1.0f. Note that this can be independent 495 // of the colorSpace min/max component values, if the 496 // getNormalizedComponents() method has been overridden for some 497 // reason, e.g. to provide greater dynamic range in the sample 498 // values than in the color component values. Unfortunately, 499 // this method can't be called at construction time, since a 500 // subclass may still have uninitialized state that would cause 501 // getNormalizedComponents() to return an incorrect result. 502 needScaleInit = false; // only needs to called once 503 if (nonStdScale || signed) { 504 // The unnormalized form is only supported for unsigned 505 // transferTypes and when the ColorSpace min/max values 506 // are 0.0/1.0. When this method is called nonStdScale is 507 // true if the latter condition does not hold. In addition, 508 // the unnormalized form requires that the full range of 509 // the pixel sample values map to the full 0.0 - 1.0 range 510 // of color component values. That condition is checked 511 // later in this method. 512 noUnnorm = true; 513 } else { 514 noUnnorm = false; 515 } 516 float[] lowVal, highVal; 517 switch (transferType) { 518 case DataBuffer.TYPE_BYTE: 519 { 520 byte[] bpixel = new byte[numComponents]; 521 for (int i = 0; i < numColorComponents; i++) { 522 bpixel[i] = 0; 523 } 524 if (supportsAlpha) { 525 bpixel[numColorComponents] = 526 (byte) ((1 << nBits[numColorComponents]) - 1); 527 } 528 lowVal = getNormalizedComponents(bpixel, null, 0); 529 for (int i = 0; i < numColorComponents; i++) { 530 bpixel[i] = (byte) ((1 << nBits[i]) - 1); 531 } 532 highVal = getNormalizedComponents(bpixel, null, 0); 533 } 534 break; 535 case DataBuffer.TYPE_USHORT: 536 { 537 short[] uspixel = new short[numComponents]; 538 for (int i = 0; i < numColorComponents; i++) { 539 uspixel[i] = 0; 540 } 541 if (supportsAlpha) { 542 uspixel[numColorComponents] = 543 (short) ((1 << nBits[numColorComponents]) - 1); 544 } 545 lowVal = getNormalizedComponents(uspixel, null, 0); 546 for (int i = 0; i < numColorComponents; i++) { 547 uspixel[i] = (short) ((1 << nBits[i]) - 1); 548 } 549 highVal = getNormalizedComponents(uspixel, null, 0); 550 } 551 break; 552 case DataBuffer.TYPE_INT: 553 { 554 int[] ipixel = new int[numComponents]; 555 for (int i = 0; i < numColorComponents; i++) { 556 ipixel[i] = 0; 557 } 558 if (supportsAlpha) { 559 ipixel[numColorComponents] = 560 ((1 << nBits[numColorComponents]) - 1); 561 } 562 lowVal = getNormalizedComponents(ipixel, null, 0); 563 for (int i = 0; i < numColorComponents; i++) { 564 ipixel[i] = ((1 << nBits[i]) - 1); 565 } 566 highVal = getNormalizedComponents(ipixel, null, 0); 567 } 568 break; 569 case DataBuffer.TYPE_SHORT: 570 { 571 short[] spixel = new short[numComponents]; 572 for (int i = 0; i < numColorComponents; i++) { 573 spixel[i] = 0; 574 } 575 if (supportsAlpha) { 576 spixel[numColorComponents] = 32767; 577 } 578 lowVal = getNormalizedComponents(spixel, null, 0); 579 for (int i = 0; i < numColorComponents; i++) { 580 spixel[i] = 32767; 581 } 582 highVal = getNormalizedComponents(spixel, null, 0); 583 } 584 break; 585 default: 586 lowVal = highVal = null; // to keep the compiler from complaining 587 break; 588 } 589 nonStdScale = false; 590 for (int i = 0; i < numColorComponents; i++) { 591 if ((lowVal[i] != 0.0f) || (highVal[i] != 1.0f)) { 592 nonStdScale = true; 593 break; 594 } 595 } 596 if (nonStdScale) { 597 noUnnorm = true; 598 is_sRGB_stdScale = false; 599 is_LinearRGB_stdScale = false; 600 is_LinearGray_stdScale = false; 601 is_ICCGray_stdScale = false; 602 compOffset = new float[numColorComponents]; 603 compScale = new float[numColorComponents]; 604 for (int i = 0; i < numColorComponents; i++) { 605 compOffset[i] = lowVal[i]; 606 compScale[i] = 1.0f / (highVal[i] - lowVal[i]); 607 } 608 } 609 } 610 611 private int getRGBComponent(int pixel, int idx) { 612 if (numComponents > 1) { 613 throw new 614 IllegalArgumentException("More than one component per pixel"); 615 } 616 if (signed) { 617 throw new 618 IllegalArgumentException("Component value is signed"); 619 } 620 if (needScaleInit) { 621 initScale(); 622 } 623 // Since there is only 1 component, there is no alpha 624 625 // Normalize the pixel in order to convert it 626 Object opixel = null; 627 switch (transferType) { 628 case DataBuffer.TYPE_BYTE: 629 { 630 byte[] bpixel = { (byte) pixel }; 631 opixel = bpixel; 632 } 633 break; 634 case DataBuffer.TYPE_USHORT: 635 { 636 short[] spixel = { (short) pixel }; 637 opixel = spixel; 638 } 639 break; 640 case DataBuffer.TYPE_INT: 641 { 642 int[] ipixel = { pixel }; 643 opixel = ipixel; 644 } 645 break; 646 } 647 float[] norm = getNormalizedComponents(opixel, null, 0); 648 float[] rgb = colorSpace.toRGB(norm); 649 650 return (int) (rgb[idx] * 255.0f + 0.5f); 651 } 652 653 /** 654 * Returns the red color component for the specified pixel, scaled 655 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 656 * is done if necessary. The pixel value is specified as an int. 657 * The returned value will be a non pre-multiplied value. 658 * If the alpha is premultiplied, this method divides 659 * it out before returning the value (if the alpha value is 0, 660 * the red value will be 0). 661 * 662 * @param pixel The pixel from which you want to get the red color component. 663 * 664 * @return The red color component for the specified pixel, as an int. 665 * 666 * @throws IllegalArgumentException If there is more than 667 * one component in this {@code ColorModel}. 668 * @throws IllegalArgumentException If the component value for this 669 * {@code ColorModel} is signed 670 */ 671 public int getRed(int pixel) { 672 return getRGBComponent(pixel, 0); 673 } 674 675 /** 676 * Returns the green color component for the specified pixel, scaled 677 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 678 * is done if necessary. The pixel value is specified as an int. 679 * The returned value will be a non 680 * pre-multiplied value. If the alpha is premultiplied, this method 681 * divides it out before returning the value (if the alpha value is 0, 682 * the green value will be 0). 683 * 684 * @param pixel The pixel from which you want to get the green color component. 685 * 686 * @return The green color component for the specified pixel, as an int. 687 * 688 * @throws IllegalArgumentException If there is more than 689 * one component in this {@code ColorModel}. 690 * @throws IllegalArgumentException If the component value for this 691 * {@code ColorModel} is signed 692 */ 693 public int getGreen(int pixel) { 694 return getRGBComponent(pixel, 1); 695 } 696 697 /** 698 * Returns the blue color component for the specified pixel, scaled 699 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 700 * is done if necessary. The pixel value is specified as an int. 701 * The returned value will be a non 702 * pre-multiplied value. If the alpha is premultiplied, this method 703 * divides it out before returning the value (if the alpha value is 0, 704 * the blue value will be 0). 705 * 706 * @param pixel The pixel from which you want to get the blue color component. 707 * 708 * @return The blue color component for the specified pixel, as an int. 709 * 710 * @throws IllegalArgumentException If there is more than 711 * one component in this {@code ColorModel}. 712 * @throws IllegalArgumentException If the component value for this 713 * {@code ColorModel} is signed 714 */ 715 public int getBlue(int pixel) { 716 return getRGBComponent(pixel, 2); 717 } 718 719 /** 720 * Returns the alpha component for the specified pixel, scaled 721 * from 0 to 255. The pixel value is specified as an int. 722 * 723 * @param pixel The pixel from which you want to get the alpha component. 724 * 725 * @return The alpha component for the specified pixel, as an int. 726 * 727 * @throws IllegalArgumentException If there is more than 728 * one component in this {@code ColorModel}. 729 * @throws IllegalArgumentException If the component value for this 730 * {@code ColorModel} is signed 731 */ 732 public int getAlpha(int pixel) { 733 if (supportsAlpha == false) { 734 return 255; 735 } 736 if (numComponents > 1) { 737 throw new 738 IllegalArgumentException("More than one component per pixel"); 739 } 740 if (signed) { 741 throw new 742 IllegalArgumentException("Component value is signed"); 743 } 744 745 return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f); 746 } 747 748 /** 749 * Returns the color/alpha components of the pixel in the default 750 * RGB color model format. A color conversion is done if necessary. 751 * The returned value will be in a non pre-multiplied format. If 752 * the alpha is premultiplied, this method divides it out of the 753 * color components (if the alpha value is 0, the color values will be 0). 754 * 755 * @param pixel The pixel from which you want to get the color/alpha components. 756 * 757 * @return The color/alpha components for the specified pixel, as an int. 758 * 759 * @throws IllegalArgumentException If there is more than 760 * one component in this {@code ColorModel}. 761 * @throws IllegalArgumentException If the component value for this 762 * {@code ColorModel} is signed 763 */ 764 public int getRGB(int pixel) { 765 if (numComponents > 1) { 766 throw new 767 IllegalArgumentException("More than one component per pixel"); 768 } 769 if (signed) { 770 throw new 771 IllegalArgumentException("Component value is signed"); 772 } 773 774 return (getAlpha(pixel) << 24) 775 | (getRed(pixel) << 16) 776 | (getGreen(pixel) << 8) 777 | (getBlue(pixel) << 0); 778 } 779 780 private int extractComponent(Object inData, int idx, int precision) { 781 // Extract component idx from inData. The precision argument 782 // should be either 8 or 16. If it's 8, this method will return 783 // an 8-bit value. If it's 16, this method will return a 16-bit 784 // value for transferTypes other than TYPE_BYTE. For TYPE_BYTE, 785 // an 8-bit value will be returned. 786 787 // This method maps the input value corresponding to a 788 // normalized ColorSpace component value of 0.0 to 0, and the 789 // input value corresponding to a normalized ColorSpace 790 // component value of 1.0 to 2^n - 1 (where n is 8 or 16), so 791 // it is appropriate only for ColorSpaces with min/max component 792 // values of 0.0/1.0. This will be true for sRGB, the built-in 793 // Linear RGB and Linear Gray spaces, and any other ICC grayscale 794 // spaces for which we have precomputed LUTs. 795 796 boolean needAlpha = (supportsAlpha && isAlphaPremultiplied); 797 int alp = 0; 798 int comp; 799 int mask = (1 << nBits[idx]) - 1; 800 801 switch (transferType) { 802 // Note: we do no clamping of the pixel data here - we 803 // assume that the data is scaled properly 804 case DataBuffer.TYPE_SHORT: { 805 short sdata[] = (short[]) inData; 806 float scalefactor = (float) ((1 << precision) - 1); 807 if (needAlpha) { 808 short s = sdata[numColorComponents]; 809 if (s != (short) 0) { 810 return (int) ((((float) sdata[idx]) / 811 ((float) s)) * scalefactor + 0.5f); 812 } else { 813 return 0; 814 } 815 } else { 816 return (int) ((sdata[idx] / 32767.0f) * scalefactor + 0.5f); 817 } 818 } 819 case DataBuffer.TYPE_FLOAT: { 820 float fdata[] = (float[]) inData; 821 float scalefactor = (float) ((1 << precision) - 1); 822 if (needAlpha) { 823 float f = fdata[numColorComponents]; 824 if (f != 0.0f) { 825 return (int) (((fdata[idx] / f) * scalefactor) + 0.5f); 826 } else { 827 return 0; 828 } 829 } else { 830 return (int) (fdata[idx] * scalefactor + 0.5f); 831 } 832 } 833 case DataBuffer.TYPE_DOUBLE: { 834 double ddata[] = (double[]) inData; 835 double scalefactor = (double) ((1 << precision) - 1); 836 if (needAlpha) { 837 double d = ddata[numColorComponents]; 838 if (d != 0.0) { 839 return (int) (((ddata[idx] / d) * scalefactor) + 0.5); 840 } else { 841 return 0; 842 } 843 } else { 844 return (int) (ddata[idx] * scalefactor + 0.5); 845 } 846 } 847 case DataBuffer.TYPE_BYTE: 848 byte bdata[] = (byte[])inData; 849 comp = bdata[idx] & mask; 850 precision = 8; 851 if (needAlpha) { 852 alp = bdata[numColorComponents] & mask; 853 } 854 break; 855 case DataBuffer.TYPE_USHORT: 856 short usdata[] = (short[])inData; 857 comp = usdata[idx] & mask; 858 if (needAlpha) { 859 alp = usdata[numColorComponents] & mask; 860 } 861 break; 862 case DataBuffer.TYPE_INT: 863 int idata[] = (int[])inData; 864 comp = idata[idx]; 865 if (needAlpha) { 866 alp = idata[numColorComponents]; 867 } 868 break; 869 default: 870 throw new 871 UnsupportedOperationException("This method has not "+ 872 "been implemented for transferType " + transferType); 873 } 874 if (needAlpha) { 875 if (alp != 0) { 876 float scalefactor = (float) ((1 << precision) - 1); 877 float fcomp = ((float) comp) / ((float)mask); 878 float invalp = ((float) ((1<<nBits[numColorComponents]) - 1)) / 879 ((float) alp); 880 return (int) (fcomp * invalp * scalefactor + 0.5f); 881 } else { 882 return 0; 883 } 884 } else { 885 if (nBits[idx] != precision) { 886 float scalefactor = (float) ((1 << precision) - 1); 887 float fcomp = ((float) comp) / ((float)mask); 888 return (int) (fcomp * scalefactor + 0.5f); 889 } 890 return comp; 891 } 892 } 893 894 private int getRGBComponent(Object inData, int idx) { 895 if (needScaleInit) { 896 initScale(); 897 } 898 if (is_sRGB_stdScale) { 899 return extractComponent(inData, idx, 8); 900 } else if (is_LinearRGB_stdScale) { 901 int lutidx = extractComponent(inData, idx, 16); 902 return tosRGB8LUT[lutidx] & 0xff; 903 } else if (is_ICCGray_stdScale) { 904 int lutidx = extractComponent(inData, 0, 16); 905 return tosRGB8LUT[lutidx] & 0xff; 906 } 907 908 // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace 909 float[] norm = getNormalizedComponents(inData, null, 0); 910 // Note that getNormalizedComponents returns non-premultiplied values 911 float[] rgb = colorSpace.toRGB(norm); 912 return (int) (rgb[idx] * 255.0f + 0.5f); 913 } 914 915 /** 916 * Returns the red color component for the specified pixel, scaled 917 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 918 * is done if necessary. The {@code pixel} value is specified by an array 919 * of data elements of type {@code transferType} passed in as an object 920 * reference. The returned value will be a non pre-multiplied value. If the 921 * alpha is premultiplied, this method divides it out before returning 922 * the value (if the alpha value is 0, the red value will be 0). Since 923 * {@code ComponentColorModel} can be subclassed, subclasses 924 * inherit the implementation of this method and if they don't override 925 * it then they throw an exception if they use an unsupported 926 * {@code transferType}. 927 * 928 * @param inData The pixel from which you want to get the red color component, 929 * specified by an array of data elements of type {@code transferType}. 930 * 931 * @return The red color component for the specified pixel, as an int. 932 * 933 * @throws ClassCastException If {@code inData} is not a primitive array 934 * of type {@code transferType}. 935 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 936 * large enough to hold a pixel value for this 937 * {@code ColorModel}. 938 * @throws UnsupportedOperationException If the transfer type of 939 * this {@code ComponentColorModel} 940 * is not one of the supported transfer types: 941 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 942 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 943 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 944 */ 945 public int getRed(Object inData) { 946 return getRGBComponent(inData, 0); 947 } 948 949 950 /** 951 * Returns the green color component for the specified pixel, scaled 952 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. 953 * A color conversion is done if necessary. The {@code pixel} value 954 * is specified by an array of data elements of type {@code transferType} 955 * passed in as an object reference. The returned value is a non pre-multiplied 956 * value. If the alpha is premultiplied, this method divides it out before 957 * returning the value (if the alpha value is 0, the green value will be 0). 958 * Since {@code ComponentColorModel} can be subclassed, 959 * subclasses inherit the implementation of this method and if they 960 * don't override it then they throw an exception if they use an 961 * unsupported {@code transferType}. 962 * 963 * @param inData The pixel from which you want to get the green color component, 964 * specified by an array of data elements of type {@code transferType}. 965 * 966 * @return The green color component for the specified pixel, as an int. 967 * 968 * @throws ClassCastException If {@code inData} is not a primitive array 969 * of type {@code transferType}. 970 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 971 * large enough to hold a pixel value for this 972 * {@code ColorModel}. 973 * @throws UnsupportedOperationException If the transfer type of 974 * this {@code ComponentColorModel} 975 * is not one of the supported transfer types: 976 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 977 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 978 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 979 */ 980 public int getGreen(Object inData) { 981 return getRGBComponent(inData, 1); 982 } 983 984 985 /** 986 * Returns the blue color component for the specified pixel, scaled 987 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. 988 * A color conversion is done if necessary. The {@code pixel} value is 989 * specified by an array of data elements of type {@code transferType} 990 * passed in as an object reference. The returned value is a non pre-multiplied 991 * value. If the alpha is premultiplied, this method divides it out before 992 * returning the value (if the alpha value is 0, the blue value will be 0). 993 * Since {@code ComponentColorModel} can be subclassed, 994 * subclasses inherit the implementation of this method and if they 995 * don't override it then they throw an exception if they use an 996 * unsupported {@code transferType}. 997 * 998 * @param inData The pixel from which you want to get the blue color component, 999 * specified by an array of data elements of type {@code transferType}. 1000 * 1001 * @return The blue color component for the specified pixel, as an int. 1002 * 1003 * @throws ClassCastException If {@code inData} is not a primitive array 1004 * of type {@code transferType}. 1005 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 1006 * large enough to hold a pixel value for this 1007 * {@code ColorModel}. 1008 * @throws UnsupportedOperationException If the transfer type of 1009 * this {@code ComponentColorModel} 1010 * is not one of the supported transfer types: 1011 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1012 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 1013 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 1014 */ 1015 public int getBlue(Object inData) { 1016 return getRGBComponent(inData, 2); 1017 } 1018 1019 /** 1020 * Returns the alpha component for the specified pixel, scaled from 1021 * 0 to 255. The pixel value is specified by an array of data 1022 * elements of type {@code transferType} passed in as an 1023 * object reference. Since {@code ComponentColorModel} can be 1024 * subclassed, subclasses inherit the 1025 * implementation of this method and if they don't override it then 1026 * they throw an exception if they use an unsupported 1027 * {@code transferType}. 1028 * 1029 * @param inData The pixel from which you want to get the alpha component, 1030 * specified by an array of data elements of type {@code transferType}. 1031 * 1032 * @return The alpha component for the specified pixel, as an int. 1033 * 1034 * @throws ClassCastException If {@code inData} is not a primitive array 1035 * of type {@code transferType}. 1036 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 1037 * large enough to hold a pixel value for this 1038 * {@code ColorModel}. 1039 * @throws UnsupportedOperationException If the transfer type of 1040 * this {@code ComponentColorModel} 1041 * is not one of the supported transfer types: 1042 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1043 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 1044 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 1045 */ 1046 public int getAlpha(Object inData) { 1047 if (supportsAlpha == false) { 1048 return 255; 1049 } 1050 1051 int alpha = 0; 1052 int aIdx = numColorComponents; 1053 int mask = (1 << nBits[aIdx]) - 1; 1054 1055 switch (transferType) { 1056 case DataBuffer.TYPE_SHORT: 1057 short sdata[] = (short[])inData; 1058 alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f); 1059 return alpha; 1060 case DataBuffer.TYPE_FLOAT: 1061 float fdata[] = (float[])inData; 1062 alpha = (int) (fdata[aIdx] * 255.0f + 0.5f); 1063 return alpha; 1064 case DataBuffer.TYPE_DOUBLE: 1065 double ddata[] = (double[])inData; 1066 alpha = (int) (ddata[aIdx] * 255.0 + 0.5); 1067 return alpha; 1068 case DataBuffer.TYPE_BYTE: 1069 byte bdata[] = (byte[])inData; 1070 alpha = bdata[aIdx] & mask; 1071 break; 1072 case DataBuffer.TYPE_USHORT: 1073 short usdata[] = (short[])inData; 1074 alpha = usdata[aIdx] & mask; 1075 break; 1076 case DataBuffer.TYPE_INT: 1077 int idata[] = (int[])inData; 1078 alpha = idata[aIdx]; 1079 break; 1080 default: 1081 throw new 1082 UnsupportedOperationException("This method has not "+ 1083 "been implemented for transferType " + transferType); 1084 } 1085 1086 if (nBits[aIdx] == 8) { 1087 return alpha; 1088 } else { 1089 return (int) 1090 ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) * 1091 255.0f + 0.5f); 1092 } 1093 } 1094 1095 /** 1096 * Returns the color/alpha components for the specified pixel in the 1097 * default RGB color model format. A color conversion is done if 1098 * necessary. The pixel value is specified by an 1099 * array of data elements of type {@code transferType} passed 1100 * in as an object reference. 1101 * The returned value is in a non pre-multiplied format. If 1102 * the alpha is premultiplied, this method divides it out of the 1103 * color components (if the alpha value is 0, the color values will be 0). 1104 * Since {@code ComponentColorModel} can be subclassed, 1105 * subclasses inherit the implementation of this method and if they 1106 * don't override it then they throw an exception if they use an 1107 * unsupported {@code transferType}. 1108 * 1109 * @param inData The pixel from which you want to get the color/alpha components, 1110 * specified by an array of data elements of type {@code transferType}. 1111 * 1112 * @return The color/alpha components for the specified pixel, as an int. 1113 * 1114 * @throws ClassCastException If {@code inData} is not a primitive array 1115 * of type {@code transferType}. 1116 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 1117 * large enough to hold a pixel value for this 1118 * {@code ColorModel}. 1119 * @throws UnsupportedOperationException If the transfer type of 1120 * this {@code ComponentColorModel} 1121 * is not one of the supported transfer types: 1122 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1123 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 1124 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 1125 * @see ColorModel#getRGBdefault 1126 */ 1127 public int getRGB(Object inData) { 1128 if (needScaleInit) { 1129 initScale(); 1130 } 1131 if (is_sRGB_stdScale || is_LinearRGB_stdScale) { 1132 return (getAlpha(inData) << 24) 1133 | (getRed(inData) << 16) 1134 | (getGreen(inData) << 8) 1135 | (getBlue(inData)); 1136 } else if (colorSpaceType == ColorSpace.TYPE_GRAY) { 1137 int gray = getRed(inData); // Red sRGB component should equal 1138 // green and blue components 1139 return (getAlpha(inData) << 24) 1140 | (gray << 16) 1141 | (gray << 8) 1142 | gray; 1143 } 1144 float[] norm = getNormalizedComponents(inData, null, 0); 1145 // Note that getNormalizedComponents returns non-premult values 1146 float[] rgb = colorSpace.toRGB(norm); 1147 return (getAlpha(inData) << 24) 1148 | (((int) (rgb[0] * 255.0f + 0.5f)) << 16) 1149 | (((int) (rgb[1] * 255.0f + 0.5f)) << 8) 1150 | (((int) (rgb[2] * 255.0f + 0.5f)) << 0); 1151 } 1152 1153 /** 1154 * Returns a data element array representation of a pixel in this 1155 * {@code ColorModel}, given an integer pixel representation 1156 * in the default RGB color model. 1157 * This array can then be passed to the {@code setDataElements} 1158 * method of a {@code WritableRaster} object. If the 1159 * {@code pixel} 1160 * parameter is null, a new array is allocated. Since 1161 * {@code ComponentColorModel} can be subclassed, subclasses 1162 * inherit the implementation of this method and if they don't 1163 * override it then 1164 * they throw an exception if they use an unsupported 1165 * {@code transferType}. 1166 * 1167 * @param rgb the integer representation of the pixel in the RGB 1168 * color model 1169 * @param pixel the specified pixel 1170 * @return The data element array representation of a pixel 1171 * in this {@code ColorModel}. 1172 * @throws ClassCastException If {@code pixel} is not null and 1173 * is not a primitive array of type {@code transferType}. 1174 * @throws ArrayIndexOutOfBoundsException If {@code pixel} is 1175 * not large enough to hold a pixel value for this 1176 * {@code ColorModel}. 1177 * @throws UnsupportedOperationException If the transfer type of 1178 * this {@code ComponentColorModel} 1179 * is not one of the supported transfer types: 1180 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1181 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 1182 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 1183 * 1184 * @see WritableRaster#setDataElements 1185 * @see SampleModel#setDataElements 1186 */ 1187 public Object getDataElements(int rgb, Object pixel) { 1188 // REMIND: Use rendering hints? 1189 1190 int red, grn, blu, alp; 1191 red = (rgb>>16) & 0xff; 1192 grn = (rgb>>8) & 0xff; 1193 blu = rgb & 0xff; 1194 1195 if (needScaleInit) { 1196 initScale(); 1197 } 1198 if (signed) { 1199 // Handle SHORT, FLOAT, & DOUBLE here 1200 1201 switch(transferType) { 1202 case DataBuffer.TYPE_SHORT: 1203 { 1204 short sdata[]; 1205 if (pixel == null) { 1206 sdata = new short[numComponents]; 1207 } else { 1208 sdata = (short[])pixel; 1209 } 1210 float factor; 1211 if (is_sRGB_stdScale || is_LinearRGB_stdScale) { 1212 factor = 32767.0f / 255.0f; 1213 if (is_LinearRGB_stdScale) { 1214 red = fromsRGB8LUT16[red] & 0xffff; 1215 grn = fromsRGB8LUT16[grn] & 0xffff; 1216 blu = fromsRGB8LUT16[blu] & 0xffff; 1217 factor = 32767.0f / 65535.0f; 1218 } 1219 if (supportsAlpha) { 1220 alp = (rgb>>24) & 0xff; 1221 sdata[3] = 1222 (short) (alp * (32767.0f / 255.0f) + 0.5f); 1223 if (isAlphaPremultiplied) { 1224 factor = alp * factor * (1.0f / 255.0f); 1225 } 1226 } 1227 sdata[0] = (short) (red * factor + 0.5f); 1228 sdata[1] = (short) (grn * factor + 0.5f); 1229 sdata[2] = (short) (blu * factor + 0.5f); 1230 } else if (is_LinearGray_stdScale) { 1231 red = fromsRGB8LUT16[red] & 0xffff; 1232 grn = fromsRGB8LUT16[grn] & 0xffff; 1233 blu = fromsRGB8LUT16[blu] & 0xffff; 1234 float gray = ((0.2125f * red) + 1235 (0.7154f * grn) + 1236 (0.0721f * blu)) / 65535.0f; 1237 factor = 32767.0f; 1238 if (supportsAlpha) { 1239 alp = (rgb>>24) & 0xff; 1240 sdata[1] = 1241 (short) (alp * (32767.0f / 255.0f) + 0.5f); 1242 if (isAlphaPremultiplied) { 1243 factor = alp * factor * (1.0f / 255.0f); 1244 } 1245 } 1246 sdata[0] = (short) (gray * factor + 0.5f); 1247 } else if (is_ICCGray_stdScale) { 1248 red = fromsRGB8LUT16[red] & 0xffff; 1249 grn = fromsRGB8LUT16[grn] & 0xffff; 1250 blu = fromsRGB8LUT16[blu] & 0xffff; 1251 int gray = (int) ((0.2125f * red) + 1252 (0.7154f * grn) + 1253 (0.0721f * blu) + 0.5f); 1254 gray = fromLinearGray16ToOtherGray16LUT[gray] & 0xffff; 1255 factor = 32767.0f / 65535.0f; 1256 if (supportsAlpha) { 1257 alp = (rgb>>24) & 0xff; 1258 sdata[1] = 1259 (short) (alp * (32767.0f / 255.0f) + 0.5f); 1260 if (isAlphaPremultiplied) { 1261 factor = alp * factor * (1.0f / 255.0f); 1262 } 1263 } 1264 sdata[0] = (short) (gray * factor + 0.5f); 1265 } else { 1266 factor = 1.0f / 255.0f; 1267 float norm[] = new float[3]; 1268 norm[0] = red * factor; 1269 norm[1] = grn * factor; 1270 norm[2] = blu * factor; 1271 norm = colorSpace.fromRGB(norm); 1272 if (nonStdScale) { 1273 for (int i = 0; i < numColorComponents; i++) { 1274 norm[i] = (norm[i] - compOffset[i]) * 1275 compScale[i]; 1276 // REMIND: need to analyze whether this 1277 // clamping is necessary 1278 if (norm[i] < 0.0f) { 1279 norm[i] = 0.0f; 1280 } 1281 if (norm[i] > 1.0f) { 1282 norm[i] = 1.0f; 1283 } 1284 } 1285 } 1286 factor = 32767.0f; 1287 if (supportsAlpha) { 1288 alp = (rgb>>24) & 0xff; 1289 sdata[numColorComponents] = 1290 (short) (alp * (32767.0f / 255.0f) + 0.5f); 1291 if (isAlphaPremultiplied) { 1292 factor *= alp * (1.0f / 255.0f); 1293 } 1294 } 1295 for (int i = 0; i < numColorComponents; i++) { 1296 sdata[i] = (short) (norm[i] * factor + 0.5f); 1297 } 1298 } 1299 return sdata; 1300 } 1301 case DataBuffer.TYPE_FLOAT: 1302 { 1303 float fdata[]; 1304 if (pixel == null) { 1305 fdata = new float[numComponents]; 1306 } else { 1307 fdata = (float[])pixel; 1308 } 1309 float factor; 1310 if (is_sRGB_stdScale || is_LinearRGB_stdScale) { 1311 if (is_LinearRGB_stdScale) { 1312 red = fromsRGB8LUT16[red] & 0xffff; 1313 grn = fromsRGB8LUT16[grn] & 0xffff; 1314 blu = fromsRGB8LUT16[blu] & 0xffff; 1315 factor = 1.0f / 65535.0f; 1316 } else { 1317 factor = 1.0f / 255.0f; 1318 } 1319 if (supportsAlpha) { 1320 alp = (rgb>>24) & 0xff; 1321 fdata[3] = alp * (1.0f / 255.0f); 1322 if (isAlphaPremultiplied) { 1323 factor *= fdata[3]; 1324 } 1325 } 1326 fdata[0] = red * factor; 1327 fdata[1] = grn * factor; 1328 fdata[2] = blu * factor; 1329 } else if (is_LinearGray_stdScale) { 1330 red = fromsRGB8LUT16[red] & 0xffff; 1331 grn = fromsRGB8LUT16[grn] & 0xffff; 1332 blu = fromsRGB8LUT16[blu] & 0xffff; 1333 fdata[0] = ((0.2125f * red) + 1334 (0.7154f * grn) + 1335 (0.0721f * blu)) / 65535.0f; 1336 if (supportsAlpha) { 1337 alp = (rgb>>24) & 0xff; 1338 fdata[1] = alp * (1.0f / 255.0f); 1339 if (isAlphaPremultiplied) { 1340 fdata[0] *= fdata[1]; 1341 } 1342 } 1343 } else if (is_ICCGray_stdScale) { 1344 red = fromsRGB8LUT16[red] & 0xffff; 1345 grn = fromsRGB8LUT16[grn] & 0xffff; 1346 blu = fromsRGB8LUT16[blu] & 0xffff; 1347 int gray = (int) ((0.2125f * red) + 1348 (0.7154f * grn) + 1349 (0.0721f * blu) + 0.5f); 1350 fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & 1351 0xffff) / 65535.0f; 1352 if (supportsAlpha) { 1353 alp = (rgb>>24) & 0xff; 1354 fdata[1] = alp * (1.0f / 255.0f); 1355 if (isAlphaPremultiplied) { 1356 fdata[0] *= fdata[1]; 1357 } 1358 } 1359 } else { 1360 float norm[] = new float[3]; 1361 factor = 1.0f / 255.0f; 1362 norm[0] = red * factor; 1363 norm[1] = grn * factor; 1364 norm[2] = blu * factor; 1365 norm = colorSpace.fromRGB(norm); 1366 if (supportsAlpha) { 1367 alp = (rgb>>24) & 0xff; 1368 fdata[numColorComponents] = alp * factor; 1369 if (isAlphaPremultiplied) { 1370 factor *= alp; 1371 for (int i = 0; i < numColorComponents; i++) { 1372 norm[i] *= factor; 1373 } 1374 } 1375 } 1376 for (int i = 0; i < numColorComponents; i++) { 1377 fdata[i] = norm[i]; 1378 } 1379 } 1380 return fdata; 1381 } 1382 case DataBuffer.TYPE_DOUBLE: 1383 { 1384 double ddata[]; 1385 if (pixel == null) { 1386 ddata = new double[numComponents]; 1387 } else { 1388 ddata = (double[])pixel; 1389 } 1390 if (is_sRGB_stdScale || is_LinearRGB_stdScale) { 1391 double factor; 1392 if (is_LinearRGB_stdScale) { 1393 red = fromsRGB8LUT16[red] & 0xffff; 1394 grn = fromsRGB8LUT16[grn] & 0xffff; 1395 blu = fromsRGB8LUT16[blu] & 0xffff; 1396 factor = 1.0 / 65535.0; 1397 } else { 1398 factor = 1.0 / 255.0; 1399 } 1400 if (supportsAlpha) { 1401 alp = (rgb>>24) & 0xff; 1402 ddata[3] = alp * (1.0 / 255.0); 1403 if (isAlphaPremultiplied) { 1404 factor *= ddata[3]; 1405 } 1406 } 1407 ddata[0] = red * factor; 1408 ddata[1] = grn * factor; 1409 ddata[2] = blu * factor; 1410 } else if (is_LinearGray_stdScale) { 1411 red = fromsRGB8LUT16[red] & 0xffff; 1412 grn = fromsRGB8LUT16[grn] & 0xffff; 1413 blu = fromsRGB8LUT16[blu] & 0xffff; 1414 ddata[0] = ((0.2125 * red) + 1415 (0.7154 * grn) + 1416 (0.0721 * blu)) / 65535.0; 1417 if (supportsAlpha) { 1418 alp = (rgb>>24) & 0xff; 1419 ddata[1] = alp * (1.0 / 255.0); 1420 if (isAlphaPremultiplied) { 1421 ddata[0] *= ddata[1]; 1422 } 1423 } 1424 } else if (is_ICCGray_stdScale) { 1425 red = fromsRGB8LUT16[red] & 0xffff; 1426 grn = fromsRGB8LUT16[grn] & 0xffff; 1427 blu = fromsRGB8LUT16[blu] & 0xffff; 1428 int gray = (int) ((0.2125f * red) + 1429 (0.7154f * grn) + 1430 (0.0721f * blu) + 0.5f); 1431 ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & 1432 0xffff) / 65535.0; 1433 if (supportsAlpha) { 1434 alp = (rgb>>24) & 0xff; 1435 ddata[1] = alp * (1.0 / 255.0); 1436 if (isAlphaPremultiplied) { 1437 ddata[0] *= ddata[1]; 1438 } 1439 } 1440 } else { 1441 float factor = 1.0f / 255.0f; 1442 float norm[] = new float[3]; 1443 norm[0] = red * factor; 1444 norm[1] = grn * factor; 1445 norm[2] = blu * factor; 1446 norm = colorSpace.fromRGB(norm); 1447 if (supportsAlpha) { 1448 alp = (rgb>>24) & 0xff; 1449 ddata[numColorComponents] = alp * (1.0 / 255.0); 1450 if (isAlphaPremultiplied) { 1451 factor *= alp; 1452 for (int i = 0; i < numColorComponents; i++) { 1453 norm[i] *= factor; 1454 } 1455 } 1456 } 1457 for (int i = 0; i < numColorComponents; i++) { 1458 ddata[i] = norm[i]; 1459 } 1460 } 1461 return ddata; 1462 } 1463 } 1464 } 1465 1466 // Handle BYTE, USHORT, & INT here 1467 //REMIND: maybe more efficient not to use int array for 1468 //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT 1469 int intpixel[]; 1470 if (transferType == DataBuffer.TYPE_INT && 1471 pixel != null) { 1472 intpixel = (int[])pixel; 1473 } else { 1474 intpixel = new int[numComponents]; 1475 } 1476 1477 if (is_sRGB_stdScale || is_LinearRGB_stdScale) { 1478 int precision; 1479 float factor; 1480 if (is_LinearRGB_stdScale) { 1481 if (transferType == DataBuffer.TYPE_BYTE) { 1482 red = fromsRGB8LUT8[red] & 0xff; 1483 grn = fromsRGB8LUT8[grn] & 0xff; 1484 blu = fromsRGB8LUT8[blu] & 0xff; 1485 precision = 8; 1486 factor = 1.0f / 255.0f; 1487 } else { 1488 red = fromsRGB8LUT16[red] & 0xffff; 1489 grn = fromsRGB8LUT16[grn] & 0xffff; 1490 blu = fromsRGB8LUT16[blu] & 0xffff; 1491 precision = 16; 1492 factor = 1.0f / 65535.0f; 1493 } 1494 } else { 1495 precision = 8; 1496 factor = 1.0f / 255.0f; 1497 } 1498 if (supportsAlpha) { 1499 alp = (rgb>>24)&0xff; 1500 if (nBits[3] == 8) { 1501 intpixel[3] = alp; 1502 } 1503 else { 1504 intpixel[3] = (int) 1505 (alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1) + 0.5f); 1506 } 1507 if (isAlphaPremultiplied) { 1508 factor *= (alp * (1.0f / 255.0f)); 1509 precision = -1; // force component calculations below 1510 } 1511 } 1512 if (nBits[0] == precision) { 1513 intpixel[0] = red; 1514 } 1515 else { 1516 intpixel[0] = (int) (red * factor * ((1<<nBits[0]) - 1) + 0.5f); 1517 } 1518 if (nBits[1] == precision) { 1519 intpixel[1] = grn; 1520 } 1521 else { 1522 intpixel[1] = (int) (grn * factor * ((1<<nBits[1]) - 1) + 0.5f); 1523 } 1524 if (nBits[2] == precision) { 1525 intpixel[2] = blu; 1526 } 1527 else { 1528 intpixel[2] = (int) (blu * factor * ((1<<nBits[2]) - 1) + 0.5f); 1529 } 1530 } else if (is_LinearGray_stdScale) { 1531 red = fromsRGB8LUT16[red] & 0xffff; 1532 grn = fromsRGB8LUT16[grn] & 0xffff; 1533 blu = fromsRGB8LUT16[blu] & 0xffff; 1534 float gray = ((0.2125f * red) + 1535 (0.7154f * grn) + 1536 (0.0721f * blu)) / 65535.0f; 1537 if (supportsAlpha) { 1538 alp = (rgb>>24) & 0xff; 1539 if (nBits[1] == 8) { 1540 intpixel[1] = alp; 1541 } else { 1542 intpixel[1] = (int) (alp * (1.0f / 255.0f) * 1543 ((1 << nBits[1]) - 1) + 0.5f); 1544 } 1545 if (isAlphaPremultiplied) { 1546 gray *= (alp * (1.0f / 255.0f)); 1547 } 1548 } 1549 intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f); 1550 } else if (is_ICCGray_stdScale) { 1551 red = fromsRGB8LUT16[red] & 0xffff; 1552 grn = fromsRGB8LUT16[grn] & 0xffff; 1553 blu = fromsRGB8LUT16[blu] & 0xffff; 1554 int gray16 = (int) ((0.2125f * red) + 1555 (0.7154f * grn) + 1556 (0.0721f * blu) + 0.5f); 1557 float gray = (fromLinearGray16ToOtherGray16LUT[gray16] & 1558 0xffff) / 65535.0f; 1559 if (supportsAlpha) { 1560 alp = (rgb>>24) & 0xff; 1561 if (nBits[1] == 8) { 1562 intpixel[1] = alp; 1563 } else { 1564 intpixel[1] = (int) (alp * (1.0f / 255.0f) * 1565 ((1 << nBits[1]) - 1) + 0.5f); 1566 } 1567 if (isAlphaPremultiplied) { 1568 gray *= (alp * (1.0f / 255.0f)); 1569 } 1570 } 1571 intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f); 1572 } else { 1573 // Need to convert the color 1574 float[] norm = new float[3]; 1575 float factor = 1.0f / 255.0f; 1576 norm[0] = red * factor; 1577 norm[1] = grn * factor; 1578 norm[2] = blu * factor; 1579 norm = colorSpace.fromRGB(norm); 1580 if (nonStdScale) { 1581 for (int i = 0; i < numColorComponents; i++) { 1582 norm[i] = (norm[i] - compOffset[i]) * 1583 compScale[i]; 1584 // REMIND: need to analyze whether this 1585 // clamping is necessary 1586 if (norm[i] < 0.0f) { 1587 norm[i] = 0.0f; 1588 } 1589 if (norm[i] > 1.0f) { 1590 norm[i] = 1.0f; 1591 } 1592 } 1593 } 1594 if (supportsAlpha) { 1595 alp = (rgb>>24) & 0xff; 1596 if (nBits[numColorComponents] == 8) { 1597 intpixel[numColorComponents] = alp; 1598 } 1599 else { 1600 intpixel[numColorComponents] = 1601 (int) (alp * factor * 1602 ((1<<nBits[numColorComponents]) - 1) + 0.5f); 1603 } 1604 if (isAlphaPremultiplied) { 1605 factor *= alp; 1606 for (int i = 0; i < numColorComponents; i++) { 1607 norm[i] *= factor; 1608 } 1609 } 1610 } 1611 for (int i = 0; i < numColorComponents; i++) { 1612 intpixel[i] = (int) (norm[i] * ((1<<nBits[i]) - 1) + 0.5f); 1613 } 1614 } 1615 1616 switch (transferType) { 1617 case DataBuffer.TYPE_BYTE: { 1618 byte bdata[]; 1619 if (pixel == null) { 1620 bdata = new byte[numComponents]; 1621 } else { 1622 bdata = (byte[])pixel; 1623 } 1624 for (int i = 0; i < numComponents; i++) { 1625 bdata[i] = (byte)(0xff&intpixel[i]); 1626 } 1627 return bdata; 1628 } 1629 case DataBuffer.TYPE_USHORT:{ 1630 short sdata[]; 1631 if (pixel == null) { 1632 sdata = new short[numComponents]; 1633 } else { 1634 sdata = (short[])pixel; 1635 } 1636 for (int i = 0; i < numComponents; i++) { 1637 sdata[i] = (short)(intpixel[i]&0xffff); 1638 } 1639 return sdata; 1640 } 1641 case DataBuffer.TYPE_INT: 1642 if (maxBits > 23) { 1643 // fix 4412670 - for components of 24 or more bits 1644 // some calculations done above with float precision 1645 // may lose enough precision that the integer result 1646 // overflows nBits, so we need to clamp. 1647 for (int i = 0; i < numComponents; i++) { 1648 if (intpixel[i] > ((1<<nBits[i]) - 1)) { 1649 intpixel[i] = (1<<nBits[i]) - 1; 1650 } 1651 } 1652 } 1653 return intpixel; 1654 } 1655 throw new IllegalArgumentException("This method has not been "+ 1656 "implemented for transferType " + transferType); 1657 } 1658 1659 /** Returns an array of unnormalized color/alpha components given a pixel 1660 * in this {@code ColorModel}. 1661 * An IllegalArgumentException is thrown if the component value for this 1662 * {@code ColorModel} is not conveniently representable in the 1663 * unnormalized form. Color/alpha components are stored 1664 * in the {@code components} array starting at {@code offset} 1665 * (even if the array is allocated by this method). 1666 * 1667 * @param pixel The pixel value specified as an integer. 1668 * @param components An integer array in which to store the unnormalized 1669 * color/alpha components. If the {@code components} array is null, 1670 * a new array is allocated. 1671 * @param offset An offset into the {@code components} array. 1672 * 1673 * @return The components array. 1674 * 1675 * @throws IllegalArgumentException If there is more than one 1676 * component in this {@code ColorModel}. 1677 * @throws IllegalArgumentException If this 1678 * {@code ColorModel} does not support the unnormalized form 1679 * @throws ArrayIndexOutOfBoundsException If the {@code components} 1680 * array is not null and is not large enough to hold all the color and 1681 * alpha components (starting at offset). 1682 */ 1683 public int[] getComponents(int pixel, int[] components, int offset) { 1684 if (numComponents > 1) { 1685 throw new 1686 IllegalArgumentException("More than one component per pixel"); 1687 } 1688 if (needScaleInit) { 1689 initScale(); 1690 } 1691 if (noUnnorm) { 1692 throw new 1693 IllegalArgumentException( 1694 "This ColorModel does not support the unnormalized form"); 1695 } 1696 if (components == null) { 1697 components = new int[offset+1]; 1698 } 1699 1700 components[offset+0] = (pixel & ((1<<nBits[0]) - 1)); 1701 return components; 1702 } 1703 1704 /** 1705 * Returns an array of unnormalized color/alpha components given a pixel 1706 * in this {@code ColorModel}. The pixel value is specified by an 1707 * array of data elements of type {@code transferType} passed in as 1708 * an object reference. 1709 * An IllegalArgumentException is thrown if the component values for this 1710 * {@code ColorModel} are not conveniently representable in the 1711 * unnormalized form. 1712 * Color/alpha components are stored in the {@code components} array 1713 * starting at {@code offset} (even if the array is allocated by 1714 * this method). Since {@code ComponentColorModel} can be 1715 * subclassed, subclasses inherit the 1716 * implementation of this method and if they don't override it then 1717 * this method might throw an exception if they use an unsupported 1718 * {@code transferType}. 1719 * 1720 * @param pixel A pixel value specified by an array of data elements of 1721 * type {@code transferType}. 1722 * @param components An integer array in which to store the unnormalized 1723 * color/alpha components. If the {@code components} array is null, 1724 * a new array is allocated. 1725 * @param offset An offset into the {@code components} array. 1726 * 1727 * @return The {@code components} array. 1728 * 1729 * @throws IllegalArgumentException If this 1730 * {@code ComponentColorModel} does not support the unnormalized form 1731 * @throws UnsupportedOperationException in some cases iff the 1732 * transfer type of this {@code ComponentColorModel} 1733 * is not one of the following transfer types: 1734 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1735 * or {@code DataBuffer.TYPE_INT}. 1736 * @throws ClassCastException If {@code pixel} is not a primitive 1737 * array of type {@code transferType}. 1738 * @throws IllegalArgumentException If the {@code components} array is 1739 * not null and is not large enough to hold all the color and alpha 1740 * components (starting at offset), or if {@code pixel} is not large 1741 * enough to hold a pixel value for this ColorModel. 1742 */ 1743 public int[] getComponents(Object pixel, int[] components, int offset) { 1744 int intpixel[]; 1745 if (needScaleInit) { 1746 initScale(); 1747 } 1748 if (noUnnorm) { 1749 throw new 1750 IllegalArgumentException( 1751 "This ColorModel does not support the unnormalized form"); 1752 } 1753 if (pixel instanceof int[]) { 1754 intpixel = (int[])pixel; 1755 } else { 1756 intpixel = DataBuffer.toIntArray(pixel); 1757 if (intpixel == null) { 1758 throw new UnsupportedOperationException("This method has not been "+ 1759 "implemented for transferType " + transferType); 1760 } 1761 } 1762 if (intpixel.length < numComponents) { 1763 throw new IllegalArgumentException 1764 ("Length of pixel array < number of components in model"); 1765 } 1766 if (components == null) { 1767 components = new int[offset+numComponents]; 1768 } 1769 else if ((components.length-offset) < numComponents) { 1770 throw new IllegalArgumentException 1771 ("Length of components array < number of components in model"); 1772 } 1773 System.arraycopy(intpixel, 0, components, offset, numComponents); 1774 1775 return components; 1776 } 1777 1778 /** 1779 * Returns an array of all of the color/alpha components in unnormalized 1780 * form, given a normalized component array. Unnormalized components 1781 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where 1782 * n is the number of bits for a particular component. Normalized 1783 * components are float values between a per component minimum and 1784 * maximum specified by the {@code ColorSpace} object for this 1785 * {@code ColorModel}. An {@code IllegalArgumentException} 1786 * will be thrown if color component values for this 1787 * {@code ColorModel} are not conveniently representable in the 1788 * unnormalized form. If the 1789 * {@code components} array is {@code null}, a new array 1790 * will be allocated. The {@code components} array will 1791 * be returned. Color/alpha components are stored in the 1792 * {@code components} array starting at {@code offset} (even 1793 * if the array is allocated by this method). An 1794 * {@code ArrayIndexOutOfBoundsException} is thrown if the 1795 * {@code components} array is not {@code null} and is not 1796 * large enough to hold all the color and alpha 1797 * components (starting at {@code offset}). An 1798 * {@code IllegalArgumentException} is thrown if the 1799 * {@code normComponents} array is not large enough to hold 1800 * all the color and alpha components starting at 1801 * {@code normOffset}. 1802 * @param normComponents an array containing normalized components 1803 * @param normOffset the offset into the {@code normComponents} 1804 * array at which to start retrieving normalized components 1805 * @param components an array that receives the components from 1806 * {@code normComponents} 1807 * @param offset the index into {@code components} at which to 1808 * begin storing normalized components from 1809 * {@code normComponents} 1810 * @return an array containing unnormalized color and alpha 1811 * components. 1812 * @throws IllegalArgumentException If this 1813 * {@code ComponentColorModel} does not support the unnormalized form 1814 * @throws IllegalArgumentException if the length of 1815 * {@code normComponents} minus {@code normOffset} 1816 * is less than {@code numComponents} 1817 */ 1818 public int[] getUnnormalizedComponents(float[] normComponents, 1819 int normOffset, 1820 int[] components, int offset) { 1821 if (needScaleInit) { 1822 initScale(); 1823 } 1824 if (noUnnorm) { 1825 throw new 1826 IllegalArgumentException( 1827 "This ColorModel does not support the unnormalized form"); 1828 } 1829 return super.getUnnormalizedComponents(normComponents, normOffset, 1830 components, offset); 1831 } 1832 1833 /** 1834 * Returns an array of all of the color/alpha components in normalized 1835 * form, given an unnormalized component array. Unnormalized components 1836 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where 1837 * n is the number of bits for a particular component. Normalized 1838 * components are float values between a per component minimum and 1839 * maximum specified by the {@code ColorSpace} object for this 1840 * {@code ColorModel}. An {@code IllegalArgumentException} 1841 * will be thrown if color component values for this 1842 * {@code ColorModel} are not conveniently representable in the 1843 * unnormalized form. If the 1844 * {@code normComponents} array is {@code null}, a new array 1845 * will be allocated. The {@code normComponents} array 1846 * will be returned. Color/alpha components are stored in the 1847 * {@code normComponents} array starting at 1848 * {@code normOffset} (even if the array is allocated by this 1849 * method). An {@code ArrayIndexOutOfBoundsException} is thrown 1850 * if the {@code normComponents} array is not {@code null} 1851 * and is not large enough to hold all the color and alpha components 1852 * (starting at {@code normOffset}). An 1853 * {@code IllegalArgumentException} is thrown if the 1854 * {@code components} array is not large enough to hold all the 1855 * color and alpha components starting at {@code offset}. 1856 * @param components an array containing unnormalized components 1857 * @param offset the offset into the {@code components} array at 1858 * which to start retrieving unnormalized components 1859 * @param normComponents an array that receives the normalized components 1860 * @param normOffset the index into {@code normComponents} at 1861 * which to begin storing normalized components 1862 * @return an array containing normalized color and alpha 1863 * components. 1864 * @throws IllegalArgumentException If this 1865 * {@code ComponentColorModel} does not support the unnormalized form 1866 */ 1867 public float[] getNormalizedComponents(int[] components, int offset, 1868 float[] normComponents, 1869 int normOffset) { 1870 if (needScaleInit) { 1871 initScale(); 1872 } 1873 if (noUnnorm) { 1874 throw new 1875 IllegalArgumentException( 1876 "This ColorModel does not support the unnormalized form"); 1877 } 1878 return super.getNormalizedComponents(components, offset, 1879 normComponents, normOffset); 1880 } 1881 1882 /** 1883 * Returns a pixel value represented as an int in this {@code ColorModel}, 1884 * given an array of unnormalized color/alpha components. 1885 * 1886 * @param components An array of unnormalized color/alpha components. 1887 * @param offset An offset into the {@code components} array. 1888 * 1889 * @return A pixel value represented as an int. 1890 * 1891 * @throws IllegalArgumentException If there is more than one component 1892 * in this {@code ColorModel}. 1893 * @throws IllegalArgumentException If this 1894 * {@code ComponentColorModel} does not support the unnormalized form 1895 */ 1896 public int getDataElement(int[] components, int offset) { 1897 if (needScaleInit) { 1898 initScale(); 1899 } 1900 if (numComponents == 1) { 1901 if (noUnnorm) { 1902 throw new 1903 IllegalArgumentException( 1904 "This ColorModel does not support the unnormalized form"); 1905 } 1906 return components[offset+0]; 1907 } 1908 throw new IllegalArgumentException("This model returns "+ 1909 numComponents+ 1910 " elements in the pixel array."); 1911 } 1912 1913 /** 1914 * Returns a data element array representation of a pixel in this 1915 * {@code ColorModel}, given an array of unnormalized color/alpha 1916 * components. This array can then be passed to the {@code setDataElements} 1917 * method of a {@code WritableRaster} object. 1918 * 1919 * @param components An array of unnormalized color/alpha components. 1920 * @param offset The integer offset into the {@code components} array. 1921 * @param obj The object in which to store the data element array 1922 * representation of the pixel. If {@code obj} variable is null, 1923 * a new array is allocated. If {@code obj} is not null, it must 1924 * be a primitive array of type {@code transferType}. An 1925 * {@code ArrayIndexOutOfBoundsException} is thrown if 1926 * {@code obj} is not large enough to hold a pixel value 1927 * for this {@code ColorModel}. Since 1928 * {@code ComponentColorModel} can be subclassed, subclasses 1929 * inherit the implementation of this method and if they don't 1930 * override it then they throw an exception if they use an 1931 * unsupported {@code transferType}. 1932 * 1933 * @return The data element array representation of a pixel 1934 * in this {@code ColorModel}. 1935 * 1936 * @throws IllegalArgumentException If the components array 1937 * is not large enough to hold all the color and alpha components 1938 * (starting at offset). 1939 * @throws ClassCastException If {@code obj} is not null and is not a 1940 * primitive array of type {@code transferType}. 1941 * @throws ArrayIndexOutOfBoundsException If {@code obj} is not large 1942 * enough to hold a pixel value for this {@code ColorModel}. 1943 * @throws IllegalArgumentException If this 1944 * {@code ComponentColorModel} does not support the unnormalized form 1945 * @throws UnsupportedOperationException If the transfer type of 1946 * this {@code ComponentColorModel} 1947 * is not one of the following transfer types: 1948 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1949 * or {@code DataBuffer.TYPE_INT}. 1950 * 1951 * @see WritableRaster#setDataElements 1952 * @see SampleModel#setDataElements 1953 */ 1954 public Object getDataElements(int[] components, int offset, Object obj) { 1955 if (needScaleInit) { 1956 initScale(); 1957 } 1958 if (noUnnorm) { 1959 throw new 1960 IllegalArgumentException( 1961 "This ColorModel does not support the unnormalized form"); 1962 } 1963 if ((components.length-offset) < numComponents) { 1964 throw new IllegalArgumentException("Component array too small"+ 1965 " (should be "+numComponents); 1966 } 1967 switch(transferType) { 1968 case DataBuffer.TYPE_INT: 1969 { 1970 int[] pixel; 1971 if (obj == null) { 1972 pixel = new int[numComponents]; 1973 } 1974 else { 1975 pixel = (int[]) obj; 1976 } 1977 System.arraycopy(components, offset, pixel, 0, 1978 numComponents); 1979 return pixel; 1980 } 1981 1982 case DataBuffer.TYPE_BYTE: 1983 { 1984 byte[] pixel; 1985 if (obj == null) { 1986 pixel = new byte[numComponents]; 1987 } 1988 else { 1989 pixel = (byte[]) obj; 1990 } 1991 for (int i=0; i < numComponents; i++) { 1992 pixel[i] = (byte) (components[offset+i]&0xff); 1993 } 1994 return pixel; 1995 } 1996 1997 case DataBuffer.TYPE_USHORT: 1998 { 1999 short[] pixel; 2000 if (obj == null) { 2001 pixel = new short[numComponents]; 2002 } 2003 else { 2004 pixel = (short[]) obj; 2005 } 2006 for (int i=0; i < numComponents; i++) { 2007 pixel[i] = (short) (components[offset+i]&0xffff); 2008 } 2009 return pixel; 2010 } 2011 2012 default: 2013 throw new UnsupportedOperationException("This method has not been "+ 2014 "implemented for transferType " + 2015 transferType); 2016 } 2017 } 2018 2019 /** 2020 * Returns a pixel value represented as an {@code int} in this 2021 * {@code ColorModel}, given an array of normalized color/alpha 2022 * components. This method will throw an 2023 * {@code IllegalArgumentException} if pixel values for this 2024 * {@code ColorModel} are not conveniently representable as a 2025 * single {@code int}. An 2026 * {@code ArrayIndexOutOfBoundsException} is thrown if the 2027 * {@code normComponents} array is not large enough to hold all the 2028 * color and alpha components (starting at {@code normOffset}). 2029 * @param normComponents an array of normalized color and alpha 2030 * components 2031 * @param normOffset the index into {@code normComponents} at which to 2032 * begin retrieving the color and alpha components 2033 * @return an {@code int} pixel value in this 2034 * {@code ColorModel} corresponding to the specified components. 2035 * @throws IllegalArgumentException if 2036 * pixel values for this {@code ColorModel} are not 2037 * conveniently representable as a single {@code int} 2038 * @throws ArrayIndexOutOfBoundsException if 2039 * the {@code normComponents} array is not large enough to 2040 * hold all of the color and alpha components starting at 2041 * {@code normOffset} 2042 * @since 1.4 2043 */ 2044 public int getDataElement(float[] normComponents, int normOffset) { 2045 if (numComponents > 1) { 2046 throw new 2047 IllegalArgumentException("More than one component per pixel"); 2048 } 2049 if (signed) { 2050 throw new 2051 IllegalArgumentException("Component value is signed"); 2052 } 2053 if (needScaleInit) { 2054 initScale(); 2055 } 2056 Object pixel = getDataElements(normComponents, normOffset, null); 2057 switch (transferType) { 2058 case DataBuffer.TYPE_BYTE: 2059 { 2060 byte bpixel[] = (byte[]) pixel; 2061 return bpixel[0] & 0xff; 2062 } 2063 case DataBuffer.TYPE_USHORT: 2064 { 2065 short[] uspixel = (short[]) pixel; 2066 return uspixel[0] & 0xffff; 2067 } 2068 case DataBuffer.TYPE_INT: 2069 { 2070 int[] ipixel = (int[]) pixel; 2071 return ipixel[0]; 2072 } 2073 default: 2074 throw new UnsupportedOperationException("This method has not been " 2075 + "implemented for transferType " + transferType); 2076 } 2077 } 2078 2079 /** 2080 * Returns a data element array representation of a pixel in this 2081 * {@code ColorModel}, given an array of normalized color/alpha 2082 * components. This array can then be passed to the 2083 * {@code setDataElements} method of a {@code WritableRaster} 2084 * object. An {@code ArrayIndexOutOfBoundsException} is thrown 2085 * if the {@code normComponents} array is not large enough to hold 2086 * all the color and alpha components (starting at 2087 * {@code normOffset}). If the {@code obj} variable is 2088 * {@code null}, a new array will be allocated. If 2089 * {@code obj} is not {@code null}, it must be a primitive 2090 * array of type transferType; otherwise, a 2091 * {@code ClassCastException} is thrown. An 2092 * {@code ArrayIndexOutOfBoundsException} is thrown if 2093 * {@code obj} is not large enough to hold a pixel value for this 2094 * {@code ColorModel}. 2095 * @param normComponents an array of normalized color and alpha 2096 * components 2097 * @param normOffset the index into {@code normComponents} at which to 2098 * begin retrieving color and alpha components 2099 * @param obj a primitive data array to hold the returned pixel 2100 * @return an {@code Object} which is a primitive data array 2101 * representation of a pixel 2102 * @throws ClassCastException if {@code obj} 2103 * is not a primitive array of type {@code transferType} 2104 * @throws ArrayIndexOutOfBoundsException if 2105 * {@code obj} is not large enough to hold a pixel value 2106 * for this {@code ColorModel} or the {@code normComponents} 2107 * array is not large enough to hold all of the color and alpha 2108 * components starting at {@code normOffset} 2109 * @see WritableRaster#setDataElements 2110 * @see SampleModel#setDataElements 2111 * @since 1.4 2112 */ 2113 public Object getDataElements(float[] normComponents, int normOffset, 2114 Object obj) { 2115 boolean needAlpha = supportsAlpha && isAlphaPremultiplied; 2116 float[] stdNormComponents; 2117 if (needScaleInit) { 2118 initScale(); 2119 } 2120 if (nonStdScale) { 2121 stdNormComponents = new float[numComponents]; 2122 for (int c = 0, nc = normOffset; c < numColorComponents; 2123 c++, nc++) { 2124 stdNormComponents[c] = (normComponents[nc] - compOffset[c]) * 2125 compScale[c]; 2126 // REMIND: need to analyze whether this 2127 // clamping is necessary 2128 if (stdNormComponents[c] < 0.0f) { 2129 stdNormComponents[c] = 0.0f; 2130 } 2131 if (stdNormComponents[c] > 1.0f) { 2132 stdNormComponents[c] = 1.0f; 2133 } 2134 } 2135 if (supportsAlpha) { 2136 stdNormComponents[numColorComponents] = 2137 normComponents[numColorComponents + normOffset]; 2138 } 2139 normOffset = 0; 2140 } else { 2141 stdNormComponents = normComponents; 2142 } 2143 switch (transferType) { 2144 case DataBuffer.TYPE_BYTE: 2145 byte[] bpixel; 2146 if (obj == null) { 2147 bpixel = new byte[numComponents]; 2148 } else { 2149 bpixel = (byte[]) obj; 2150 } 2151 if (needAlpha) { 2152 float alpha = 2153 stdNormComponents[numColorComponents + normOffset]; 2154 for (int c = 0, nc = normOffset; c < numColorComponents; 2155 c++, nc++) { 2156 bpixel[c] = (byte) ((stdNormComponents[nc] * alpha) * 2157 ((float) ((1 << nBits[c]) - 1)) + 0.5f); 2158 } 2159 bpixel[numColorComponents] = 2160 (byte) (alpha * 2161 ((float) ((1 << nBits[numColorComponents]) - 1)) + 2162 0.5f); 2163 } else { 2164 for (int c = 0, nc = normOffset; c < numComponents; 2165 c++, nc++) { 2166 bpixel[c] = (byte) (stdNormComponents[nc] * 2167 ((float) ((1 << nBits[c]) - 1)) + 0.5f); 2168 } 2169 } 2170 return bpixel; 2171 case DataBuffer.TYPE_USHORT: 2172 short[] uspixel; 2173 if (obj == null) { 2174 uspixel = new short[numComponents]; 2175 } else { 2176 uspixel = (short[]) obj; 2177 } 2178 if (needAlpha) { 2179 float alpha = 2180 stdNormComponents[numColorComponents + normOffset]; 2181 for (int c = 0, nc = normOffset; c < numColorComponents; 2182 c++, nc++) { 2183 uspixel[c] = (short) ((stdNormComponents[nc] * alpha) * 2184 ((float) ((1 << nBits[c]) - 1)) + 2185 0.5f); 2186 } 2187 uspixel[numColorComponents] = 2188 (short) (alpha * 2189 ((float) ((1 << nBits[numColorComponents]) - 1)) + 2190 0.5f); 2191 } else { 2192 for (int c = 0, nc = normOffset; c < numComponents; 2193 c++, nc++) { 2194 uspixel[c] = (short) (stdNormComponents[nc] * 2195 ((float) ((1 << nBits[c]) - 1)) + 2196 0.5f); 2197 } 2198 } 2199 return uspixel; 2200 case DataBuffer.TYPE_INT: 2201 int[] ipixel; 2202 if (obj == null) { 2203 ipixel = new int[numComponents]; 2204 } else { 2205 ipixel = (int[]) obj; 2206 } 2207 if (needAlpha) { 2208 float alpha = 2209 stdNormComponents[numColorComponents + normOffset]; 2210 for (int c = 0, nc = normOffset; c < numColorComponents; 2211 c++, nc++) { 2212 ipixel[c] = (int) ((stdNormComponents[nc] * alpha) * 2213 ((float) ((1 << nBits[c]) - 1)) + 0.5f); 2214 } 2215 ipixel[numColorComponents] = 2216 (int) (alpha * 2217 ((float) ((1 << nBits[numColorComponents]) - 1)) + 2218 0.5f); 2219 } else { 2220 for (int c = 0, nc = normOffset; c < numComponents; 2221 c++, nc++) { 2222 ipixel[c] = (int) (stdNormComponents[nc] * 2223 ((float) ((1 << nBits[c]) - 1)) + 0.5f); 2224 } 2225 } 2226 return ipixel; 2227 case DataBuffer.TYPE_SHORT: 2228 short[] spixel; 2229 if (obj == null) { 2230 spixel = new short[numComponents]; 2231 } else { 2232 spixel = (short[]) obj; 2233 } 2234 if (needAlpha) { 2235 float alpha = 2236 stdNormComponents[numColorComponents + normOffset]; 2237 for (int c = 0, nc = normOffset; c < numColorComponents; 2238 c++, nc++) { 2239 spixel[c] = (short) 2240 (stdNormComponents[nc] * alpha * 32767.0f + 0.5f); 2241 } 2242 spixel[numColorComponents] = (short) (alpha * 32767.0f + 0.5f); 2243 } else { 2244 for (int c = 0, nc = normOffset; c < numComponents; 2245 c++, nc++) { 2246 spixel[c] = (short) 2247 (stdNormComponents[nc] * 32767.0f + 0.5f); 2248 } 2249 } 2250 return spixel; 2251 case DataBuffer.TYPE_FLOAT: 2252 float[] fpixel; 2253 if (obj == null) { 2254 fpixel = new float[numComponents]; 2255 } else { 2256 fpixel = (float[]) obj; 2257 } 2258 if (needAlpha) { 2259 float alpha = normComponents[numColorComponents + normOffset]; 2260 for (int c = 0, nc = normOffset; c < numColorComponents; 2261 c++, nc++) { 2262 fpixel[c] = normComponents[nc] * alpha; 2263 } 2264 fpixel[numColorComponents] = alpha; 2265 } else { 2266 for (int c = 0, nc = normOffset; c < numComponents; 2267 c++, nc++) { 2268 fpixel[c] = normComponents[nc]; 2269 } 2270 } 2271 return fpixel; 2272 case DataBuffer.TYPE_DOUBLE: 2273 double[] dpixel; 2274 if (obj == null) { 2275 dpixel = new double[numComponents]; 2276 } else { 2277 dpixel = (double[]) obj; 2278 } 2279 if (needAlpha) { 2280 double alpha = 2281 (double) (normComponents[numColorComponents + normOffset]); 2282 for (int c = 0, nc = normOffset; c < numColorComponents; 2283 c++, nc++) { 2284 dpixel[c] = normComponents[nc] * alpha; 2285 } 2286 dpixel[numColorComponents] = alpha; 2287 } else { 2288 for (int c = 0, nc = normOffset; c < numComponents; 2289 c++, nc++) { 2290 dpixel[c] = (double) normComponents[nc]; 2291 } 2292 } 2293 return dpixel; 2294 default: 2295 throw new UnsupportedOperationException("This method has not been "+ 2296 "implemented for transferType " + 2297 transferType); 2298 } 2299 } 2300 2301 /** 2302 * Returns an array of all of the color/alpha components in normalized 2303 * form, given a pixel in this {@code ColorModel}. The pixel 2304 * value is specified by an array of data elements of type transferType 2305 * passed in as an object reference. If pixel is not a primitive array 2306 * of type transferType, a {@code ClassCastException} is thrown. 2307 * An {@code ArrayIndexOutOfBoundsException} is thrown if 2308 * {@code pixel} is not large enough to hold a pixel value for this 2309 * {@code ColorModel}. 2310 * Normalized components are float values between a per component minimum 2311 * and maximum specified by the {@code ColorSpace} object for this 2312 * {@code ColorModel}. If the 2313 * {@code normComponents} array is {@code null}, a new array 2314 * will be allocated. The {@code normComponents} array 2315 * will be returned. Color/alpha components are stored in the 2316 * {@code normComponents} array starting at 2317 * {@code normOffset} (even if the array is allocated by this 2318 * method). An {@code ArrayIndexOutOfBoundsException} is thrown 2319 * if the {@code normComponents} array is not {@code null} 2320 * and is not large enough to hold all the color and alpha components 2321 * (starting at {@code normOffset}). 2322 * <p> 2323 * This method must be overridden by a subclass if that subclass 2324 * is designed to translate pixel sample values to color component values 2325 * in a non-default way. The default translations implemented by this 2326 * class is described in the class comments. Any subclass implementing 2327 * a non-default translation must follow the constraints on allowable 2328 * translations defined there. 2329 * @param pixel the specified pixel 2330 * @param normComponents an array to receive the normalized components 2331 * @param normOffset the offset into the {@code normComponents} 2332 * array at which to start storing normalized components 2333 * @return an array containing normalized color and alpha 2334 * components. 2335 * @throws ClassCastException if {@code pixel} is not a primitive 2336 * array of type transferType 2337 * @throws ArrayIndexOutOfBoundsException if 2338 * {@code normComponents} is not large enough to hold all 2339 * color and alpha components starting at {@code normOffset} 2340 * @throws ArrayIndexOutOfBoundsException if 2341 * {@code pixel} is not large enough to hold a pixel 2342 * value for this {@code ColorModel}. 2343 * @since 1.4 2344 */ 2345 public float[] getNormalizedComponents(Object pixel, 2346 float[] normComponents, 2347 int normOffset) { 2348 if (normComponents == null) { 2349 normComponents = new float[numComponents+normOffset]; 2350 } 2351 switch (transferType) { 2352 case DataBuffer.TYPE_BYTE: 2353 byte[] bpixel = (byte[]) pixel; 2354 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2355 normComponents[nc] = ((float) (bpixel[c] & 0xff)) / 2356 ((float) ((1 << nBits[c]) - 1)); 2357 } 2358 break; 2359 case DataBuffer.TYPE_USHORT: 2360 short[] uspixel = (short[]) pixel; 2361 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2362 normComponents[nc] = ((float) (uspixel[c] & 0xffff)) / 2363 ((float) ((1 << nBits[c]) - 1)); 2364 } 2365 break; 2366 case DataBuffer.TYPE_INT: 2367 int[] ipixel = (int[]) pixel; 2368 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2369 normComponents[nc] = ((float) ipixel[c]) / 2370 ((float) ((1 << nBits[c]) - 1)); 2371 } 2372 break; 2373 case DataBuffer.TYPE_SHORT: 2374 short[] spixel = (short[]) pixel; 2375 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2376 normComponents[nc] = ((float) spixel[c]) / 32767.0f; 2377 } 2378 break; 2379 case DataBuffer.TYPE_FLOAT: 2380 float[] fpixel = (float[]) pixel; 2381 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2382 normComponents[nc] = fpixel[c]; 2383 } 2384 break; 2385 case DataBuffer.TYPE_DOUBLE: 2386 double[] dpixel = (double[]) pixel; 2387 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2388 normComponents[nc] = (float) dpixel[c]; 2389 } 2390 break; 2391 default: 2392 throw new UnsupportedOperationException("This method has not been "+ 2393 "implemented for transferType " + 2394 transferType); 2395 } 2396 2397 if (supportsAlpha && isAlphaPremultiplied) { 2398 float alpha = normComponents[numColorComponents + normOffset]; 2399 if (alpha != 0.0f) { 2400 float invAlpha = 1.0f / alpha; 2401 for (int c = normOffset; c < numColorComponents + normOffset; 2402 c++) { 2403 normComponents[c] *= invAlpha; 2404 } 2405 } 2406 } 2407 if (min != null) { 2408 // Normally (i.e. when this class is not subclassed to override 2409 // this method), the test (min != null) will be equivalent to 2410 // the test (nonStdScale). However, there is an unlikely, but 2411 // possible case, in which this method is overridden, nonStdScale 2412 // is set true by initScale(), the subclass method for some 2413 // reason calls this superclass method, but the min and 2414 // diffMinMax arrays were never initialized by setupLUTs(). In 2415 // that case, the right thing to do is follow the intended 2416 // semantics of this method, and rescale the color components 2417 // only if the ColorSpace min/max were detected to be other 2418 // than 0.0/1.0 by setupLUTs(). Note that this implies the 2419 // transferType is byte, ushort, int, or short - i.e. components 2420 // derived from float and double pixel data are never rescaled. 2421 for (int c = 0; c < numColorComponents; c++) { 2422 normComponents[c + normOffset] = min[c] + 2423 diffMinMax[c] * normComponents[c + normOffset]; 2424 } 2425 } 2426 return normComponents; 2427 } 2428 2429 /** 2430 * Forces the raster data to match the state specified in the 2431 * {@code isAlphaPremultiplied} variable, assuming the data 2432 * is currently correctly described by this {@code ColorModel}. 2433 * It may multiply or divide the color raster data by alpha, or 2434 * do nothing if the data is in the correct state. If the data needs 2435 * to be coerced, this method also returns an instance of 2436 * this {@code ColorModel} with 2437 * the {@code isAlphaPremultiplied} flag set appropriately. 2438 * Since {@code ColorModel} can be subclassed, subclasses inherit 2439 * the implementation of this method and if they don't override it 2440 * then they throw an exception if they use an unsupported 2441 * {@code transferType}. 2442 * 2443 * @throws NullPointerException if {@code raster} is 2444 * {@code null} and data coercion is required. 2445 * @throws UnsupportedOperationException if the transfer type of 2446 * this {@code ComponentColorModel} 2447 * is not one of the supported transfer types: 2448 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 2449 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 2450 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 2451 */ 2452 public ColorModel coerceData (WritableRaster raster, 2453 boolean isAlphaPremultiplied) { 2454 if ((supportsAlpha == false) || 2455 (this.isAlphaPremultiplied == isAlphaPremultiplied)) 2456 { 2457 // Nothing to do 2458 return this; 2459 } 2460 2461 int w = raster.getWidth(); 2462 int h = raster.getHeight(); 2463 int aIdx = raster.getNumBands() - 1; 2464 float normAlpha; 2465 int rminX = raster.getMinX(); 2466 int rY = raster.getMinY(); 2467 int rX; 2468 if (isAlphaPremultiplied) { 2469 switch (transferType) { 2470 case DataBuffer.TYPE_BYTE: { 2471 byte pixel[] = null; 2472 byte zpixel[] = null; 2473 float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); 2474 for (int y = 0; y < h; y++, rY++) { 2475 rX = rminX; 2476 for (int x = 0; x < w; x++, rX++) { 2477 pixel = (byte[])raster.getDataElements(rX, rY, 2478 pixel); 2479 normAlpha = (pixel[aIdx] & 0xff) * alphaScale; 2480 if (normAlpha != 0.0f) { 2481 for (int c=0; c < aIdx; c++) { 2482 pixel[c] = (byte)((pixel[c] & 0xff) * 2483 normAlpha + 0.5f); 2484 } 2485 raster.setDataElements(rX, rY, pixel); 2486 } else { 2487 if (zpixel == null) { 2488 zpixel = new byte[numComponents]; 2489 java.util.Arrays.fill(zpixel, (byte) 0); 2490 } 2491 raster.setDataElements(rX, rY, zpixel); 2492 } 2493 } 2494 } 2495 } 2496 break; 2497 case DataBuffer.TYPE_USHORT: { 2498 short pixel[] = null; 2499 short zpixel[] = null; 2500 float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); 2501 for (int y = 0; y < h; y++, rY++) { 2502 rX = rminX; 2503 for (int x = 0; x < w; x++, rX++) { 2504 pixel = (short[])raster.getDataElements(rX, rY, 2505 pixel); 2506 normAlpha = (pixel[aIdx] & 0xffff) * alphaScale; 2507 if (normAlpha != 0.0f) { 2508 for (int c=0; c < aIdx; c++) { 2509 pixel[c] = (short) 2510 ((pixel[c] & 0xffff) * normAlpha + 2511 0.5f); 2512 } 2513 raster.setDataElements(rX, rY, pixel); 2514 } else { 2515 if (zpixel == null) { 2516 zpixel = new short[numComponents]; 2517 java.util.Arrays.fill(zpixel, (short) 0); 2518 } 2519 raster.setDataElements(rX, rY, zpixel); 2520 } 2521 } 2522 } 2523 } 2524 break; 2525 case DataBuffer.TYPE_INT: { 2526 int pixel[] = null; 2527 int zpixel[] = null; 2528 float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); 2529 for (int y = 0; y < h; y++, rY++) { 2530 rX = rminX; 2531 for (int x = 0; x < w; x++, rX++) { 2532 pixel = (int[])raster.getDataElements(rX, rY, 2533 pixel); 2534 normAlpha = pixel[aIdx] * alphaScale; 2535 if (normAlpha != 0.0f) { 2536 for (int c=0; c < aIdx; c++) { 2537 pixel[c] = (int) (pixel[c] * normAlpha + 2538 0.5f); 2539 } 2540 raster.setDataElements(rX, rY, pixel); 2541 } else { 2542 if (zpixel == null) { 2543 zpixel = new int[numComponents]; 2544 java.util.Arrays.fill(zpixel, 0); 2545 } 2546 raster.setDataElements(rX, rY, zpixel); 2547 } 2548 } 2549 } 2550 } 2551 break; 2552 case DataBuffer.TYPE_SHORT: { 2553 short pixel[] = null; 2554 short zpixel[] = null; 2555 float alphaScale = 1.0f / 32767.0f; 2556 for (int y = 0; y < h; y++, rY++) { 2557 rX = rminX; 2558 for (int x = 0; x < w; x++, rX++) { 2559 pixel = (short[]) raster.getDataElements(rX, rY, 2560 pixel); 2561 normAlpha = pixel[aIdx] * alphaScale; 2562 if (normAlpha != 0.0f) { 2563 for (int c=0; c < aIdx; c++) { 2564 pixel[c] = (short) (pixel[c] * normAlpha + 2565 0.5f); 2566 } 2567 raster.setDataElements(rX, rY, pixel); 2568 } else { 2569 if (zpixel == null) { 2570 zpixel = new short[numComponents]; 2571 java.util.Arrays.fill(zpixel, (short) 0); 2572 } 2573 raster.setDataElements(rX, rY, zpixel); 2574 } 2575 } 2576 } 2577 } 2578 break; 2579 case DataBuffer.TYPE_FLOAT: { 2580 float pixel[] = null; 2581 float zpixel[] = null; 2582 for (int y = 0; y < h; y++, rY++) { 2583 rX = rminX; 2584 for (int x = 0; x < w; x++, rX++) { 2585 pixel = (float[]) raster.getDataElements(rX, rY, 2586 pixel); 2587 normAlpha = pixel[aIdx]; 2588 if (normAlpha != 0.0f) { 2589 for (int c=0; c < aIdx; c++) { 2590 pixel[c] *= normAlpha; 2591 } 2592 raster.setDataElements(rX, rY, pixel); 2593 } else { 2594 if (zpixel == null) { 2595 zpixel = new float[numComponents]; 2596 java.util.Arrays.fill(zpixel, 0.0f); 2597 } 2598 raster.setDataElements(rX, rY, zpixel); 2599 } 2600 } 2601 } 2602 } 2603 break; 2604 case DataBuffer.TYPE_DOUBLE: { 2605 double pixel[] = null; 2606 double zpixel[] = null; 2607 for (int y = 0; y < h; y++, rY++) { 2608 rX = rminX; 2609 for (int x = 0; x < w; x++, rX++) { 2610 pixel = (double[]) raster.getDataElements(rX, rY, 2611 pixel); 2612 double dnormAlpha = pixel[aIdx]; 2613 if (dnormAlpha != 0.0) { 2614 for (int c=0; c < aIdx; c++) { 2615 pixel[c] *= dnormAlpha; 2616 } 2617 raster.setDataElements(rX, rY, pixel); 2618 } else { 2619 if (zpixel == null) { 2620 zpixel = new double[numComponents]; 2621 java.util.Arrays.fill(zpixel, 0.0); 2622 } 2623 raster.setDataElements(rX, rY, zpixel); 2624 } 2625 } 2626 } 2627 } 2628 break; 2629 default: 2630 throw new UnsupportedOperationException("This method has not been "+ 2631 "implemented for transferType " + transferType); 2632 } 2633 } 2634 else { 2635 // We are premultiplied and want to divide it out 2636 switch (transferType) { 2637 case DataBuffer.TYPE_BYTE: { 2638 byte pixel[] = null; 2639 float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); 2640 for (int y = 0; y < h; y++, rY++) { 2641 rX = rminX; 2642 for (int x = 0; x < w; x++, rX++) { 2643 pixel = (byte[])raster.getDataElements(rX, rY, 2644 pixel); 2645 normAlpha = (pixel[aIdx] & 0xff) * alphaScale; 2646 if (normAlpha != 0.0f) { 2647 float invAlpha = 1.0f / normAlpha; 2648 for (int c=0; c < aIdx; c++) { 2649 pixel[c] = (byte) 2650 ((pixel[c] & 0xff) * invAlpha + 0.5f); 2651 } 2652 raster.setDataElements(rX, rY, pixel); 2653 } 2654 } 2655 } 2656 } 2657 break; 2658 case DataBuffer.TYPE_USHORT: { 2659 short pixel[] = null; 2660 float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); 2661 for (int y = 0; y < h; y++, rY++) { 2662 rX = rminX; 2663 for (int x = 0; x < w; x++, rX++) { 2664 pixel = (short[])raster.getDataElements(rX, rY, 2665 pixel); 2666 normAlpha = (pixel[aIdx] & 0xffff) * alphaScale; 2667 if (normAlpha != 0.0f) { 2668 float invAlpha = 1.0f / normAlpha; 2669 for (int c=0; c < aIdx; c++) { 2670 pixel[c] = (short) 2671 ((pixel[c] & 0xffff) * invAlpha + 0.5f); 2672 } 2673 raster.setDataElements(rX, rY, pixel); 2674 } 2675 } 2676 } 2677 } 2678 break; 2679 case DataBuffer.TYPE_INT: { 2680 int pixel[] = null; 2681 float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); 2682 for (int y = 0; y < h; y++, rY++) { 2683 rX = rminX; 2684 for (int x = 0; x < w; x++, rX++) { 2685 pixel = (int[])raster.getDataElements(rX, rY, 2686 pixel); 2687 normAlpha = pixel[aIdx] * alphaScale; 2688 if (normAlpha != 0.0f) { 2689 float invAlpha = 1.0f / normAlpha; 2690 for (int c=0; c < aIdx; c++) { 2691 pixel[c] = (int) 2692 (pixel[c] * invAlpha + 0.5f); 2693 } 2694 raster.setDataElements(rX, rY, pixel); 2695 } 2696 } 2697 } 2698 } 2699 break; 2700 case DataBuffer.TYPE_SHORT: { 2701 short pixel[] = null; 2702 float alphaScale = 1.0f / 32767.0f; 2703 for (int y = 0; y < h; y++, rY++) { 2704 rX = rminX; 2705 for (int x = 0; x < w; x++, rX++) { 2706 pixel = (short[])raster.getDataElements(rX, rY, 2707 pixel); 2708 normAlpha = pixel[aIdx] * alphaScale; 2709 if (normAlpha != 0.0f) { 2710 float invAlpha = 1.0f / normAlpha; 2711 for (int c=0; c < aIdx; c++) { 2712 pixel[c] = (short) 2713 (pixel[c] * invAlpha + 0.5f); 2714 } 2715 raster.setDataElements(rX, rY, pixel); 2716 } 2717 } 2718 } 2719 } 2720 break; 2721 case DataBuffer.TYPE_FLOAT: { 2722 float pixel[] = null; 2723 for (int y = 0; y < h; y++, rY++) { 2724 rX = rminX; 2725 for (int x = 0; x < w; x++, rX++) { 2726 pixel = (float[])raster.getDataElements(rX, rY, 2727 pixel); 2728 normAlpha = pixel[aIdx]; 2729 if (normAlpha != 0.0f) { 2730 float invAlpha = 1.0f / normAlpha; 2731 for (int c=0; c < aIdx; c++) { 2732 pixel[c] *= invAlpha; 2733 } 2734 raster.setDataElements(rX, rY, pixel); 2735 } 2736 } 2737 } 2738 } 2739 break; 2740 case DataBuffer.TYPE_DOUBLE: { 2741 double pixel[] = null; 2742 for (int y = 0; y < h; y++, rY++) { 2743 rX = rminX; 2744 for (int x = 0; x < w; x++, rX++) { 2745 pixel = (double[])raster.getDataElements(rX, rY, 2746 pixel); 2747 double dnormAlpha = pixel[aIdx]; 2748 if (dnormAlpha != 0.0) { 2749 double invAlpha = 1.0 / dnormAlpha; 2750 for (int c=0; c < aIdx; c++) { 2751 pixel[c] *= invAlpha; 2752 } 2753 raster.setDataElements(rX, rY, pixel); 2754 } 2755 } 2756 } 2757 } 2758 break; 2759 default: 2760 throw new UnsupportedOperationException("This method has not been "+ 2761 "implemented for transferType " + transferType); 2762 } 2763 } 2764 2765 // Return a new color model 2766 if (!signed) { 2767 return new ComponentColorModel(colorSpace, nBits, supportsAlpha, 2768 isAlphaPremultiplied, transparency, 2769 transferType); 2770 } else { 2771 return new ComponentColorModel(colorSpace, supportsAlpha, 2772 isAlphaPremultiplied, transparency, 2773 transferType); 2774 } 2775 2776 } 2777 2778 /** 2779 * Returns true if {@code raster} is compatible with this 2780 * {@code ColorModel}; false if it is not. 2781 * 2782 * @param raster The {@code Raster} object to test for compatibility. 2783 * 2784 * @return {@code true} if {@code raster} is compatible with this 2785 * {@code ColorModel}, {@code false} if it is not. 2786 */ 2787 public boolean isCompatibleRaster(Raster raster) { 2788 2789 SampleModel sm = raster.getSampleModel(); 2790 2791 if (sm instanceof ComponentSampleModel) { 2792 if (sm.getNumBands() != getNumComponents()) { 2793 return false; 2794 } 2795 for (int i=0; i<nBits.length; i++) { 2796 if (sm.getSampleSize(i) < nBits[i]) { 2797 return false; 2798 } 2799 } 2800 return (raster.getTransferType() == transferType); 2801 } 2802 else { 2803 return false; 2804 } 2805 } 2806 2807 /** 2808 * Creates a {@code WritableRaster} with the specified width and height, 2809 * that has a data layout ({@code SampleModel}) compatible with 2810 * this {@code ColorModel}. 2811 * 2812 * @param w The width of the {@code WritableRaster} you want to create. 2813 * @param h The height of the {@code WritableRaster} you want to create. 2814 * 2815 * @return A {@code WritableRaster} that is compatible with 2816 * this {@code ColorModel}. 2817 * @see WritableRaster 2818 * @see SampleModel 2819 */ 2820 public WritableRaster createCompatibleWritableRaster (int w, int h) { 2821 int dataSize = w*h*numComponents; 2822 WritableRaster raster = null; 2823 2824 switch (transferType) { 2825 case DataBuffer.TYPE_BYTE: 2826 case DataBuffer.TYPE_USHORT: 2827 raster = Raster.createInterleavedRaster(transferType, 2828 w, h, 2829 numComponents, null); 2830 break; 2831 default: 2832 SampleModel sm = createCompatibleSampleModel(w, h); 2833 DataBuffer db = sm.createDataBuffer(); 2834 raster = Raster.createWritableRaster(sm, db, null); 2835 } 2836 2837 return raster; 2838 } 2839 2840 /** 2841 * Creates a {@code SampleModel} with the specified width and height, 2842 * that has a data layout compatible with this {@code ColorModel}. 2843 * 2844 * @param w The width of the {@code SampleModel} you want to create. 2845 * @param h The height of the {@code SampleModel} you want to create. 2846 * 2847 * @return A {@code SampleModel} that is compatible with this 2848 * {@code ColorModel}. 2849 * 2850 * @see SampleModel 2851 */ 2852 public SampleModel createCompatibleSampleModel(int w, int h) { 2853 int[] bandOffsets = new int[numComponents]; 2854 for (int i=0; i < numComponents; i++) { 2855 bandOffsets[i] = i; 2856 } 2857 switch (transferType) { 2858 case DataBuffer.TYPE_BYTE: 2859 case DataBuffer.TYPE_USHORT: 2860 return new PixelInterleavedSampleModel(transferType, w, h, 2861 numComponents, 2862 w*numComponents, 2863 bandOffsets); 2864 default: 2865 return new ComponentSampleModel(transferType, w, h, 2866 numComponents, 2867 w*numComponents, 2868 bandOffsets); 2869 } 2870 } 2871 2872 /** 2873 * Checks whether or not the specified {@code SampleModel} 2874 * is compatible with this {@code ColorModel}. 2875 * 2876 * @param sm The {@code SampleModel} to test for compatibility. 2877 * 2878 * @return {@code true} if the {@code SampleModel} is 2879 * compatible with this {@code ColorModel}, {@code false} 2880 * if it is not. 2881 * 2882 * @see SampleModel 2883 */ 2884 public boolean isCompatibleSampleModel(SampleModel sm) { 2885 if (!(sm instanceof ComponentSampleModel)) { 2886 return false; 2887 } 2888 2889 // Must have the same number of components 2890 if (numComponents != sm.getNumBands()) { 2891 return false; 2892 } 2893 2894 if (sm.getTransferType() != transferType) { 2895 return false; 2896 } 2897 2898 return true; 2899 } 2900 2901 /** 2902 * Returns a {@code Raster} representing the alpha channel of an image, 2903 * extracted from the input {@code Raster}. 2904 * This method assumes that {@code Raster} objects associated with 2905 * this {@code ColorModel} store the alpha band, if present, as 2906 * the last band of image data. Returns null if there is no separate spatial 2907 * alpha channel associated with this {@code ColorModel}. 2908 * This method creates a new {@code Raster}, but will share the data 2909 * array. 2910 * 2911 * @param raster The {@code WritableRaster} from which to extract the 2912 * alpha channel. 2913 * 2914 * @return A {@code WritableRaster} containing the image's alpha channel. 2915 * 2916 */ 2917 public WritableRaster getAlphaRaster(WritableRaster raster) { 2918 if (hasAlpha() == false) { 2919 return null; 2920 } 2921 2922 int x = raster.getMinX(); 2923 int y = raster.getMinY(); 2924 int[] band = new int[1]; 2925 band[0] = raster.getNumBands() - 1; 2926 return raster.createWritableChild(x, y, raster.getWidth(), 2927 raster.getHeight(), x, y, 2928 band); 2929 } 2930 2931 /** 2932 * Tests if the specified {@code Object} is an instance 2933 * of {@code ComponentColorModel} and equals this 2934 * {@code ComponentColorModel}. 2935 * @param obj the {@code Object} to test for equality 2936 * @return {@code true} if the specified {@code Object} 2937 * is an instance of {@code ComponentColorModel} and equals this 2938 * {@code ComponentColorModel}; {@code false} otherwise. 2939 */ 2940 @Override 2941 public boolean equals(Object obj) { 2942 if (!(obj instanceof ComponentColorModel)) { 2943 return false; 2944 } 2945 2946 ComponentColorModel cm = (ComponentColorModel) obj; 2947 if (supportsAlpha != cm.hasAlpha() || 2948 isAlphaPremultiplied != cm.isAlphaPremultiplied() || 2949 pixel_bits != cm.getPixelSize() || 2950 transparency != cm.getTransparency() || 2951 numComponents != cm.getNumComponents() || 2952 (!(colorSpace.equals(cm.colorSpace))) || 2953 transferType != cm.transferType) 2954 { 2955 return false; 2956 } 2957 2958 if (!(Arrays.equals(nBits, cm.getComponentSize()))) { 2959 return false; 2960 } 2961 2962 return true; 2963 } 2964 2965 /** 2966 * Returns the hash code for this ComponentColorModel. 2967 * 2968 * @return a hash code for this ComponentColorModel. 2969 */ 2970 @Override 2971 public int hashCode() { 2972 int result = hashCode; 2973 if (result == 0) { 2974 result = 7; 2975 result = 89 * result + this.pixel_bits; 2976 result = 89 * result + Arrays.hashCode(this.nBits); 2977 result = 89 * result + this.transparency; 2978 result = 89 * result + (this.supportsAlpha ? 1 : 0); 2979 result = 89 * result + (this.isAlphaPremultiplied ? 1 : 0); 2980 result = 89 * result + this.numComponents; 2981 result = 89 * result + this.colorSpace.hashCode(); 2982 result = 89 * result + this.transferType; 2983 hashCode = result; 2984 } 2985 return result; 2986 } 2987 }