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