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