1 /* 2 * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt.image; 27 28 import java.awt.Transparency; 29 import java.awt.color.ColorSpace; 30 import java.awt.color.ICC_ColorSpace; 31 import sun.java2d.cmm.CMSManager; 32 import sun.java2d.cmm.ColorTransform; 33 import sun.java2d.cmm.PCMM; 34 import java.util.Arrays; 35 import java.util.Collections; 36 import java.util.Map; 37 import java.util.WeakHashMap; 38 import java.util.Objects; 39 40 /** 41 * The {@code ColorModel} abstract class encapsulates the 42 * methods for translating a pixel value to color components 43 * (for example, red, green, and blue) and an alpha component. 44 * In order to render an image to the screen, a printer, or another 45 * image, pixel values must be converted to color and alpha components. 46 * As arguments to or return values from methods of this class, 47 * pixels are represented as 32-bit ints or as arrays of primitive types. 48 * The number, order, and interpretation of color components for a 49 * {@code ColorModel} is specified by its {@code ColorSpace}. 50 * A {@code ColorModel} used with pixel data that does not include 51 * alpha information treats all pixels as opaque, which is an alpha 52 * value of 1.0. 53 * <p> 54 * This {@code ColorModel} class supports two representations of 55 * pixel values. A pixel value can be a single 32-bit int or an 56 * array of primitive types. The Java(tm) Platform 1.0 and 1.1 APIs 57 * represented pixels as single {@code byte} or single 58 * {@code int} values. For purposes of the {@code ColorModel} 59 * class, pixel value arguments were passed as ints. The Java(tm) 2 60 * Platform API introduced additional classes for representing images. 61 * With {@link BufferedImage} or {@link RenderedImage} 62 * objects, based on {@link Raster} and {@link SampleModel} classes, pixel 63 * values might not be conveniently representable as a single int. 64 * Consequently, {@code ColorModel} now has methods that accept 65 * pixel values represented as arrays of primitive types. The primitive 66 * type used by a particular {@code ColorModel} object is called its 67 * transfer type. 68 * <p> 69 * {@code ColorModel} objects used with images for which pixel values 70 * are not conveniently representable as a single int throw an 71 * {@link IllegalArgumentException} when methods taking a single int pixel 72 * argument are called. Subclasses of {@code ColorModel} must 73 * specify the conditions under which this occurs. This does not 74 * occur with {@link DirectColorModel} or {@link IndexColorModel} objects. 75 * <p> 76 * Currently, the transfer types supported by the Java 2D(tm) API are 77 * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, 78 * DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, and DataBuffer.TYPE_DOUBLE. 79 * Most rendering operations will perform much faster when using ColorModels 80 * and images based on the first three of these types. In addition, some 81 * image filtering operations are not supported for ColorModels and 82 * images based on the latter three types. 83 * The transfer type for a particular {@code ColorModel} object is 84 * specified when the object is created, either explicitly or by default. 85 * All subclasses of {@code ColorModel} must specify what the 86 * possible transfer types are and how the number of elements in the 87 * primitive arrays representing pixels is determined. 88 * <p> 89 * For {@code BufferedImages}, the transfer type of its 90 * {@code Raster} and of the {@code Raster} object's 91 * {@code SampleModel} (available from the 92 * {@code getTransferType} methods of these classes) must match that 93 * of the {@code ColorModel}. The number of elements in an array 94 * representing a pixel for the {@code Raster} and 95 * {@code SampleModel} (available from the 96 * {@code getNumDataElements} methods of these classes) must match 97 * that of the {@code ColorModel}. 98 * <p> 99 * The algorithm used to convert from pixel values to color and alpha 100 * components varies by subclass. For example, there is not necessarily 101 * a one-to-one correspondence between samples obtained from the 102 * {@code SampleModel} of a {@code BufferedImage} object's 103 * {@code Raster} and color/alpha components. Even when 104 * there is such a correspondence, the number of bits in a sample is not 105 * necessarily the same as the number of bits in the corresponding color/alpha 106 * component. Each subclass must specify how the translation from 107 * pixel values to color/alpha components is done. 108 * <p> 109 * Methods in the {@code ColorModel} class use two different 110 * representations of color and alpha components - a normalized form 111 * and an unnormalized form. In the normalized form, each component is a 112 * {@code float} value between some minimum and maximum values. For 113 * the alpha component, the minimum is 0.0 and the maximum is 1.0. For 114 * color components the minimum and maximum values for each component can 115 * be obtained from the {@code ColorSpace} object. These values 116 * will often be 0.0 and 1.0 (e.g. normalized component values for the 117 * default sRGB color space range from 0.0 to 1.0), but some color spaces 118 * have component values with different upper and lower limits. These 119 * limits can be obtained using the {@code getMinValue} and 120 * {@code getMaxValue} methods of the {@code ColorSpace} 121 * class. Normalized color component values are not premultiplied. 122 * All {@code ColorModels} must support the normalized form. 123 * <p> 124 * In the unnormalized 125 * form, each component is an unsigned integral value between 0 and 126 * 2<sup>n</sup> - 1, where n is the number of significant bits for a 127 * particular component. If pixel values for a particular 128 * {@code ColorModel} represent color samples premultiplied by 129 * the alpha sample, unnormalized color component values are 130 * also premultiplied. The unnormalized form is used only with instances 131 * of {@code ColorModel} whose {@code ColorSpace} has minimum 132 * component values of 0.0 for all components and maximum values of 133 * 1.0 for all components. 134 * The unnormalized form for color and alpha components can be a convenient 135 * representation for {@code ColorModels} whose normalized component 136 * values all lie 137 * between 0.0 and 1.0. In such cases the integral value 0 maps to 0.0 and 138 * the value 2<sup>n</sup> - 1 maps to 1.0. In other cases, such as 139 * when the normalized component values can be either negative or positive, 140 * the unnormalized form is not convenient. Such {@code ColorModel} 141 * objects throw an {@link IllegalArgumentException} when methods involving 142 * an unnormalized argument are called. Subclasses of {@code ColorModel} 143 * must specify the conditions under which this occurs. 144 * 145 * @see IndexColorModel 146 * @see ComponentColorModel 147 * @see PackedColorModel 148 * @see DirectColorModel 149 * @see java.awt.Image 150 * @see BufferedImage 151 * @see RenderedImage 152 * @see java.awt.color.ColorSpace 153 * @see SampleModel 154 * @see Raster 155 * @see DataBuffer 156 */ 157 public abstract class ColorModel implements Transparency{ 158 private long pData; // Placeholder for data for native functions 159 160 /** 161 * The total number of bits in the pixel. 162 */ 163 protected int pixel_bits; 164 int nBits[]; 165 int transparency = Transparency.TRANSLUCENT; 166 boolean supportsAlpha = true; 167 boolean isAlphaPremultiplied = false; 168 int numComponents = -1; 169 int numColorComponents = -1; 170 ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); 171 int colorSpaceType = ColorSpace.TYPE_RGB; 172 int maxBits; 173 boolean is_sRGB = true; 174 private volatile int hashCode; 175 176 /** 177 * Data type of the array used to represent pixel values. 178 */ 179 protected int transferType; 180 181 /** 182 * This is copied from java.awt.Toolkit since we need the library 183 * loaded in java.awt.image also: 184 * 185 * WARNING: This is a temporary workaround for a problem in the 186 * way the AWT loads native libraries. A number of classes in the 187 * AWT package have a native method, initIDs(), which initializes 188 * the JNI field and method ids used in the native portion of 189 * their implementation. 190 * 191 * Since the use and storage of these ids is done by the 192 * implementation libraries, the implementation of these method is 193 * provided by the particular AWT implementations (for example, 194 * "Toolkit"s/Peer), such as Motif, Microsoft Windows, or Tiny. The 195 * problem is that this means that the native libraries must be 196 * loaded by the java.* classes, which do not necessarily know the 197 * names of the libraries to load. A better way of doing this 198 * would be to provide a separate library which defines java.awt.* 199 * initIDs, and exports the relevant symbols out to the 200 * implementation libraries. 201 * 202 * For now, we know it's done by the implementation, and we assume 203 * that the name of the library is "awt". -br. 204 */ 205 private static boolean loaded = false; 206 static void loadLibraries() { 207 if (!loaded) { 208 java.security.AccessController.doPrivileged( 209 new java.security.PrivilegedAction<Void>() { 210 public Void run() { 211 System.loadLibrary("awt"); 212 return null; 213 } 214 }); 215 loaded = true; 216 } 217 } 218 private static native void initIDs(); 219 static { 220 /* ensure that the proper libraries are loaded */ 221 loadLibraries(); 222 initIDs(); 223 } 224 private static ColorModel RGBdefault; 225 226 /** 227 * Returns a {@code DirectColorModel} that describes the default 228 * format for integer RGB values used in many of the methods in the 229 * AWT image interfaces for the convenience of the programmer. 230 * The color space is the default {@link ColorSpace}, sRGB. 231 * The format for the RGB values is an integer with 8 bits 232 * each of alpha, red, green, and blue color components ordered 233 * correspondingly from the most significant byte to the least 234 * significant byte, as in: 0xAARRGGBB. Color components are 235 * not premultiplied by the alpha component. This format does not 236 * necessarily represent the native or the most efficient 237 * {@code ColorModel} for a particular device or for all images. 238 * It is merely used as a common color model format. 239 * @return a {@code DirectColorModel} object describing default 240 * RGB values. 241 */ 242 public static ColorModel getRGBdefault() { 243 if (RGBdefault == null) { 244 RGBdefault = new DirectColorModel(32, 245 0x00ff0000, // Red 246 0x0000ff00, // Green 247 0x000000ff, // Blue 248 0xff000000 // Alpha 249 ); 250 } 251 return RGBdefault; 252 } 253 254 /** 255 * Constructs a {@code ColorModel} that translates pixels of the 256 * specified number of bits to color/alpha components. The color 257 * space is the default RGB {@code ColorSpace}, which is sRGB. 258 * Pixel values are assumed to include alpha information. If color 259 * and alpha information are represented in the pixel value as 260 * separate spatial bands, the color bands are assumed not to be 261 * premultiplied with the alpha value. The transparency type is 262 * java.awt.Transparency.TRANSLUCENT. The transfer type will be the 263 * smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 264 * or DataBuffer.TYPE_INT that can hold a single pixel 265 * (or DataBuffer.TYPE_UNDEFINED if bits is greater 266 * than 32). Since this constructor has no information about the 267 * number of bits per color and alpha component, any subclass calling 268 * this constructor should override any method that requires this 269 * information. 270 * @param bits the number of bits of a pixel 271 * @throws IllegalArgumentException if the number 272 * of bits in {@code bits} is less than 1 273 */ 274 public ColorModel(int bits) { 275 pixel_bits = bits; 276 if (bits < 1) { 277 throw new IllegalArgumentException("Number of bits must be > 0"); 278 } 279 numComponents = 4; 280 numColorComponents = 3; 281 maxBits = bits; 282 // REMIND: make sure transferType is set correctly 283 transferType = ColorModel.getDefaultTransferType(bits); 284 } 285 286 /** 287 * Constructs a {@code ColorModel} that translates pixel values 288 * to color/alpha components. Color components will be in the 289 * specified {@code ColorSpace}. {@code pixel_bits} is the 290 * number of bits in the pixel values. The bits array 291 * specifies the number of significant bits per color and alpha component. 292 * Its length should be the number of components in the 293 * {@code ColorSpace} if there is no alpha information in the 294 * pixel values, or one more than this number if there is alpha 295 * information. {@code hasAlpha} indicates whether or not alpha 296 * information is present. The {@code boolean} 297 * {@code isAlphaPremultiplied} specifies how to interpret pixel 298 * values in which color and alpha information are represented as 299 * separate spatial bands. If the {@code boolean} 300 * is {@code true}, color samples are assumed to have been 301 * multiplied by the alpha sample. The {@code transparency} 302 * specifies what alpha values can be represented by this color model. 303 * The transfer type is the type of primitive array used to represent 304 * pixel values. Note that the bits array contains the number of 305 * significant bits per color/alpha component after the translation 306 * from pixel values. For example, for an 307 * {@code IndexColorModel} with {@code pixel_bits} equal to 308 * 16, the bits array might have four elements with each element set 309 * to 8. 310 * @param pixel_bits the number of bits in the pixel values 311 * @param bits array that specifies the number of significant bits 312 * per color and alpha component 313 * @param cspace the specified {@code ColorSpace} 314 * @param hasAlpha {@code true} if alpha information is present; 315 * {@code false} otherwise 316 * @param isAlphaPremultiplied {@code true} if color samples are 317 * assumed to be premultiplied by the alpha samples; 318 * {@code false} otherwise 319 * @param transparency what alpha values can be represented by this 320 * color model 321 * @param transferType the type of the array used to represent pixel 322 * values 323 * @throws IllegalArgumentException if the length of 324 * the bit array is less than the number of color or alpha 325 * components in this {@code ColorModel}, or if the 326 * transparency is not a valid value. 327 * @throws IllegalArgumentException if the sum of the number 328 * of bits in {@code bits} is less than 1 or if 329 * any of the elements in {@code bits} is less than 0. 330 * @see java.awt.Transparency 331 */ 332 protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace, 333 boolean hasAlpha, 334 boolean isAlphaPremultiplied, 335 int transparency, 336 int transferType) { 337 colorSpace = cspace; 338 colorSpaceType = cspace.getType(); 339 numColorComponents = cspace.getNumComponents(); 340 numComponents = numColorComponents + (hasAlpha ? 1 : 0); 341 supportsAlpha = hasAlpha; 342 if (bits.length < numComponents) { 343 throw new IllegalArgumentException("Number of color/alpha "+ 344 "components should be "+ 345 numComponents+ 346 " but length of bits array is "+ 347 bits.length); 348 } 349 350 // 4186669 351 if (transparency < Transparency.OPAQUE || 352 transparency > Transparency.TRANSLUCENT) 353 { 354 throw new IllegalArgumentException("Unknown transparency: "+ 355 transparency); 356 } 357 358 if (supportsAlpha == false) { 359 this.isAlphaPremultiplied = false; 360 this.transparency = Transparency.OPAQUE; 361 } 362 else { 363 this.isAlphaPremultiplied = isAlphaPremultiplied; 364 this.transparency = transparency; 365 } 366 367 /* 368 * We need significant bits value only for the length 369 * of number of components, so we truncate remaining part. 370 * It also helps in hashCode calculation since bits[] can contain 371 * different values after the length of number of components between 372 * two ColorModels. 373 */ 374 nBits = Arrays.copyOf(bits, numComponents); 375 this.pixel_bits = pixel_bits; 376 if (pixel_bits <= 0) { 377 throw new IllegalArgumentException("Number of pixel bits must "+ 378 "be > 0"); 379 } 380 // Check for bits < 0 381 maxBits = 0; 382 for (int i=0; i < bits.length; i++) { 383 // bug 4304697 384 if (bits[i] < 0) { 385 throw new 386 IllegalArgumentException("Number of bits must be >= 0"); 387 } 388 if (maxBits < bits[i]) { 389 maxBits = bits[i]; 390 } 391 } 392 393 // Make sure that we don't have all 0-bit components 394 if (maxBits == 0) { 395 throw new IllegalArgumentException("There must be at least "+ 396 "one component with > 0 "+ 397 "pixel bits."); 398 } 399 400 // Save this since we always need to check if it is the default CS 401 if (cspace != ColorSpace.getInstance(ColorSpace.CS_sRGB)) { 402 is_sRGB = false; 403 } 404 405 // Save the transfer type 406 this.transferType = transferType; 407 } 408 409 /** 410 * Returns whether or not alpha is supported in this 411 * {@code ColorModel}. 412 * @return {@code true} if alpha is supported in this 413 * {@code ColorModel}; {@code false} otherwise. 414 */ 415 public final boolean hasAlpha() { 416 return supportsAlpha; 417 } 418 419 /** 420 * Returns whether or not the alpha has been premultiplied in the 421 * pixel values to be translated by this {@code ColorModel}. 422 * If the boolean is {@code true}, this {@code ColorModel} 423 * is to be used to interpret pixel values in which color and alpha 424 * information are represented as separate spatial bands, and color 425 * samples are assumed to have been multiplied by the 426 * alpha sample. 427 * @return {@code true} if the alpha values are premultiplied 428 * in the pixel values to be translated by this 429 * {@code ColorModel}; {@code false} otherwise. 430 */ 431 public final boolean isAlphaPremultiplied() { 432 return isAlphaPremultiplied; 433 } 434 435 /** 436 * Returns the transfer type of this {@code ColorModel}. 437 * The transfer type is the type of primitive array used to represent 438 * pixel values as arrays. 439 * @return the transfer type. 440 * @since 1.3 441 */ 442 public final int getTransferType() { 443 return transferType; 444 } 445 446 /** 447 * Returns the number of bits per pixel described by this 448 * {@code ColorModel}. 449 * @return the number of bits per pixel. 450 */ 451 public int getPixelSize() { 452 return pixel_bits; 453 } 454 455 /** 456 * Returns the number of bits for the specified color/alpha component. 457 * Color components are indexed in the order specified by the 458 * {@code ColorSpace}. Typically, this order reflects the name 459 * of the color space type. For example, for TYPE_RGB, index 0 460 * corresponds to red, index 1 to green, and index 2 461 * to blue. If this {@code ColorModel} supports alpha, the alpha 462 * component corresponds to the index following the last color 463 * component. 464 * @param componentIdx the index of the color/alpha component 465 * @return the number of bits for the color/alpha component at the 466 * specified index. 467 * @throws ArrayIndexOutOfBoundsException if {@code componentIdx} 468 * is greater than the number of components or 469 * less than zero 470 * @throws NullPointerException if the number of bits array is 471 * {@code null} 472 */ 473 public int getComponentSize(int componentIdx) { 474 // REMIND: 475 if (nBits == null) { 476 throw new NullPointerException("Number of bits array is null."); 477 } 478 479 return nBits[componentIdx]; 480 } 481 482 /** 483 * Returns an array of the number of bits per color/alpha component. 484 * The array contains the color components in the order specified by the 485 * {@code ColorSpace}, followed by the alpha component, if 486 * present. 487 * @return an array of the number of bits per color/alpha component 488 */ 489 public int[] getComponentSize() { 490 if (nBits != null) { 491 return nBits.clone(); 492 } 493 494 return null; 495 } 496 497 /** 498 * Returns the transparency. Returns either OPAQUE, BITMASK, 499 * or TRANSLUCENT. 500 * @return the transparency of this {@code ColorModel}. 501 * @see Transparency#OPAQUE 502 * @see Transparency#BITMASK 503 * @see Transparency#TRANSLUCENT 504 */ 505 public int getTransparency() { 506 return transparency; 507 } 508 509 /** 510 * Returns the number of components, including alpha, in this 511 * {@code ColorModel}. This is equal to the number of color 512 * components, optionally plus one, if there is an alpha component. 513 * @return the number of components in this {@code ColorModel} 514 */ 515 public int getNumComponents() { 516 return numComponents; 517 } 518 519 /** 520 * Returns the number of color components in this 521 * {@code ColorModel}. 522 * This is the number of components returned by 523 * {@link ColorSpace#getNumComponents}. 524 * @return the number of color components in this 525 * {@code ColorModel}. 526 * @see ColorSpace#getNumComponents 527 */ 528 public int getNumColorComponents() { 529 return numColorComponents; 530 } 531 532 /** 533 * Returns the red color component for the specified pixel, scaled 534 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 535 * is done if necessary. The pixel value is specified as an int. 536 * An {@code IllegalArgumentException} is thrown if pixel 537 * values for this {@code ColorModel} are not conveniently 538 * representable as a single int. The returned value is not a 539 * pre-multiplied value. For example, if the 540 * alpha is premultiplied, this method divides it out before returning 541 * the value. If the alpha value is 0, the red value is 0. 542 * @param pixel a specified pixel 543 * @return the value of the red component of the specified pixel. 544 */ 545 public abstract int getRed(int pixel); 546 547 /** 548 * Returns the green color component for the specified pixel, scaled 549 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 550 * is done if necessary. The pixel value is specified as an int. 551 * An {@code IllegalArgumentException} is thrown if pixel 552 * values for this {@code ColorModel} are not conveniently 553 * representable as a single int. The returned value is a non 554 * pre-multiplied value. For example, if the alpha is premultiplied, 555 * this method divides it out before returning 556 * the value. If the alpha value is 0, the green value is 0. 557 * @param pixel the specified pixel 558 * @return the value of the green component of the specified pixel. 559 */ 560 public abstract int getGreen(int pixel); 561 562 /** 563 * Returns the blue color component for the specified pixel, scaled 564 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 565 * is done if necessary. The pixel value is specified as an int. 566 * An {@code IllegalArgumentException} is thrown if pixel values 567 * for this {@code ColorModel} are not conveniently representable 568 * as a single int. The returned value is a non pre-multiplied 569 * value, for example, if the alpha is premultiplied, this method 570 * divides it out before returning the value. If the alpha value is 571 * 0, the blue value is 0. 572 * @param pixel the specified pixel 573 * @return the value of the blue component of the specified pixel. 574 */ 575 public abstract int getBlue(int pixel); 576 577 /** 578 * Returns the alpha component for the specified pixel, scaled 579 * from 0 to 255. The pixel value is specified as an int. 580 * An {@code IllegalArgumentException} is thrown if pixel 581 * values for this {@code ColorModel} are not conveniently 582 * representable as a single int. 583 * @param pixel the specified pixel 584 * @return the value of alpha component of the specified pixel. 585 */ 586 public abstract int getAlpha(int pixel); 587 588 /** 589 * Returns the color/alpha components of the pixel in the default 590 * RGB color model format. A color conversion is done if necessary. 591 * The pixel value is specified as an int. 592 * An {@code IllegalArgumentException} thrown if pixel values 593 * for this {@code ColorModel} are not conveniently representable 594 * as a single int. The returned value is in a non 595 * pre-multiplied format. For example, if the alpha is premultiplied, 596 * this method divides it out of the color components. If the alpha 597 * value is 0, the color values are 0. 598 * @param pixel the specified pixel 599 * @return the RGB value of the color/alpha components of the 600 * specified pixel. 601 * @see ColorModel#getRGBdefault 602 */ 603 public int getRGB(int pixel) { 604 return (getAlpha(pixel) << 24) 605 | (getRed(pixel) << 16) 606 | (getGreen(pixel) << 8) 607 | (getBlue(pixel) << 0); 608 } 609 610 /** 611 * Returns the red color component for the specified pixel, scaled 612 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A 613 * color conversion is done if necessary. The pixel value is 614 * specified by an array of data elements of type transferType passed 615 * in as an object reference. The returned value is a non 616 * pre-multiplied value. For example, if alpha is premultiplied, 617 * this method divides it out before returning 618 * the value. If the alpha value is 0, the red value is 0. 619 * If {@code inData} is not a primitive array of type 620 * transferType, a {@code ClassCastException} is thrown. An 621 * {@code ArrayIndexOutOfBoundsException} is thrown if 622 * {@code inData} is not large enough to hold a pixel value for 623 * this {@code ColorModel}. 624 * If this {@code transferType} is not supported, a 625 * {@code UnsupportedOperationException} will be 626 * thrown. Since 627 * {@code ColorModel} is an abstract class, any instance 628 * must be an instance of a subclass. Subclasses inherit the 629 * implementation of this method and if they don't override it, this 630 * method throws an exception if the subclass uses a 631 * {@code transferType} other than 632 * {@code DataBuffer.TYPE_BYTE}, 633 * {@code DataBuffer.TYPE_USHORT}, or 634 * {@code DataBuffer.TYPE_INT}. 635 * @param inData an array of pixel values 636 * @return the value of the red component of the specified pixel. 637 * @throws ClassCastException if {@code inData} 638 * is not a primitive array of type {@code transferType} 639 * @throws ArrayIndexOutOfBoundsException if 640 * {@code inData} is not large enough to hold a pixel value 641 * for this {@code ColorModel} 642 * @throws UnsupportedOperationException if this 643 * {@code transferType} is not supported by this 644 * {@code ColorModel} 645 */ 646 public int getRed(Object inData) { 647 int pixel=0,length=0; 648 switch (transferType) { 649 case DataBuffer.TYPE_BYTE: 650 byte bdata[] = (byte[])inData; 651 pixel = bdata[0] & 0xff; 652 length = bdata.length; 653 break; 654 case DataBuffer.TYPE_USHORT: 655 short sdata[] = (short[])inData; 656 pixel = sdata[0] & 0xffff; 657 length = sdata.length; 658 break; 659 case DataBuffer.TYPE_INT: 660 int idata[] = (int[])inData; 661 pixel = idata[0]; 662 length = idata.length; 663 break; 664 default: 665 throw new UnsupportedOperationException("This method has not been "+ 666 "implemented for transferType " + transferType); 667 } 668 if (length == 1) { 669 return getRed(pixel); 670 } 671 else { 672 throw new UnsupportedOperationException 673 ("This method is not supported by this color model"); 674 } 675 } 676 677 /** 678 * Returns the green color component for the specified pixel, scaled 679 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A 680 * color conversion is done if necessary. The pixel value is 681 * specified by an array of data elements of type transferType passed 682 * in as an object reference. The returned value will be a non 683 * pre-multiplied value. For example, if the alpha is premultiplied, 684 * this method divides it out before returning the value. If the 685 * alpha value is 0, the green value is 0. If {@code inData} is 686 * not a primitive array of type transferType, a 687 * {@code ClassCastException} is thrown. An 688 * {@code ArrayIndexOutOfBoundsException} is thrown if 689 * {@code inData} is not large enough to hold a pixel value for 690 * this {@code ColorModel}. 691 * If this {@code transferType} is not supported, a 692 * {@code UnsupportedOperationException} will be 693 * thrown. Since 694 * {@code ColorModel} is an abstract class, any instance 695 * must be an instance of a subclass. Subclasses inherit the 696 * implementation of this method and if they don't override it, this 697 * method throws an exception if the subclass uses a 698 * {@code transferType} other than 699 * {@code DataBuffer.TYPE_BYTE}, 700 * {@code DataBuffer.TYPE_USHORT}, or 701 * {@code DataBuffer.TYPE_INT}. 702 * @param inData an array of pixel values 703 * @return the value of the green component of the specified pixel. 704 * @throws ClassCastException if {@code inData} 705 * is not a primitive array of type {@code transferType} 706 * @throws ArrayIndexOutOfBoundsException if 707 * {@code inData} is not large enough to hold a pixel value 708 * for this {@code ColorModel} 709 * @throws UnsupportedOperationException if this 710 * {@code transferType} is not supported by this 711 * {@code ColorModel} 712 */ 713 public int getGreen(Object inData) { 714 int pixel=0,length=0; 715 switch (transferType) { 716 case DataBuffer.TYPE_BYTE: 717 byte bdata[] = (byte[])inData; 718 pixel = bdata[0] & 0xff; 719 length = bdata.length; 720 break; 721 case DataBuffer.TYPE_USHORT: 722 short sdata[] = (short[])inData; 723 pixel = sdata[0] & 0xffff; 724 length = sdata.length; 725 break; 726 case DataBuffer.TYPE_INT: 727 int idata[] = (int[])inData; 728 pixel = idata[0]; 729 length = idata.length; 730 break; 731 default: 732 throw new UnsupportedOperationException("This method has not been "+ 733 "implemented for transferType " + transferType); 734 } 735 if (length == 1) { 736 return getGreen(pixel); 737 } 738 else { 739 throw new UnsupportedOperationException 740 ("This method is not supported by this color model"); 741 } 742 } 743 744 /** 745 * Returns the blue color component for the specified pixel, scaled 746 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A 747 * color conversion is done if necessary. The pixel value is 748 * specified by an array of data elements of type transferType passed 749 * in as an object reference. The returned value is a non 750 * pre-multiplied value. For example, if the alpha is premultiplied, 751 * this method divides it out before returning the value. If the 752 * alpha value is 0, the blue value will be 0. If 753 * {@code inData} is not a primitive array of type transferType, 754 * a {@code ClassCastException} is thrown. An 755 * {@code ArrayIndexOutOfBoundsException} is 756 * thrown if {@code inData} is not large enough to hold a pixel 757 * value for this {@code ColorModel}. 758 * If this {@code transferType} is not supported, a 759 * {@code UnsupportedOperationException} will be 760 * thrown. Since 761 * {@code ColorModel} is an abstract class, any instance 762 * must be an instance of a subclass. Subclasses inherit the 763 * implementation of this method and if they don't override it, this 764 * method throws an exception if the subclass uses a 765 * {@code transferType} other than 766 * {@code DataBuffer.TYPE_BYTE}, 767 * {@code DataBuffer.TYPE_USHORT}, or 768 * {@code DataBuffer.TYPE_INT}. 769 * @param inData an array of pixel values 770 * @return the value of the blue component of the specified pixel. 771 * @throws ClassCastException if {@code inData} 772 * is not a primitive array of type {@code transferType} 773 * @throws ArrayIndexOutOfBoundsException if 774 * {@code inData} is not large enough to hold a pixel value 775 * for this {@code ColorModel} 776 * @throws UnsupportedOperationException if this 777 * {@code transferType} is not supported by this 778 * {@code ColorModel} 779 */ 780 public int getBlue(Object inData) { 781 int pixel=0,length=0; 782 switch (transferType) { 783 case DataBuffer.TYPE_BYTE: 784 byte bdata[] = (byte[])inData; 785 pixel = bdata[0] & 0xff; 786 length = bdata.length; 787 break; 788 case DataBuffer.TYPE_USHORT: 789 short sdata[] = (short[])inData; 790 pixel = sdata[0] & 0xffff; 791 length = sdata.length; 792 break; 793 case DataBuffer.TYPE_INT: 794 int idata[] = (int[])inData; 795 pixel = idata[0]; 796 length = idata.length; 797 break; 798 default: 799 throw new UnsupportedOperationException("This method has not been "+ 800 "implemented for transferType " + transferType); 801 } 802 if (length == 1) { 803 return getBlue(pixel); 804 } 805 else { 806 throw new UnsupportedOperationException 807 ("This method is not supported by this color model"); 808 } 809 } 810 811 /** 812 * Returns the alpha component for the specified pixel, scaled 813 * from 0 to 255. The pixel value is specified by an array of data 814 * elements of type transferType passed in as an object reference. 815 * If inData is not a primitive array of type transferType, a 816 * {@code ClassCastException} is thrown. An 817 * {@code ArrayIndexOutOfBoundsException} is thrown if 818 * {@code inData} is not large enough to hold a pixel value for 819 * this {@code ColorModel}. 820 * If this {@code transferType} is not supported, a 821 * {@code UnsupportedOperationException} will be 822 * thrown. Since 823 * {@code ColorModel} is an abstract class, any instance 824 * must be an instance of a subclass. Subclasses inherit the 825 * implementation of this method and if they don't override it, this 826 * method throws an exception if the subclass uses a 827 * {@code transferType} other than 828 * {@code DataBuffer.TYPE_BYTE}, 829 * {@code DataBuffer.TYPE_USHORT}, or 830 * {@code DataBuffer.TYPE_INT}. 831 * @param inData the specified pixel 832 * @return the alpha component of the specified pixel, scaled from 833 * 0 to 255. 834 * @throws ClassCastException if {@code inData} 835 * is not a primitive array of type {@code transferType} 836 * @throws ArrayIndexOutOfBoundsException if 837 * {@code inData} is not large enough to hold a pixel value 838 * for this {@code ColorModel} 839 * @throws UnsupportedOperationException if this 840 * {@code tranferType} is not supported by this 841 * {@code ColorModel} 842 */ 843 public int getAlpha(Object inData) { 844 int pixel=0,length=0; 845 switch (transferType) { 846 case DataBuffer.TYPE_BYTE: 847 byte bdata[] = (byte[])inData; 848 pixel = bdata[0] & 0xff; 849 length = bdata.length; 850 break; 851 case DataBuffer.TYPE_USHORT: 852 short sdata[] = (short[])inData; 853 pixel = sdata[0] & 0xffff; 854 length = sdata.length; 855 break; 856 case DataBuffer.TYPE_INT: 857 int idata[] = (int[])inData; 858 pixel = idata[0]; 859 length = idata.length; 860 break; 861 default: 862 throw new UnsupportedOperationException("This method has not been "+ 863 "implemented for transferType " + transferType); 864 } 865 if (length == 1) { 866 return getAlpha(pixel); 867 } 868 else { 869 throw new UnsupportedOperationException 870 ("This method is not supported by this color model"); 871 } 872 } 873 874 /** 875 * Returns the color/alpha components for the specified pixel in the 876 * default RGB color model format. A color conversion is done if 877 * necessary. The pixel value is specified by an array of data 878 * elements of type transferType passed in as an object reference. 879 * If inData is not a primitive array of type transferType, a 880 * {@code ClassCastException} is thrown. An 881 * {@code ArrayIndexOutOfBoundsException} is 882 * thrown if {@code inData} is not large enough to hold a pixel 883 * value for this {@code ColorModel}. 884 * The returned value will be in a non pre-multiplied format, i.e. if 885 * the alpha is premultiplied, this method will divide it out of the 886 * color components (if the alpha value is 0, the color values will be 0). 887 * @param inData the specified pixel 888 * @return the color and alpha components of the specified pixel. 889 * @see ColorModel#getRGBdefault 890 */ 891 public int getRGB(Object inData) { 892 return (getAlpha(inData) << 24) 893 | (getRed(inData) << 16) 894 | (getGreen(inData) << 8) 895 | (getBlue(inData) << 0); 896 } 897 898 /** 899 * Returns a data element array representation of a pixel in this 900 * {@code ColorModel}, given an integer pixel representation in 901 * the default RGB color model. 902 * This array can then be passed to the 903 * {@link WritableRaster#setDataElements} method of 904 * a {@link WritableRaster} object. If the pixel variable is 905 * {@code null}, a new array will be allocated. If 906 * {@code pixel} is not 907 * {@code null}, it must be a primitive array of type 908 * {@code transferType}; otherwise, a 909 * {@code ClassCastException} is thrown. An 910 * {@code ArrayIndexOutOfBoundsException} is thrown if 911 * {@code pixel} is 912 * not large enough to hold a pixel value for this 913 * {@code ColorModel}. The pixel array is returned. 914 * If this {@code transferType} is not supported, a 915 * {@code UnsupportedOperationException} will be 916 * thrown. Since {@code ColorModel} is an abstract class, 917 * any instance is an instance of a subclass. Subclasses must 918 * override this method since the implementation in this abstract 919 * class throws an {@code UnsupportedOperationException}. 920 * @param rgb the integer pixel representation in the default RGB 921 * color model 922 * @param pixel the specified pixel 923 * @return an array representation of the specified pixel in this 924 * {@code ColorModel}. 925 * @throws ClassCastException if {@code pixel} 926 * is not a primitive array of type {@code transferType} 927 * @throws ArrayIndexOutOfBoundsException if 928 * {@code pixel} is not large enough to hold a pixel value 929 * for this {@code ColorModel} 930 * @throws UnsupportedOperationException if this 931 * method is not supported by this {@code ColorModel} 932 * @see WritableRaster#setDataElements 933 * @see SampleModel#setDataElements 934 */ 935 public Object getDataElements(int rgb, Object pixel) { 936 throw new UnsupportedOperationException 937 ("This method is not supported by this color model."); 938 } 939 940 /** 941 * Returns an array of unnormalized color/alpha components given a pixel 942 * in this {@code ColorModel}. The pixel value is specified as 943 * an {@code int}. An {@code IllegalArgumentException} 944 * will be thrown if pixel values for this {@code ColorModel} are 945 * not conveniently representable as a single {@code int} or if 946 * color component values for this {@code ColorModel} are not 947 * conveniently representable in the unnormalized form. 948 * For example, this method can be used to retrieve the 949 * components for a specific pixel value in a 950 * {@code DirectColorModel}. If the components array is 951 * {@code null}, a new array will be allocated. The 952 * components array will be returned. Color/alpha components are 953 * stored in the components array starting at {@code offset} 954 * (even if the array is allocated by this method). An 955 * {@code ArrayIndexOutOfBoundsException} is thrown if the 956 * components array is not {@code null} and is not large 957 * enough to hold all the color and alpha components (starting at offset). 958 * Since {@code ColorModel} is an abstract class, 959 * any instance is an instance of a subclass. Subclasses must 960 * override this method since the implementation in this abstract 961 * class throws an {@code UnsupportedOperationException}. 962 * @param pixel the specified pixel 963 * @param components the array to receive the color and alpha 964 * components of the specified pixel 965 * @param offset the offset into the {@code components} array at 966 * which to start storing the color and alpha components 967 * @return an array containing the color and alpha components of the 968 * specified pixel starting at the specified offset. 969 * @throws UnsupportedOperationException if this 970 * method is not supported by this {@code ColorModel} 971 */ 972 public int[] getComponents(int pixel, int[] components, int offset) { 973 throw new UnsupportedOperationException 974 ("This method is not supported by this color model."); 975 } 976 977 /** 978 * Returns an array of unnormalized color/alpha components given a pixel 979 * in this {@code ColorModel}. The pixel value is specified by 980 * an array of data elements of type transferType passed in as an 981 * object reference. If {@code pixel} is not a primitive array 982 * of type transferType, a {@code ClassCastException} is thrown. 983 * An {@code IllegalArgumentException} will be thrown if color 984 * component values for this {@code ColorModel} are not 985 * conveniently representable in the unnormalized form. 986 * An {@code ArrayIndexOutOfBoundsException} is 987 * thrown if {@code pixel} is not large enough to hold a pixel 988 * value for this {@code ColorModel}. 989 * This method can be used to retrieve the components for a specific 990 * pixel value in any {@code ColorModel}. If the components 991 * array is {@code null}, a new array will be allocated. The 992 * components array will be returned. Color/alpha components are 993 * stored in the {@code components} array starting at 994 * {@code offset} (even if the array is allocated by this 995 * method). An {@code ArrayIndexOutOfBoundsException} 996 * is thrown if the components array is not {@code null} and is 997 * not large enough to hold all the color and alpha components 998 * (starting at {@code offset}). 999 * Since {@code ColorModel} is an abstract class, 1000 * any instance is an instance of a subclass. Subclasses must 1001 * override this method since the implementation in this abstract 1002 * class throws an {@code UnsupportedOperationException}. 1003 * @param pixel the specified pixel 1004 * @param components an array that receives the color and alpha 1005 * components of the specified pixel 1006 * @param offset the index into the {@code components} array at 1007 * which to begin storing the color and alpha components of the 1008 * specified pixel 1009 * @return an array containing the color and alpha components of the 1010 * specified pixel starting at the specified offset. 1011 * @throws UnsupportedOperationException if this 1012 * method is not supported by this {@code ColorModel} 1013 */ 1014 public int[] getComponents(Object pixel, int[] components, int offset) { 1015 throw new UnsupportedOperationException 1016 ("This method is not supported by this color model."); 1017 } 1018 1019 /** 1020 * Returns an array of all of the color/alpha components in unnormalized 1021 * form, given a normalized component array. Unnormalized components 1022 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where 1023 * n is the number of bits for a particular component. Normalized 1024 * components are float values between a per component minimum and 1025 * maximum specified by the {@code ColorSpace} object for this 1026 * {@code ColorModel}. An {@code IllegalArgumentException} 1027 * will be thrown if color component values for this 1028 * {@code ColorModel} are not conveniently representable in the 1029 * unnormalized form. If the 1030 * {@code components} array is {@code null}, a new array 1031 * will be allocated. The {@code components} array will 1032 * be returned. Color/alpha components are stored in the 1033 * {@code components} array starting at {@code offset} (even 1034 * if the array is allocated by this method). An 1035 * {@code ArrayIndexOutOfBoundsException} is thrown if the 1036 * {@code components} array is not {@code null} and is not 1037 * large enough to hold all the color and alpha 1038 * components (starting at {@code offset}). An 1039 * {@code IllegalArgumentException} is thrown if the 1040 * {@code normComponents} array is not large enough to hold 1041 * all the color and alpha components starting at 1042 * {@code normOffset}. 1043 * @param normComponents an array containing normalized components 1044 * @param normOffset the offset into the {@code normComponents} 1045 * array at which to start retrieving normalized components 1046 * @param components an array that receives the components from 1047 * {@code normComponents} 1048 * @param offset the index into {@code components} at which to 1049 * begin storing normalized components from 1050 * {@code normComponents} 1051 * @return an array containing unnormalized color and alpha 1052 * components. 1053 * @throws IllegalArgumentException If the component values for this 1054 * {@code ColorModel} are not conveniently representable in the 1055 * unnormalized form. 1056 * @throws IllegalArgumentException if the length of 1057 * {@code normComponents} minus {@code normOffset} 1058 * is less than {@code numComponents} 1059 * @throws UnsupportedOperationException if the 1060 * constructor of this {@code ColorModel} called the 1061 * {@code super(bits)} constructor, but did not 1062 * override this method. See the constructor, 1063 * {@link #ColorModel(int)}. 1064 */ 1065 public int[] getUnnormalizedComponents(float[] normComponents, 1066 int normOffset, 1067 int[] components, int offset) { 1068 // Make sure that someone isn't using a custom color model 1069 // that called the super(bits) constructor. 1070 if (colorSpace == null) { 1071 throw new UnsupportedOperationException("This method is not supported "+ 1072 "by this color model."); 1073 } 1074 1075 if (nBits == null) { 1076 throw new UnsupportedOperationException ("This method is not supported. "+ 1077 "Unable to determine #bits per "+ 1078 "component."); 1079 } 1080 if ((normComponents.length - normOffset) < numComponents) { 1081 throw new 1082 IllegalArgumentException( 1083 "Incorrect number of components. Expecting "+ 1084 numComponents); 1085 } 1086 1087 if (components == null) { 1088 components = new int[offset+numComponents]; 1089 } 1090 1091 if (supportsAlpha && isAlphaPremultiplied) { 1092 float normAlpha = normComponents[normOffset+numColorComponents]; 1093 for (int i=0; i < numColorComponents; i++) { 1094 components[offset+i] = (int) (normComponents[normOffset+i] 1095 * ((1<<nBits[i]) - 1) 1096 * normAlpha + 0.5f); 1097 } 1098 components[offset+numColorComponents] = (int) 1099 (normAlpha * ((1<<nBits[numColorComponents]) - 1) + 0.5f); 1100 } 1101 else { 1102 for (int i=0; i < numComponents; i++) { 1103 components[offset+i] = (int) (normComponents[normOffset+i] 1104 * ((1<<nBits[i]) - 1) + 0.5f); 1105 } 1106 } 1107 1108 return components; 1109 } 1110 1111 /** 1112 * Returns an array of all of the color/alpha components in normalized 1113 * form, given an unnormalized component array. Unnormalized components 1114 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where 1115 * n is the number of bits for a particular component. Normalized 1116 * components are float values between a per component minimum and 1117 * maximum specified by the {@code ColorSpace} object for this 1118 * {@code ColorModel}. An {@code IllegalArgumentException} 1119 * will be thrown if color component values for this 1120 * {@code ColorModel} are not conveniently representable in the 1121 * unnormalized form. If the 1122 * {@code normComponents} array is {@code null}, a new array 1123 * will be allocated. The {@code normComponents} array 1124 * will be returned. Color/alpha components are stored in the 1125 * {@code normComponents} array starting at 1126 * {@code normOffset} (even if the array is allocated by this 1127 * method). An {@code ArrayIndexOutOfBoundsException} is thrown 1128 * if the {@code normComponents} array is not {@code null} 1129 * and is not large enough to hold all the color and alpha components 1130 * (starting at {@code normOffset}). An 1131 * {@code IllegalArgumentException} is thrown if the 1132 * {@code components} array is not large enough to hold all the 1133 * color and alpha components starting at {@code offset}. 1134 * <p> 1135 * Since {@code ColorModel} is an abstract class, 1136 * any instance is an instance of a subclass. The default implementation 1137 * of this method in this abstract class assumes that component values 1138 * for this class are conveniently representable in the unnormalized 1139 * form. Therefore, subclasses which may 1140 * have instances which do not support the unnormalized form must 1141 * override this method. 1142 * @param components an array containing unnormalized components 1143 * @param offset the offset into the {@code components} array at 1144 * which to start retrieving unnormalized components 1145 * @param normComponents an array that receives the normalized components 1146 * @param normOffset the index into {@code normComponents} at 1147 * which to begin storing normalized components 1148 * @return an array containing normalized color and alpha 1149 * components. 1150 * @throws IllegalArgumentException If the component values for this 1151 * {@code ColorModel} are not conveniently representable in the 1152 * unnormalized form. 1153 * @throws UnsupportedOperationException if the 1154 * constructor of this {@code ColorModel} called the 1155 * {@code super(bits)} constructor, but did not 1156 * override this method. See the constructor, 1157 * {@link #ColorModel(int)}. 1158 * @throws UnsupportedOperationException if this method is unable 1159 * to determine the number of bits per component 1160 */ 1161 public float[] getNormalizedComponents(int[] components, int offset, 1162 float[] normComponents, 1163 int normOffset) { 1164 // Make sure that someone isn't using a custom color model 1165 // that called the super(bits) constructor. 1166 if (colorSpace == null) { 1167 throw new UnsupportedOperationException("This method is not supported by "+ 1168 "this color model."); 1169 } 1170 if (nBits == null) { 1171 throw new UnsupportedOperationException ("This method is not supported. "+ 1172 "Unable to determine #bits per "+ 1173 "component."); 1174 } 1175 1176 if ((components.length - offset) < numComponents) { 1177 throw new 1178 IllegalArgumentException( 1179 "Incorrect number of components. Expecting "+ 1180 numComponents); 1181 } 1182 1183 if (normComponents == null) { 1184 normComponents = new float[numComponents+normOffset]; 1185 } 1186 1187 if (supportsAlpha && isAlphaPremultiplied) { 1188 // Normalized coordinates are non premultiplied 1189 float normAlpha = (float)components[offset+numColorComponents]; 1190 normAlpha /= (float) ((1<<nBits[numColorComponents]) - 1); 1191 if (normAlpha != 0.0f) { 1192 for (int i=0; i < numColorComponents; i++) { 1193 normComponents[normOffset+i] = 1194 ((float) components[offset+i]) / 1195 (normAlpha * ((float) ((1<<nBits[i]) - 1))); 1196 } 1197 } else { 1198 for (int i=0; i < numColorComponents; i++) { 1199 normComponents[normOffset+i] = 0.0f; 1200 } 1201 } 1202 normComponents[normOffset+numColorComponents] = normAlpha; 1203 } 1204 else { 1205 for (int i=0; i < numComponents; i++) { 1206 normComponents[normOffset+i] = ((float) components[offset+i]) / 1207 ((float) ((1<<nBits[i]) - 1)); 1208 } 1209 } 1210 1211 return normComponents; 1212 } 1213 1214 /** 1215 * Returns a pixel value represented as an {@code int} in this 1216 * {@code ColorModel}, given an array of unnormalized color/alpha 1217 * components. This method will throw an 1218 * {@code IllegalArgumentException} if component values for this 1219 * {@code ColorModel} are not conveniently representable as a 1220 * single {@code int} or if color component values for this 1221 * {@code ColorModel} are not conveniently representable in the 1222 * unnormalized form. An 1223 * {@code ArrayIndexOutOfBoundsException} is thrown if the 1224 * {@code components} array is not large enough to hold all the 1225 * color and alpha components (starting at {@code offset}). 1226 * Since {@code ColorModel} is an abstract class, 1227 * any instance is an instance of a subclass. Subclasses must 1228 * override this method since the implementation in this abstract 1229 * class throws an {@code UnsupportedOperationException}. 1230 * @param components an array of unnormalized color and alpha 1231 * components 1232 * @param offset the index into {@code components} at which to 1233 * begin retrieving the color and alpha components 1234 * @return an {@code int} pixel value in this 1235 * {@code ColorModel} corresponding to the specified components. 1236 * @throws IllegalArgumentException if 1237 * pixel values for this {@code ColorModel} are not 1238 * conveniently representable as a single {@code int} 1239 * @throws IllegalArgumentException if 1240 * component values for this {@code ColorModel} are not 1241 * conveniently representable in the unnormalized form 1242 * @throws ArrayIndexOutOfBoundsException if 1243 * the {@code components} array is not large enough to 1244 * hold all of the color and alpha components starting at 1245 * {@code offset} 1246 * @throws UnsupportedOperationException if this 1247 * method is not supported by this {@code ColorModel} 1248 */ 1249 public int getDataElement(int[] components, int offset) { 1250 throw new UnsupportedOperationException("This method is not supported "+ 1251 "by this color model."); 1252 } 1253 1254 /** 1255 * Returns a data element array representation of a pixel in this 1256 * {@code ColorModel}, given an array of unnormalized color/alpha 1257 * components. This array can then be passed to the 1258 * {@code setDataElements} method of a {@code WritableRaster} 1259 * object. This method will throw an {@code IllegalArgumentException} 1260 * if color component values for this {@code ColorModel} are not 1261 * conveniently representable in the unnormalized form. 1262 * An {@code ArrayIndexOutOfBoundsException} is thrown 1263 * if the {@code components} array is not large enough to hold 1264 * all the color and alpha components (starting at 1265 * {@code offset}). If the {@code obj} variable is 1266 * {@code null}, a new array will be allocated. If 1267 * {@code obj} is not {@code null}, it must be a primitive 1268 * array of type transferType; otherwise, a 1269 * {@code ClassCastException} is thrown. An 1270 * {@code ArrayIndexOutOfBoundsException} is thrown if 1271 * {@code obj} is not large enough to hold a pixel value for this 1272 * {@code ColorModel}. 1273 * Since {@code ColorModel} is an abstract class, 1274 * any instance is an instance of a subclass. Subclasses must 1275 * override this method since the implementation in this abstract 1276 * class throws an {@code UnsupportedOperationException}. 1277 * @param components an array of unnormalized color and alpha 1278 * components 1279 * @param offset the index into {@code components} at which to 1280 * begin retrieving color and alpha components 1281 * @param obj the {@code Object} representing an array of color 1282 * and alpha components 1283 * @return an {@code Object} representing an array of color and 1284 * alpha components. 1285 * @throws ClassCastException if {@code obj} 1286 * is not a primitive array of type {@code transferType} 1287 * @throws ArrayIndexOutOfBoundsException if 1288 * {@code obj} is not large enough to hold a pixel value 1289 * for this {@code ColorModel} or the {@code components} 1290 * array is not large enough to hold all of the color and alpha 1291 * components starting at {@code offset} 1292 * @throws IllegalArgumentException if 1293 * component values for this {@code ColorModel} are not 1294 * conveniently representable in the unnormalized form 1295 * @throws UnsupportedOperationException if this 1296 * method is not supported by this {@code ColorModel} 1297 * @see WritableRaster#setDataElements 1298 * @see SampleModel#setDataElements 1299 */ 1300 public Object getDataElements(int[] components, int offset, Object obj) { 1301 throw new UnsupportedOperationException("This method has not been implemented "+ 1302 "for this color model."); 1303 } 1304 1305 /** 1306 * Returns a pixel value represented as an {@code int} in this 1307 * {@code ColorModel}, given an array of normalized color/alpha 1308 * components. This method will throw an 1309 * {@code IllegalArgumentException} if pixel values for this 1310 * {@code ColorModel} are not conveniently representable as a 1311 * single {@code int}. An 1312 * {@code ArrayIndexOutOfBoundsException} is thrown if the 1313 * {@code normComponents} array is not large enough to hold all the 1314 * color and alpha components (starting at {@code normOffset}). 1315 * Since {@code ColorModel} is an abstract class, 1316 * any instance is an instance of a subclass. The default implementation 1317 * of this method in this abstract class first converts from the 1318 * normalized form to the unnormalized form and then calls 1319 * {@code getDataElement(int[], int)}. Subclasses which may 1320 * have instances which do not support the unnormalized form must 1321 * override this method. 1322 * @param normComponents an array of normalized color and alpha 1323 * components 1324 * @param normOffset the index into {@code normComponents} at which to 1325 * begin retrieving the color and alpha components 1326 * @return an {@code int} pixel value in this 1327 * {@code ColorModel} corresponding to the specified components. 1328 * @throws IllegalArgumentException if 1329 * pixel values for this {@code ColorModel} are not 1330 * conveniently representable as a single {@code int} 1331 * @throws ArrayIndexOutOfBoundsException if 1332 * the {@code normComponents} array is not large enough to 1333 * hold all of the color and alpha components starting at 1334 * {@code normOffset} 1335 * @since 1.4 1336 */ 1337 public int getDataElement(float[] normComponents, int normOffset) { 1338 int components[] = getUnnormalizedComponents(normComponents, 1339 normOffset, null, 0); 1340 return getDataElement(components, 0); 1341 } 1342 1343 /** 1344 * Returns a data element array representation of a pixel in this 1345 * {@code ColorModel}, given an array of normalized color/alpha 1346 * components. This array can then be passed to the 1347 * {@code setDataElements} method of a {@code WritableRaster} 1348 * object. An {@code ArrayIndexOutOfBoundsException} is thrown 1349 * if the {@code normComponents} array is not large enough to hold 1350 * all the color and alpha components (starting at 1351 * {@code normOffset}). If the {@code obj} variable is 1352 * {@code null}, a new array will be allocated. If 1353 * {@code obj} is not {@code null}, it must be a primitive 1354 * array of type transferType; otherwise, a 1355 * {@code ClassCastException} is thrown. An 1356 * {@code ArrayIndexOutOfBoundsException} is thrown if 1357 * {@code obj} is not large enough to hold a pixel value for this 1358 * {@code ColorModel}. 1359 * Since {@code ColorModel} is an abstract class, 1360 * any instance is an instance of a subclass. The default implementation 1361 * of this method in this abstract class first converts from the 1362 * normalized form to the unnormalized form and then calls 1363 * {@code getDataElement(int[], int, Object)}. Subclasses which may 1364 * have instances which do not support the unnormalized form must 1365 * override this method. 1366 * @param normComponents an array of normalized color and alpha 1367 * components 1368 * @param normOffset the index into {@code normComponents} at which to 1369 * begin retrieving color and alpha components 1370 * @param obj a primitive data array to hold the returned pixel 1371 * @return an {@code Object} which is a primitive data array 1372 * representation of a pixel 1373 * @throws ClassCastException if {@code obj} 1374 * is not a primitive array of type {@code transferType} 1375 * @throws ArrayIndexOutOfBoundsException if 1376 * {@code obj} is not large enough to hold a pixel value 1377 * for this {@code ColorModel} or the {@code normComponents} 1378 * array is not large enough to hold all of the color and alpha 1379 * components starting at {@code normOffset} 1380 * @see WritableRaster#setDataElements 1381 * @see SampleModel#setDataElements 1382 * @since 1.4 1383 */ 1384 public Object getDataElements(float[] normComponents, int normOffset, 1385 Object obj) { 1386 int components[] = getUnnormalizedComponents(normComponents, 1387 normOffset, null, 0); 1388 return getDataElements(components, 0, obj); 1389 } 1390 1391 /** 1392 * Returns an array of all of the color/alpha components in normalized 1393 * form, given a pixel in this {@code ColorModel}. The pixel 1394 * value is specified by an array of data elements of type transferType 1395 * passed in as an object reference. If pixel is not a primitive array 1396 * of type transferType, a {@code ClassCastException} is thrown. 1397 * An {@code ArrayIndexOutOfBoundsException} is thrown if 1398 * {@code pixel} is not large enough to hold a pixel value for this 1399 * {@code ColorModel}. 1400 * Normalized components are float values between a per component minimum 1401 * and maximum specified by the {@code ColorSpace} object for this 1402 * {@code ColorModel}. If the 1403 * {@code normComponents} array is {@code null}, a new array 1404 * will be allocated. The {@code normComponents} array 1405 * will be returned. Color/alpha components are stored in the 1406 * {@code normComponents} array starting at 1407 * {@code normOffset} (even if the array is allocated by this 1408 * method). An {@code ArrayIndexOutOfBoundsException} is thrown 1409 * if the {@code normComponents} array is not {@code null} 1410 * and is not large enough to hold all the color and alpha components 1411 * (starting at {@code normOffset}). 1412 * Since {@code ColorModel} is an abstract class, 1413 * any instance is an instance of a subclass. The default implementation 1414 * of this method in this abstract class first retrieves color and alpha 1415 * components in the unnormalized form using 1416 * {@code getComponents(Object, int[], int)} and then calls 1417 * {@code getNormalizedComponents(int[], int, float[], int)}. 1418 * Subclasses which may 1419 * have instances which do not support the unnormalized form must 1420 * override this method. 1421 * @param pixel the specified pixel 1422 * @param normComponents an array to receive the normalized components 1423 * @param normOffset the offset into the {@code normComponents} 1424 * array at which to start storing normalized components 1425 * @return an array containing normalized color and alpha 1426 * components. 1427 * @throws ClassCastException if {@code pixel} is not a primitive 1428 * array of type transferType 1429 * @throws ArrayIndexOutOfBoundsException if 1430 * {@code normComponents} is not large enough to hold all 1431 * color and alpha components starting at {@code normOffset} 1432 * @throws ArrayIndexOutOfBoundsException if 1433 * {@code pixel} is not large enough to hold a pixel 1434 * value for this {@code ColorModel}. 1435 * @throws UnsupportedOperationException if the 1436 * constructor of this {@code ColorModel} called the 1437 * {@code super(bits)} constructor, but did not 1438 * override this method. See the constructor, 1439 * {@link #ColorModel(int)}. 1440 * @throws UnsupportedOperationException if this method is unable 1441 * to determine the number of bits per component 1442 * @since 1.4 1443 */ 1444 public float[] getNormalizedComponents(Object pixel, 1445 float[] normComponents, 1446 int normOffset) { 1447 int components[] = getComponents(pixel, null, 0); 1448 return getNormalizedComponents(components, 0, 1449 normComponents, normOffset); 1450 } 1451 1452 /** 1453 * Tests if the specified {@code Object} equals this 1454 * {@code ColorModel}. 1455 * In order to protect the symmetry property of 1456 * {@code (a.equals(b) == b.equals(a))}, 1457 * the target object must be the same class (and not a subclass) 1458 * as this object to evaluate as {@code equals}. 1459 * <p> 1460 * Subclasses may check additional properties, but this method 1461 * will check the following basic properties for equivalence to 1462 * determine if the target object equals this object: 1463 * 1464 * <ul> 1465 * <li>Support for alpha component. 1466 * <li>Is alpha premultiplied. 1467 * <li>Number of bits per pixel. 1468 * <li>Type of transparency like Opaque, Bitmask or Translucent. 1469 * <li>Number of components in a pixel. 1470 * <li>{@code ColorSpace} type. 1471 * <li>Type of the array used to represent pixel values. 1472 * <li>Number of significant bits per color and alpha component. 1473 * </ul> 1474 * <p> 1475 * Subclasses should override this method if they have any additional 1476 * properties to compare and should use the following implementation. 1477 * Note that the base {@code ColorModel} class already ensures that 1478 * the target object is the same class as this object so the cast to 1479 * the subclass type can be assumed if {@code super.equals(obj)} returns 1480 * true. 1481 * <pre> 1482 * public boolean equals(Object obj) { 1483 * if (!super.equals(obj)) { 1484 * return false; 1485 * } 1486 * MyCMClass cm = (MyCMClass) obj; 1487 * // test additional properties on "cm" and "this" 1488 * } 1489 * </pre> 1490 * <p> 1491 * @param obj the {@code Object} to test for equality 1492 * @return {@code true} if the specified {@code Object} 1493 * equals this {@code ColorModel}; {@code false} otherwise. 1494 */ 1495 @Override 1496 public boolean equals(Object obj) { 1497 if (this == obj) { 1498 return true; 1499 } 1500 if ((obj == null) || (obj.getClass() != getClass())) { 1501 return false; 1502 } 1503 1504 ColorModel cm = (ColorModel) obj; 1505 if (supportsAlpha != cm.hasAlpha() || 1506 isAlphaPremultiplied != cm.isAlphaPremultiplied() || 1507 pixel_bits != cm.getPixelSize() || 1508 transparency != cm.getTransparency() || 1509 numComponents != cm.getNumComponents() || 1510 (!(colorSpace.equals(cm.colorSpace))) || 1511 transferType != cm.transferType) 1512 { 1513 return false; 1514 } 1515 1516 int[] nb = cm.getComponentSize(); 1517 1518 if ((nBits != null) && (nb != null)) { 1519 for (int i = 0; i < numComponents; i++) { 1520 if (nBits[i] != nb[i]) { 1521 return false; 1522 } 1523 } 1524 } else { 1525 return ((nBits == null) && (nb == null)); 1526 } 1527 1528 return true; 1529 } 1530 1531 /** 1532 * Returns the hash code for this ColorModel. 1533 * 1534 * @return a hash code for this ColorModel. 1535 */ 1536 @Override 1537 public int hashCode() { 1538 int result = hashCode; 1539 if (result == 0) { 1540 result = 7; 1541 result = 89 * result + this.pixel_bits; 1542 result = 89 * result + Arrays.hashCode(this.nBits); 1543 result = 89 * result + this.transparency; 1544 result = 89 * result + (this.supportsAlpha ? 1 : 0); 1545 result = 89 * result + (this.isAlphaPremultiplied ? 1 : 0); 1546 result = 89 * result + this.numComponents; 1547 result = 89 * result + Objects.hashCode(this.colorSpace); 1548 result = 89 * result + this.transferType; 1549 hashCode = result; 1550 } 1551 return result; 1552 } 1553 1554 /** 1555 * Returns the {@code ColorSpace} associated with this 1556 * {@code ColorModel}. 1557 * @return the {@code ColorSpace} of this 1558 * {@code ColorModel}. 1559 */ 1560 public final ColorSpace getColorSpace() { 1561 return colorSpace; 1562 } 1563 1564 /** 1565 * Forces the raster data to match the state specified in the 1566 * {@code isAlphaPremultiplied} variable, assuming the data is 1567 * currently correctly described by this {@code ColorModel}. It 1568 * may multiply or divide the color raster data by alpha, or do 1569 * nothing if the data is in the correct state. If the data needs to 1570 * be coerced, this method will also return an instance of this 1571 * {@code ColorModel} with the {@code isAlphaPremultiplied} 1572 * flag set appropriately. This method will throw a 1573 * {@code UnsupportedOperationException} if it is not supported 1574 * by this {@code ColorModel}. 1575 * Since {@code ColorModel} is an abstract class, 1576 * any instance is an instance of a subclass. Subclasses must 1577 * override this method since the implementation in this abstract 1578 * class throws an {@code UnsupportedOperationException}. 1579 * @param raster the {@code WritableRaster} data 1580 * @param isAlphaPremultiplied {@code true} if the alpha is 1581 * premultiplied; {@code false} otherwise 1582 * @return a {@code ColorModel} object that represents the 1583 * coerced data. 1584 */ 1585 public ColorModel coerceData (WritableRaster raster, 1586 boolean isAlphaPremultiplied) { 1587 throw new UnsupportedOperationException 1588 ("This method is not supported by this color model"); 1589 } 1590 1591 /** 1592 * Returns {@code true} if {@code raster} is compatible 1593 * with this {@code ColorModel} and {@code false} if it is 1594 * not. 1595 * Since {@code ColorModel} is an abstract class, 1596 * any instance is an instance of a subclass. Subclasses must 1597 * override this method since the implementation in this abstract 1598 * class throws an {@code UnsupportedOperationException}. 1599 * @param raster the {@link Raster} object to test for compatibility 1600 * @return {@code true} if {@code raster} is compatible 1601 * with this {@code ColorModel}. 1602 * @throws UnsupportedOperationException if this 1603 * method has not been implemented for this 1604 * {@code ColorModel} 1605 */ 1606 public boolean isCompatibleRaster(Raster raster) { 1607 throw new UnsupportedOperationException( 1608 "This method has not been implemented for this ColorModel."); 1609 } 1610 1611 /** 1612 * Creates a {@code WritableRaster} with the specified width and 1613 * height that has a data layout ({@code SampleModel}) compatible 1614 * with this {@code ColorModel}. 1615 * Since {@code ColorModel} is an abstract class, 1616 * any instance is an instance of a subclass. Subclasses must 1617 * override this method since the implementation in this abstract 1618 * class throws an {@code UnsupportedOperationException}. 1619 * @param w the width to apply to the new {@code WritableRaster} 1620 * @param h the height to apply to the new {@code WritableRaster} 1621 * @return a {@code WritableRaster} object with the specified 1622 * width and height. 1623 * @throws UnsupportedOperationException if this 1624 * method is not supported by this {@code ColorModel} 1625 * @see WritableRaster 1626 * @see SampleModel 1627 */ 1628 public WritableRaster createCompatibleWritableRaster(int w, int h) { 1629 throw new UnsupportedOperationException 1630 ("This method is not supported by this color model"); 1631 } 1632 1633 /** 1634 * Creates a {@code SampleModel} with the specified width and 1635 * height that has a data layout compatible with this 1636 * {@code ColorModel}. 1637 * Since {@code ColorModel} is an abstract class, 1638 * any instance is an instance of a subclass. Subclasses must 1639 * override this method since the implementation in this abstract 1640 * class throws an {@code UnsupportedOperationException}. 1641 * @param w the width to apply to the new {@code SampleModel} 1642 * @param h the height to apply to the new {@code SampleModel} 1643 * @return a {@code SampleModel} object with the specified 1644 * width and height. 1645 * @throws UnsupportedOperationException if this 1646 * method is not supported by this {@code ColorModel} 1647 * @see SampleModel 1648 */ 1649 public SampleModel createCompatibleSampleModel(int w, int h) { 1650 throw new UnsupportedOperationException 1651 ("This method is not supported by this color model"); 1652 } 1653 1654 /** Checks if the {@code SampleModel} is compatible with this 1655 * {@code ColorModel}. 1656 * Since {@code ColorModel} is an abstract class, 1657 * any instance is an instance of a subclass. Subclasses must 1658 * override this method since the implementation in this abstract 1659 * class throws an {@code UnsupportedOperationException}. 1660 * @param sm the specified {@code SampleModel} 1661 * @return {@code true} if the specified {@code SampleModel} 1662 * is compatible with this {@code ColorModel}; {@code false} 1663 * otherwise. 1664 * @throws UnsupportedOperationException if this 1665 * method is not supported by this {@code ColorModel} 1666 * @see SampleModel 1667 */ 1668 public boolean isCompatibleSampleModel(SampleModel sm) { 1669 throw new UnsupportedOperationException 1670 ("This method is not supported by this color model"); 1671 } 1672 1673 /** 1674 * Disposes of system resources associated with this 1675 * {@code ColorModel} once this {@code ColorModel} is no 1676 * longer referenced. 1677 */ 1678 public void finalize() { 1679 } 1680 1681 1682 /** 1683 * Returns a {@code Raster} representing the alpha channel of an 1684 * image, extracted from the input {@code Raster}, provided that 1685 * pixel values of this {@code ColorModel} represent color and 1686 * alpha information as separate spatial bands (e.g. 1687 * {@link ComponentColorModel} and {@code DirectColorModel}). 1688 * This method assumes that {@code Raster} objects associated 1689 * with such a {@code ColorModel} store the alpha band, if 1690 * present, as the last band of image data. Returns {@code null} 1691 * if there is no separate spatial alpha channel associated with this 1692 * {@code ColorModel}. If this is an 1693 * {@code IndexColorModel} which has alpha in the lookup table, 1694 * this method will return {@code null} since 1695 * there is no spatially discrete alpha channel. 1696 * This method will create a new {@code Raster} (but will share 1697 * the data array). 1698 * Since {@code ColorModel} is an abstract class, any instance 1699 * is an instance of a subclass. Subclasses must override this 1700 * method to get any behavior other than returning {@code null} 1701 * because the implementation in this abstract class returns 1702 * {@code null}. 1703 * @param raster the specified {@code Raster} 1704 * @return a {@code Raster} representing the alpha channel of 1705 * an image, obtained from the specified {@code Raster}. 1706 */ 1707 public WritableRaster getAlphaRaster(WritableRaster raster) { 1708 return null; 1709 } 1710 1711 /** 1712 * Returns the {@code String} representation of the contents of 1713 * this {@code ColorModel} object. 1714 * @return a {@code String} representing the contents of this 1715 * {@code ColorModel} object. 1716 */ 1717 public String toString() { 1718 return new String("ColorModel: #pixelBits = "+pixel_bits 1719 + " numComponents = "+numComponents 1720 + " color space = "+colorSpace 1721 + " transparency = "+transparency 1722 + " has alpha = "+supportsAlpha 1723 + " isAlphaPre = "+isAlphaPremultiplied 1724 ); 1725 } 1726 1727 static int getDefaultTransferType(int pixel_bits) { 1728 if (pixel_bits <= 8) { 1729 return DataBuffer.TYPE_BYTE; 1730 } else if (pixel_bits <= 16) { 1731 return DataBuffer.TYPE_USHORT; 1732 } else if (pixel_bits <= 32) { 1733 return DataBuffer.TYPE_INT; 1734 } else { 1735 return DataBuffer.TYPE_UNDEFINED; 1736 } 1737 } 1738 1739 static byte[] l8Tos8 = null; // 8-bit linear to 8-bit non-linear sRGB LUT 1740 static byte[] s8Tol8 = null; // 8-bit non-linear sRGB to 8-bit linear LUT 1741 static byte[] l16Tos8 = null; // 16-bit linear to 8-bit non-linear sRGB LUT 1742 static short[] s8Tol16 = null; // 8-bit non-linear sRGB to 16-bit linear LUT 1743 1744 // Maps to hold LUTs for grayscale conversions 1745 static Map<ICC_ColorSpace, byte[]> g8Tos8Map = null; // 8-bit gray values to 8-bit sRGB values 1746 static Map<ICC_ColorSpace, byte[]> lg16Toog8Map = null; // 16-bit linear to 8-bit "other" gray 1747 static Map<ICC_ColorSpace, byte[]> g16Tos8Map = null; // 16-bit gray values to 8-bit sRGB values 1748 static Map<ICC_ColorSpace, short[]> lg16Toog16Map = null; // 16-bit linear to 16-bit "other" gray 1749 1750 static boolean isLinearRGBspace(ColorSpace cs) { 1751 // Note: CMM.LINEAR_RGBspace will be null if the linear 1752 // RGB space has not been created yet. 1753 return (cs == CMSManager.LINEAR_RGBspace); 1754 } 1755 1756 static boolean isLinearGRAYspace(ColorSpace cs) { 1757 // Note: CMM.GRAYspace will be null if the linear 1758 // gray space has not been created yet. 1759 return (cs == CMSManager.GRAYspace); 1760 } 1761 1762 static byte[] getLinearRGB8TosRGB8LUT() { 1763 if (l8Tos8 == null) { 1764 l8Tos8 = new byte[256]; 1765 float input, output; 1766 // algorithm for linear RGB to nonlinear sRGB conversion 1767 // is from the IEC 61966-2-1 International Standard, 1768 // Colour Management - Default RGB colour space - sRGB, 1769 // First Edition, 1999-10, 1770 // available for order at http://www.iec.ch 1771 for (int i = 0; i <= 255; i++) { 1772 input = ((float) i) / 255.0f; 1773 if (input <= 0.0031308f) { 1774 output = input * 12.92f; 1775 } else { 1776 output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4))) 1777 - 0.055f; 1778 } 1779 l8Tos8[i] = (byte) Math.round(output * 255.0f); 1780 } 1781 } 1782 return l8Tos8; 1783 } 1784 1785 static byte[] getsRGB8ToLinearRGB8LUT() { 1786 if (s8Tol8 == null) { 1787 s8Tol8 = new byte[256]; 1788 float input, output; 1789 // algorithm from IEC 61966-2-1 International Standard 1790 for (int i = 0; i <= 255; i++) { 1791 input = ((float) i) / 255.0f; 1792 if (input <= 0.04045f) { 1793 output = input / 12.92f; 1794 } else { 1795 output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4); 1796 } 1797 s8Tol8[i] = (byte) Math.round(output * 255.0f); 1798 } 1799 } 1800 return s8Tol8; 1801 } 1802 1803 static byte[] getLinearRGB16TosRGB8LUT() { 1804 if (l16Tos8 == null) { 1805 l16Tos8 = new byte[65536]; 1806 float input, output; 1807 // algorithm from IEC 61966-2-1 International Standard 1808 for (int i = 0; i <= 65535; i++) { 1809 input = ((float) i) / 65535.0f; 1810 if (input <= 0.0031308f) { 1811 output = input * 12.92f; 1812 } else { 1813 output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4))) 1814 - 0.055f; 1815 } 1816 l16Tos8[i] = (byte) Math.round(output * 255.0f); 1817 } 1818 } 1819 return l16Tos8; 1820 } 1821 1822 static short[] getsRGB8ToLinearRGB16LUT() { 1823 if (s8Tol16 == null) { 1824 s8Tol16 = new short[256]; 1825 float input, output; 1826 // algorithm from IEC 61966-2-1 International Standard 1827 for (int i = 0; i <= 255; i++) { 1828 input = ((float) i) / 255.0f; 1829 if (input <= 0.04045f) { 1830 output = input / 12.92f; 1831 } else { 1832 output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4); 1833 } 1834 s8Tol16[i] = (short) Math.round(output * 65535.0f); 1835 } 1836 } 1837 return s8Tol16; 1838 } 1839 1840 /* 1841 * Return a byte LUT that converts 8-bit gray values in the grayCS 1842 * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut 1843 * is the byte array returned by this method and sval = lut[gval], 1844 * then the sRGB triple (sval,sval,sval) is the best match to gval. 1845 * Cache references to any computed LUT in a Map. 1846 */ 1847 static byte[] getGray8TosRGB8LUT(ICC_ColorSpace grayCS) { 1848 if (isLinearGRAYspace(grayCS)) { 1849 return getLinearRGB8TosRGB8LUT(); 1850 } 1851 if (g8Tos8Map != null) { 1852 byte[] g8Tos8LUT = g8Tos8Map.get(grayCS); 1853 if (g8Tos8LUT != null) { 1854 return g8Tos8LUT; 1855 } 1856 } 1857 byte[] g8Tos8LUT = new byte[256]; 1858 for (int i = 0; i <= 255; i++) { 1859 g8Tos8LUT[i] = (byte) i; 1860 } 1861 ColorTransform[] transformList = new ColorTransform[2]; 1862 PCMM mdl = CMSManager.getModule(); 1863 ICC_ColorSpace srgbCS = 1864 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB); 1865 transformList[0] = mdl.createTransform( 1866 grayCS.getProfile(), ColorTransform.Any, ColorTransform.In); 1867 transformList[1] = mdl.createTransform( 1868 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); 1869 ColorTransform t = mdl.createTransform(transformList); 1870 byte[] tmp = t.colorConvert(g8Tos8LUT, null); 1871 for (int i = 0, j= 2; i <= 255; i++, j += 3) { 1872 // All three components of tmp should be equal, since 1873 // the input color space to colorConvert is a gray scale 1874 // space. However, there are slight anomalies in the results. 1875 // Copy tmp starting at index 2, since colorConvert seems 1876 // to be slightly more accurate for the third component! 1877 g8Tos8LUT[i] = tmp[j]; 1878 } 1879 if (g8Tos8Map == null) { 1880 g8Tos8Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, byte[]>(2)); 1881 } 1882 g8Tos8Map.put(grayCS, g8Tos8LUT); 1883 return g8Tos8LUT; 1884 } 1885 1886 /* 1887 * Return a byte LUT that converts 16-bit gray values in the CS_GRAY 1888 * linear gray ColorSpace to the appropriate 8-bit value in the 1889 * grayCS ColorSpace. Cache references to any computed LUT in a Map. 1890 */ 1891 static byte[] getLinearGray16ToOtherGray8LUT(ICC_ColorSpace grayCS) { 1892 if (lg16Toog8Map != null) { 1893 byte[] lg16Toog8LUT = lg16Toog8Map.get(grayCS); 1894 if (lg16Toog8LUT != null) { 1895 return lg16Toog8LUT; 1896 } 1897 } 1898 short[] tmp = new short[65536]; 1899 for (int i = 0; i <= 65535; i++) { 1900 tmp[i] = (short) i; 1901 } 1902 ColorTransform[] transformList = new ColorTransform[2]; 1903 PCMM mdl = CMSManager.getModule(); 1904 ICC_ColorSpace lgCS = 1905 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY); 1906 transformList[0] = mdl.createTransform ( 1907 lgCS.getProfile(), ColorTransform.Any, ColorTransform.In); 1908 transformList[1] = mdl.createTransform ( 1909 grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out); 1910 ColorTransform t = mdl.createTransform(transformList); 1911 tmp = t.colorConvert(tmp, null); 1912 byte[] lg16Toog8LUT = new byte[65536]; 1913 for (int i = 0; i <= 65535; i++) { 1914 // scale unsigned short (0 - 65535) to unsigned byte (0 - 255) 1915 lg16Toog8LUT[i] = 1916 (byte) (((float) (tmp[i] & 0xffff)) * (1.0f /257.0f) + 0.5f); 1917 } 1918 if (lg16Toog8Map == null) { 1919 lg16Toog8Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, byte[]>(2)); 1920 } 1921 lg16Toog8Map.put(grayCS, lg16Toog8LUT); 1922 return lg16Toog8LUT; 1923 } 1924 1925 /* 1926 * Return a byte LUT that converts 16-bit gray values in the grayCS 1927 * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut 1928 * is the byte array returned by this method and sval = lut[gval], 1929 * then the sRGB triple (sval,sval,sval) is the best match to gval. 1930 * Cache references to any computed LUT in a Map. 1931 */ 1932 static byte[] getGray16TosRGB8LUT(ICC_ColorSpace grayCS) { 1933 if (isLinearGRAYspace(grayCS)) { 1934 return getLinearRGB16TosRGB8LUT(); 1935 } 1936 if (g16Tos8Map != null) { 1937 byte[] g16Tos8LUT = g16Tos8Map.get(grayCS); 1938 if (g16Tos8LUT != null) { 1939 return g16Tos8LUT; 1940 } 1941 } 1942 short[] tmp = new short[65536]; 1943 for (int i = 0; i <= 65535; i++) { 1944 tmp[i] = (short) i; 1945 } 1946 ColorTransform[] transformList = new ColorTransform[2]; 1947 PCMM mdl = CMSManager.getModule(); 1948 ICC_ColorSpace srgbCS = 1949 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB); 1950 transformList[0] = mdl.createTransform ( 1951 grayCS.getProfile(), ColorTransform.Any, ColorTransform.In); 1952 transformList[1] = mdl.createTransform ( 1953 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); 1954 ColorTransform t = mdl.createTransform(transformList); 1955 tmp = t.colorConvert(tmp, null); 1956 byte[] g16Tos8LUT = new byte[65536]; 1957 for (int i = 0, j= 2; i <= 65535; i++, j += 3) { 1958 // All three components of tmp should be equal, since 1959 // the input color space to colorConvert is a gray scale 1960 // space. However, there are slight anomalies in the results. 1961 // Copy tmp starting at index 2, since colorConvert seems 1962 // to be slightly more accurate for the third component! 1963 1964 // scale unsigned short (0 - 65535) to unsigned byte (0 - 255) 1965 g16Tos8LUT[i] = 1966 (byte) (((float) (tmp[j] & 0xffff)) * (1.0f /257.0f) + 0.5f); 1967 } 1968 if (g16Tos8Map == null) { 1969 g16Tos8Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, byte[]>(2)); 1970 } 1971 g16Tos8Map.put(grayCS, g16Tos8LUT); 1972 return g16Tos8LUT; 1973 } 1974 1975 /* 1976 * Return a short LUT that converts 16-bit gray values in the CS_GRAY 1977 * linear gray ColorSpace to the appropriate 16-bit value in the 1978 * grayCS ColorSpace. Cache references to any computed LUT in a Map. 1979 */ 1980 static short[] getLinearGray16ToOtherGray16LUT(ICC_ColorSpace grayCS) { 1981 if (lg16Toog16Map != null) { 1982 short[] lg16Toog16LUT = lg16Toog16Map.get(grayCS); 1983 if (lg16Toog16LUT != null) { 1984 return lg16Toog16LUT; 1985 } 1986 } 1987 short[] tmp = new short[65536]; 1988 for (int i = 0; i <= 65535; i++) { 1989 tmp[i] = (short) i; 1990 } 1991 ColorTransform[] transformList = new ColorTransform[2]; 1992 PCMM mdl = CMSManager.getModule(); 1993 ICC_ColorSpace lgCS = 1994 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY); 1995 transformList[0] = mdl.createTransform ( 1996 lgCS.getProfile(), ColorTransform.Any, ColorTransform.In); 1997 transformList[1] = mdl.createTransform( 1998 grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out); 1999 ColorTransform t = mdl.createTransform( 2000 transformList); 2001 short[] lg16Toog16LUT = t.colorConvert(tmp, null); 2002 if (lg16Toog16Map == null) { 2003 lg16Toog16Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, short[]>(2)); 2004 } 2005 lg16Toog16Map.put(grayCS, lg16Toog16LUT); 2006 return lg16Toog16LUT; 2007 } 2008 2009 }