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