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