1 /* 2 * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt.image; 27 28 import java.awt.Transparency; 29 import java.awt.color.ColorSpace; 30 import java.awt.color.ICC_ColorSpace; 31 import sun.java2d.cmm.CMSManager; 32 import sun.java2d.cmm.ColorTransform; 33 import sun.java2d.cmm.PCMM; 34 import java.util.Arrays; 35 import java.util.Collections; 36 import java.util.Map; 37 import java.util.WeakHashMap; 38 import java.util.Objects; 39 40 /** 41 * The {@code ColorModel} abstract class encapsulates the 42 * methods for translating a pixel value to color components 43 * (for example, red, green, and blue) and an alpha component. 44 * In order to render an image to the screen, a printer, or another 45 * image, pixel values must be converted to color and alpha components. 46 * As arguments to or return values from methods of this class, 47 * pixels are represented as 32-bit ints or as arrays of primitive types. 48 * The number, order, and interpretation of color components for a 49 * {@code ColorModel} is specified by its {@code ColorSpace}. 50 * A {@code ColorModel} used with pixel data that does not include 51 * alpha information treats all pixels as opaque, which is an alpha 52 * value of 1.0. 53 * <p> 54 * This {@code ColorModel} class supports two representations of 55 * pixel values. A pixel value can be a single 32-bit int or an 56 * array of primitive types. The Java(tm) Platform 1.0 and 1.1 APIs 57 * represented pixels as single {@code byte} or single 58 * {@code int} values. For purposes of the {@code ColorModel} 59 * class, pixel value arguments were passed as ints. The Java(tm) 2 60 * Platform API introduced additional classes for representing images. 61 * With {@link BufferedImage} or {@link RenderedImage} 62 * objects, based on {@link Raster} and {@link SampleModel} classes, pixel 63 * values might not be conveniently representable as a single int. 64 * Consequently, {@code ColorModel} now has methods that accept 65 * pixel values represented as arrays of primitive types. The primitive 66 * type used by a particular {@code ColorModel} object is called its 67 * transfer type. 68 * <p> 69 * {@code ColorModel} objects used with images for which pixel values 70 * are not conveniently representable as a single int throw an 71 * {@link IllegalArgumentException} when methods taking a single int pixel 72 * argument are called. Subclasses of {@code ColorModel} must 73 * specify the conditions under which this occurs. This does not 74 * occur with {@link DirectColorModel} or {@link IndexColorModel} objects. 75 * <p> 76 * Currently, the transfer types supported by the Java 2D(tm) API are 77 * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, 78 * DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, and DataBuffer.TYPE_DOUBLE. 79 * Most rendering operations will perform much faster when using ColorModels 80 * and images based on the first three of these types. In addition, some 81 * image filtering operations are not supported for ColorModels and 82 * images based on the latter three types. 83 * The transfer type for a particular {@code ColorModel} object is 84 * specified when the object is created, either explicitly or by default. 85 * All subclasses of {@code ColorModel} must specify what the 86 * possible transfer types are and how the number of elements in the 87 * primitive arrays representing pixels is determined. 88 * <p> 89 * For {@code BufferedImages}, the transfer type of its 90 * {@code Raster} and of the {@code Raster} object's 91 * {@code SampleModel} (available from the 92 * {@code getTransferType} methods of these classes) must match that 93 * of the {@code ColorModel}. The number of elements in an array 94 * representing a pixel for the {@code Raster} and 95 * {@code SampleModel} (available from the 96 * {@code getNumDataElements} methods of these classes) must match 97 * that of the {@code ColorModel}. 98 * <p> 99 * The algorithm used to convert from pixel values to color and alpha 100 * components varies by subclass. For example, there is not necessarily 101 * a one-to-one correspondence between samples obtained from the 102 * {@code SampleModel} of a {@code BufferedImage} object's 103 * {@code Raster} and color/alpha components. Even when 104 * there is such a correspondence, the number of bits in a sample is not 105 * necessarily the same as the number of bits in the corresponding color/alpha 106 * component. Each subclass must specify how the translation from 107 * pixel values to color/alpha components is done. 108 * <p> 109 * Methods in the {@code ColorModel} class use two different 110 * representations of color and alpha components - a normalized form 111 * and an unnormalized form. In the normalized form, each component is a 112 * {@code float} value between some minimum and maximum values. For 113 * the alpha component, the minimum is 0.0 and the maximum is 1.0. For 114 * color components the minimum and maximum values for each component can 115 * be obtained from the {@code ColorSpace} object. These values 116 * will often be 0.0 and 1.0 (e.g. normalized component values for the 117 * default sRGB color space range from 0.0 to 1.0), but some color spaces 118 * have component values with different upper and lower limits. These 119 * limits can be obtained using the {@code getMinValue} and 120 * {@code getMaxValue} methods of the {@code ColorSpace} 121 * class. Normalized color component values are not premultiplied. 122 * All {@code ColorModels} must support the normalized form. 123 * <p> 124 * In the unnormalized 125 * form, each component is an unsigned integral value between 0 and 126 * 2<sup>n</sup> - 1, where n is the number of significant bits for a 127 * particular component. If pixel values for a particular 128 * {@code ColorModel} represent color samples premultiplied by 129 * the alpha sample, unnormalized color component values are 130 * also premultiplied. The unnormalized form is used only with instances 131 * of {@code ColorModel} whose {@code ColorSpace} has minimum 132 * component values of 0.0 for all components and maximum values of 133 * 1.0 for all components. 134 * The unnormalized form for color and alpha components can be a convenient 135 * representation for {@code ColorModels} whose normalized component 136 * values all lie 137 * between 0.0 and 1.0. In such cases the integral value 0 maps to 0.0 and 138 * the value 2<sup>n</sup> - 1 maps to 1.0. In other cases, such as 139 * when the normalized component values can be either negative or positive, 140 * the unnormalized form is not convenient. Such {@code ColorModel} 141 * objects throw an {@link IllegalArgumentException} when methods involving 142 * an unnormalized argument are called. Subclasses of {@code ColorModel} 143 * must specify the conditions under which this occurs. 144 * 145 * @see IndexColorModel 146 * @see ComponentColorModel 147 * @see PackedColorModel 148 * @see DirectColorModel 149 * @see java.awt.Image 150 * @see BufferedImage 151 * @see RenderedImage 152 * @see java.awt.color.ColorSpace 153 * @see SampleModel 154 * @see Raster 155 * @see DataBuffer 156 */ 157 public abstract class ColorModel implements Transparency{ 158 private long pData; // Placeholder for data for native functions 159 160 /** 161 * The total number of bits in the pixel. 162 */ 163 protected int pixel_bits; 164 int nBits[]; 165 int transparency = Transparency.TRANSLUCENT; 166 boolean supportsAlpha = true; 167 boolean isAlphaPremultiplied = false; 168 int numComponents = -1; 169 int numColorComponents = -1; 170 ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); 171 int colorSpaceType = ColorSpace.TYPE_RGB; 172 int maxBits; 173 boolean is_sRGB = true; 174 175 /** 176 * Data type of the array used to represent pixel values. 177 */ 178 protected int transferType; 179 180 /** 181 * This is copied from java.awt.Toolkit since we need the library 182 * loaded in java.awt.image also: 183 * 184 * WARNING: This is a temporary workaround for a problem in the 185 * way the AWT loads native libraries. A number of classes in the 186 * AWT package have a native method, initIDs(), which initializes 187 * the JNI field and method ids used in the native portion of 188 * their implementation. 189 * 190 * Since the use and storage of these ids is done by the 191 * implementation libraries, the implementation of these method is 192 * provided by the particular AWT implementations (for example, 193 * "Toolkit"s/Peer), such as Motif, Microsoft Windows, or Tiny. The 194 * problem is that this means that the native libraries must be 195 * loaded by the java.* classes, which do not necessarily know the 196 * names of the libraries to load. A better way of doing this 197 * would be to provide a separate library which defines java.awt.* 198 * initIDs, and exports the relevant symbols out to the 199 * implementation libraries. 200 * 201 * For now, we know it's done by the implementation, and we assume 202 * that the name of the library is "awt". -br. 203 */ 204 private static boolean loaded = false; 205 static void loadLibraries() { 206 if (!loaded) { 207 java.security.AccessController.doPrivileged( 208 new java.security.PrivilegedAction<Void>() { 209 public Void run() { 210 System.loadLibrary("awt"); 211 return null; 212 } 213 }); 214 loaded = true; 215 } 216 } 217 private static native void initIDs(); 218 static { 219 /* ensure that the proper libraries are loaded */ 220 loadLibraries(); 221 initIDs(); 222 } 223 private static ColorModel RGBdefault; 224 225 /** 226 * Returns a {@code DirectColorModel} that describes the default 227 * format for integer RGB values used in many of the methods in the 228 * AWT image interfaces for the convenience of the programmer. 229 * The color space is the default {@link ColorSpace}, sRGB. 230 * The format for the RGB values is an integer with 8 bits 231 * each of alpha, red, green, and blue color components ordered 232 * correspondingly from the most significant byte to the least 233 * significant byte, as in: 0xAARRGGBB. Color components are 234 * not premultiplied by the alpha component. This format does not 235 * necessarily represent the native or the most efficient 236 * {@code ColorModel} for a particular device or for all images. 237 * It is merely used as a common color model format. 238 * @return a {@code DirectColorModel} object describing default 239 * RGB values. 240 */ 241 public static ColorModel getRGBdefault() { 242 if (RGBdefault == null) { 243 RGBdefault = new DirectColorModel(32, 244 0x00ff0000, // Red 245 0x0000ff00, // Green 246 0x000000ff, // Blue 247 0xff000000 // Alpha 248 ); 249 } 250 return RGBdefault; 251 } 252 253 /** 254 * Constructs a {@code ColorModel} that translates pixels of the 255 * specified number of bits to color/alpha components. The color 256 * space is the default RGB {@code ColorSpace}, which is sRGB. 257 * Pixel values are assumed to include alpha information. If color 258 * and alpha information are represented in the pixel value as 259 * separate spatial bands, the color bands are assumed not to be 260 * premultiplied with the alpha value. The transparency type is 261 * java.awt.Transparency.TRANSLUCENT. The transfer type will be the 262 * smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 263 * or DataBuffer.TYPE_INT that can hold a single pixel 264 * (or DataBuffer.TYPE_UNDEFINED if bits is greater 265 * than 32). Since this constructor has no information about the 266 * number of bits per color and alpha component, any subclass calling 267 * this constructor should override any method that requires this 268 * information. 269 * @param bits the number of bits of a pixel 270 * @throws IllegalArgumentException if the number 271 * of bits in {@code bits} is less than 1 272 */ 273 public ColorModel(int bits) { 274 pixel_bits = bits; 275 if (bits < 1) { 276 throw new IllegalArgumentException("Number of bits must be > 0"); 277 } 278 numComponents = 4; 279 numColorComponents = 3; 280 maxBits = bits; 281 // REMIND: make sure transferType is set correctly 282 transferType = ColorModel.getDefaultTransferType(bits); 283 } 284 285 /** 286 * Constructs a {@code ColorModel} that translates pixel values 287 * to color/alpha components. Color components will be in the 288 * specified {@code ColorSpace}. {@code pixel_bits} is the 289 * number of bits in the pixel values. The bits array 290 * specifies the number of significant bits per color and alpha component. 291 * Its length should be the number of components in the 292 * {@code ColorSpace} if there is no alpha information in the 293 * pixel values, or one more than this number if there is alpha 294 * information. {@code hasAlpha} indicates whether or not alpha 295 * information is present. The {@code boolean} 296 * {@code isAlphaPremultiplied} specifies how to interpret pixel 297 * values in which color and alpha information are represented as 298 * separate spatial bands. If the {@code boolean} 299 * is {@code true}, color samples are assumed to have been 300 * multiplied by the alpha sample. The {@code transparency} 301 * specifies what alpha values can be represented by this color model. 302 * The transfer type is the type of primitive array used to represent 303 * pixel values. Note that the bits array contains the number of 304 * significant bits per color/alpha component after the translation 305 * from pixel values. For example, for an 306 * {@code IndexColorModel} with {@code pixel_bits} equal to 307 * 16, the bits array might have four elements with each element set 308 * to 8. 309 * @param pixel_bits the number of bits in the pixel values 310 * @param bits array that specifies the number of significant bits 311 * per color and alpha component 312 * @param cspace the specified {@code ColorSpace} 313 * @param hasAlpha {@code true} if alpha information is present; 314 * {@code false} otherwise 315 * @param isAlphaPremultiplied {@code true} if color samples are 316 * assumed to be premultiplied by the alpha samples; 317 * {@code false} otherwise 318 * @param transparency what alpha values can be represented by this 319 * color model 320 * @param transferType the type of the array used to represent pixel 321 * values 322 * @throws IllegalArgumentException if the length of 323 * the bit array is less than the number of color or alpha 324 * components in this {@code ColorModel}, or if the 325 * transparency is not a valid value. 326 * @throws IllegalArgumentException if the sum of the number 327 * of bits in {@code bits} is less than 1 or if 328 * any of the elements in {@code bits} is less than 0. 329 * @see java.awt.Transparency 330 */ 331 protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace, 332 boolean hasAlpha, 333 boolean isAlphaPremultiplied, 334 int transparency, 335 int transferType) { 336 colorSpace = cspace; 337 colorSpaceType = cspace.getType(); 338 numColorComponents = cspace.getNumComponents(); 339 numComponents = numColorComponents + (hasAlpha ? 1 : 0); 340 supportsAlpha = hasAlpha; 341 if (bits.length < numComponents) { 342 throw new IllegalArgumentException("Number of color/alpha "+ 343 "components should be "+ 344 numComponents+ 345 " but length of bits array is "+ 346 bits.length); 347 } 348 349 // 4186669 350 if (transparency < Transparency.OPAQUE || 351 transparency > Transparency.TRANSLUCENT) 352 { 353 throw new IllegalArgumentException("Unknown transparency: "+ 354 transparency); 355 } 356 357 if (supportsAlpha == false) { 358 this.isAlphaPremultiplied = false; 359 this.transparency = Transparency.OPAQUE; 360 } 361 else { 362 this.isAlphaPremultiplied = isAlphaPremultiplied; 363 this.transparency = transparency; 364 } 365 366 nBits = bits.clone(); 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 * Tests if the specified {@code Object} equals this 1446 * {@code ColorModel}. 1447 * In order to protect the symmetry property of 1448 * {@code (a.equals(b) == b.equals(a))}, 1449 * the target object must be the exact same class as this 1450 * object to evaluate as {equals}. 1451 * @param obj the {@code Object} to test for equality 1452 * @return {@code true} if the specified {@code Object} 1453 * equals this {@code ColorModel}; {@code false} otherwise. 1454 */ 1455 @Override 1456 public boolean equals(Object obj) { 1457 if (this == obj) { 1458 return true; 1459 } 1460 if ((obj == null) || (obj.getClass() != getClass())) { 1461 return false; 1462 } 1463 1464 ColorModel cm = (ColorModel) obj; 1465 if (supportsAlpha != cm.hasAlpha() || 1466 isAlphaPremultiplied != cm.isAlphaPremultiplied() || 1467 pixel_bits != cm.getPixelSize() || 1468 transparency != cm.getTransparency() || 1469 numComponents != cm.getNumComponents() || 1470 colorSpace != cm.colorSpace || 1471 transferType != cm.transferType) 1472 { 1473 return false; 1474 } 1475 1476 int[] nb = cm.getComponentSize(); 1477 1478 if ((nBits != null) && (nb != null)) { 1479 for (int i = 0; i < numComponents; i++) { 1480 if (nBits[i] != nb[i]) { 1481 return false; 1482 } 1483 } 1484 } else { 1485 return ((nBits == null) && (nb == null)); 1486 } 1487 1488 return true; 1489 } 1490 1491 /** 1492 * Returns the hash code for this ColorModel. 1493 * 1494 * @return a hash code for this ColorModel. 1495 */ 1496 @Override 1497 public int hashCode() { 1498 int hash = 7; 1499 hash = 89 * hash + this.pixel_bits; 1500 hash = 89 * hash + Arrays.hashCode(this.nBits); 1501 hash = 89 * hash + this.transparency; 1502 hash = 89 * hash + (this.supportsAlpha ? 1 : 0); 1503 hash = 89 * hash + (this.isAlphaPremultiplied ? 1 : 0); 1504 hash = 89 * hash + this.numComponents; 1505 hash = 89 * hash + Objects.hashCode(this.colorSpace); 1506 hash = 89 * hash + this.transferType; 1507 return hash; 1508 } 1509 1510 /** 1511 * Returns the {@code ColorSpace} associated with this 1512 * {@code ColorModel}. 1513 * @return the {@code ColorSpace} of this 1514 * {@code ColorModel}. 1515 */ 1516 public final ColorSpace getColorSpace() { 1517 return colorSpace; 1518 } 1519 1520 /** 1521 * Forces the raster data to match the state specified in the 1522 * {@code isAlphaPremultiplied} variable, assuming the data is 1523 * currently correctly described by this {@code ColorModel}. It 1524 * may multiply or divide the color raster data by alpha, or do 1525 * nothing if the data is in the correct state. If the data needs to 1526 * be coerced, this method will also return an instance of this 1527 * {@code ColorModel} with the {@code isAlphaPremultiplied} 1528 * flag set appropriately. This method will throw a 1529 * {@code UnsupportedOperationException} if it is not supported 1530 * by this {@code ColorModel}. 1531 * Since {@code ColorModel} is an abstract class, 1532 * any instance is an instance of a subclass. Subclasses must 1533 * override this method since the implementation in this abstract 1534 * class throws an {@code UnsupportedOperationException}. 1535 * @param raster the {@code WritableRaster} data 1536 * @param isAlphaPremultiplied {@code true} if the alpha is 1537 * premultiplied; {@code false} otherwise 1538 * @return a {@code ColorModel} object that represents the 1539 * coerced data. 1540 */ 1541 public ColorModel coerceData (WritableRaster raster, 1542 boolean isAlphaPremultiplied) { 1543 throw new UnsupportedOperationException 1544 ("This method is not supported by this color model"); 1545 } 1546 1547 /** 1548 * Returns {@code true} if {@code raster} is compatible 1549 * with this {@code ColorModel} and {@code false} if it is 1550 * not. 1551 * Since {@code ColorModel} is an abstract class, 1552 * any instance is an instance of a subclass. Subclasses must 1553 * override this method since the implementation in this abstract 1554 * class throws an {@code UnsupportedOperationException}. 1555 * @param raster the {@link Raster} object to test for compatibility 1556 * @return {@code true} if {@code raster} is compatible 1557 * with this {@code ColorModel}. 1558 * @throws UnsupportedOperationException if this 1559 * method has not been implemented for this 1560 * {@code ColorModel} 1561 */ 1562 public boolean isCompatibleRaster(Raster raster) { 1563 throw new UnsupportedOperationException( 1564 "This method has not been implemented for this ColorModel."); 1565 } 1566 1567 /** 1568 * Creates a {@code WritableRaster} with the specified width and 1569 * height that has a data layout ({@code SampleModel}) compatible 1570 * with this {@code ColorModel}. 1571 * Since {@code ColorModel} is an abstract class, 1572 * any instance is an instance of a subclass. Subclasses must 1573 * override this method since the implementation in this abstract 1574 * class throws an {@code UnsupportedOperationException}. 1575 * @param w the width to apply to the new {@code WritableRaster} 1576 * @param h the height to apply to the new {@code WritableRaster} 1577 * @return a {@code WritableRaster} object with the specified 1578 * width and height. 1579 * @throws UnsupportedOperationException if this 1580 * method is not supported by this {@code ColorModel} 1581 * @see WritableRaster 1582 * @see SampleModel 1583 */ 1584 public WritableRaster createCompatibleWritableRaster(int w, int h) { 1585 throw new UnsupportedOperationException 1586 ("This method is not supported by this color model"); 1587 } 1588 1589 /** 1590 * Creates a {@code SampleModel} with the specified width and 1591 * height that has a data layout compatible with this 1592 * {@code ColorModel}. 1593 * Since {@code ColorModel} is an abstract class, 1594 * any instance is an instance of a subclass. Subclasses must 1595 * override this method since the implementation in this abstract 1596 * class throws an {@code UnsupportedOperationException}. 1597 * @param w the width to apply to the new {@code SampleModel} 1598 * @param h the height to apply to the new {@code SampleModel} 1599 * @return a {@code SampleModel} object with the specified 1600 * width and height. 1601 * @throws UnsupportedOperationException if this 1602 * method is not supported by this {@code ColorModel} 1603 * @see SampleModel 1604 */ 1605 public SampleModel createCompatibleSampleModel(int w, int h) { 1606 throw new UnsupportedOperationException 1607 ("This method is not supported by this color model"); 1608 } 1609 1610 /** Checks if the {@code SampleModel} is compatible with this 1611 * {@code ColorModel}. 1612 * Since {@code ColorModel} is an abstract class, 1613 * any instance is an instance of a subclass. Subclasses must 1614 * override this method since the implementation in this abstract 1615 * class throws an {@code UnsupportedOperationException}. 1616 * @param sm the specified {@code SampleModel} 1617 * @return {@code true} if the specified {@code SampleModel} 1618 * is compatible with this {@code ColorModel}; {@code false} 1619 * otherwise. 1620 * @throws UnsupportedOperationException if this 1621 * method is not supported by this {@code ColorModel} 1622 * @see SampleModel 1623 */ 1624 public boolean isCompatibleSampleModel(SampleModel sm) { 1625 throw new UnsupportedOperationException 1626 ("This method is not supported by this color model"); 1627 } 1628 1629 /** 1630 * Disposes of system resources associated with this 1631 * {@code ColorModel} once this {@code ColorModel} is no 1632 * longer referenced. 1633 */ 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 }