1. /*
  2. * @(#)DirectColorModel.java 1.78 03/12/19
  3. *
  4. * Copyright 2004 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.color.ColorSpace;
  9. import java.awt.Transparency;
  10. /**
  11. * The <code>DirectColorModel</code> class is a <code>ColorModel</code>
  12. * class that works with pixel values that represent RGB
  13. * color and alpha information as separate samples and that pack all
  14. * samples for a single pixel into a single int, short, or byte quantity.
  15. * This class can be used only with ColorSpaces of type ColorSpace.TYPE_RGB.
  16. * In addition, for each component of the ColorSpace, the minimum
  17. * normalized component value obtained via the <code>getMinValue()</code>
  18. * method of ColorSpace must be 0.0, and the maximum value obtained via
  19. * the <code>getMaxValue()</code> method must be 1.0 (these min/max
  20. * values are typical for RGB spaces).
  21. * There must be three color samples in the pixel values and there can
  22. * be a single alpha sample. For those methods that use a primitive array
  23. * pixel representation of type <code>transferType</code>, the array
  24. * length is always one. The transfer
  25. * types supported are DataBuffer.TYPE_BYTE,
  26. * DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
  27. * Color and alpha samples are stored in the single
  28. * element of the array in bits indicated by bit masks. Each bit mask
  29. * must be contiguous and masks must not overlap. The same masks apply to
  30. * the single int pixel representation used by other methods. The
  31. * correspondence of masks and color/alpha samples is as follows:
  32. * <ul>
  33. * <li> Masks are identified by indices running from 0 through 2
  34. * if no alpha is present, or 3 if an alpha is present.
  35. * <li> The first three indices refer to color samples;
  36. * index 0 corresponds to red, index 1 to green, and index 2 to blue.
  37. * <li> Index 3 corresponds to the alpha sample, if present.
  38. * </ul>
  39. * <p>
  40. * The translation from pixel values to color/alpha components for
  41. * display or processing purposes is a one-to-one correspondence of
  42. * samples to components. A <code>DirectColorModel</code> is
  43. * typically used with image data which uses masks to define packed
  44. * samples. For example, a <code>DirectColorModel</code> can be used in
  45. * conjunction with a <code>SinglePixelPackedSampleModel</code> to
  46. * construct a {@link BufferedImage}. Normally the masks used by the
  47. * {@link SampleModel} and the <code>ColorModel</code> would be the
  48. * same. However, if they are different, the color interpretation
  49. * of pixel data will be done according to the masks of the
  50. * <code>ColorModel</code>.
  51. * <p>
  52. * A single int pixel representation is valid for all objects of this
  53. * class, since it is always possible to represent pixel values used with
  54. * this class in a single int. Therefore, methods which use this
  55. * representation will not throw an <code>IllegalArgumentException</code>
  56. * due to an invalid pixel value.
  57. * <p>
  58. * This color model is similar to an X11 TrueColor visual.
  59. * The default RGB ColorModel specified by the
  60. * {@link ColorModel#getRGBdefault() getRGBdefault} method is a
  61. * <code>DirectColorModel</code> with the following parameters:
  62. * <pre>
  63. * Number of bits: 32
  64. * Red mask: 0x00ff0000
  65. * Green mask: 0x0000ff00
  66. * Blue mask: 0x000000ff
  67. * Alpha mask: 0xff000000
  68. * Color space: sRGB
  69. * isAlphaPremultiplied: False
  70. * Transparency: Transparency.TRANSLUCENT
  71. * transferType: DataBuffer.TYPE_INT
  72. * </pre>
  73. * <p>
  74. * Many of the methods in this class are final. This is because the
  75. * underlying native graphics code makes assumptions about the layout
  76. * and operation of this class and those assumptions are reflected in
  77. * the implementations of the methods here that are marked final. You
  78. * can subclass this class for other reasons, but you cannot override
  79. * or modify the behavior of those methods.
  80. *
  81. * @see ColorModel
  82. * @see ColorSpace
  83. * @see SinglePixelPackedSampleModel
  84. * @see BufferedImage
  85. * @see ColorModel#getRGBdefault
  86. *
  87. * @version 10 Feb 1997
  88. */
  89. public class DirectColorModel extends PackedColorModel {
  90. private int red_mask;
  91. private int green_mask;
  92. private int blue_mask;
  93. private int alpha_mask;
  94. private int red_offset;
  95. private int green_offset;
  96. private int blue_offset;
  97. private int alpha_offset;
  98. private int red_scale;
  99. private int green_scale;
  100. private int blue_scale;
  101. private int alpha_scale;
  102. private boolean is_LinearRGB;
  103. private int lRGBprecision;
  104. private byte[] tosRGB8LUT;
  105. private byte[] fromsRGB8LUT8;
  106. private short[] fromsRGB8LUT16;
  107. /**
  108. * Constructs a <code>DirectColorModel</code> from the specified masks
  109. * that indicate which bits in an <code>int</code> pixel representation
  110. * contain the red, green and blue color samples. As pixel values do not
  111. * contain alpha information, all pixels are treated as opaque, which
  112. * means that alpha = 1.0. All of the bits
  113. * in each mask must be contiguous and fit in the specified number
  114. * of least significant bits of an <code>int</code> pixel representation.
  115. * The <code>ColorSpace</code> is the default sRGB space. The
  116. * transparency value is Transparency.OPAQUE. The transfer type
  117. * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
  118. * or DataBuffer.TYPE_INT that can hold a single pixel.
  119. * @param bits the number of bits in the pixel values; for example,
  120. * the sum of the number of bits in the masks.
  121. * @param rmask specifies a mask indicating which bits in an
  122. * integer pixel contain the red component
  123. * @param gmask specifies a mask indicating which bits in an
  124. * integer pixel contain the green component
  125. * @param bmask specifies a mask indicating which bits in an
  126. * integer pixel contain the blue component
  127. *
  128. */
  129. public DirectColorModel(int bits,
  130. int rmask, int gmask, int bmask) {
  131. this(bits, rmask, gmask, bmask, 0);
  132. }
  133. /**
  134. * Constructs a <code>DirectColorModel</code> from the specified masks
  135. * that indicate which bits in an <code>int</code> pixel representation
  136. * contain the red, green and blue color samples and the alpha sample,
  137. * if present. If <code>amask</code> is 0, pixel values do not contain
  138. * alpha information and all pixels are treated as opaque, which means
  139. * that alpha = 1.0. All of the bits in each mask must
  140. * be contiguous and fit in the specified number of least significant bits
  141. * of an <code>int</code> pixel representation. Alpha, if present, is not
  142. * premultiplied. The <code>ColorSpace</code> is the default sRGB space.
  143. * The transparency value is Transparency.OPAQUE if no alpha is
  144. * present, or Transparency.TRANSLUCENT otherwise. The transfer type
  145. * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
  146. * or DataBuffer.TYPE_INT that can hold a single pixel.
  147. * @param bits the number of bits in the pixel values; for example,
  148. * the sum of the number of bits in the masks.
  149. * @param rmask specifies a mask indicating which bits in an
  150. * integer pixel contain the red component
  151. * @param gmask specifies a mask indicating which bits in an
  152. * integer pixel contain the green component
  153. * @param bmask specifies a mask indicating which bits in an
  154. * integer pixel contain the blue component
  155. * @param amask specifies a mask indicating which bits in an
  156. * integer pixel contain the alpha component
  157. */
  158. public DirectColorModel(int bits, int rmask, int gmask,
  159. int bmask, int amask) {
  160. super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
  161. bits, rmask, gmask, bmask, amask, false,
  162. amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
  163. ColorModel.getDefaultTransferType(bits));
  164. setFields();
  165. }
  166. /**
  167. * Constructs a <code>DirectColorModel</code> from the specified
  168. * parameters. Color components are in the specified
  169. * <code>ColorSpace</code>, which must be of type ColorSpace.TYPE_RGB
  170. * and have minimum normalized component values which are all 0.0
  171. * and maximum values which are all 1.0.
  172. * The masks specify which bits in an <code>int</code> pixel
  173. * representation contain the red, green and blue color samples and
  174. * the alpha sample, if present. If <code>amask</code> is 0, pixel
  175. * values do not contain alpha information and all pixels are treated
  176. * as opaque, which means that alpha = 1.0. All of the
  177. * bits in each mask must be contiguous and fit in the specified number
  178. * of least significant bits of an <code>int</code> pixel
  179. * representation. If there is alpha, the <code>boolean</code>
  180. * <code>isAlphaPremultiplied</code> specifies how to interpret
  181. * color and alpha samples in pixel values. If the <code>boolean</code>
  182. * is <code>true</code>, color samples are assumed to have been
  183. * multiplied by the alpha sample. The transparency value is
  184. * Transparency.OPAQUE, if no alpha is present, or
  185. * Transparency.TRANSLUCENT otherwise. The transfer type
  186. * is the type of primitive array used to represent pixel values and
  187. * must be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or
  188. * DataBuffer.TYPE_INT.
  189. * @param space the specified <code>ColorSpace</code>
  190. * @param bits the number of bits in the pixel values; for example,
  191. * the sum of the number of bits in the masks.
  192. * @param rmask specifies a mask indicating which bits in an
  193. * integer pixel contain the red component
  194. * @param gmask specifies a mask indicating which bits in an
  195. * integer pixel contain the green component
  196. * @param bmask specifies a mask indicating which bits in an
  197. * integer pixel contain the blue component
  198. * @param amask specifies a mask indicating which bits in an
  199. * integer pixel contain the alpha component
  200. * @param isAlphaPremultiplied <code>true</code> if color samples are
  201. * premultiplied by the alpha sample; <code>false</code> otherwise
  202. * @param transferType the type of array used to represent pixel values
  203. * @throws IllegalArgumentException if <code>space</code> is not a
  204. * TYPE_RGB space or if the min/max normalized component
  205. * values are not 0.0/1.0.
  206. */
  207. public DirectColorModel(ColorSpace space, int bits, int rmask,
  208. int gmask, int bmask, int amask,
  209. boolean isAlphaPremultiplied,
  210. int transferType) {
  211. super (space, bits, rmask, gmask, bmask, amask,
  212. isAlphaPremultiplied,
  213. amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
  214. transferType);
  215. if (ColorModel.isLinearRGBspace(colorSpace)) {
  216. is_LinearRGB = true;
  217. if (maxBits <= 8) {
  218. lRGBprecision = 8;
  219. tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
  220. fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
  221. } else {
  222. lRGBprecision = 16;
  223. tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
  224. fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
  225. }
  226. } else if (!is_sRGB) {
  227. for (int i = 0; i < 3; i++) {
  228. // super constructor checks that space is TYPE_RGB
  229. // check here that min/max are all 0.0/1.0
  230. if ((space.getMinValue(i) != 0.0f) ||
  231. (space.getMaxValue(i) != 1.0f)) {
  232. throw new IllegalArgumentException(
  233. "Illegal min/max RGB component value");
  234. }
  235. }
  236. }
  237. setFields();
  238. }
  239. /**
  240. * Returns the mask indicating which bits in an <code>int</code> pixel
  241. * representation contain the red color component.
  242. * @return the mask, which indicates which bits of the <code>int</code>
  243. * pixel representation contain the red color sample.
  244. */
  245. final public int getRedMask() {
  246. return maskArray[0];
  247. }
  248. /**
  249. * Returns the mask indicating which bits in an <code>int</code> pixel
  250. * representation contain the green color component.
  251. * @return the mask, which indicates which bits of the <code>int</code>
  252. * pixel representation contain the green color sample.
  253. */
  254. final public int getGreenMask() {
  255. return maskArray[1];
  256. }
  257. /**
  258. * Returns the mask indicating which bits in an <code>int</code> pixel
  259. * representation contain the blue color component.
  260. * @return the mask, which indicates which bits of the <code>int</code>
  261. * pixel representation contain the blue color sample.
  262. */
  263. final public int getBlueMask() {
  264. return maskArray[2];
  265. }
  266. /**
  267. * Returns the mask indicating which bits in an <code>int</code> pixel
  268. * representation contain the alpha component.
  269. * @return the mask, which indicates which bits of the <code>int</code>
  270. * pixel representation contain the alpha sample.
  271. */
  272. final public int getAlphaMask() {
  273. if (supportsAlpha) {
  274. return maskArray[3];
  275. } else {
  276. return 0;
  277. }
  278. }
  279. /*
  280. * Given an int pixel in this ColorModel's ColorSpace, converts
  281. * it to the default sRGB ColorSpace and returns the R, G, and B
  282. * components as float values between 0.0 and 1.0.
  283. */
  284. private float[] getDefaultRGBComponents(int pixel) {
  285. int components[] = getComponents(pixel, null, 0);
  286. float norm[] = getNormalizedComponents(components, 0, null, 0);
  287. // Note that getNormalizedComponents returns non-premultiplied values
  288. return colorSpace.toRGB(norm);
  289. }
  290. private int getsRGBComponentFromsRGB(int pixel, int idx) {
  291. int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
  292. if (isAlphaPremultiplied) {
  293. int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
  294. c = (a == 0) ? 0 :
  295. (int) (((c * scaleFactors[idx]) * 255.0f /
  296. (a * scaleFactors[3])) + 0.5f);
  297. } else if (scaleFactors[idx] != 1.0f) {
  298. c = (int) ((c * scaleFactors[idx]) + 0.5f);
  299. }
  300. return c;
  301. }
  302. private int getsRGBComponentFromLinearRGB(int pixel, int idx) {
  303. int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
  304. if (isAlphaPremultiplied) {
  305. float factor = (float) ((1 << lRGBprecision) - 1);
  306. int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
  307. c = (a == 0) ? 0 :
  308. (int) (((c * scaleFactors[idx]) * factor /
  309. (a * scaleFactors[3])) + 0.5f);
  310. } else if (nBits[idx] != lRGBprecision) {
  311. if (lRGBprecision == 16) {
  312. c = (int) ((c * scaleFactors[idx] * 257.0f) + 0.5f);
  313. } else {
  314. c = (int) ((c * scaleFactors[idx]) + 0.5f);
  315. }
  316. }
  317. // now range of c is 0-255 or 0-65535, depending on lRGBprecision
  318. return tosRGB8LUT[c] & 0xff;
  319. }
  320. /**
  321. * Returns the red color component for the specified pixel, scaled
  322. * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
  323. * color conversion is done if necessary. The pixel value is specified
  324. * as an <code>int</code>.
  325. * The returned value is a non pre-multiplied value. Thus, if the
  326. * alpha is premultiplied, this method divides it out before returning
  327. * the value. If the alpha value is 0, for example, the red value
  328. * is 0.
  329. * @param pixel the specified pixel
  330. * @return the red color component for the specified pixel, from
  331. * 0 to 255 in the sRGB <code>ColorSpace</code>.
  332. */
  333. final public int getRed(int pixel) {
  334. if (is_sRGB) {
  335. return getsRGBComponentFromsRGB(pixel, 0);
  336. } else if (is_LinearRGB) {
  337. return getsRGBComponentFromLinearRGB(pixel, 0);
  338. }
  339. float rgb[] = getDefaultRGBComponents(pixel);
  340. return (int) (rgb[0] * 255.0f + 0.5f);
  341. }
  342. /**
  343. * Returns the green color component for the specified pixel, scaled
  344. * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
  345. * color conversion is done if necessary. The pixel value is specified
  346. * as an <code>int</code>.
  347. * The returned value is a non pre-multiplied value. Thus, if the
  348. * alpha is premultiplied, this method divides it out before returning
  349. * the value. If the alpha value is 0, for example, the green value
  350. * is 0.
  351. * @param pixel the specified pixel
  352. * @return the green color component for the specified pixel, from
  353. * 0 to 255 in the sRGB <code>ColorSpace</code>.
  354. */
  355. final public int getGreen(int pixel) {
  356. if (is_sRGB) {
  357. return getsRGBComponentFromsRGB(pixel, 1);
  358. } else if (is_LinearRGB) {
  359. return getsRGBComponentFromLinearRGB(pixel, 1);
  360. }
  361. float rgb[] = getDefaultRGBComponents(pixel);
  362. return (int) (rgb[1] * 255.0f + 0.5f);
  363. }
  364. /**
  365. * Returns the blue color component for the specified pixel, scaled
  366. * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
  367. * color conversion is done if necessary. The pixel value is specified
  368. * as an <code>int</code>.
  369. * The returned value is a non pre-multiplied value. Thus, if the
  370. * alpha is premultiplied, this method divides it out before returning
  371. * the value. If the alpha value is 0, for example, the blue value
  372. * is 0.
  373. * @param pixel the specified pixel
  374. * @return the blue color component for the specified pixel, from
  375. * 0 to 255 in the sRGB <code>ColorSpace</code>.
  376. */
  377. final public int getBlue(int pixel) {
  378. if (is_sRGB) {
  379. return getsRGBComponentFromsRGB(pixel, 2);
  380. } else if (is_LinearRGB) {
  381. return getsRGBComponentFromLinearRGB(pixel, 2);
  382. }
  383. float rgb[] = getDefaultRGBComponents(pixel);
  384. return (int) (rgb[2] * 255.0f + 0.5f);
  385. }
  386. /**
  387. * Returns the alpha component for the specified pixel, scaled
  388. * from 0 to 255. The pixel value is specified as an <code>int</code>.
  389. * @param pixel the specified pixel
  390. * @return the value of the alpha component of <code>pixel</code>
  391. * from 0 to 255.
  392. */
  393. final public int getAlpha(int pixel) {
  394. if (!supportsAlpha) return 255;
  395. int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
  396. if (scaleFactors[3] != 1.0f) {
  397. a = (int)(a * scaleFactors[3] + 0.5f);
  398. }
  399. return a;
  400. }
  401. /**
  402. * Returns the color/alpha components of the pixel in the default
  403. * RGB color model format. A color conversion is done if necessary.
  404. * The pixel value is specified as an <code>int</code>.
  405. * The returned value is in a non pre-multiplied format. Thus, if
  406. * the alpha is premultiplied, this method divides it out of the
  407. * color components. If the alpha value is 0, for example, the color
  408. * values are each 0.
  409. * @param pixel the specified pixel
  410. * @return the RGB value of the color/alpha components of the specified
  411. * pixel.
  412. * @see ColorModel#getRGBdefault
  413. */
  414. final public int getRGB(int pixel) {
  415. if (is_sRGB || is_LinearRGB) {
  416. return (getAlpha(pixel) << 24)
  417. | (getRed(pixel) << 16)
  418. | (getGreen(pixel) << 8)
  419. | (getBlue(pixel) << 0);
  420. }
  421. float rgb[] = getDefaultRGBComponents(pixel);
  422. return (getAlpha(pixel) << 24)
  423. | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
  424. | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
  425. | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
  426. }
  427. /**
  428. * Returns the red color component for the specified pixel, scaled
  429. * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
  430. * color conversion is done if necessary. The pixel value is specified
  431. * by an array of data elements of type <code>transferType</code> passed
  432. * in as an object reference.
  433. * The returned value is a non pre-multiplied value. Thus, if the
  434. * alpha is premultiplied, this method divides it out before returning
  435. * the value. If the alpha value is 0, for example, the red value
  436. * is 0.
  437. * If <code>inData</code> is not a primitive array of type
  438. * <code>transferType</code>, a <code>ClassCastException</code> is
  439. * thrown. An <code>ArrayIndexOutOfBoundsException</code> is
  440. * thrown if <code>inData</code> is not large enough to hold a
  441. * pixel value for this <code>ColorModel</code>. Since
  442. * <code>DirectColorModel</code> can be subclassed, subclasses inherit
  443. * the implementation of this method and if they don't override it
  444. * then they throw an exception if they use an unsupported
  445. * <code>transferType</code>.
  446. * An <code>UnsupportedOperationException</code> is thrown if this
  447. * <code>transferType</code> is not supported by this
  448. * <code>ColorModel</code>.
  449. * @param inData the array containing the pixel value
  450. * @return the value of the red component of the specified pixel.
  451. * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
  452. * large enough to hold a pixel value for this color model
  453. * @throws ClassCastException if <code>inData</code> is not a
  454. * primitive array of type <code>transferType</code>
  455. * @throws UnsupportedOperationException if this <code>transferType</code>
  456. * is not supported by this color model
  457. */
  458. public int getRed(Object inData) {
  459. int pixel=0;
  460. switch (transferType) {
  461. case DataBuffer.TYPE_BYTE:
  462. byte bdata[] = (byte[])inData;
  463. pixel = bdata[0] & 0xff;
  464. break;
  465. case DataBuffer.TYPE_USHORT:
  466. short sdata[] = (short[])inData;
  467. pixel = sdata[0] & 0xffff;
  468. break;
  469. case DataBuffer.TYPE_INT:
  470. int idata[] = (int[])inData;
  471. pixel = idata[0];
  472. break;
  473. default:
  474. throw new UnsupportedOperationException("This method has not been "+
  475. "implemented for transferType " + transferType);
  476. }
  477. return getRed(pixel);
  478. }
  479. /**
  480. * Returns the green color component for the specified pixel, scaled
  481. * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
  482. * color conversion is done if necessary. The pixel value is specified
  483. * by an array of data elements of type <code>transferType</code> passed
  484. * in as an object reference.
  485. * The returned value is a non pre-multiplied value. Thus, if the
  486. * alpha is premultiplied, this method divides it out before returning
  487. * the value. If the alpha value is 0, for example, the green value
  488. * is 0. If <code>inData</code> is not a primitive array of type
  489. * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
  490. * An <code>ArrayIndexOutOfBoundsException</code> is
  491. * thrown if <code>inData</code> is not large enough to hold a pixel
  492. * value for this <code>ColorModel</code>. Since
  493. * <code>DirectColorModel</code> can be subclassed, subclasses inherit
  494. * the implementation of this method and if they don't override it
  495. * then they throw an exception if they use an unsupported
  496. * <code>transferType</code>.
  497. * An <code>UnsupportedOperationException</code> is
  498. * thrown if this <code>transferType</code> is not supported by this
  499. * <code>ColorModel</code>.
  500. * @param inData the array containing the pixel value
  501. * @return the value of the green component of the specified pixel.
  502. * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
  503. * large enough to hold a pixel value for this color model
  504. * @throws ClassCastException if <code>inData</code> is not a
  505. * primitive array of type <code>transferType</code>
  506. * @throws UnsupportedOperationException if this <code>transferType</code>
  507. * is not supported by this color model
  508. */
  509. public int getGreen(Object inData) {
  510. int pixel=0;
  511. switch (transferType) {
  512. case DataBuffer.TYPE_BYTE:
  513. byte bdata[] = (byte[])inData;
  514. pixel = bdata[0] & 0xff;
  515. break;
  516. case DataBuffer.TYPE_USHORT:
  517. short sdata[] = (short[])inData;
  518. pixel = sdata[0] & 0xffff;
  519. break;
  520. case DataBuffer.TYPE_INT:
  521. int idata[] = (int[])inData;
  522. pixel = idata[0];
  523. break;
  524. default:
  525. throw new UnsupportedOperationException("This method has not been "+
  526. "implemented for transferType " + transferType);
  527. }
  528. return getGreen(pixel);
  529. }
  530. /**
  531. * Returns the blue color component for the specified pixel, scaled
  532. * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
  533. * color conversion is done if necessary. The pixel value is specified
  534. * by an array of data elements of type <code>transferType</code> passed
  535. * in as an object reference.
  536. * The returned value is a non pre-multiplied value. Thus, if the
  537. * alpha is premultiplied, this method divides it out before returning
  538. * the value. If the alpha value is 0, for example, the blue value
  539. * is 0. If <code>inData</code> is not a primitive array of type
  540. * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
  541. * An <code>ArrayIndexOutOfBoundsException</code> is
  542. * thrown if <code>inData</code> is not large enough to hold a pixel
  543. * value for this <code>ColorModel</code>. Since
  544. * <code>DirectColorModel</code> can be subclassed, subclasses inherit
  545. * the implementation of this method and if they don't override it
  546. * then they throw an exception if they use an unsupported
  547. * <code>transferType</code>.
  548. * An <code>UnsupportedOperationException</code> is
  549. * thrown if this <code>transferType</code> is not supported by this
  550. * <code>ColorModel</code>.
  551. * @param inData the array containing the pixel value
  552. * @return the value of the blue component of the specified pixel.
  553. * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
  554. * large enough to hold a pixel value for this color model
  555. * @throws ClassCastException if <code>inData</code> is not a
  556. * primitive array of type <code>transferType</code>
  557. * @throws UnsupportedOperationException if this <code>transferType</code>
  558. * is not supported by this color model
  559. */
  560. public int getBlue(Object inData) {
  561. int pixel=0;
  562. switch (transferType) {
  563. case DataBuffer.TYPE_BYTE:
  564. byte bdata[] = (byte[])inData;
  565. pixel = bdata[0] & 0xff;
  566. break;
  567. case DataBuffer.TYPE_USHORT:
  568. short sdata[] = (short[])inData;
  569. pixel = sdata[0] & 0xffff;
  570. break;
  571. case DataBuffer.TYPE_INT:
  572. int idata[] = (int[])inData;
  573. pixel = idata[0];
  574. break;
  575. default:
  576. throw new UnsupportedOperationException("This method has not been "+
  577. "implemented for transferType " + transferType);
  578. }
  579. return getBlue(pixel);
  580. }
  581. /**
  582. * Returns the alpha component for the specified pixel, scaled
  583. * from 0 to 255. The pixel value is specified by an array of data
  584. * elements of type <code>transferType</code> passed in as an object
  585. * reference.
  586. * If <code>inData</code> is not a primitive array of type
  587. * <code>transferType</code>, a <code>ClassCastException</code> is
  588. * thrown. An <code>ArrayIndexOutOfBoundsException</code> is
  589. * thrown if <code>inData</code> is not large enough to hold a pixel
  590. * value for this <code>ColorModel</code>. Since
  591. * <code>DirectColorModel</code> can be subclassed, subclasses inherit
  592. * the implementation of this method and if they don't override it
  593. * then they throw an exception if they use an unsupported
  594. * <code>transferType</code>.
  595. * If this <code>transferType</code> is not supported, an
  596. * <code>UnsupportedOperationException</code> is thrown.
  597. * @param inData the specified pixel
  598. * @return the alpha component of the specified pixel, scaled from
  599. * 0 to 255.
  600. * @exception <code>ClassCastException</code> if <code>inData</code>
  601. * is not a primitive array of type <code>transferType</code>
  602. * @exception <code>ArrayIndexOutOfBoundsException</code> if
  603. * <code>inData</code> is not large enough to hold a pixel value
  604. * for this <code>ColorModel</code>
  605. * @exception <code>UnsupportedOperationException</code> if this
  606. * <code>tranferType</code> is not supported by this
  607. * <code>ColorModel</code>
  608. */
  609. public int getAlpha(Object inData) {
  610. int pixel=0;
  611. switch (transferType) {
  612. case DataBuffer.TYPE_BYTE:
  613. byte bdata[] = (byte[])inData;
  614. pixel = bdata[0] & 0xff;
  615. break;
  616. case DataBuffer.TYPE_USHORT:
  617. short sdata[] = (short[])inData;
  618. pixel = sdata[0] & 0xffff;
  619. break;
  620. case DataBuffer.TYPE_INT:
  621. int idata[] = (int[])inData;
  622. pixel = idata[0];
  623. break;
  624. default:
  625. throw new UnsupportedOperationException("This method has not been "+
  626. "implemented for transferType " + transferType);
  627. }
  628. return getAlpha(pixel);
  629. }
  630. /**
  631. * Returns the color/alpha components for the specified pixel in the
  632. * default RGB color model format. A color conversion is done if
  633. * necessary. The pixel value is specified by an array of data
  634. * elements of type <code>transferType</code> passed in as an object
  635. * reference. If <code>inData</code> is not a primitive array of type
  636. * <code>transferType</code>, a <code>ClassCastException</code> is
  637. * thrown. An <code>ArrayIndexOutOfBoundsException</code> is
  638. * thrown if <code>inData</code> is not large enough to hold a pixel
  639. * value for this <code>ColorModel</code>.
  640. * The returned value is in a non pre-multiplied format. Thus, if
  641. * the alpha is premultiplied, this method divides it out of the
  642. * color components. If the alpha value is 0, for example, the color
  643. * values is 0. Since <code>DirectColorModel</code> can be
  644. * subclassed, subclasses inherit the implementation of this method
  645. * and if they don't override it then
  646. * they throw an exception if they use an unsupported
  647. * <code>transferType</code>.
  648. *
  649. * @param inData the specified pixel
  650. * @return the color and alpha components of the specified pixel.
  651. * @exception UnsupportedOperationException if this
  652. * <code>transferType</code> is not supported by this
  653. * <code>ColorModel</code>
  654. * @see ColorModel#getRGBdefault
  655. */
  656. public int getRGB(Object inData) {
  657. int pixel=0;
  658. switch (transferType) {
  659. case DataBuffer.TYPE_BYTE:
  660. byte bdata[] = (byte[])inData;
  661. pixel = bdata[0] & 0xff;
  662. break;
  663. case DataBuffer.TYPE_USHORT:
  664. short sdata[] = (short[])inData;
  665. pixel = sdata[0] & 0xffff;
  666. break;
  667. case DataBuffer.TYPE_INT:
  668. int idata[] = (int[])inData;
  669. pixel = idata[0];
  670. break;
  671. default:
  672. throw new UnsupportedOperationException("This method has not been "+
  673. "implemented for transferType " + transferType);
  674. }
  675. return getRGB(pixel);
  676. }
  677. /**
  678. * Returns a data element array representation of a pixel in this
  679. * <code>ColorModel</code>, given an integer pixel representation in the
  680. * default RGB color model.
  681. * This array can then be passed to the <code>setDataElements</code>
  682. * method of a <code>WritableRaster</code> object. If the pixel variable
  683. * is <code>null</code>, a new array is allocated. If <code>pixel</code>
  684. * is not <code>null</code>, it must be a primitive array of type
  685. * <code>transferType</code> otherwise, a
  686. * <code>ClassCastException</code> is thrown. An
  687. * <code>ArrayIndexOutOfBoundsException</code> is
  688. * thrown if <code>pixel</code> is not large enough to hold a pixel
  689. * value for this <code>ColorModel</code>. The pixel array is returned.
  690. * Since <code>DirectColorModel</code> can be subclassed, subclasses
  691. * inherit the implementation of this method and if they don't
  692. * override it then they throw an exception if they use an unsupported
  693. * <code>transferType</code>.
  694. *
  695. * @param rgb the integer pixel representation in the default RGB
  696. * color model
  697. * @param pixel the specified pixel
  698. * @return an array representation of the specified pixel in this
  699. * <code>ColorModel</code>
  700. * @exception ClassCastException if <code>pixel</code>
  701. * is not a primitive array of type <code>transferType</code>
  702. * @exception ArrayIndexOutOfBoundsException if
  703. * <code>pixel</code> is not large enough to hold a pixel value
  704. * for this <code>ColorModel</code>
  705. * @exception UnsupportedOperationException if this
  706. * <code>transferType</code> is not supported by this
  707. * <code>ColorModel</code>
  708. * @see WritableRaster#setDataElements
  709. * @see SampleModel#setDataElements
  710. */
  711. public Object getDataElements(int rgb, Object pixel) {
  712. //REMIND: maybe more efficient not to use int array for
  713. //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
  714. int intpixel[] = null;
  715. if (transferType == DataBuffer.TYPE_INT &&
  716. pixel != null) {
  717. intpixel = (int[])pixel;
  718. intpixel[0] = 0;
  719. } else {
  720. intpixel = new int[1];
  721. }
  722. ColorModel defaultCM = ColorModel.getRGBdefault();
  723. if (this == defaultCM || equals(defaultCM)) {
  724. intpixel[0] = rgb;
  725. return intpixel;
  726. }
  727. int red, grn, blu, alp;
  728. red = (rgb>>16) & 0xff;
  729. grn = (rgb>>8) & 0xff;
  730. blu = rgb & 0xff;
  731. if (is_sRGB || is_LinearRGB) {
  732. int precision;
  733. float factor;
  734. if (is_LinearRGB) {
  735. if (lRGBprecision == 8) {
  736. red = fromsRGB8LUT8[red] & 0xff;
  737. grn = fromsRGB8LUT8[grn] & 0xff;
  738. blu = fromsRGB8LUT8[blu] & 0xff;
  739. precision = 8;
  740. factor = 1.0f / 255.0f;
  741. } else {
  742. red = fromsRGB8LUT16[red] & 0xffff;
  743. grn = fromsRGB8LUT16[grn] & 0xffff;
  744. blu = fromsRGB8LUT16[blu] & 0xffff;
  745. precision = 16;
  746. factor = 1.0f / 65535.0f;
  747. }
  748. } else {
  749. precision = 8;
  750. factor = 1.0f / 255.0f;
  751. }
  752. if (supportsAlpha) {
  753. alp = (rgb>>24) & 0xff;
  754. if (isAlphaPremultiplied) {
  755. factor *= (alp * (1.0f / 255.0f));
  756. precision = -1; // force component calculations below
  757. }
  758. if (nBits[3] != 8) {
  759. alp = (int)
  760. ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
  761. if (alp > ((1<<nBits[3]) - 1)) {
  762. // fix 4412670 - see comment below
  763. alp = (1<<nBits[3]) - 1;
  764. }
  765. }
  766. intpixel[0] = alp << maskOffsets[3];
  767. }
  768. if (nBits[0] != precision) {
  769. red = (int) ((red * factor * ((1<<nBits[0]) - 1)) + 0.5f);
  770. }
  771. if (nBits[1] != precision) {
  772. grn = (int) ((grn * factor * ((1<<nBits[1]) - 1)) + 0.5f);
  773. }
  774. if (nBits[2] != precision) {
  775. blu = (int) ((blu * factor * ((1<<nBits[2]) - 1)) + 0.5f);
  776. }
  777. } else {
  778. // Need to convert the color
  779. float[] norm = new float[3];
  780. float factor = 1.0f / 255.0f;
  781. norm[0] = red * factor;
  782. norm[1] = grn * factor;
  783. norm[2] = blu * factor;
  784. norm = colorSpace.fromRGB(norm);
  785. if (supportsAlpha) {
  786. alp = (rgb>>24) & 0xff;
  787. if (isAlphaPremultiplied) {
  788. factor *= alp;
  789. for (int i = 0; i < 3; i++) {
  790. norm[i] *= factor;
  791. }
  792. }
  793. if (nBits[3] != 8) {
  794. alp = (int)
  795. ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
  796. if (alp > ((1<<nBits[3]) - 1)) {
  797. // fix 4412670 - see comment below
  798. alp = (1<<nBits[3]) - 1;
  799. }
  800. }
  801. intpixel[0] = alp << maskOffsets[3];
  802. }
  803. red = (int) ((norm[0] * ((1<<nBits[0]) - 1)) + 0.5f);
  804. grn = (int) ((norm[1] * ((1<<nBits[1]) - 1)) + 0.5f);
  805. blu = (int) ((norm[2] * ((1<<nBits[2]) - 1)) + 0.5f);
  806. }
  807. if (maxBits > 23) {
  808. // fix 4412670 - for components of 24 or more bits
  809. // some calculations done above with float precision
  810. // may lose enough precision that the integer result
  811. // overflows nBits, so we need to clamp.
  812. if (red > ((1<<nBits[0]) - 1)) {
  813. red = (1<<nBits[0]) - 1;
  814. }
  815. if (grn > ((1<<nBits[1]) - 1)) {
  816. grn = (1<<nBits[1]) - 1;
  817. }
  818. if (blu > ((1<<nBits[2]) - 1)) {
  819. blu = (1<<nBits[2]) - 1;
  820. }
  821. }
  822. intpixel[0] |= (red << maskOffsets[0]) |
  823. (grn << maskOffsets[1]) |
  824. (blu << maskOffsets[2]);
  825. switch (transferType) {
  826. case DataBuffer.TYPE_BYTE: {
  827. byte bdata[];
  828. if (pixel == null) {
  829. bdata = new byte[1];
  830. } else {
  831. bdata = (byte[])pixel;
  832. }
  833. bdata[0] = (byte)(0xff&intpixel[0]);
  834. return bdata;
  835. }
  836. case DataBuffer.TYPE_USHORT:{
  837. short sdata[];
  838. if (pixel == null) {
  839. sdata = new short[1];
  840. } else {
  841. sdata = (short[])pixel;
  842. }
  843. sdata[0] = (short)(intpixel[0]&0xffff);
  844. return sdata;
  845. }
  846. case DataBuffer.TYPE_INT:
  847. return intpixel;
  848. }
  849. throw new UnsupportedOperationException("This method has not been "+
  850. "implemented for transferType " + transferType);
  851. }
  852. /**
  853. * Returns an array of unnormalized color/alpha components given a pixel
  854. * in this <code>ColorModel</code>. The pixel value is specified as an
  855. * <code>int</code>. If the <code>components</code> array is
  856. * <code>null</code>, a new array is allocated. The
  857. * <code>components</code> array is returned. Color/alpha components are
  858. * stored in the <code>components</code> array starting at
  859. * <code>offset</code>, even if the array is allocated by this method.
  860. * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
  861. * <code>components</code> array is not <code>null</code> and is not large
  862. * enough to hold all the color and alpha components, starting at
  863. * <code>offset</code>.
  864. * @param pixel the specified pixel
  865. * @param components the array to receive the color and alpha
  866. * components of the specified pixel
  867. * @param offset the offset into the <code>components</code> array at
  868. * which to start storing the color and alpha components
  869. * @return an array containing the color and alpha components of the
  870. * specified pixel starting at the specified offset.
  871. */
  872. final public int[] getComponents(int pixel, int[] components, int offset) {
  873. if (components == null) {
  874. components = new int[offset+numComponents];
  875. }
  876. for (int i=0; i < numComponents; i++) {
  877. components[offset+i] = (pixel & maskArray[i]) >>> maskOffsets[i];
  878. }
  879. return components;
  880. }
  881. /**
  882. * Returns an array of unnormalized color/alpha components given a pixel
  883. * in this <code>ColorModel</code>. The pixel value is specified by an
  884. * array of data elements of type <code>transferType</code> passed in as
  885. * an object reference. If <code>pixel</code> is not a primitive array
  886. * of type <code>transferType</code>, a <code>ClassCastException</code>
  887. * is thrown. An <code>ArrayIndexOutOfBoundsException</code> is
  888. * thrown if <code>pixel</code> is not large enough to hold a
  889. * pixel value for this <code>ColorModel</code>. If the
  890. * <code>components</code> array is <code>null</code>, a new
  891. * array is allocated. The <code>components</code> array is returned.
  892. * Color/alpha components are stored in the <code>components</code> array
  893. * starting at <code>offset</code>, even if the array is allocated by
  894. * this method. An <code>ArrayIndexOutOfBoundsException</code>
  895. * is thrown if the <code>components</code> array is not
  896. * <code>null</code> and is not large enough to hold all the color and
  897. * alpha components, starting at <code>offset</code>.
  898. * Since <code>DirectColorModel</code> can be subclassed, subclasses
  899. * inherit the implementation of this method and if they don't
  900. * override it then they throw an exception if they use an unsupported
  901. * <code>transferType</code>.
  902. * @param pixel the specified pixel
  903. * @param components the array to receive the color and alpha
  904. * components of the specified pixel
  905. * @param offset the offset into the <code>components</code> array at
  906. * which to start storing the color and alpha components
  907. * @return an array containing the color and alpha components of the
  908. * specified pixel starting at the specified offset.
  909. * @exception ClassCastException if <code>pixel</code>
  910. * is not a primitive array of type <code>transferType</code>
  911. * @exception ArrayIndexOutOfBoundsException if
  912. * <code>pixel</code> is not large enough to hold a pixel value
  913. * for this <code>ColorModel</code>, or if <code>components</code>
  914. * is not <code>null</code> and is not large enough to hold all the
  915. * color and alpha components, starting at <code>offset</code>
  916. * @exception UnsupportedOperationException if this
  917. * <code>transferType</code> is not supported by this
  918. * color model
  919. */
  920. final public int[] getComponents(Object pixel, int[] components,
  921. int offset) {
  922. int intpixel=0;
  923. switch (transferType) {
  924. case DataBuffer.TYPE_BYTE:
  925. byte bdata[] = (byte[])pixel;
  926. intpixel = bdata[0] & 0xff;
  927. break;
  928. case DataBuffer.TYPE_USHORT:
  929. short sdata[] = (short[])pixel;
  930. intpixel = sdata[0] & 0xffff;
  931. break;
  932. case DataBuffer.TYPE_INT:
  933. int idata[] = (int[])pixel;
  934. intpixel = idata[0];
  935. break;
  936. default:
  937. throw new UnsupportedOperationException("This method has not been "+
  938. "implemented for transferType " + transferType);
  939. }
  940. return getComponents(intpixel, components, offset);
  941. }
  942. /**
  943. * Creates a <code>WritableRaster</code> with the specified width and
  944. * height that has a data layout (<code>SampleModel</code>) compatible
  945. * with this <code>ColorModel</code>.
  946. * @param w the width to apply to the new <code>WritableRaster</code>
  947. * @param h the height to apply to the new <code>WritableRaster</code>
  948. * @return a <code>WritableRaster</code> object with the specified
  949. * width and height.
  950. * @throws IllegalArgumentException if <code>w</code> or <code>h</code>
  951. * is less than or equal to zero
  952. * @see WritableRaster
  953. * @see SampleModel
  954. */
  955. final public WritableRaster createCompatibleWritableRaster (int w,
  956. int h) {
  957. if ((w <= 0) || (h <= 0)) {
  958. throw new IllegalArgumentException("Width (" + w + ") and height (" + h +
  959. ") cannot be <= 0");
  960. }
  961. int[] bandmasks;
  962. if (supportsAlpha) {
  963. bandmasks = new int[4];
  964. bandmasks[3] = alpha_mask;
  965. }
  966. else {
  967. bandmasks = new int[3];
  968. }
  969. bandmasks[0] = red_mask;
  970. bandmasks[1] = green_mask;
  971. bandmasks[2] = blue_mask;
  972. if (pixel_bits > 16) {
  973. return Raster.createPackedRaster(DataBuffer.TYPE_INT,
  974. w,h,bandmasks,null);
  975. }
  976. else if (pixel_bits > 8) {
  977. return Raster.createPackedRaster(DataBuffer.TYPE_USHORT,
  978. w,h,bandmasks,null);
  979. }
  980. else {
  981. return Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
  982. w,h,bandmasks,null);
  983. }
  984. }
  985. /**
  986. * Returns a pixel value represented as an <code>int</code> in this
  987. * <code>ColorModel</code>, given an array of unnormalized color/alpha
  988. * components. An <code>ArrayIndexOutOfBoundsException</code> is
  989. * thrown if the <code>components</code> array is
  990. * not large enough to hold all the color and alpha components, starting
  991. * at <code>offset</code>.
  992. * @param components an array of unnormalized color and alpha
  993. * components
  994. * @param offset the index into <code>components</code> at which to
  995. * begin retrieving the color and alpha components
  996. * @return an <code>int</code> pixel value in this
  997. * <code>ColorModel</code> corresponding to the specified components.
  998. * @exception <code>ArrayIndexOutOfBoundsException</code> if
  999. * the <code>components</code> array is not large enough to
  1000. * hold all of the color and alpha components starting at
  1001. * <code>offset</code>
  1002. */
  1003. public int getDataElement(int[] components, int offset) {
  1004. int pixel = 0;
  1005. for (int i=0; i < numComponents; i++) {
  1006. pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
  1007. }
  1008. return pixel;
  1009. }
  1010. /**
  1011. * Returns a data element array representation of a pixel in this
  1012. * <code>ColorModel</code>, given an array of unnormalized color/alpha
  1013. * components.
  1014. * This array can then be passed to the <code>setDataElements</code>
  1015. * method of a <code>WritableRaster</code> object.
  1016. * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
  1017. * <code>components</code> array
  1018. * is not large enough to hold all the color and alpha components,
  1019. * starting at offset. If the <code>obj</code> variable is
  1020. * <code>null</code>, a new array is allocated. If <code>obj</code> is
  1021. * not <code>null</code>, it must be a primitive array
  1022. * of type <code>transferType</code> otherwise, a
  1023. * <code>ClassCastException</code> is thrown.
  1024. * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
  1025. * <code>obj</code> is not large enough to hold a pixel value for this
  1026. * <code>ColorModel</code>.
  1027. * Since <code>DirectColorModel</code> can be subclassed, subclasses
  1028. * inherit the implementation of this method and if they don't
  1029. * override it then they throw an exception if they use an unsupported
  1030. * <code>transferType</code>.
  1031. * @param components an array of unnormalized color and alpha
  1032. * components
  1033. * @param offset the index into <code>components</code> at which to
  1034. * begin retrieving color and alpha components
  1035. * @param obj the <code>Object</code> representing an array of color
  1036. * and alpha components
  1037. * @return an <code>Object</code> representing an array of color and
  1038. * alpha components.
  1039. * @exception <code>ClassCastException</code> if <code>obj</code>
  1040. * is not a primitive array of type <code>transferType</code>
  1041. * @exception <code>ArrayIndexOutOfBoundsException</code> if
  1042. * <code>obj</code> is not large enough to hold a pixel value
  1043. * for this <code>ColorModel</code> or the <code>components</code>
  1044. * array is not large enough to hold all of the color and alpha
  1045. * components starting at <code>offset</code>
  1046. * @exception UnsupportedOperationException if this
  1047. * <code>transferType</code> is not supported by this
  1048. * color model
  1049. * @see WritableRaster#setDataElements
  1050. * @see SampleModel#setDataElements
  1051. */
  1052. public Object getDataElements(int[] components, int offset, Object obj) {
  1053. int pixel = 0;
  1054. for (int i=0; i < numComponents; i++) {
  1055. pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
  1056. }
  1057. switch (transferType) {
  1058. case DataBuffer.TYPE_BYTE:
  1059. if (obj instanceof byte[]) {
  1060. byte bdata[] = (byte[])obj;
  1061. bdata[0] = (byte)(pixel&0xff);
  1062. return bdata;
  1063. } else {
  1064. byte bdata[] = {(byte)(pixel&0xff)};
  1065. return bdata;
  1066. }
  1067. case DataBuffer.TYPE_USHORT:
  1068. if (obj instanceof short[]) {
  1069. short sdata[] = (short[])obj;
  1070. sdata[0] = (short)(pixel&0xffff);
  1071. return sdata;
  1072. } else {
  1073. short sdata[] = {(short)(pixel&0xffff)};
  1074. return sdata;
  1075. }
  1076. case DataBuffer.TYPE_INT:
  1077. if (obj instanceof int[]) {
  1078. int idata[] = (int[])obj;
  1079. idata[0] = pixel;
  1080. return idata;
  1081. } else {
  1082. int idata[] = {pixel};
  1083. return idata;
  1084. }
  1085. default:
  1086. throw new ClassCastException("This method has not been "+
  1087. "implemented for transferType " + transferType);
  1088. }
  1089. }
  1090. /**
  1091. * Forces the raster data to match the state specified in the
  1092. * <code>isAlphaPremultiplied</code> variable, assuming the data is
  1093. * currently correctly described by this <code>ColorModel</code>. It
  1094. * may multiply or divide the color raster data by alpha, or do
  1095. * nothing if the data is in the correct state. If the data needs to
  1096. * be coerced, this method will also return an instance of this
  1097. * <code>ColorModel</code> with the <code>isAlphaPremultiplied</code>
  1098. * flag set appropriately. This method will throw a
  1099. * <code>UnsupportedOperationException</code> if this transferType is
  1100. * not supported by this <code>ColorModel</code>. Since
  1101. * <code>ColorModel</code> can be subclassed, subclasses inherit the
  1102. * implementation of this method and if they don't override it then
  1103. * they throw an exception if they use an unsupported transferType.
  1104. *
  1105. * @param raster the <code>WritableRaster</code> data
  1106. * @param isAlphaPremultiplied <code>true</code> if the alpha is
  1107. * premultiplied; <code>false</code> otherwise
  1108. * @return a <code>ColorModel</code> object that represents the
  1109. * coerced data.
  1110. * @exception UnsupportedOperationException if this
  1111. * <code>transferType</code> is not supported by this
  1112. * color model
  1113. */
  1114. final public ColorModel coerceData (WritableRaster raster,
  1115. boolean isAlphaPremultiplied)
  1116. {
  1117. if (!supportsAlpha ||
  1118. this.isAlphaPremultiplied() == isAlphaPremultiplied) {
  1119. return this;
  1120. }
  1121. int w = raster.getWidth();
  1122. int h = raster.getHeight();
  1123. int aIdx = numColorComponents;
  1124. float normAlpha;
  1125. float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
  1126. int rminX = raster.getMinX();
  1127. int rY = raster.getMinY();
  1128. int rX;
  1129. int pixel[] = null;
  1130. int zpixel[] = null;
  1131. if (isAlphaPremultiplied) {
  1132. // Must mean that we are currently not premultiplied so
  1133. // multiply by alpha
  1134. switch (transferType) {
  1135. case DataBuffer.TYPE_BYTE: {
  1136. for (int y = 0; y < h; y++, rY++) {
  1137. rX = rminX;
  1138. for (int x = 0; x < w; x++, rX++) {
  1139. pixel = raster.getPixel(rX, rY, pixel);
  1140. normAlpha = pixel[aIdx] * alphaScale;
  1141. if (normAlpha != 0.f) {
  1142. for (int c=0; c < aIdx; c++) {
  1143. pixel[c] = (int) (pixel[c] * normAlpha +
  1144. 0.5f);
  1145. }
  1146. raster.setPixel(rX, rY, pixel);
  1147. } else {
  1148. if (zpixel == null) {
  1149. zpixel = new int[numComponents];
  1150. java.util.Arrays.fill(zpixel, 0);
  1151. }
  1152. raster.setPixel(rX, rY, zpixel);
  1153. }
  1154. }
  1155. }
  1156. }
  1157. break;
  1158. case DataBuffer.TYPE_USHORT: {
  1159. for (int y = 0; y < h; y++, rY++) {
  1160. rX = rminX;
  1161. for (int x = 0; x < w; x++, rX++) {
  1162. pixel = raster.getPixel(rX, rY, pixel);
  1163. normAlpha = pixel[aIdx] * alphaScale;
  1164. if (normAlpha != 0.f) {
  1165. for (int c=0; c < aIdx; c++) {
  1166. pixel[c] = (int) (pixel[c] * normAlpha +
  1167. 0.5f);
  1168. }
  1169. raster.setPixel(rX, rY, pixel);
  1170. } else {
  1171. if (zpixel == null) {
  1172. zpixel = new int[numComponents];
  1173. java.util.Arrays.fill(zpixel, 0);
  1174. }
  1175. raster.setPixel(rX, rY, zpixel);
  1176. }
  1177. }
  1178. }
  1179. }
  1180. break;
  1181. case DataBuffer.TYPE_INT: {
  1182. for (int y = 0; y < h; y++, rY++) {
  1183. rX = rminX;
  1184. for (int x = 0; x < w; x++, rX++) {
  1185. pixel = raster.getPixel(rX, rY, pixel);
  1186. normAlpha = pixel[aIdx] * alphaScale;
  1187. if (normAlpha != 0.f) {
  1188. for (int c=0; c < aIdx; c++) {
  1189. pixel[c] = (int) (pixel[c] * normAlpha +
  1190. 0.5f);
  1191. }
  1192. raster.setPixel(rX, rY, pixel);
  1193. } else {
  1194. if (zpixel == null) {
  1195. zpixel = new int[numComponents];
  1196. java.util.Arrays.fill(zpixel, 0);
  1197. }
  1198. raster.setPixel(rX, rY, zpixel);
  1199. }
  1200. }
  1201. }
  1202. }
  1203. break;
  1204. default:
  1205. throw new UnsupportedOperationException("This method has not been "+
  1206. "implemented for transferType " + transferType);
  1207. }
  1208. }
  1209. else {
  1210. // We are premultiplied and want to divide it out
  1211. switch (transferType) {
  1212. case DataBuffer.TYPE_BYTE: {
  1213. for (int y = 0; y < h; y++, rY++) {
  1214. rX = rminX;
  1215. for (int x = 0; x < w; x++, rX++) {
  1216. pixel = raster.getPixel(rX, rY, pixel);
  1217. normAlpha = pixel[aIdx] * alphaScale;
  1218. if (normAlpha != 0.0f) {
  1219. float invAlpha = 1.0f / normAlpha;
  1220. for (int c=0; c < aIdx; c++) {
  1221. pixel[c] = (int) (pixel[c] * invAlpha +
  1222. 0.5f);
  1223. }
  1224. raster.setPixel(rX, rY, pixel);
  1225. }
  1226. }
  1227. }
  1228. }
  1229. break;
  1230. case DataBuffer.TYPE_USHORT: {
  1231. for (int y = 0; y < h; y++, rY++) {
  1232. rX = rminX;
  1233. for (int x = 0; x < w; x++, rX++) {
  1234. pixel = raster.getPixel(rX, rY, pixel);
  1235. normAlpha = pixel[aIdx] * alphaScale;
  1236. if (normAlpha != 0) {
  1237. float invAlpha = 1.0f / normAlpha;
  1238. for (int c=0; c < aIdx; c++) {
  1239. pixel[c] = (int) (pixel[c] * invAlpha +
  1240. 0.5f);
  1241. }
  1242. raster.setPixel(rX, rY, pixel);
  1243. }
  1244. }
  1245. }
  1246. }
  1247. break;
  1248. case DataBuffer.TYPE_INT: {
  1249. for (int y = 0; y < h; y++, rY++) {
  1250. rX = rminX;
  1251. for (int x = 0; x < w; x++, rX++) {
  1252. pixel = raster.getPixel(rX, rY, pixel);
  1253. normAlpha = pixel[aIdx] * alphaScale;
  1254. if (normAlpha != 0) {
  1255. float invAlpha = 1.0f / normAlpha;
  1256. for (int c=0; c < aIdx; c++) {
  1257. pixel[c] = (int) (pixel[c] * invAlpha +
  1258. 0.5f);
  1259. }
  1260. raster.setPixel(rX, rY, pixel);
  1261. }
  1262. }
  1263. }
  1264. }
  1265. break;
  1266. default:
  1267. throw new UnsupportedOperationException("This method has not been "+
  1268. "implemented for transferType " + transferType);
  1269. }
  1270. }
  1271. // Return a new color model
  1272. return new DirectColorModel(colorSpace, pixel_bits, maskArray[0],
  1273. maskArray[1], maskArray[2], maskArray[3],
  1274. isAlphaPremultiplied,
  1275. transferType);
  1276. }
  1277. /**
  1278. * Returns <code>true</code> if <code>raster</code> is compatible
  1279. * with this <code>ColorModel</code> and <code>false</code> if it is
  1280. * not.
  1281. * @param raster the {@link Raster} object to test for compatibility
  1282. * @return <code>true</code> if <code>raster</code> is compatible
  1283. * with this <code>ColorModel</code> <code>false</code> otherwise.
  1284. */
  1285. public boolean isCompatibleRaster(Raster raster) {
  1286. SampleModel sm = raster.getSampleModel();
  1287. SinglePixelPackedSampleModel spsm;
  1288. if (sm instanceof SinglePixelPackedSampleModel) {
  1289. spsm = (SinglePixelPackedSampleModel) sm;
  1290. }
  1291. else {
  1292. return false;
  1293. }
  1294. if (spsm.getNumBands() != getNumComponents()) {
  1295. return false;
  1296. }
  1297. int[] bitMasks = spsm.getBitMasks();
  1298. for (int i=0; i<numComponents; i++) {
  1299. if (bitMasks[i] != maskArray[i]) {
  1300. return false;
  1301. }
  1302. }
  1303. return (raster.getTransferType() == transferType);
  1304. }
  1305. private void setFields() {
  1306. // Set the private fields
  1307. // REMIND: Get rid of these from the native code
  1308. red_mask = maskArray[0];
  1309. red_offset = maskOffsets[0];
  1310. green_mask = maskArray[1];
  1311. green_offset = maskOffsets[1];
  1312. blue_mask = maskArray[2];
  1313. blue_offset = maskOffsets[2];
  1314. if (nBits[0] < 8) {
  1315. red_scale = (1 << nBits[0]) - 1;
  1316. }
  1317. if (nBits[1] < 8) {
  1318. green_scale = (1 << nBits[1]) - 1;
  1319. }
  1320. if (nBits[2] < 8) {
  1321. blue_scale = (1 << nBits[2]) - 1;
  1322. }
  1323. if (supportsAlpha) {
  1324. alpha_mask = maskArray[3];
  1325. alpha_offset = maskOffsets[3];
  1326. if (nBits[3] < 8) {
  1327. alpha_scale = (1 << nBits[3]) - 1;
  1328. }
  1329. }
  1330. }
  1331. /**
  1332. * Returns a <code>String</code> that represents this
  1333. * <code>DirectColorModel</code>.
  1334. * @return a <code>String</code> representing this
  1335. * <code>DirectColorModel</code>.
  1336. */
  1337. public String toString() {
  1338. return new String("DirectColorModel: rmask="
  1339. +Integer.toHexString(red_mask)+" gmask="
  1340. +Integer.toHexString(green_mask)+" bmask="
  1341. +Integer.toHexString(blue_mask)+" amask="
  1342. +Integer.toHexString(alpha_mask));
  1343. }
  1344. }