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