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