1. /*
  2. * @(#)DirectColorModel.java 1.60 01/11/29
  3. *
  4. * Copyright 2002 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. * A ColorModel class that works with pixel values which represent RGB
  12. * color and alpha information as separate samples and which pack all
  13. * samples for a single pixel into a single int, short, or byte quantity.
  14. * This class can be used only with ColorSpaces of type ColorSpace.TYPE_RGB.
  15. * There must be three color samples in the pixel values and there may
  16. * be a single alpha sample. For those methods which use a primitive array
  17. * pixel representation of type transferType, the array length is always
  18. * one. Color and alpha samples are stored in the single element of the
  19. * array in bits indicated by bit masks. Each bit mask must be contiguous
  20. * and masks must not overlap. The same masks apply to the single int
  21. * pixel representation used by other methods. The correspondence of
  22. * masks and color/alpha samples is as follows. Masks are identified by
  23. * indices running from 0 through 2, if no alpha is present, or 3. The
  24. * first three indices refer to color samples; index 0 corresponds to red,
  25. * index 1 to green, and index 2 to blue. Index 3 corresponds to the alpha
  26. * sample, if present. The transfer types supported are DataBuffer.TYPE_BYTE,
  27. * DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
  28. * <p>
  29. * The translation from pixel values to color/alpha components for
  30. * display or processing purposes is a one-to-one correspondence of
  31. * samples to components.
  32. * A DirectColorModel is typically used with image data which uses masks
  33. * to define packed samples. For example, a DirectColorModel can be used in
  34. * conjunction with a SinglePixelPackedSampleModel to construct a
  35. * BufferedImage. Normally the masks used by the SampleModel and the
  36. * ColorModel would be the same. However, if they are different, the
  37. * color interpretation of pixel data will be done according to the
  38. * masks of the ColorModel.
  39. * <p>
  40. * A single int pixel representation is valid for all objects of this
  41. * class, since it is always possible to represent pixel values used with
  42. * this class in a single int. Therefore, methods which use this
  43. * representation will not throw an IllegalArgumentException due to
  44. * an invalid pixel value.
  45. * <p>
  46. * This color model is similar to an X11 TrueColor visual.
  47. * The default RGB ColorModel specified by the ColorModel.getRGBdefault
  48. * method is a DirectColorModel with the following parameters:
  49. * <pre>
  50. * Number of bits: 32
  51. * Red mask: 0x00ff0000
  52. * Green mask: 0x0000ff00
  53. * Blue mask: 0x000000ff
  54. * Alpha mask: 0xff000000
  55. * Color space: sRGB
  56. * isAlphaPremultiplied: False
  57. * Transparency: Transparency.TRANSLUCENT
  58. * transferType: DataBuffer.TYPE_INT
  59. * </pre>
  60. * <p>
  61. * Many of the methods in this class are final. This is because the
  62. * underlying native graphics code makes assumptions about the layout
  63. * and operation of this class and those assumptions are reflected in
  64. * the implementations of the methods here that are marked final. You
  65. * can subclass this class for other reasons, but you cannot override
  66. * or modify the behavior of those methods.
  67. *
  68. * @see ColorModel
  69. * @see ColorSpace
  70. * @see SinglePixelPackedSampleModel
  71. * @see BufferedImage
  72. * @see ColorModel#getRGBdefault
  73. *
  74. * @version 10 Feb 1997
  75. */
  76. public class DirectColorModel extends PackedColorModel {
  77. private int red_mask;
  78. private int green_mask;
  79. private int blue_mask;
  80. private int alpha_mask;
  81. private int red_offset;
  82. private int green_offset;
  83. private int blue_offset;
  84. private int alpha_offset;
  85. private int red_scale;
  86. private int green_scale;
  87. private int blue_scale;
  88. private int alpha_scale;
  89. /**
  90. * Constructs a DirectColorModel from the given masks specifying which
  91. * bits in an int pixel representation contain the red, green and blue
  92. * color samples. Pixel values do not contain alpha information, so
  93. * all pixels will be treated as opaque (alpha = 1.0). All of the bits
  94. * in each mask must be contiguous and fit in the specified number
  95. * of least significant bits of an int pixel representation. The
  96. * ColorSpace will be the default sRGB space. The
  97. * transparency value will be Transparency.OPAQUE. The transfer type
  98. * will be the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
  99. * or DataBuffer.TYPE_INT that can hold a single pixel.
  100. */
  101. public DirectColorModel(int bits,
  102. int rmask, int gmask, int bmask) {
  103. this(bits, rmask, gmask, bmask, 0);
  104. }
  105. /**
  106. * Constructs a DirectColorModel from the given masks specifying which
  107. * bits in an int pixel representation contain the red, green and blue
  108. * color samples and the alpha sample, if present. If amask is 0,
  109. * pixel values do not contain alpha information, so all pixels will
  110. * be treated as opaque (alpha = 1.0). All of the bits in each mask must
  111. * be contiguous and fit in the specified number of least significant bits
  112. * of an int pixel representation. Alpha, if present, will not be
  113. * premultiplied. The ColorSpace will be the default sRGB space. The
  114. * transparency value will be Transparency.OPAQUE, if no alpha is
  115. * present, or Transparency.TRANSLUCENT otherwise. The transfer type
  116. * will be the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
  117. * or DataBuffer.TYPE_INT that can hold a single pixel.
  118. */
  119. public DirectColorModel(int bits, int rmask, int gmask,
  120. int bmask, int amask) {
  121. super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
  122. bits, rmask, gmask, bmask, amask, false,
  123. amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
  124. ColorModel.getDefaultTransferType(bits));
  125. setFields();
  126. }
  127. /**
  128. * Constructs a DirectColorModel from the specified parameters.
  129. * Color components will be in the specified ColorSpace, which must
  130. * be of type ColorSpace.TYPE_RGB.
  131. * The masks specify which bits in an int pixel representation contain
  132. * the red, green and blue color samples and the alpha sample, if present.
  133. * If amask is 0, pixel values do not contain alpha information, so
  134. * all pixels will be treated as opaque (alpha = 1.0). All of the bits
  135. * in each mask must be contiguous and fit in the specified number of
  136. * least significant bits of an int pixel representation. If there
  137. * is alpha, the boolean isAlphaPremultiplied specifies how to interpret
  138. * color and alpha samples in pixel values. If the boolean is true, color
  139. * samples are assumed to have been multiplied by the alpha sample.
  140. * The transparency value will be Transparency.OPAQUE, if no alpha is
  141. * present, or Transparency.TRANSLUCENT otherwise. The transfer type
  142. * is the type of primitive array used to represent pixel values and
  143. * must be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or
  144. * DataBuffer.TYPE_INT.
  145. */
  146. public DirectColorModel(ColorSpace space, int bits, int rmask,
  147. int gmask, int bmask, int amask,
  148. boolean isAlphaPremultiplied,
  149. int transferType) {
  150. super (space, bits, rmask, gmask, bmask, amask,
  151. isAlphaPremultiplied,
  152. amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
  153. transferType);
  154. setFields();
  155. }
  156. /**
  157. * Returns the mask indicating which bits in an int pixel representation
  158. * contain the red color component.
  159. */
  160. final public int getRedMask() {
  161. return maskArray[0];
  162. }
  163. /**
  164. * Returns the mask indicating which bits in an int pixel representation
  165. * contain the green color component.
  166. */
  167. final public int getGreenMask() {
  168. return maskArray[1];
  169. }
  170. /**
  171. * Returns the mask indicating which bits in an int pixel representation
  172. * contain the blue color component.
  173. */
  174. final public int getBlueMask() {
  175. return maskArray[2];
  176. }
  177. /**
  178. * Returns the mask indicating which bits in an int pixel representation
  179. * contain the alpha component.
  180. */
  181. final public int getAlphaMask() {
  182. if (supportsAlpha) {
  183. return maskArray[3];
  184. } else {
  185. return 0;
  186. }
  187. }
  188. /**
  189. * Returns the red color component for the specified pixel, scaled
  190. * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
  191. * is done if necessary. The pixel value is specified as an int.
  192. * The returned value will be a non pre-multiplied value, i.e. if the
  193. * alpha is premultiplied, this method will divide it out before returning
  194. * the value (if the alpha value is 0, the red value will be 0).
  195. */
  196. final public int getRed(int pixel) {
  197. int r = ((pixel & maskArray[0]) >>> maskOffsets[0]);
  198. if (scaleFactors[0] != 1.) {
  199. r = (int)(r * scaleFactors[0]);
  200. }
  201. if (isAlphaPremultiplied) {
  202. int a = getAlpha(pixel);
  203. r = (a == 0) ? 0 : (r * 255/a);
  204. if (r > 255) {
  205. r = 255;
  206. }
  207. }
  208. return r;
  209. }
  210. /**
  211. * Returns the green color component for the specified pixel, scaled
  212. * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
  213. * is done if necessary. The pixel value is specified as an int.
  214. * The returned value will be a non pre-multiplied value, i.e. if the
  215. * alpha is premultiplied, this method will divide it out before returning
  216. * the value (if the alpha value is 0, the green value will be 0).
  217. */
  218. final public int getGreen(int pixel) {
  219. int g = ((pixel & maskArray[1]) >>> maskOffsets[1]);
  220. if (scaleFactors[1] != 1.) {
  221. g = (int) (g * scaleFactors[1]);
  222. }
  223. if (isAlphaPremultiplied) {
  224. int a = getAlpha(pixel);
  225. g = (a == 0) ? 0 : (g * 255/a);
  226. if (g > 255) {
  227. g = 255;
  228. }
  229. }
  230. return g;
  231. }
  232. /**
  233. * Returns the blue color component for the specified pixel, scaled
  234. * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
  235. * is done if necessary. The pixel value is specified as an int.
  236. * The returned value will be a non pre-multiplied value, i.e. if the
  237. * alpha is premultiplied, this method will divide it out before returning
  238. * the value (if the alpha value is 0, the blue value will be 0).
  239. */
  240. final public int getBlue(int pixel) {
  241. int b = ((pixel & maskArray[2]) >>> maskOffsets[2]);
  242. if (scaleFactors[2] != 1.) {
  243. b = (int)(b * scaleFactors[2]);
  244. }
  245. if (isAlphaPremultiplied) {
  246. int a = getAlpha(pixel);
  247. b = (a == 0) ? 0 : (b * 255/a);
  248. if (b > 255) {
  249. b = 255;
  250. }
  251. }
  252. return b;
  253. }
  254. /**
  255. * Returns the alpha component for the specified pixel, scaled
  256. * from 0 to 255. The pixel value is specified as an int.
  257. */
  258. final public int getAlpha(int pixel) {
  259. if (!supportsAlpha) return 255;
  260. int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
  261. if (scaleFactors[3] != 1.) {
  262. a = (int)(a * scaleFactors[3]);
  263. }
  264. return a;
  265. }
  266. /**
  267. * Returns the color/alpha components of the pixel in the default
  268. * RGB color model format. A color conversion is done if necessary.
  269. * The pixel value is specified as an int.
  270. * The returned value will be in a non pre-multiplied format, i.e. if
  271. * the alpha is premultiplied, this method will divide it out of the
  272. * color components (if the alpha value is 0, the color values will be 0).
  273. * @see ColorModel#getRGBdefault
  274. */
  275. final public int getRGB(int pixel) {
  276. return (getAlpha(pixel) << 24)
  277. | (getRed(pixel) << 16)
  278. | (getGreen(pixel) << 8)
  279. | (getBlue(pixel) << 0);
  280. }
  281. /**
  282. * Returns the red color component for the specified pixel, scaled
  283. * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
  284. * is done if necessary. The pixel value is specified by an array
  285. * of data elements of type transferType passed in as an object reference.
  286. * The returned value will be a non pre-multiplied value, i.e. if the
  287. * alpha is premultiplied, this method will divide it out before returning
  288. * the value (if the alpha value is 0, the red value will be 0).
  289. * If inData is not a primitive array of type transferType, a
  290. * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
  291. * thrown if inData is not large enough to hold a pixel value for this
  292. * ColorModel.
  293. */
  294. public int getRed(Object inData) {
  295. int pixel=0;
  296. switch (transferType) {
  297. case DataBuffer.TYPE_BYTE:
  298. byte bdata[] = (byte[])inData;
  299. pixel = bdata[0] & 0xff;
  300. break;
  301. case DataBuffer.TYPE_USHORT:
  302. short sdata[] = (short[])inData;
  303. pixel = sdata[0] & 0xffff;
  304. break;
  305. case DataBuffer.TYPE_INT:
  306. int idata[] = (int[])inData;
  307. pixel = idata[0];
  308. break;
  309. default:
  310. throw new UnsupportedOperationException("This method has not been "+
  311. "implemented for transferType " + transferType);
  312. }
  313. return getRed(pixel);
  314. }
  315. /**
  316. * Returns the green color component for the specified pixel, scaled
  317. * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
  318. * is done if necessary. The pixel value is specified by an array
  319. * of data elements of type transferType passed in as an object reference.
  320. * The returned value will be a non pre-multiplied value, i.e. if the
  321. * alpha is premultiplied, this method will divide it out before returning
  322. * the value (if the alpha value is 0, the green value will be 0).
  323. * If inData is not a primitive array of type transferType, a
  324. * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
  325. * thrown if inData is not large enough to hold a pixel value for this
  326. * ColorModel.
  327. */
  328. public int getGreen(Object inData) {
  329. int pixel=0;
  330. switch (transferType) {
  331. case DataBuffer.TYPE_BYTE:
  332. byte bdata[] = (byte[])inData;
  333. pixel = bdata[0] & 0xff;
  334. break;
  335. case DataBuffer.TYPE_USHORT:
  336. short sdata[] = (short[])inData;
  337. pixel = sdata[0] & 0xffff;
  338. break;
  339. case DataBuffer.TYPE_INT:
  340. int idata[] = (int[])inData;
  341. pixel = idata[0];
  342. break;
  343. default:
  344. throw new UnsupportedOperationException("This method has not been "+
  345. "implemented for transferType " + transferType);
  346. }
  347. return getGreen(pixel);
  348. }
  349. /**
  350. * Returns the blue color component for the specified pixel, scaled
  351. * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
  352. * is done if necessary. The pixel value is specified by an array
  353. * of data elements of type transferType passed in as an object reference.
  354. * The returned value will be a non pre-multiplied value, i.e. if the
  355. * alpha is premultiplied, this method will divide it out before returning
  356. * the value (if the alpha value is 0, the blue value will be 0).
  357. * If inData is not a primitive array of type transferType, a
  358. * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
  359. * thrown if inData is not large enough to hold a pixel value for this
  360. * ColorModel.
  361. */
  362. public int getBlue(Object inData) {
  363. int pixel=0;
  364. switch (transferType) {
  365. case DataBuffer.TYPE_BYTE:
  366. byte bdata[] = (byte[])inData;
  367. pixel = bdata[0] & 0xff;
  368. break;
  369. case DataBuffer.TYPE_USHORT:
  370. short sdata[] = (short[])inData;
  371. pixel = sdata[0] & 0xffff;
  372. break;
  373. case DataBuffer.TYPE_INT:
  374. int idata[] = (int[])inData;
  375. pixel = idata[0];
  376. break;
  377. default:
  378. throw new UnsupportedOperationException("This method has not been "+
  379. "implemented for transferType " + transferType);
  380. }
  381. return getBlue(pixel);
  382. }
  383. /**
  384. * Returns the alpha component for the specified pixel, scaled
  385. * from 0 to 255. The pixel value is specified by an array of data
  386. * elements of type transferType passed in as an object reference.
  387. * If inData is not a primitive array of type transferType, a
  388. * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
  389. * thrown if inData is not large enough to hold a pixel value for this
  390. * ColorModel.
  391. */
  392. public int getAlpha(Object inData) {
  393. int pixel=0;
  394. switch (transferType) {
  395. case DataBuffer.TYPE_BYTE:
  396. byte bdata[] = (byte[])inData;
  397. pixel = bdata[0] & 0xff;
  398. break;
  399. case DataBuffer.TYPE_USHORT:
  400. short sdata[] = (short[])inData;
  401. pixel = sdata[0] & 0xffff;
  402. break;
  403. case DataBuffer.TYPE_INT:
  404. int idata[] = (int[])inData;
  405. pixel = idata[0];
  406. break;
  407. default:
  408. throw new UnsupportedOperationException("This method has not been "+
  409. "implemented for transferType " + transferType);
  410. }
  411. return getAlpha(pixel);
  412. }
  413. /**
  414. * Returns the color/alpha components for the specified pixel in the
  415. * default RGB color model format. A color conversion is done if
  416. * necessary. The pixel value is specified by an array of data
  417. * elements of type transferType passed in as an object reference.
  418. * If inData is not a primitive array of type transferType, a
  419. * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
  420. * thrown if inData is not large enough to hold a pixel value for this
  421. * ColorModel.
  422. * The returned value will be in a non pre-multiplied format, i.e. if
  423. * the alpha is premultiplied, this method will divide it out of the
  424. * color components (if the alpha value is 0, the color values will be 0).
  425. * @see ColorModel#getRGBdefault
  426. */
  427. public int getRGB(Object inData) {
  428. int pixel=0;
  429. switch (transferType) {
  430. case DataBuffer.TYPE_BYTE:
  431. byte bdata[] = (byte[])inData;
  432. pixel = bdata[0] & 0xff;
  433. break;
  434. case DataBuffer.TYPE_USHORT:
  435. short sdata[] = (short[])inData;
  436. pixel = sdata[0] & 0xffff;
  437. break;
  438. case DataBuffer.TYPE_INT:
  439. int idata[] = (int[])inData;
  440. pixel = idata[0];
  441. break;
  442. default:
  443. throw new UnsupportedOperationException("This method has not been "+
  444. "implemented for transferType " + transferType);
  445. }
  446. return getRGB(pixel);
  447. }
  448. /**
  449. * Returns a data element array representation of a pixel in this
  450. * ColorModel, given an integer pixel representation in the
  451. * default RGB color model.
  452. * This array can then be passed to the setDataElements method of
  453. * a WritableRaster object. If the pixel variable is null, a new
  454. * array will be allocated. If pixel is not null, it must be
  455. * a primitive array of type transferType; otherwise, a
  456. * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
  457. * thrown if pixel is not large enough to hold a pixel value for this
  458. * ColorModel. The pixel array will be returned.
  459. * @see WritableRaster#setDataElements
  460. * @see SampleModel#setDataElements
  461. */
  462. public Object getDataElements(int rgb, Object pixel) {
  463. //REMIND: maybe more efficient not to use int array for
  464. //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
  465. int i;
  466. int intpixel[] = null;
  467. if (transferType == DataBuffer.TYPE_INT &&
  468. pixel != null) {
  469. intpixel = (int[])pixel;
  470. } else {
  471. intpixel = new int[1];
  472. }
  473. ColorModel defaultCM = ColorModel.getRGBdefault();
  474. if (this == defaultCM || equals(defaultCM)) {
  475. intpixel[0] = rgb;
  476. } else {
  477. double normAlpha = 1.;
  478. int c;
  479. if (isAlphaPremultiplied) {
  480. normAlpha = ((rgb>>24)&0xff)/255.;
  481. }
  482. double value;
  483. int[] shifts = {16, 8, 0, 24};
  484. int nbands = 3+(supportsAlpha ? 1 : 0);
  485. intpixel[0] = 0;
  486. for (i=0; i < nbands; i++) {
  487. c = (int)(((rgb>>shifts[i])&0xff)*normAlphascaleFactors[i]);
  488. intpixel[0] |= (c << maskOffsets[i]) & maskArray[i];
  489. }
  490. }
  491. switch (transferType) {
  492. case DataBuffer.TYPE_BYTE: {
  493. byte bdata[];
  494. if (pixel == null) {
  495. bdata = new byte[1];
  496. } else {
  497. bdata = (byte[])pixel;
  498. }
  499. bdata[0] = (byte)(0xff&intpixel[0]);
  500. return bdata;
  501. }
  502. case DataBuffer.TYPE_USHORT:{
  503. short sdata[];
  504. if (pixel == null) {
  505. sdata = new short[1];
  506. } else {
  507. sdata = (short[])pixel;
  508. }
  509. sdata[0] = (short)(intpixel[0]&0xffff);
  510. return sdata;
  511. }
  512. case DataBuffer.TYPE_INT:
  513. return intpixel;
  514. }
  515. throw new UnsupportedOperationException("This method has not been "+
  516. "implemented for transferType " + transferType);
  517. }
  518. /**
  519. * Returns an array of unnormalized color/alpha components given a pixel
  520. * in this ColorModel. The pixel value is specified as an int. If the
  521. * components array is null, a new array will be allocated. The
  522. * components array will be returned. Color/alpha components are
  523. * stored in the components array starting at offset (even if the
  524. * array is allocated by this method). An ArrayIndexOutOfBoundsException
  525. * is thrown if the components array is not null and is not large
  526. * enough to hold all the color and alpha components (starting at offset).
  527. */
  528. final public int[] getComponents(int pixel, int[] components, int offset) {
  529. if (components == null) {
  530. components = new int[offset+numComponents];
  531. }
  532. for (int i=0; i < numComponents; i++) {
  533. components[offset+i] = (pixel & maskArray[i]) >>> maskOffsets[i];
  534. }
  535. return components;
  536. }
  537. /**
  538. * Returns an array of unnormalized color/alpha components given a pixel
  539. * in this ColorModel. The pixel value is specified by an array of
  540. * data elements of type transferType passed in as an object reference.
  541. * If pixel is not a primitive array of type transferType, a
  542. * ClassCastException is thrown. An ArrayIndexOutOfBoundsException is
  543. * thrown if pixel is not large enough to hold a pixel value for this
  544. * ColorModel. If the components array is null, a new
  545. * array will be allocated. The components array will be returned.
  546. * Color/alpha components are
  547. * stored in the components array starting at offset (even if the
  548. * array is allocated by this method). An ArrayIndexOutOfBoundsException
  549. * is thrown if the components array is not null and is not large
  550. * enough to hold all the color and alpha components (starting at offset).
  551. */
  552. final public int[] getComponents(Object pixel, int[] components,
  553. int offset) {
  554. int intpixel=0;
  555. switch (transferType) {
  556. case DataBuffer.TYPE_BYTE:
  557. byte bdata[] = (byte[])pixel;
  558. intpixel = bdata[0] & 0xff;
  559. break;
  560. case DataBuffer.TYPE_USHORT:
  561. short sdata[] = (short[])pixel;
  562. intpixel = sdata[0] & 0xffff;
  563. break;
  564. case DataBuffer.TYPE_INT:
  565. int idata[] = (int[])pixel;
  566. intpixel = idata[0];
  567. break;
  568. default:
  569. throw new UnsupportedOperationException("This method has not been "+
  570. "implemented for transferType " + transferType);
  571. }
  572. return getComponents(intpixel, components, offset);
  573. }
  574. /**
  575. * Creates a WritableRaster with the specified width and height that
  576. * has a data layout (SampleModel) compatible with this ColorModel.
  577. * @see WritableRaster
  578. * @see SampleModel
  579. */
  580. final public WritableRaster createCompatibleWritableRaster (int w,
  581. int h) {
  582. int[] bandmasks;
  583. if (supportsAlpha) {
  584. bandmasks = new int[4];
  585. bandmasks[3] = alpha_mask;
  586. }
  587. else {
  588. bandmasks = new int[3];
  589. }
  590. bandmasks[0] = red_mask;
  591. bandmasks[1] = green_mask;
  592. bandmasks[2] = blue_mask;
  593. if (pixel_bits > 16) {
  594. return Raster.createPackedRaster(DataBuffer.TYPE_INT,
  595. w,h,bandmasks,null);
  596. }
  597. else if (pixel_bits > 8) {
  598. return Raster.createPackedRaster(DataBuffer.TYPE_USHORT,
  599. w,h,bandmasks,null);
  600. }
  601. else {
  602. return Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
  603. w,h,bandmasks,null);
  604. }
  605. }
  606. /**
  607. * Returns a pixel value represented as an int in this ColorModel,
  608. * given an array of unnormalized color/alpha components. An
  609. * ArrayIndexOutOfBoundsException is thrown if the components array is
  610. * not large enough to hold all the color and alpha components (starting
  611. * at offset).
  612. */
  613. public int getDataElement(int[] components, int offset) {
  614. int pixel = 0;
  615. for (int i=0; i < numComponents; i++) {
  616. pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
  617. }
  618. return pixel;
  619. }
  620. /**
  621. * Returns a data element array representation of a pixel in this
  622. * ColorModel, given an array of unnormalized color/alpha components.
  623. * This array can then be passed to the setDataElements method of
  624. * a WritableRaster object.
  625. * An ArrayIndexOutOfBoundsException is thrown if the components array
  626. * is not large enough to hold all the color and alpha components
  627. * (starting at offset). If the obj variable is null, a new array
  628. * will be allocated. If obj is not null, it must be a primitive array
  629. * of type transferType; otherwise, a ClassCastException is thrown.
  630. * An ArrayIndexOutOfBoundsException is thrown if obj is not large
  631. * enough to hold a pixel value for this ColorModel.
  632. * @see WritableRaster#setDataElements
  633. * @see SampleModel#setDataElements
  634. */
  635. public Object getDataElements(int[] components, int offset, Object obj) {
  636. int pixel = 0;
  637. for (int i=0; i < numComponents; i++) {
  638. pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
  639. }
  640. switch (transferType) {
  641. case DataBuffer.TYPE_BYTE:
  642. if (obj instanceof byte[]) {
  643. byte bdata[] = (byte[])obj;
  644. bdata[0] = (byte)(pixel&0xff);
  645. return bdata;
  646. } else {
  647. byte bdata[] = {(byte)(pixel&0xff)};
  648. return bdata;
  649. }
  650. case DataBuffer.TYPE_USHORT:
  651. if (obj instanceof short[]) {
  652. short sdata[] = (short[])obj;
  653. sdata[0] = (short)(pixel&0xffff);
  654. return sdata;
  655. } else {
  656. short sdata[] = {(short)(pixel&0xffff)};
  657. return sdata;
  658. }
  659. case DataBuffer.TYPE_INT:
  660. if (obj instanceof int[]) {
  661. int idata[] = (int[])obj;
  662. idata[0] = pixel;
  663. return idata;
  664. } else {
  665. int idata[] = {pixel};
  666. return idata;
  667. }
  668. default:
  669. throw new ClassCastException("This method has not been "+
  670. "implemented for transferType " + transferType);
  671. }
  672. }
  673. /**
  674. * Forces the Raster data to match the state specified in the
  675. * isAlphaPremultiplied variable, assuming the data is currently
  676. * correctly described by this ColorModel. It may multiply or divide
  677. * the color Raster data by alpha, or do nothing if the data is
  678. * in the correct state. If the data needs to be coerced, this
  679. * method will also return an instance of this ColorModel with
  680. * the isAlphaPremultiplied flag set appropriately.
  681. */
  682. final public ColorModel coerceData (WritableRaster raster,
  683. boolean isAlphaPremultiplied)
  684. {
  685. if (!supportsAlpha ||
  686. this.isAlphaPremultiplied() == isAlphaPremultiplied) {
  687. return this;
  688. }
  689. int w = raster.getWidth();
  690. int h = raster.getHeight();
  691. int aIdx = numColorComponents;
  692. float normAlpha;
  693. int alphaScale = (1 << nBits[aIdx]) - 1;
  694. int rminX = raster.getMinX();
  695. int rY = raster.getMinY();
  696. int rX;
  697. int pixel[] = null;
  698. if (isAlphaPremultiplied) {
  699. // Must mean that we are currently not premultiplied so
  700. // multiply by alpha
  701. switch (transferType) {
  702. case DataBuffer.TYPE_BYTE: {
  703. for (int y = 0; y < h; y++, rY++) {
  704. rX = rminX;
  705. for (int x = 0; x < w; x++, rX++) {
  706. pixel = raster.getPixel(rX, rY, pixel);
  707. normAlpha = pixel[aIdx]/alphaScale;
  708. if (normAlpha != 0.f) {
  709. for (int c=0; c < aIdx; c++) {
  710. pixel[c] = (int)(pixel[c]*normAlpha);
  711. }
  712. raster.setPixel(rX, rY, pixel);
  713. }
  714. }
  715. }
  716. }
  717. break;
  718. case DataBuffer.TYPE_USHORT: {
  719. for (int y = 0; y < h; y++, rY++) {
  720. rX = rminX;
  721. for (int x = 0; x < w; x++, rX++) {
  722. pixel = raster.getPixel(rX, rY, pixel);
  723. normAlpha = pixel[aIdx]/alphaScale;
  724. if (normAlpha != 0.f) {
  725. for (int c=0; c < aIdx; c++) {
  726. pixel[c] = (int)(pixel[c]*normAlpha);
  727. }
  728. raster.setPixel(rX, rY, pixel);
  729. }
  730. }
  731. }
  732. }
  733. break;
  734. case DataBuffer.TYPE_INT: {
  735. for (int y = 0; y < h; y++, rY++) {
  736. rX = rminX;
  737. for (int x = 0; x < w; x++, rX++) {
  738. pixel = raster.getPixel(rX, rY, pixel);
  739. normAlpha = pixel[aIdx]/alphaScale;
  740. if (normAlpha != 0.f) {
  741. for (int c=0; c < aIdx; c++) {
  742. pixel[c] = (int)(pixel[c]*normAlpha);
  743. }
  744. raster.setPixel(rX, rY, pixel);
  745. }
  746. }
  747. }
  748. }
  749. break;
  750. default:
  751. throw new UnsupportedOperationException("This method has not been "+
  752. "implemented for transferType " + transferType);
  753. }
  754. }
  755. else {
  756. // We are premultiplied and want to divide it out
  757. switch (transferType) {
  758. case DataBuffer.TYPE_BYTE: {
  759. for (int y = 0; y < h; y++, rY++) {
  760. rX = rminX;
  761. for (int x = 0; x < w; x++, rX++) {
  762. pixel = raster.getPixel(rX, rY, pixel);
  763. normAlpha = pixel[aIdx]/alphaScale;
  764. if (normAlpha != 0) {
  765. for (int c=0; c < aIdx; c++) {
  766. pixel[c] /= normAlpha;
  767. }
  768. }
  769. raster.setPixel(rX, rY, pixel);
  770. }
  771. }
  772. }
  773. break;
  774. case DataBuffer.TYPE_USHORT: {
  775. for (int y = 0; y < h; y++, rY++) {
  776. rX = rminX;
  777. for (int x = 0; x < w; x++, rX++) {
  778. pixel = raster.getPixel(rX, rY, pixel);
  779. normAlpha = pixel[aIdx]/alphaScale;
  780. if (normAlpha != 0) {
  781. for (int c=0; c < aIdx; c++) {
  782. pixel[c] /= normAlpha;
  783. }
  784. }
  785. raster.setPixel(rX, rY, pixel);
  786. }
  787. }
  788. }
  789. break;
  790. case DataBuffer.TYPE_INT: {
  791. for (int y = 0; y < h; y++, rY++) {
  792. rX = rminX;
  793. for (int x = 0; x < w; x++, rX++) {
  794. pixel = raster.getPixel(rX, rY, pixel);
  795. normAlpha = pixel[aIdx]/alphaScale;
  796. if (normAlpha != 0) {
  797. for (int c=0; c < aIdx; c++) {
  798. pixel[c] /= normAlpha;
  799. }
  800. }
  801. raster.setPixel(rX, rY, pixel);
  802. }
  803. }
  804. }
  805. break;
  806. default:
  807. throw new UnsupportedOperationException("This method has not been "+
  808. "implemented for transferType " + transferType);
  809. }
  810. }
  811. // Return a new color model
  812. return new DirectColorModel(colorSpace, pixel_bits, maskArray[0],
  813. maskArray[1], maskArray[2], maskArray[3],
  814. isAlphaPremultiplied,
  815. transferType);
  816. }
  817. /**
  818. * Returns true if raster is compatible with this ColorModel and
  819. * false if it is not.
  820. */
  821. public boolean isCompatibleRaster(Raster raster) {
  822. SampleModel sm = raster.getSampleModel();
  823. SinglePixelPackedSampleModel spsm;
  824. if (sm instanceof SinglePixelPackedSampleModel) {
  825. spsm = (SinglePixelPackedSampleModel) sm;
  826. }
  827. else {
  828. return false;
  829. }
  830. if (spsm.getNumBands() != getNumComponents()) {
  831. return false;
  832. }
  833. boolean flag = true;
  834. int[] bitMasks = spsm.getBitMasks();
  835. int[] bitSizes = spsm.getSampleSize();
  836. int[] bitOffsets = spsm.getBitOffsets();
  837. int totalBitSize = 0;
  838. /*if[Linux]
  839. int testBitSize=0;
  840. end[Linux]*/
  841. for(int i=0; i<bitSizes.length; i++) {
  842. if (bitSizes[i]+bitOffsets[i] > totalBitSize) {
  843. totalBitSize = bitSizes[i]+bitOffsets[i];
  844. }
  845. }
  846. for (int i=0; i<numComponents; i++) {
  847. if (bitMasks[i] != maskArray[i])
  848. flag = false;
  849. /*if[Linux]
  850. testBitSize+=bitSizes[i];
  851. end[Linux]*/
  852. }
  853. return ( (raster.getTransferType() == transferType) &&
  854. /*if[Linux]
  855. (totalBitSize == testBitSize ) && flag );
  856. else[Linux]*/
  857. (totalBitSize == pixel_bits ) && flag );
  858. /*end[Linux]*/
  859. }
  860. private void setFields() {
  861. // Set the private fields
  862. // REMIND: Get rid of these from the native code
  863. red_mask = maskArray[0];
  864. red_offset = maskOffsets[0];
  865. green_mask = maskArray[1];
  866. green_offset = maskOffsets[1];
  867. blue_mask = maskArray[2];
  868. blue_offset = maskOffsets[2];
  869. if (nBits[0] < 8) {
  870. red_scale = (1 << nBits[0]) - 1;
  871. }
  872. if (nBits[1] < 8) {
  873. green_scale = (1 << nBits[1]) - 1;
  874. }
  875. if (nBits[2] < 8) {
  876. blue_scale = (1 << nBits[2]) - 1;
  877. }
  878. if (supportsAlpha) {
  879. alpha_mask = maskArray[3];
  880. alpha_offset = maskOffsets[3];
  881. if (nBits[3] < 8) {
  882. alpha_scale = (1 << nBits[3]) - 1;
  883. }
  884. }
  885. }
  886. /**
  887. * Returns a <code>String</code> that represents this
  888. * <code>DirectColorModel</code>.
  889. * @return a <code>String</code> representing this
  890. * <code>DirectColorModel</code>.
  891. */
  892. public String toString() {
  893. return new String("DirectColorModel: rmask="
  894. +Integer.toHexString(red_mask)+" gmask="
  895. +Integer.toHexString(green_mask)+" bmask="
  896. +Integer.toHexString(blue_mask)+" amask="
  897. +Integer.toHexString(alpha_mask));
  898. }
  899. }