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