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