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