1. /*
  2. * @(#)IndexColorModel.java 1.84 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.Transparency;
  12. import java.awt.color.ColorSpace;
  13. import sun.java2d.loops.ImageData;
  14. import java.math.BigInteger;
  15. /**
  16. * The <code>IndexColorModel</code> class is a <code>ColorModel</code>
  17. * class that works with pixel values consisting of a
  18. * single sample which is an index into a fixed colormap in the default
  19. * sRGB ColorSpace. The colormap specifies red, green, blue, and
  20. * optional alpha components corresponding to each index. All components
  21. * are represented in the colormap as 8-bit unsigned integral values. If
  22. * alpha is not present, an opaque alpha component (alpha = 1.0) is
  23. * assumed for each entry. An optional transparent
  24. * pixel value can be supplied that indicates a completely transparent
  25. * pixel, regardless of any alpha component recorded for that pixel value.
  26. * Note that alpha values in <code>IndexColorModel</code> objects are
  27. * never premultiplied.
  28. * This color model is similar to an X11 PseudoColor visual.
  29. * <p>
  30. * The index represented by a pixel value is stored in the least
  31. * significant n bits of the pixel representations passed to the
  32. * methods of this class, where n is the pixel size specified to the
  33. * constructor for a particular <code>IndexColorModel</code> object
  34. * and n must be between 1 and 16.
  35. * Higher order bits in pixel representations are assumed to be zero.
  36. * For those methods that use a primitive array pixel representation of
  37. * type <code>transferType</code>, the array length is always one.
  38. * The transfer types supported are DataBuffer.TYPE_BYTE and
  39. * DataBuffer.TYPE_USHORT. A single int pixel
  40. * representation is valid for all objects of this class, since it is
  41. * always possible to represent pixel values used with this class in a
  42. * single int. Therefore, methods that use this representation do
  43. * not throw an <code>IllegalArgumentException</code> due to an invalid
  44. * pixel value.
  45. * <p>
  46. * Many of the methods in this class are final. The reason for
  47. * this is that the underlying native graphics code makes assumptions
  48. * about the layout and operation of this class and those assumptions
  49. * are reflected in the implementations of the methods here that are
  50. * marked final. You can subclass this class for other reaons, but
  51. * you cannot override or modify the behaviour of those methods.
  52. *
  53. * @see ColorModel
  54. * @see ColorSpace
  55. * @see DataBuffer
  56. *
  57. * @version 10 Feb 1997
  58. */
  59. public class IndexColorModel extends ColorModel {
  60. private int rgb[];
  61. private int map_size;
  62. private int transparent_index = -1;
  63. private boolean allgrayopaque;
  64. private BigInteger validBits;
  65. static private native void initIDs();
  66. static {
  67. ColorModel.loadLibraries();
  68. initIDs();
  69. }
  70. /**
  71. * Constructs an <code>IndexColorModel</code> from the specified
  72. * arrays of red, green, and blue components. Pixels described
  73. * by this color model all have alpha components of 255
  74. * unnormalized (1.0 normalized), which means they
  75. * are fully opaque. All of the arrays specifying the color
  76. * components must have at least the specified number of entries.
  77. * The <code>ColorSpace</code> is the default sRGB space. The
  78. * transparency value is Transparency.OPAQUE. The transfer type is
  79. * the smallest of DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT
  80. * that can hold a single pixel.
  81. * @param bits the number of bits each pixel occupies
  82. * @param size the size of the color component arrays
  83. * @param r the array of red color components
  84. * @param g the array of green color components
  85. * @param b the array of blue color components
  86. * @throws IllegalArgumentException if <code>bits</code> is less
  87. * than 1 or greater than 16
  88. * @throws IllegalArgumentException if <code>size</code> is less
  89. * than 1
  90. */
  91. public IndexColorModel(int bits, int size,
  92. byte r[], byte g[], byte b[]) {
  93. super(bits, IndexColorModel.setBits(bits, false),
  94. ColorSpace.getInstance(ColorSpace.CS_sRGB),
  95. false, false, Transparency.OPAQUE,
  96. ColorModel.getDefaultTransferType(bits));
  97. if (bits < 1 || bits > 16) {
  98. throw new IllegalArgumentException("Number of bits must be between"
  99. +" 1 and 16.");
  100. }
  101. setRGBs(size, r, g, b, null);
  102. checkAllGrayOpaque();
  103. }
  104. /**
  105. * Constructs an <code>IndexColorModel</code> from the given arrays
  106. * of red, green, and blue components. Pixels described by this color
  107. * model all have alpha components of 255 unnormalized
  108. * (1.0 normalized), which means they are fully opaque, except
  109. * for the indicated transparent pixel. All of the arrays
  110. * specifying the color components must have at least the specified
  111. * number of entries. The ColorSpace is the default sRGB space.
  112. * The transparency value is Transparency.BITMASK.
  113. * The transfer type is the smallest of DataBuffer.TYPE_BYTE or
  114. * DataBuffer.TYPE_USHORT that can hold a
  115. * single pixel.
  116. * @param bits the number of bits each pixel occupies
  117. * @param size the size of the color component arrays
  118. * @param r the array of red color components
  119. * @param g the array of green color components
  120. * @param b the array of blue color components
  121. * @param trans the index of the transparent pixel
  122. * @throws IllegalArgumentException if <code>bits</code> is less than
  123. * 1 or greater than 16
  124. * @throws IllegalArgumentException if <code>size</code> is less than
  125. * 1
  126. */
  127. public IndexColorModel(int bits, int size,
  128. byte r[], byte g[], byte b[], int trans) {
  129. super(bits, IndexColorModel.setBits(bits, (trans>=0)),
  130. ColorSpace.getInstance(ColorSpace.CS_sRGB),
  131. (trans > -1), false, Transparency.BITMASK,
  132. ColorModel.getDefaultTransferType(bits));
  133. if (bits < 1 || bits > 16) {
  134. throw new IllegalArgumentException("Number of bits must be between"
  135. +" 1 and 16.");
  136. }
  137. setRGBs(size, r, g, b, null);
  138. if (trans > -1) {
  139. transparency = Transparency.BITMASK;
  140. setTransparentPixel(trans);
  141. }
  142. checkAllGrayOpaque();
  143. }
  144. /**
  145. * Constructs an <code>IndexColorModel</code> from the given
  146. * arrays of red, green, blue and alpha components. All of the
  147. * arrays specifying the components must have at least the specified
  148. * number of entries. The ColorSpace is the default sRGB space.
  149. * The transparency value is Transparency.TRANSLUCENT.
  150. * The transfer type is the smallest of DataBuffer.TYPE_BYTE or
  151. * DataBuffer.TYPE_USHORT that can hold a single pixel.
  152. * @param bits the number of bits each pixel occupies
  153. * @param size the size of the color component arrays
  154. * @param r the array of red color components
  155. * @param g the array of green color components
  156. * @param b the array of blue color components
  157. * @param a the array of alpha value components
  158. * @throws IllegalArgumentException if <code>bits</code> is less
  159. * than 1 or greater than 16
  160. * @throws IllegalArgumentException if <code>size</code> is less
  161. * than 1
  162. */
  163. public IndexColorModel(int bits, int size,
  164. byte r[], byte g[], byte b[], byte a[]) {
  165. super (bits, IndexColorModel.setBits(bits, true),
  166. ColorSpace.getInstance(ColorSpace.CS_sRGB),
  167. true, false, Transparency.TRANSLUCENT,
  168. ColorModel.getDefaultTransferType(bits));
  169. if (bits < 1 || bits > 16) {
  170. throw new IllegalArgumentException("Number of bits must be between"
  171. +" 1 and 16.");
  172. }
  173. setRGBs (size, r, g, b, a);
  174. setTransparentPixel (-1);
  175. checkAllGrayOpaque();
  176. }
  177. /**
  178. * Constructs an <code>IndexColorModel</code> from a single
  179. * array of interleaved red, green, blue and optional alpha
  180. * components. The array must have enough values in it to
  181. * fill all of the needed component arrays of the specified
  182. * size. The ColorSpace is the default sRGB space. The
  183. * transparency value is Transparency.TRANSLUCENT if
  184. * <code>hasAlpha</code> is <code>true</code>, Transparency.OPAQUE
  185. * otherwise. The transfer type is the smallest of
  186. * DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT
  187. * that can hold a single pixel.
  188. *
  189. * @param bits the number of bits each pixel occupies
  190. * @param size the size of the color component arrays
  191. * @param cmap the array of color components
  192. * @param start the starting offset of the first color component
  193. * @param hasalpha indicates whether alpha values are contained in
  194. * the <code>cmap</code> array
  195. * @throws IllegalArgumentException if <code>bits</code> is less
  196. * than 1 or greater than 16
  197. * @throws IllegalArgumentException if <code>size</code> is less
  198. * than 1
  199. */
  200. public IndexColorModel(int bits, int size, byte cmap[], int start,
  201. boolean hasalpha) {
  202. this(bits, size, cmap, start, hasalpha, -1);
  203. if (bits < 1 || bits > 16) {
  204. throw new IllegalArgumentException("Number of bits must be between"
  205. +" 1 and 16.");
  206. }
  207. }
  208. /**
  209. * Constructs an <code>IndexColorModel</code> from a single array of
  210. * interleaved red, green, blue and optional alpha components. The
  211. * specified transparent index represents a pixel that is considered
  212. * entirely transparent regardless of any alpha value specified
  213. * for it. The array must have enough values in it to fill all
  214. * of the needed component arrays of the specified size.
  215. * The ColorSpace is the default sRGB space. The transparency
  216. * value is Transparency.TRANSLUCENT if <code>hasAlpha</code>
  217. * is <code>true</code> otherwise it is Transparency.BITMASK
  218. * if <code>trans</code> is a valid index into the colormap
  219. * (between 0 and size - 1) or Transparency.OPAQUE if <code>trans</code>
  220. * is not a valid index. The transfer type is the smallest of
  221. * DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT
  222. * that can hold a single pixel.
  223. * @param bits the number of bits each pixel occupies
  224. * @param size the size of the color component arrays
  225. * @param cmap the array of color components
  226. * @param start the starting offset of the first color component
  227. * @param hasalpha indicates whether alpha values are contained in
  228. * the <code>cmap</code> array
  229. * @param trans the index of the fully transparent pixel
  230. * @throws IllegalArgumentException if <code>bits</code> is less than
  231. * 1 or greater than 16
  232. * @throws IllegalArgumentException if <code>size</code> is less than
  233. * 1
  234. */
  235. public IndexColorModel(int bits, int size, byte cmap[], int start,
  236. boolean hasalpha, int trans) {
  237. // REMIND: This assumes the ordering: RGB[A]
  238. super(bits, IndexColorModel.setBits(bits, hasalpha || (trans > -1)),
  239. ColorSpace.getInstance(ColorSpace.CS_sRGB),
  240. (hasalpha || (trans > -1)), false,
  241. hasalpha ? Transparency.TRANSLUCENT
  242. : (trans >= 0 ? Transparency.BITMASK
  243. : Transparency.OPAQUE),
  244. ColorModel.getDefaultTransferType(bits));
  245. if (bits < 1 || bits > 16) {
  246. throw new IllegalArgumentException("Number of bits must be between"
  247. +" 1 and 16.");
  248. }
  249. if (size < 1) {
  250. throw new IllegalArgumentException("Map size ("+size+
  251. ") must be >= 1");
  252. }
  253. map_size = size;
  254. rgb = new int[Math.max(size, 256)];
  255. int j = start;
  256. int alpha = 0xff;
  257. transparency = OPAQUE;
  258. for (int i = 0; i < size; i++) {
  259. rgb[i] = ((cmap[j++] & 0xff) << 16)
  260. | ((cmap[j++] & 0xff) << 8)
  261. | (cmap[j++] & 0xff);
  262. if (hasalpha) {
  263. alpha = cmap[j++];
  264. if (alpha != 0xff && transparency != TRANSLUCENT) {
  265. transparency = (alpha == 0x0
  266. ? BITMASK
  267. : TRANSLUCENT);
  268. }
  269. }
  270. rgb[i] |= (alpha << 24);
  271. }
  272. setTransparentPixel(trans);
  273. if (transparent_index >= 0) {
  274. if (transparency == OPAQUE) {
  275. transparency = BITMASK;
  276. }
  277. }
  278. else if (transparency == OPAQUE) {
  279. // Force it in case transparent_index was invalid
  280. supportsAlpha = false;
  281. numComponents = 3;
  282. }
  283. if (supportsAlpha) {
  284. nBits = new int[4];
  285. nBits[0] = nBits[1] = nBits[2] = nBits[3] = 8;
  286. }
  287. else {
  288. if (transparent_index > -1) {
  289. nBits = new int[4];
  290. nBits[3] = 1;
  291. }
  292. else {
  293. nBits = new int[3];
  294. }
  295. nBits[0] = nBits[1] = nBits[2] = 8;
  296. }
  297. checkAllGrayOpaque();
  298. }
  299. /**
  300. * Constructs an <code>IndexColorModel</code> from an array of
  301. * ints where each int is comprised of red, green, blue, and
  302. * optional alpha components in the default RGB color model format.
  303. * The specified transparent index represents a pixel that is considered
  304. * entirely transparent regardless of any alpha value specified
  305. * for it. The array must have enough values in it to fill all
  306. * of the needed component arrays of the specified size.
  307. * The ColorSpace is the default sRGB space. The transparency
  308. * value is Transparency.TRANSLUCENT if <code>hasAlpha</code> is
  309. * <code>true</code> otherwise it is Transparency.BITMASK if
  310. * <code>trans</code> is a valid index into the colormap
  311. * (between 0 and size - 1) or Transparency.OPAQUE if
  312. * <code>trans</code> is not a valid index.
  313. * @param bits the number of bits each pixel occupies
  314. * @param size the size of the color component arrays
  315. * @param cmap the array of color components
  316. * @param start the starting offset of the first color component
  317. * @param hasalpha indicates whether alpha values are contained in
  318. * the <code>cmap</code> array
  319. * @param trans the index of the fully transparent pixel
  320. * @param transferType the data type of the array used to represent
  321. * pixel values. The data type must be either
  322. * <code>DataBuffer.TYPE_BYTE</code> or
  323. * <code>DataBuffer.TYPE_USHORT</code>.
  324. * @throws IllegalArgumentException if <code>bits</code> is less
  325. * than 1 or greater than 16
  326. * @throws IllegalArgumentException if <code>size</code> is less
  327. * than 1
  328. */
  329. public IndexColorModel(int bits, int size,
  330. int cmap[], int start,
  331. boolean hasalpha, int trans, int transferType) {
  332. // REMIND: This assumes the ordering: RGB[A]
  333. super(bits, IndexColorModel.setBits(bits, hasalpha),
  334. ColorSpace.getInstance(ColorSpace.CS_sRGB),
  335. hasalpha ? true : (trans >= 0 ? true : false),
  336. false,
  337. hasalpha ? Transparency.TRANSLUCENT
  338. : (trans >= 0 ? Transparency.BITMASK
  339. : Transparency.OPAQUE),
  340. transferType);
  341. if (bits < 1 || bits > 16) {
  342. throw new IllegalArgumentException("Number of bits must be between"
  343. +" 1 and 16.");
  344. }
  345. if (size < 1) {
  346. throw new IllegalArgumentException("Map size ("+size+
  347. ") must be >= 1");
  348. }
  349. map_size = size;
  350. rgb = new int[Math.max(size, 256)];
  351. int j = start;
  352. int alpha = 0xff000000;
  353. transparency = OPAQUE;
  354. if (!hasalpha) {
  355. // Need to make sure that the alpha is 0xff
  356. for (int i=0; i < size; i++, j++) {
  357. rgb[i] = cmap[j] | 0xff000000;
  358. }
  359. }
  360. else {
  361. for (int i = 0; i < size; i++, j++) {
  362. rgb[i] = cmap[j];
  363. alpha = cmap[j] & 0xff000000;
  364. if (alpha != 0xff000000 && transparency != TRANSLUCENT) {
  365. transparency = (alpha == 0x0
  366. ? BITMASK
  367. : TRANSLUCENT);
  368. }
  369. }
  370. }
  371. setTransparentPixel(trans);
  372. if (transparent_index >= 0) {
  373. if (transparency == OPAQUE) {
  374. transparency = BITMASK;
  375. }
  376. }
  377. checkAllGrayOpaque();
  378. }
  379. /**
  380. * Constructs an <code>IndexColorModel</code> from an
  381. * <code>int</code> array where each <code>int</code> is
  382. * comprised of red, green, blue, and alpha
  383. * components in the default RGB color model format.
  384. * The array must have enough values in it to fill all
  385. * of the needed component arrays of the specified size.
  386. * The <code>ColorSpace</code> is the default sRGB space.
  387. * The transfer type is the smallest of
  388. * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
  389. * that can hold a single pixel.
  390. * The <code>BigInteger</code> object specifies the valid/invalid pixels
  391. * in the <code>cmap</code> array. A pixel is valid if the
  392. * <code>BigInteger</code> value at that index is set, and is invalid
  393. * if the <code>BigInteger</code> bit at that index is not set.
  394. * @param bits the number of bits each pixel occupies
  395. * @param size the size of the color component array
  396. * @param cmap the array of color components
  397. * @param start the starting offset of the first color component
  398. * @param transferType the specified data type
  399. * @param validBits a <code>BigInteger</code> object. If a bit is
  400. * set in the BigInteger, the pixel at that index is valid.
  401. * If a bit is not set, the pixel at that index
  402. * is considered invalid. If null, all pixels are valid.
  403. * Only bits from 0 to map_size will be considered.
  404. *
  405. */
  406. public IndexColorModel(int bits, int size, int cmap[], int start,
  407. int transferType, BigInteger validBits) {
  408. super (bits, IndexColorModel.setBits(bits, true),
  409. ColorSpace.getInstance(ColorSpace.CS_sRGB),
  410. true, false, Transparency.TRANSLUCENT,
  411. transferType);
  412. if (bits < 1 || bits > 32) {
  413. throw new IllegalArgumentException("Number of bits must be between"
  414. +" 1 and 32.");
  415. }
  416. if (size < 1) {
  417. throw new IllegalArgumentException("Map size ("+size+
  418. ") must be >= 1");
  419. }
  420. map_size = size;
  421. if (validBits != null) {
  422. // Check to see if it is all valid
  423. for (int i=0; i < size; i++) {
  424. if (!validBits.testBit(i)) {
  425. this.validBits = validBits;
  426. break;
  427. }
  428. }
  429. }
  430. rgb = new int[Math.max(size, 256)];
  431. int j = start;
  432. int alpha;
  433. transparency = OPAQUE;
  434. for (int i = 0; i < size; i++, j++) {
  435. rgb[i] = cmap[j];
  436. alpha = cmap[j] & 0xff000000;
  437. if (alpha != 0xff000000 && transparency != TRANSLUCENT) {
  438. transparency = (alpha == 0x0
  439. ? BITMASK
  440. : TRANSLUCENT);
  441. }
  442. }
  443. checkAllGrayOpaque();
  444. }
  445. private void setRGBs(int size, byte r[], byte g[], byte b[], byte a[]) {
  446. if (size < 1) {
  447. throw new IllegalArgumentException("Map size ("+size+
  448. ") must be >= 1");
  449. }
  450. map_size = size;
  451. rgb = new int[Math.max(size, 256)];
  452. int alpha = 0xff;
  453. transparency = OPAQUE;
  454. for (int i = 0; i < size; i++) {
  455. if (a != null) {
  456. alpha = (a[i] & 0xff);
  457. if (alpha != 0xff && transparency != TRANSLUCENT) {
  458. transparency = (alpha == 0x0
  459. ? BITMASK
  460. : TRANSLUCENT);
  461. }
  462. }
  463. rgb[i] = (alpha << 24)
  464. | ((r[i] & 0xff) << 16)
  465. | ((g[i] & 0xff) << 8)
  466. | (b[i] & 0xff);
  467. }
  468. nBits = new int[4];
  469. nBits[0] = nBits[1] = nBits[2] = nBits[3] = 8;
  470. maxBits = 8;
  471. }
  472. private BigInteger getAllValid() {
  473. BigInteger validBits;
  474. int numbytes = (map_size+7)/8;
  475. byte[] valid = new byte[numbytes];
  476. java.util.Arrays.fill(valid, (byte)0xff);
  477. valid[0] = (byte)(0xff >>> (numbytes*8 - map_size));
  478. return new BigInteger(1, valid);
  479. }
  480. private void checkAllGrayOpaque() {
  481. int c;
  482. allgrayopaque = false;
  483. if ((transparent_index >= 0) || (transparency == TRANSLUCENT)) {
  484. return;
  485. }
  486. for (int i = 0; i < map_size; i++) {
  487. c = rgb[i];
  488. if (c == 0x0) {
  489. /* ignore transparent black */
  490. continue;
  491. }
  492. if ((c & 0xff000000) != 0xff000000) {
  493. return;
  494. }
  495. if ((((c >> 16) & 0xff) != ((c >> 8) & 0xff)) ||
  496. (((c >> 8) & 0xff) != (c & 0xff))) {
  497. return;
  498. }
  499. }
  500. allgrayopaque = true;
  501. transparency = OPAQUE;
  502. }
  503. /**
  504. * Returns the transparency. Returns either OPAQUE, BITMASK,
  505. * or TRANSLUCENT
  506. * @return the transparency of this <code>IndexColorModel</code>
  507. * @see Transparency#OPAQUE
  508. * @see Transparency#BITMASK
  509. * @see Transparency#TRANSLUCENT
  510. */
  511. public int getTransparency() {
  512. return transparency;
  513. }
  514. /**
  515. * Returns an array of the number of bits for each color/alpha component.
  516. * The array contains the color components in the order red, green,
  517. * blue, followed by the alpha component, if present.
  518. * @return an array containing the number of bits of each color
  519. * and alpha component of this <code>IndexColorModel</code>
  520. */
  521. public int[] getComponentSize() {
  522. if (nBits == null) {
  523. if (supportsAlpha) {
  524. nBits = new int[4];
  525. nBits[3] = 8;
  526. }
  527. else {
  528. nBits = new int[3];
  529. }
  530. nBits[0] = nBits[1] = nBits[2] = 8;
  531. }
  532. return nBits;
  533. }
  534. /**
  535. * Returns the size of the color/alpha component arrays in this
  536. * <code>IndexColorModel</code>.
  537. * @return the size of the color and alpha component arrays.
  538. */
  539. final public int getMapSize() {
  540. return map_size;
  541. }
  542. /**
  543. * Returns the index of the transparent pixel in this
  544. * <code>IndexColorModel</code> or -1 if there is no transparent pixel.
  545. * @return the index of this <code>IndexColorModel</code> object's
  546. * transparent pixel, or -1 if there is no such pixel.
  547. */
  548. final public int getTransparentPixel() {
  549. return transparent_index;
  550. }
  551. /**
  552. * Copies the array of red color components into the specified array.
  553. * Only the initial entries of the array as specified by
  554. * {@link #getMapSize() getMapSize} are written.
  555. * @param r the specified array into which the elements of the
  556. * array of red color components are copied
  557. */
  558. final public void getReds(byte r[]) {
  559. for (int i = 0; i < map_size; i++) {
  560. r[i] = (byte) (rgb[i] >> 16);
  561. }
  562. }
  563. /**
  564. * Copies the array of green color components into the specified array.
  565. * Only the initial entries of the array as specified by
  566. * <code>getMapSize</code> are written.
  567. * @param g the specified array into which the elements of the
  568. * array of green color components are copied
  569. */
  570. final public void getGreens(byte g[]) {
  571. for (int i = 0; i < map_size; i++) {
  572. g[i] = (byte) (rgb[i] >> 8);
  573. }
  574. }
  575. /**
  576. * Copies the array of blue color components into the specified array.
  577. * Only the initial entries of the array as specified by
  578. * <code>getMapSize</code> are written.
  579. * @param b the specified array into which the elements of the
  580. * array of blue color components are copied
  581. */
  582. final public void getBlues(byte b[]) {
  583. for (int i = 0; i < map_size; i++) {
  584. b[i] = (byte) rgb[i];
  585. }
  586. }
  587. /**
  588. * Copies the array of alpha transparency components into the
  589. * specified array. Only the initial entries of the array as specified
  590. * by <code>getMapSize</code> are written.
  591. * @param a the specified array into which the elements of the
  592. * array of alpha components are copied
  593. */
  594. final public void getAlphas(byte a[]) {
  595. for (int i = 0; i < map_size; i++) {
  596. a[i] = (byte) (rgb[i] >> 24);
  597. }
  598. }
  599. /**
  600. * Converts data for each index from the color and alpha component
  601. * arrays to an int in the default RGB ColorModel format and copies
  602. * the resulting 32-bit ARGB values into the specified array. Only
  603. * the initial entries of the array as specified by
  604. * <code>getMapSize</code> are
  605. * written.
  606. * @param rgb the specified array into which the converted ARGB
  607. * values from this array of color and alpha components
  608. * are copied.
  609. */
  610. final public void getRGBs(int rgb[]) {
  611. System.arraycopy(this.rgb, 0, rgb, 0, map_size);
  612. }
  613. private void setTransparentPixel(int trans) {
  614. if (trans >= map_size || trans < 0) {
  615. trans = -1;
  616. } else {
  617. rgb[trans] &= 0x00ffffff;
  618. }
  619. transparent_index = trans;
  620. }
  621. /**
  622. * Returns the red color component for the specified pixel, scaled
  623. * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
  624. * is specified as an int. The returned value is a
  625. * non pre-multiplied value.
  626. * @param pixel the specified pixel
  627. * @return the value of the red color component for the specified pixel
  628. */
  629. final public int getRed(int pixel) {
  630. return (rgb[pixel] >> 16) & 0xff;
  631. }
  632. /**
  633. * Returns the green color component for the specified pixel, scaled
  634. * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
  635. * is specified as an int. The returned value is a
  636. * non pre-multiplied value.
  637. * @param pixel the specified pixel
  638. * @return the value of the green color component for the specified pixel
  639. */
  640. final public int getGreen(int pixel) {
  641. return (rgb[pixel] >> 8) & 0xff;
  642. }
  643. /**
  644. * Returns the blue color component for the specified pixel, scaled
  645. * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
  646. * is specified as an int. The returned value is a
  647. * non pre-multiplied value.
  648. * @param pixel the specified pixel
  649. * @return the value of the blue color component for the specified pixel
  650. */
  651. final public int getBlue(int pixel) {
  652. return rgb[pixel] & 0xff;
  653. }
  654. /**
  655. * Returns the alpha component for the specified pixel, scaled
  656. * from 0 to 255. The pixel value is specified as an int.
  657. * @param pixel the specified pixel
  658. * @return the value of the alpha component for the specified pixel
  659. */
  660. final public int getAlpha(int pixel) {
  661. return (rgb[pixel] >> 24) & 0xff;
  662. }
  663. /**
  664. * Returns the color/alpha components of the pixel in the default
  665. * RGB color model format. The pixel value is specified as an int.
  666. * The returned value is in a non pre-multiplied format.
  667. * @param pixel the specified pixel
  668. * @return the color and alpha components of the specified pixel
  669. * @see ColorModel#getRGBdefault
  670. */
  671. final public int getRGB(int pixel) {
  672. return rgb[pixel];
  673. }
  674. private static final int CACHESIZE = 40;
  675. private int lookupcache[] = new int[CACHESIZE];
  676. /**
  677. * Returns a data element array representation of a pixel in this
  678. * ColorModel, given an integer pixel representation in the
  679. * default RGB color model. This array can then be passed to the
  680. * {@link WritableRaster#setDataElements(int, int, java.lang.Object) setDataElements}
  681. * method of a {@link WritableRaster} object. If the pixel variable is
  682. * <code>null</code>, a new array is allocated. If <code>pixel</code>
  683. * is not <code>null</code>, it must be
  684. * a primitive array of type <code>transferType</code> otherwise, a
  685. * <code>ClassCastException</code> is thrown. An
  686. * <code>ArrayIndexOutOfBoundsException</code> is
  687. * thrown if <code>pixel</code> is not large enough to hold a pixel
  688. * value for this <code>ColorModel</code>. The pixel array is returned.
  689. * <p>
  690. * Since <code>IndexColorModel</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
  693. * unsupported <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>IndexColorModel</code>.
  700. * @throws ClassCastException if <code>pixel</code>
  701. * is not a primitive array of type <code>transferType</code>
  702. * @throws ArrayIndexOutOfBoundsException if
  703. * <code>pixel</code> is not large enough to hold a pixel value
  704. * for this <code>ColorModel</code>
  705. * @throws UnsupportedOperationException if <code>transferType</code>
  706. * is invalid
  707. * @see WritableRaster#setDataElements
  708. * @see SampleModel#setDataElements
  709. */
  710. public synchronized Object getDataElements(int rgb, Object pixel) {
  711. int red = (rgb>>16) & 0xff;
  712. int green = (rgb>>8) & 0xff;
  713. int blue = rgb & 0xff;
  714. int alpha = (rgb>>>24);
  715. int pix = 0;
  716. for (int i = CACHESIZE - 2; i >= 0; i -= 2) {
  717. if ((pix = lookupcache[i]) == 0) {
  718. break;
  719. }
  720. if (rgb == lookupcache[i+1]) {
  721. return installpixel(pixel, ~pix);
  722. }
  723. }
  724. if (alpha == 0) {
  725. // Look for another transparent pixel
  726. if (transparent_index > -1) {
  727. pix = transparent_index;
  728. }
  729. else {
  730. // Search for one
  731. for (int i=0; i < map_size; i++) {
  732. if (this.rgb[i] < (1 << 24)) {
  733. transparent_index = i;
  734. pix = i;
  735. break;
  736. }
  737. }
  738. }
  739. } else {
  740. // a heuristic which says find the closest color,
  741. // after finding the closest alpha
  742. // if user wants different behavior, they can derive
  743. // a class and override this method
  744. // SLOW --- but accurate
  745. // REMIND - need a native implementation, and inverse color-map
  746. int smallestError = 255 * 255 * 255; // largest possible
  747. int smallestAlphaError = 255;
  748. if (false && red == green && green == blue) {
  749. // Grayscale
  750. }
  751. for (int i=0; i < map_size; i++) {
  752. int lutrgb = this.rgb[i];
  753. if (lutrgb == rgb) {
  754. pix = i;
  755. break;
  756. }
  757. int tmp = (lutrgb>>>24) - alpha;
  758. if (tmp < 0) {
  759. tmp = -tmp;
  760. }
  761. if (tmp <= smallestAlphaError) {
  762. smallestAlphaError = tmp;
  763. tmp = ((lutrgb>>16) & 0xff) - red;
  764. int currentError = tmp * tmp;
  765. if (currentError < smallestError) {
  766. tmp = ((lutrgb>>8) & 0xff) - green;
  767. currentError += tmp * tmp;
  768. if (currentError < smallestError) {
  769. tmp = (lutrgb & 0xff) - blue;
  770. currentError += tmp * tmp;
  771. if (currentError < smallestError) {
  772. pix = i;
  773. smallestError = currentError;
  774. }
  775. }
  776. }
  777. }
  778. }
  779. }
  780. System.arraycopy(lookupcache, 2, lookupcache, 0, CACHESIZE - 2);
  781. lookupcache[CACHESIZE - 1] = rgb;
  782. lookupcache[CACHESIZE - 2] = ~pix;
  783. return installpixel(pixel, pix);
  784. }
  785. private Object installpixel(Object pixel, int pix) {
  786. switch (transferType) {
  787. case DataBuffer.TYPE_INT:
  788. int[] intObj;
  789. if (pixel == null) {
  790. pixel = intObj = new int[1];
  791. } else {
  792. intObj = (int[]) pixel;
  793. }
  794. intObj[0] = pix;
  795. break;
  796. case DataBuffer.TYPE_BYTE:
  797. byte[] byteObj;
  798. if (pixel == null) {
  799. pixel = byteObj = new byte[1];
  800. } else {
  801. byteObj = (byte[]) pixel;
  802. }
  803. byteObj[0] = (byte) pix;
  804. break;
  805. case DataBuffer.TYPE_USHORT:
  806. short[] shortObj;
  807. if (pixel == null) {
  808. pixel = shortObj = new short[1];
  809. } else {
  810. shortObj = (short[]) pixel;
  811. }
  812. shortObj[0] = (short) pix;
  813. break;
  814. default:
  815. throw new UnsupportedOperationException("This method has not been "+
  816. "implemented for transferType " + transferType);
  817. }
  818. return pixel;
  819. }
  820. /**
  821. * Returns an array of unnormalized color/alpha components for a
  822. * specified pixel in this <code>ColorModel</code>. The pixel value
  823. * is specified as an int. If the components array is <code>null</code>,
  824. * a new array is allocated. The components array is returned.
  825. * Color/alpha components are stored in the components array starting
  826. * at <code>offset</code> even if the array is allocated by this method.
  827. * An <code>ArrayIndexOutOfBoundsException</code>
  828. * is thrown if the components array is not <code>null</code> and is
  829. * not large enough to hold all the color and alpha components
  830. * starting at <code>offset</code>.
  831. * @param pixel the specified pixel
  832. * @param components the array to receive the color and alpha
  833. * components of the specified pixel
  834. * @param offset the offset into the <code>components</code> array at
  835. * which to start storing the color and alpha components
  836. * @return an array containing the color and alpha components of the
  837. * specified pixel starting at the specified offset.
  838. */
  839. public int[] getComponents(int pixel, int[] components, int offset) {
  840. if (components == null) {
  841. components = new int[offset+numComponents];
  842. }
  843. // REMIND: Needs to change if different color space
  844. components[offset+0] = getRed(pixel);
  845. components[offset+1] = getGreen(pixel);
  846. components[offset+2] = getBlue(pixel);
  847. if (supportsAlpha && (components.length-offset) > 3) {
  848. components[offset+3] = getAlpha(pixel);
  849. }
  850. return components;
  851. }
  852. /**
  853. * Returns an array of unnormalized color/alpha components for
  854. * a specified pixel in this <code>ColorModel</code>. The pixel
  855. * value is specified by an array of data elements of type
  856. * <code>transferType</code> passed in as an object reference.
  857. * If <code>pixel</code> is not a primitive array of type
  858. * <code>transferType</code>, a <code>ClassCastException</code>
  859. * is thrown. An <code>ArrayIndexOutOfBoundsException</code>
  860. * is thrown if <code>pixel</code> is not large enough to hold
  861. * a pixel value for this <code>ColorModel</code>. If the
  862. * <code>components</code> array is <code>null</code>, a new array
  863. * is allocated. The <code>components</code> array is returned.
  864. * Color/alpha components are stored in the <code>components</code>
  865. * array starting at <code>offset</code> even if the array is
  866. * allocated by this method. An
  867. * <code>ArrayIndexOutOfBoundsException</code> is also
  868. * thrown if the <code>components</code> array is not
  869. * <code>null</code> and is not large enough to hold all the color
  870. * and alpha components starting at <code>offset</code>.
  871. * <p>
  872. * Since <code>IndexColorModel</code> can be subclassed, subclasses
  873. * inherit the implementation of this method and if they don't
  874. * override it then they throw an exception if they use an
  875. * unsupported <code>transferType</code>.
  876. *
  877. * @param pixel the specified pixel
  878. * @param components an array that receives the color and alpha
  879. * components of the specified pixel
  880. * @param offset the index into the <code>components</code> array at
  881. * which to begin storing the color and alpha components of the
  882. * specified pixel
  883. * @return an array containing the color and alpha components of the
  884. * specified pixel starting at the specified offset.
  885. * @throws ArrayIndexOutOfBoundsException if <code>pixel</code>
  886. * is not large enough to hold a pixel value for this
  887. * <code>ColorModel</code> or if the
  888. * <code>components</code> array is not <code>null</code>
  889. * and is not large enough to hold all the color
  890. * and alpha components starting at <code>offset</code>
  891. * @throws ClassCastException if <code>pixel</code> is not a
  892. * primitive array of type <code>transferType</code>
  893. * @throws UnsupportedOperationException if <code>transferType</code>
  894. * is not one of the supported transer types
  895. */
  896. public int[] getComponents(Object pixel, int[] components, int offset) {
  897. int intpixel;
  898. switch (transferType) {
  899. case DataBuffer.TYPE_BYTE:
  900. byte bdata[] = (byte[])pixel;
  901. intpixel = bdata[0] & 0xff;
  902. break;
  903. case DataBuffer.TYPE_USHORT:
  904. short sdata[] = (short[])pixel;
  905. intpixel = sdata[0] & 0xffff;
  906. break;
  907. case DataBuffer.TYPE_INT:
  908. int idata[] = (int[])pixel;
  909. intpixel = idata[0];
  910. break;
  911. default:
  912. throw new UnsupportedOperationException("This method has not been "+
  913. "implemented for transferType " + transferType);
  914. }
  915. return getComponents(intpixel, components, offset);
  916. }
  917. /**
  918. * Returns a pixel value represented as an int in this
  919. * <code>ColorModel</code> given an array of unnormalized
  920. * color/alpha components. An
  921. * <code>ArrayIndexOutOfBoundsException</code>
  922. * is thrown if the <code>components</code> array is not large
  923. * enough to hold all of the color and alpha components starting
  924. * at <code>offset</code>. Since
  925. * <code>ColorModel</code> can be subclassed, subclasses inherit the
  926. * implementation of this method and if they don't override it then
  927. * they throw an exception if they use an unsupported transferType.
  928. * @param components an array of unnormalized color and alpha
  929. * components
  930. * @param offset the index into <code>components</code> at which to
  931. * begin retrieving the color and alpha components
  932. * @return an <code>int</code> pixel value in this
  933. * <code>ColorModel</code> corresponding to the specified components.
  934. * @throws ArrayIndexOutOfBoundsException if
  935. * the <code>components</code> array is not large enough to
  936. * hold all of the color and alpha components starting at
  937. * <code>offset</code>
  938. * @throws UnsupportedOperationException if <code>transferType</code>
  939. * is invalid
  940. */
  941. public int getDataElement(int[] components, int offset) {
  942. int rgb = (components[offset+0]<<16)
  943. | (components[offset+1]<<8) | (components[offset+2]);
  944. if (supportsAlpha) {
  945. rgb |= (components[offset+3]<<24);
  946. }
  947. else {
  948. rgb |= 0xff000000;
  949. }
  950. Object inData = getDataElements(rgb, null);
  951. int pixel;
  952. switch (transferType) {
  953. case DataBuffer.TYPE_BYTE:
  954. byte bdata[] = (byte[])inData;
  955. pixel = bdata[0] & 0xff;
  956. break;
  957. case DataBuffer.TYPE_USHORT:
  958. short sdata[] = (short[])inData;
  959. pixel = sdata[0];
  960. break;
  961. case DataBuffer.TYPE_INT:
  962. int idata[] = (int[])inData;
  963. pixel = idata[0];
  964. break;
  965. default:
  966. throw new UnsupportedOperationException("This method has not been "+
  967. "implemented for transferType " + transferType);
  968. }
  969. return pixel;
  970. }
  971. /**
  972. * Returns a data element array representation of a pixel in this
  973. * <code>ColorModel</code> given an array of unnormalized color/alpha
  974. * components. This array can then be passed to the
  975. * <code>setDataElements</code> method of a <code>WritableRaster</code>
  976. * object. An <code>ArrayIndexOutOfBoundsException</code> is
  977. * thrown if the
  978. * <code>components</code> array is not large enough to hold all of the
  979. * color and alpha components starting at <code>offset</code>.
  980. * If the pixel variable is <code>null</code>, a new array
  981. * is allocated. If <code>pixel</code> is not <code>null</code>,
  982. * it must be a primitive array of type <code>transferType</code>
  983. * otherwise, a <code>ClassCastException</code> is thrown.
  984. * An <code>ArrayIndexOutOfBoundsException</code> is thrown if pixel
  985. * is not large enough to hold a pixel value for this
  986. * <code>ColorModel</code>.
  987. * <p>
  988. * Since <code>IndexColorModel</code> can be subclassed, subclasses
  989. * inherit the implementation of this method and if they don't
  990. * override it then they throw an exception if they use an
  991. * unsupported <code>transferType</code>
  992. *
  993. * @param components an array of unnormalized color and alpha
  994. * components
  995. * @param offset the index into <code>components</code> at which to
  996. * begin retrieving color and alpha components
  997. * @param pixel the <code>Object</code> representing an array of color
  998. * and alpha components
  999. * @return an <code>Object</code> representing an array of color and
  1000. * alpha components.
  1001. * @throws ClassCastException if <code>pixel</code>
  1002. * is not a primitive array of type <code>transferType</code>
  1003. * @throws ArrayIndexOutOfBoundsException if
  1004. * <code>pixel</code> is not large enough to hold a pixel value
  1005. * for this <code>ColorModel</code> or the <code>components</code>
  1006. * array is not large enough to hold all of the color and alpha
  1007. * components starting at <code>offset</code>
  1008. * @throws UnsupportedOperationException if <code>transferType</code>
  1009. * is not one of the supported transer types
  1010. * @see WritableRaster#setDataElements
  1011. * @see SampleModel#setDataElements
  1012. */
  1013. public Object getDataElements(int[] components, int offset, Object pixel) {
  1014. int rgb = (components[offset+0]<<16) | (components[offset+1]<<8)
  1015. | (components[offset+2]);
  1016. if (supportsAlpha) {
  1017. rgb |= (components[offset+3]<<24);
  1018. }
  1019. else {
  1020. rgb &= 0xff000000;
  1021. }
  1022. return getDataElements(rgb, pixel);
  1023. }
  1024. /**
  1025. * Creates a <code>WritableRaster</code> with the specified width
  1026. * and height that has a data layout (<code>SampleModel</code>)
  1027. * compatible with this <code>ColorModel</code>. This method
  1028. * only works for color models with 16 or fewer bits per pixel.
  1029. * <p>
  1030. * Since <code>IndexColorModel</code> can be subclassed, any
  1031. * subclass that supports greater than 16 bits per pixel must
  1032. * override this method.
  1033. *
  1034. * @param w the width to apply to the new <code>WritableRaster</code>
  1035. * @param h the height to apply to the new <code>WritableRaster</code>
  1036. * @return a <code>WritableRaster</code> object with the specified
  1037. * width and height.
  1038. * @throws UnsupportedOperationException if the number of bits in a
  1039. * pixel is greater than 16
  1040. * @see WritableRaster
  1041. * @see SampleModel
  1042. */
  1043. public WritableRaster createCompatibleWritableRaster(int w, int h) {
  1044. WritableRaster raster;
  1045. if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
  1046. // TYPE_BINARY
  1047. raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
  1048. w, h, 1, pixel_bits, null);
  1049. }
  1050. else if (pixel_bits <= 8) {
  1051. raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
  1052. w,h,1,null);
  1053. }
  1054. else if (pixel_bits <= 16) {
  1055. raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT,
  1056. w,h,1,null);
  1057. }
  1058. else {
  1059. throw new
  1060. UnsupportedOperationException("This method is not supported "+
  1061. " for pixel bits > 16.");
  1062. }
  1063. return raster;
  1064. }
  1065. /**
  1066. * Returns <code>true</code> if <code>raster</code> is compatible
  1067. * with this <code>ColorModel</code> or <code>false</code> if it
  1068. * is not compatible with this <code>ColorModel</code>.
  1069. * @param raster the {@link Raster} object to test for compatibility
  1070. * @return <code>true</code> if <code>raster</code> is compatible
  1071. * with this <code>ColorModel</code> <code>false</code> otherwise.
  1072. *
  1073. */
  1074. public boolean isCompatibleRaster(Raster raster) {
  1075. int size = raster.getSampleModel().getSampleSize(0);
  1076. return ((raster.getTransferType() == transferType) &&
  1077. (raster.getNumBands() == 1) && ((1 << size) >= map_size));
  1078. }
  1079. /**
  1080. * Creates a <code>SampleModel</code> with the specified
  1081. * width and height that has a data layout compatible with
  1082. * this <code>ColorModel</code>.
  1083. * @param w the width to apply to the new <code>SampleModel</code>
  1084. * @param h the height to apply to the new <code>SampleModel</code>
  1085. * @return a <code>SampleModel</code> object with the specified
  1086. * width and height.
  1087. * @throws IllegalArgumentException if <code>w</code> or
  1088. * <code>h</code> is not greater than 0
  1089. * @see SampleModel
  1090. */
  1091. public SampleModel createCompatibleSampleModel(int w, int h) {
  1092. int[] off = new int[1];
  1093. off[0] = 0;
  1094. if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
  1095. return new MultiPixelPackedSampleModel(transferType, w, h,
  1096. pixel_bits);
  1097. }
  1098. else {
  1099. return new ComponentSampleModel(transferType, w, h, 1, w,
  1100. off);
  1101. }
  1102. }
  1103. /**
  1104. * Checks if the specified <code>SampleModel</code> is compatible
  1105. * with this <code>ColorModel</code>. If <code>sm</code> is
  1106. * <code>null</code>, this method returns <code>false</code>.
  1107. * @param sm the specified <code>SampleModel</code>,
  1108. * or <code>null</code>
  1109. * @return <code>true</code> if the specified <code>SampleModel</code>
  1110. * is compatible with this <code>ColorModel</code> <code>false</code>
  1111. * otherwise.
  1112. * @see SampleModel
  1113. */
  1114. public boolean isCompatibleSampleModel(SampleModel sm) {
  1115. // fix 4238629
  1116. if (! (sm instanceof ComponentSampleModel) &&
  1117. ! (sm instanceof MultiPixelPackedSampleModel) ) {
  1118. return false;
  1119. }
  1120. // Transfer type must be the same
  1121. if (sm.getTransferType() != transferType) {
  1122. return false;
  1123. }
  1124. if (sm.getNumBands() != 1) {
  1125. return false;
  1126. }
  1127. return true;
  1128. }
  1129. /**
  1130. * Returns a new <code>BufferedImage</code> of TYPE_INT_ARGB or
  1131. * TYPE_INT_RGB that has a <code>Raster</code> with pixel data
  1132. * computed by expanding the indices in the source <code>Raster</code>
  1133. * using the color/alpha component arrays of this <code>ColorModel</code>.
  1134. * If <code>forceARGB</code> is <code>true</code>, a TYPE_INT_ARGB image is
  1135. * returned regardless of whether or not this <code>ColorModel</code>
  1136. * has an alpha component array or a transparent pixel.
  1137. * @param raster the specified <code>Raster</code>
  1138. * @param forceARGB if <code>true</code>, the returned
  1139. * <code>BufferedImage</code> is TYPE_INT_ARGB; otherwise it is
  1140. * TYPE_INT_RGB
  1141. * @return a <code>BufferedImage</code> created with the specified
  1142. * <code>Raster</code>
  1143. */
  1144. public BufferedImage convertToIntDiscrete(Raster raster,
  1145. boolean forceARGB) {
  1146. ColorModel cm;
  1147. if (forceARGB || transparency == TRANSLUCENT) {
  1148. cm = ColorModel.getRGBdefault();
  1149. }
  1150. else if (transparency == BITMASK) {
  1151. cm = new DirectColorModel(25, 0xff0000, 0x00ff00, 0x0000ff,
  1152. 0x1000000);
  1153. }
  1154. else {
  1155. cm = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff);
  1156. }
  1157. int w = raster.getWidth();
  1158. int h = raster.getHeight();
  1159. WritableRaster discreteRaster =
  1160. cm.createCompatibleWritableRaster(w, h);
  1161. Object obj = null;
  1162. int[] data = null;
  1163. int rX = raster.getMinX();
  1164. int rY = raster.getMinY();
  1165. for (int y=0; y < h; y++, rY++) {
  1166. obj = raster.getDataElements(rX, rY, w, 1, obj);
  1167. if (obj instanceof int[]) {
  1168. data = (int[])obj;
  1169. } else {
  1170. data = DataBuffer.toIntArray(obj);
  1171. }
  1172. for (int x=0; x < w; x++) {
  1173. data[x] = rgb[data[x]];
  1174. }
  1175. discreteRaster.setDataElements(0, y, w, 1, data);
  1176. }
  1177. return new BufferedImage(cm, discreteRaster, false, null);
  1178. }
  1179. /**
  1180. * Returns whether or not the pixel is valid.
  1181. * @param pixel the specified pixel value
  1182. * @return <code>true</code> if <code>pixel</code>
  1183. * is valid; <code>false</code> otherwise.
  1184. */
  1185. public boolean isValid(int pixel) {
  1186. if (validBits == null) {
  1187. return (pixel >= 0 && pixel < map_size);
  1188. }
  1189. else {
  1190. return (pixel < map_size && validBits.testBit(pixel));
  1191. }
  1192. }
  1193. /**
  1194. * Returns whether or not all of the pixels are valid.
  1195. * @return <code>true</code> if all pixels are valid;
  1196. * <code>false</code> otherwise.
  1197. */
  1198. public boolean isValid() {
  1199. return (validBits == null);
  1200. }
  1201. /**
  1202. * Returns a <code>BigInteger</code> that indicates the valid/invalid
  1203. * pixels in the colormap. A bit is valid if the
  1204. * <code>BigInteger</code> value at that index is set, and is invalid
  1205. * if the <code>BigInteger</code> value at that index is not set.
  1206. * The only valid ranges to query in the <code>BigInteger</code> are
  1207. * between 0 and map_size.
  1208. * @return a <code>BigInteger</code> indicating the valid/invalid pixels.
  1209. */
  1210. public BigInteger getValidPixels() {
  1211. if (validBits == null) {
  1212. return getAllValid();
  1213. }
  1214. else {
  1215. return validBits;
  1216. }
  1217. }
  1218. private static int[] setBits(int bits, boolean hasAlpha) {
  1219. int[] b = new int[3+(hasAlpha ? 1 : 0)];
  1220. b[0] = b[1] = b[2] = 8;
  1221. if (hasAlpha) {
  1222. b[3] = 8;
  1223. }
  1224. return b;
  1225. }
  1226. /**
  1227. * Disposes of system resources associated with this
  1228. * <code>ColorModel</code> once this <code>ColorModel</code> is no
  1229. * longer referenced.
  1230. */
  1231. public void finalize() {
  1232. ImageData.freeNativeICMData(this);
  1233. }
  1234. /**
  1235. * Returns the <code>String</code> representation of the contents of
  1236. * this <code>ColorModel</code>object.
  1237. * @return a <code>String</code> representing the contents of this
  1238. * <code>ColorModel</code> object.
  1239. */
  1240. public String toString() {
  1241. return new String("IndexColorModel: #pixelBits = "+pixel_bits
  1242. + " numComponents = "+numComponents
  1243. + " color space = "+colorSpace
  1244. + " transparency = "+transparency
  1245. + " transIndex = "+transparent_index
  1246. + " has alpha = "+supportsAlpha
  1247. + " isAlphaPre = "+isAlphaPremultiplied
  1248. );
  1249. }
  1250. }