1. /*
  2. * @(#)MultiPixelPackedSampleModel.java 1.36 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /* ****************************************************************
  8. ******************************************************************
  9. ******************************************************************
  10. *** COPYRIGHT (c) Eastman Kodak Company, 1997
  11. *** As an unpublished work pursuant to Title 17 of the United
  12. *** States Code. All rights reserved.
  13. ******************************************************************
  14. ******************************************************************
  15. ******************************************************************/
  16. package java.awt.image;
  17. /**
  18. * The <code>MultiPixelPackedSampleModel</code> class represents
  19. * one-banded images and can pack multiple one-sample
  20. * pixels into one data element. Pixels are not allowed to span data elements.
  21. * The data type can be DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
  22. * or DataBuffer.TYPE_INT. Each pixel must be a power of 2 number of bits
  23. * and a power of 2 number of pixels must fit exactly in one data element.
  24. * Pixel bit stride is equal to the number of bits per pixel. Scanline
  25. * stride is in data elements and the last several data elements might be
  26. * padded with unused pixels. Data bit offset is the offset in bits from
  27. * the beginning of the {@link DataBuffer} to the first pixel and must be
  28. * a multiple of pixel bit stride.
  29. * <p>
  30. * The following code illustrates extracting the bits for pixel
  31. * <code>x, y</code> from <code>DataBuffer</code> <code>data</code>
  32. * and storing the pixel data in data elements of type
  33. * <code>dataType</code>:
  34. * <pre>
  35. * int dataElementSize = DataBuffer.getDataTypeSize(dataType);
  36. * int bitnum = dataBitOffset + x*pixelBitStride;
  37. * int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
  38. * int shift = dataElementSize - (bitnum & (dataElementSize-1))
  39. * - pixelBitStride;
  40. * int pixel = (element >> shift) & ((1 << pixelBitStride) - 1);
  41. * </pre>
  42. */
  43. public class MultiPixelPackedSampleModel extends SampleModel
  44. {
  45. /** The number of bits from one pixel to the next. */
  46. int pixelBitStride;
  47. /** Bitmask that extracts the rightmost pixel of a data element. */
  48. int bitMask;
  49. /**
  50. * The number of pixels that fit in a data element. Also used
  51. * as the number of bits per pixel.
  52. */
  53. int pixelsPerDataElement;
  54. /** The size of a data element in bits. */
  55. int dataElementSize;
  56. /** The bit offset into the data array where the first pixel begins.
  57. */
  58. int dataBitOffset;
  59. /** ScanlineStride of the data buffer described in data array elements. */
  60. int scanlineStride;
  61. /**
  62. * Constructs a <code>MultiPixelPackedSampleModel</code> with the
  63. * specified data type, width, height and number of bits per pixel.
  64. * @param dataType the data type for storing samples
  65. * @param w the width, in pixels, of the region of
  66. * image data described
  67. * @param h the height, in pixels, of the region of
  68. * image data described
  69. * @param numberOfBits the number of bits per pixel
  70. * @throws IllegalArgumentException if <code>dataType</code> is not
  71. * either <code>DataBuffer.TYPE_BYTE</code>,
  72. * <code>DataBuffer.TYPE_USHORT</code>, or
  73. * <code>DataBuffer.TYPE_INT</code>
  74. */
  75. public MultiPixelPackedSampleModel(int dataType,
  76. int w,
  77. int h,
  78. int numberOfBits) {
  79. this(dataType,w,h,
  80. numberOfBits,
  81. (w*numberOfBits+DataBuffer.getDataTypeSize(dataType)-1)/
  82. DataBuffer.getDataTypeSize(dataType),
  83. 0);
  84. if (dataType != DataBuffer.TYPE_BYTE &&
  85. dataType != DataBuffer.TYPE_USHORT &&
  86. dataType != DataBuffer.TYPE_INT) {
  87. throw new IllegalArgumentException("Unsupported data type "+
  88. dataType);
  89. }
  90. }
  91. /**
  92. * Constructs a <code>MultiPixelPackedSampleModel</code> with
  93. * specified data type, width, height, number of bits per pixel,
  94. * scanline stride and data bit offset.
  95. * @param dataType the data type for storing samples
  96. * @param w the width, in pixels, of the region of
  97. * image data described
  98. * @param h the height, in pixels, of the region of
  99. * image data described
  100. * @param numberOfBits the number of bits per pixel
  101. * @param scanlineStride the line stride of the image data
  102. * @param dataBitOffset the data bit offset for the region of image
  103. * data described
  104. * @exception RasterFormatException if the number of bits per pixel
  105. * is not a power of 2 or if a power of 2 number of
  106. * pixels do not fit in one data element.
  107. * @throws IllegalArgumentException if <code>w</code> or
  108. * <code>h</code> is not greater than 0
  109. * @throws IllegalArgumentException if <code>dataType</code> is not
  110. * either <code>DataBuffer.TYPE_BYTE</code>,
  111. * <code>DataBuffer.TYPE_USHORT</code>, or
  112. * <code>DataBuffer.TYPE_INT</code>
  113. */
  114. public MultiPixelPackedSampleModel(int dataType, int w, int h,
  115. int numberOfBits,
  116. int scanlineStride,
  117. int dataBitOffset) {
  118. super(dataType, w, h, 1);
  119. if (dataType != DataBuffer.TYPE_BYTE &&
  120. dataType != DataBuffer.TYPE_USHORT &&
  121. dataType != DataBuffer.TYPE_INT) {
  122. throw new IllegalArgumentException("Unsupported data type "+
  123. dataType);
  124. }
  125. this.dataType = dataType;
  126. this.pixelBitStride = numberOfBits;
  127. this.scanlineStride = scanlineStride;
  128. this.dataBitOffset = dataBitOffset;
  129. this.dataElementSize = DataBuffer.getDataTypeSize(dataType);
  130. this.pixelsPerDataElement = dataElementSizenumberOfBits;
  131. if (pixelsPerDataElement*numberOfBits != dataElementSize) {
  132. throw new RasterFormatException("MultiPixelPackedSampleModel " +
  133. "does not allow pixels to " +
  134. "span data element boundaries");
  135. }
  136. this.bitMask = (1 << numberOfBits) - 1;
  137. }
  138. /**
  139. * Creates a new <code>MultiPixelPackedSampleModel</code> with the
  140. * specified width and height. The new
  141. * <code>MultiPixelPackedSampleModel</code> has the
  142. * same storage data type and number of bits per pixel as this
  143. * <code>MultiPixelPackedSampleModel</code>.
  144. * @param w the specified width
  145. * @param h the specified height
  146. * @return a {@link SampleModel} with the specified width and height
  147. * and with the same storage data type and number of bits per pixel
  148. * as this <code>MultiPixelPackedSampleModel</code>.
  149. * @throws IllegalArgumentException if <code>w</code> or
  150. * <code>h</code> is not greater than 0
  151. */
  152. public SampleModel createCompatibleSampleModel(int w, int h) {
  153. SampleModel sampleModel =
  154. new MultiPixelPackedSampleModel(dataType, w, h, pixelBitStride);
  155. return sampleModel;
  156. }
  157. /**
  158. * Creates a <code>DataBuffer</code> that corresponds to this
  159. * <code>MultiPixelPackedSampleModel</code>. The
  160. * <code>DataBuffer</code> object's data type and size
  161. * is consistent with this <code>MultiPixelPackedSampleModel</code>.
  162. * The <code>DataBuffer</code> has a single bank.
  163. * @return a <code>DataBuffer</code> with the same data type and
  164. * size as this <code>MultiPixelPackedSampleModel</code>.
  165. */
  166. public DataBuffer createDataBuffer() {
  167. DataBuffer dataBuffer = null;
  168. int size = (int)scanlineStride*height;
  169. switch (dataType) {
  170. case DataBuffer.TYPE_BYTE:
  171. dataBuffer = new DataBufferByte(size+(dataBitOffset+7)/8);
  172. break;
  173. case DataBuffer.TYPE_USHORT:
  174. dataBuffer = new DataBufferUShort(size+(dataBitOffset+15)/16);
  175. break;
  176. case DataBuffer.TYPE_INT:
  177. dataBuffer = new DataBufferInt(size+(dataBitOffset+31)/32);
  178. break;
  179. }
  180. return dataBuffer;
  181. }
  182. /**
  183. * Returns the number of data elements needed to transfer one pixel
  184. * via the {@link #getDataElements} and {@link #setDataElements}
  185. * methods. For a <code>MultiPixelPackedSampleModel</code>, this is
  186. * one.
  187. * @return the number of data elements.
  188. */
  189. public int getNumDataElements() {
  190. return 1;
  191. }
  192. /**
  193. * Returns the number of bits per sample for all bands.
  194. * @return the number of bits per sample.
  195. */
  196. public int[] getSampleSize() {
  197. int sampleSize[] = {pixelBitStride};
  198. return sampleSize;
  199. }
  200. /**
  201. * Returns the number of bits per sample for the specified band.
  202. * @param band the specified band
  203. * @return the number of bits per sample for the specified band.
  204. */
  205. public int getSampleSize(int band) {
  206. return pixelBitStride;
  207. }
  208. /**
  209. * Returns the offset of pixel (x, y) in data array elements.
  210. * @param x, y the specified pixel
  211. * @return the offset of the specified pixel.
  212. */
  213. public int getOffset(int x, int y) {
  214. int offset = y * scanlineStride;
  215. offset += (x*pixelBitStride+dataBitOffset)/dataElementSize;
  216. return offset;
  217. }
  218. /**
  219. * Returns the offset, in bits, into the data element in which it is
  220. * stored for the <code>x</code>th pixel of a scanline.
  221. * This offset is the same for all scanlines.
  222. * @param x the specified pixel
  223. * @return the bit offset of the specified pixel.
  224. */
  225. public int getBitOffset(int x){
  226. return (x*pixelBitStride+dataBitOffset)%dataElementSize;
  227. }
  228. /**
  229. * Returns the scanline stride.
  230. * @return the scanline stride of this
  231. * <code>MultiPixelPackedSampleModel</code>.
  232. */
  233. public int getScanlineStride() {
  234. return scanlineStride;
  235. }
  236. /**
  237. * Returns the pixel bit stride in bits. This value is the same as
  238. * the number of bits per pixel.
  239. * @return the <code>pixelBitStride</code> of this
  240. * <code>MultiPixelPackedSampleModel</code>.
  241. */
  242. public int getPixelBitStride() {
  243. return pixelBitStride;
  244. }
  245. /**
  246. * Returns the data bit offset in bits.
  247. * @return the <code>dataBitOffset</code> of this
  248. * <code>MultiPixelPackedSampleModel</code>.
  249. */
  250. public int getDataBitOffset() {
  251. return dataBitOffset;
  252. }
  253. /**
  254. * Returns the TransferType used to transfer pixels by way of the
  255. * <code>getDataElements</code> and <code>setDataElements</code>
  256. * methods. The TransferType might or might not be the same as the
  257. * storage DataType. The TransferType is one of
  258. * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
  259. * or DataBuffer.TYPE_INT.
  260. * @return the transfertype.
  261. */
  262. public int getTransferType() {
  263. if (pixelBitStride > 16)
  264. return DataBuffer.TYPE_INT;
  265. else if (pixelBitStride > 8)
  266. return DataBuffer.TYPE_USHORT;
  267. else
  268. return DataBuffer.TYPE_BYTE;
  269. }
  270. /**
  271. * Creates a new <code>MultiPixelPackedSampleModel</code> with a
  272. * subset of the bands of this
  273. * <code>MultiPixelPackedSampleModel</code>. Since a
  274. * <code>MultiPixelPackedSampleModel</code> only has one band, the
  275. * bands argument must have a length of one and indicate the zeroth
  276. * band.
  277. * @param bands the specified bands
  278. * @return a new <code>SampleModel</code> with a subset of bands of
  279. * this <code>MultiPixelPackedSampleModel</code>.
  280. * @exception RasterFormatException if the number of bands requested
  281. * is not one.
  282. * @throws IllegalArgumentException if <code>w</code> or
  283. * <code>h</code> is not greater than 0
  284. */
  285. public SampleModel createSubsetSampleModel(int bands[]) {
  286. if (bands != null) {
  287. if (bands.length != 1)
  288. throw new RasterFormatException("MultiPixelPackedSampleModel has "
  289. + "only one band.");
  290. }
  291. SampleModel sm = createCompatibleSampleModel(width, height);
  292. return sm;
  293. }
  294. /**
  295. * Returns as <code>int</code> the sample in a specified band for the
  296. * pixel located at (x, y). An
  297. * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
  298. * coordinates are not in bounds.
  299. * @param x, y the coordinates of the specified pixel
  300. * @param b the band to return, which is assumed to be 0
  301. * @param data the <code>DataBuffer</code> containing the image
  302. * data
  303. * @return the specified band containing the sample of the specified
  304. * pixel.
  305. * @exception ArrayIndexOutOfBoundException if the specified
  306. * coordinates are not in bounds.
  307. * @see #setSample(int, int, int, int, DataBuffer)
  308. */
  309. public int getSample(int x, int y, int b, DataBuffer data) {
  310. // 'b' must be 0
  311. if ((x < 0) || (y < 0) || (x >= width) || (y >= height) ||
  312. (b != 0)) {
  313. throw new ArrayIndexOutOfBoundsException
  314. ("Coordinate out of bounds!");
  315. }
  316. int bitnum = dataBitOffset + x*pixelBitStride;
  317. int element = data.getElem(y*scanlineStride + bitnumdataElementSize);
  318. int shift = dataElementSize - (bitnum & (dataElementSize-1))
  319. - pixelBitStride;
  320. return (element >> shift) & bitMask;
  321. }
  322. /**
  323. * Sets a sample in the specified band for the pixel located at
  324. * (x, y) in the <code>DataBuffer</code> using an
  325. * <code>int</code> for input.
  326. * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
  327. * coordinates are not in bounds.
  328. * @param x, y the coordinates of the specified pixel
  329. * @param b the band to return, which is assumed to be 0
  330. * @param s the input sample as an <code>int</code>
  331. * @param data the <code>DataBuffer</code> where image data is stored
  332. * @exception ArrayIndexOutOfBoundsException if the coordinates are
  333. * not in bounds.
  334. * @see #getSample(int, int, int, DataBuffer)
  335. */
  336. public void setSample(int x, int y, int b, int s,
  337. DataBuffer data) {
  338. // 'b' must be 0
  339. if ((x < 0) || (y < 0) || (x >= width) || (y >= height) ||
  340. (b != 0)) {
  341. throw new ArrayIndexOutOfBoundsException
  342. ("Coordinate out of bounds!");
  343. }
  344. int bitnum = dataBitOffset + x * pixelBitStride;
  345. int index = y * scanlineStride + (bitnum / dataElementSize);
  346. int shift = dataElementSize - (bitnum & (dataElementSize-1))
  347. - pixelBitStride;
  348. int element = data.getElem(index);
  349. element &= ~(bitMask << shift);
  350. element |= (s & bitMask) << shift;
  351. data.setElem(index,element);
  352. }
  353. /**
  354. * Returns data for a single pixel in a primitive array of type
  355. * TransferType. For a <code>MultiPixelPackedSampleModel</code>,
  356. * the array has one element, and the type is the smallest of
  357. * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
  358. * that can hold a single pixel. Generally, <code>obj</code>
  359. * should be passed in as <code>null</code>, so that the
  360. * <code>Object</code> is created automatically and is the
  361. * correct primitive data type.
  362. * <p>
  363. * The following code illustrates transferring data for one pixel from
  364. * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
  365. * described by <code>MultiPixelPackedSampleModel</code>
  366. * <code>mppsm1</code>, to <code>DataBuffer</code> <code>db2</code>,
  367. * whose storage layout is described by
  368. * <code>MultiPixelPackedSampleModel</code> <code>mppsm2</code>.
  369. * The transfer is generally more efficient than using
  370. * <code>getPixel</code> or <code>setPixel</code>.
  371. * <pre>
  372. * MultiPixelPackedSampleModel mppsm1, mppsm2;
  373. * DataBufferInt db1, db2;
  374. * mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
  375. * db1), db2);
  376. * </pre>
  377. * Using <code>getDataElements</code> or <code>setDataElements</code>
  378. * to transfer between two <code>DataBuffer/SampleModel</code> pairs
  379. * is legitimate if the <code>SampleModels</code> have the same number
  380. * of bands, corresponding bands have the same number of
  381. * bits per sample, and the TransferTypes are the same.
  382. * <p>
  383. * If <code>obj</code> is not <code>null</code>, it should be a
  384. * primitive array of type TransferType. Otherwise, a
  385. * <code>ClassCastException</code> is thrown. An
  386. * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
  387. * coordinates are not in bounds, or if <code>obj</code> is not
  388. * <code>null</code> and is not large enough to hold the pixel data.
  389. * @param x, y coordinates of the pixel location.
  390. * @param obj a primitive array in which to return the pixel data or
  391. * <code>null</code>.
  392. * @param data the <code>DataBuffer</code> containing the image data.
  393. * @return an <code>Object</code> containing data for the specified
  394. * pixel.
  395. * @exception ClassCastException if <code>obj</code> is not a
  396. * primitive array of type TransferType or is not <code>null</code>
  397. * @exception ArrayIndexOutOfBoundsException if the coordinates are
  398. * not in bounds, or if <code>obj</code> is not <code>null</code> or
  399. * not large enough to hold the pixel data
  400. * @see #setDataElements(int, int, Object, DataBuffer)
  401. */
  402. public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
  403. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  404. throw new ArrayIndexOutOfBoundsException
  405. ("Coordinate out of bounds!");
  406. }
  407. int type = getTransferType();
  408. int bitnum = dataBitOffset + x*pixelBitStride;
  409. int shift = dataElementSize - (bitnum & (dataElementSize-1))
  410. - pixelBitStride;
  411. int element = 0;
  412. switch(type) {
  413. case DataBuffer.TYPE_BYTE:
  414. byte[] bdata;
  415. if (obj == null)
  416. bdata = new byte[1];
  417. else
  418. bdata = (byte[])obj;
  419. element = data.getElem(y*scanlineStride +
  420. bitnumdataElementSize);
  421. bdata[0] = (byte)((element >> shift) & bitMask);
  422. obj = (Object)bdata;
  423. break;
  424. case DataBuffer.TYPE_USHORT:
  425. short[] sdata;
  426. if (obj == null)
  427. sdata = new short[1];
  428. else
  429. sdata = (short[])obj;
  430. element = data.getElem(y*scanlineStride +
  431. bitnumdataElementSize);
  432. sdata[0] = (short)((element >> shift) & bitMask);
  433. obj = (Object)sdata;
  434. break;
  435. case DataBuffer.TYPE_INT:
  436. int[] idata;
  437. if (obj == null)
  438. idata = new int[1];
  439. else
  440. idata = (int[])obj;
  441. element = data.getElem(y*scanlineStride +
  442. bitnumdataElementSize);
  443. idata[0] = (element >> shift) & bitMask;
  444. obj = (Object)idata;
  445. break;
  446. }
  447. return obj;
  448. }
  449. /**
  450. * Returns the specified single band pixel in the first element
  451. * of an <code>int</code> array.
  452. * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
  453. * coordinates are not in bounds.
  454. * @param x, y the coordinates of the pixel location
  455. * @param iArray the array containing the pixel to be returned or
  456. * <code>null</code>
  457. * @param data the <code>DataBuffer</code> where image data is stored
  458. * @return an array containing the specified pixel.
  459. * @exception ArrayIndexOutOfBoundsException if the coordinates
  460. * are not in bounds
  461. * @see #setPixel(int, int, int[], DataBuffer)
  462. */
  463. public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
  464. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  465. throw new ArrayIndexOutOfBoundsException
  466. ("Coordinate out of bounds!");
  467. }
  468. int pixels[];
  469. if (iArray != null) {
  470. pixels = iArray;
  471. } else {
  472. pixels = new int [numBands];
  473. }
  474. int bitnum = dataBitOffset + x*pixelBitStride;
  475. int element = data.getElem(y*scanlineStride + bitnumdataElementSize);
  476. int shift = dataElementSize - (bitnum & (dataElementSize-1))
  477. - pixelBitStride;
  478. pixels[0] = (element >> shift) & bitMask;
  479. return pixels;
  480. }
  481. /**
  482. * Sets the data for a single pixel in the specified
  483. * <code>DataBuffer</code> from a primitive array of type
  484. * TransferType. For a <code>MultiPixelPackedSampleModel</code>,
  485. * only the first element of the array holds valid data,
  486. * and the type must be the smallest of
  487. * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
  488. * that can hold a single pixel.
  489. * <p>
  490. * The following code illustrates transferring data for one pixel from
  491. * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
  492. * described by <code>MultiPixelPackedSampleModel</code>
  493. * <code>mppsm1</code>, to <code>DataBuffer</code> <code>db2</code>,
  494. * whose storage layout is described by
  495. * <code>MultiPixelPackedSampleModel</code> <code>mppsm2</code>.
  496. * The transfer is generally more efficient than using
  497. * <code>getPixel</code> or <code>setPixel</code>.
  498. * <pre>
  499. * MultiPixelPackedSampleModel mppsm1, mppsm2;
  500. * DataBufferInt db1, db2;
  501. * mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
  502. * db1), db2);
  503. * </pre>
  504. * Using <code>getDataElements</code> or <code>setDataElements</code> to
  505. * transfer between two <code>DataBuffer/SampleModel</code> pairs is
  506. * legitimate if the <code>SampleModel</code> objects have
  507. * the same number of bands, corresponding bands have the same number of
  508. * bits per sample, and the TransferTypes are the same.
  509. * <p>
  510. * <code>obj</code> must be a primitive array of type TransferType.
  511. * Otherwise, a <code>ClassCastException</code> is thrown. An
  512. * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
  513. * coordinates are not in bounds, or if <code>obj</code> is not large
  514. * enough to hold the pixel data.
  515. * @param x, y the coordinates of the pixel location
  516. * @param obj a primitive array containing pixel data
  517. * @param data the <code>DataBuffer</code> containing the image data
  518. * @see #getDataElements(int, int, Object, DataBuffer)
  519. */
  520. public void setDataElements(int x, int y, Object obj, DataBuffer data) {
  521. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  522. throw new ArrayIndexOutOfBoundsException
  523. ("Coordinate out of bounds!");
  524. }
  525. int type = getTransferType();
  526. int bitnum = dataBitOffset + x * pixelBitStride;
  527. int index = y * scanlineStride + (bitnum / dataElementSize);
  528. int shift = dataElementSize - (bitnum & (dataElementSize-1))
  529. - pixelBitStride;
  530. int element = data.getElem(index);
  531. element &= ~(bitMask << shift);
  532. switch(type) {
  533. case DataBuffer.TYPE_BYTE:
  534. byte[] barray = (byte[])obj;
  535. element |= ( ((int)(barray[0])&0xff) & bitMask) << shift;
  536. data.setElem(index, element);
  537. break;
  538. case DataBuffer.TYPE_USHORT:
  539. short[] sarray = (short[])obj;
  540. element |= ( ((int)(sarray[0])&0xffff) & bitMask) << shift;
  541. data.setElem(index, element);
  542. break;
  543. case DataBuffer.TYPE_INT:
  544. int[] iarray = (int[])obj;
  545. element |= (iarray[0] & bitMask) << shift;
  546. data.setElem(index, element);
  547. break;
  548. }
  549. }
  550. /**
  551. * Sets a pixel in the <code>DataBuffer</code> using an
  552. * <code>int</code> array for input.
  553. * <code>ArrayIndexOutOfBoundsException</code> is thrown if
  554. * the coordinates are not in bounds.
  555. * @param x, y the coordinates of the pixel location
  556. * @param iArray the input pixel in an <code>int</code> array
  557. * @param data the <code>DataBuffer</code> containing the image data
  558. * @see #getPixel(int, int, int[], DataBuffer)
  559. */
  560. public void setPixel(int x, int y, int[] iArray, DataBuffer data) {
  561. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  562. throw new ArrayIndexOutOfBoundsException
  563. ("Coordinate out of bounds!");
  564. }
  565. int bitnum = dataBitOffset + x * pixelBitStride;
  566. int index = y * scanlineStride + (bitnum / dataElementSize);
  567. int shift = dataElementSize - (bitnum & (dataElementSize-1))
  568. - pixelBitStride;
  569. int element = data.getElem(index);
  570. element &= ~(bitMask << shift);
  571. element |= (iArray[0] & bitMask) << shift;
  572. data.setElem(index,element);
  573. }
  574. public boolean equals(Object o) {
  575. if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) {
  576. return false;
  577. }
  578. MultiPixelPackedSampleModel that = (MultiPixelPackedSampleModel)o;
  579. return this.width == that.width &&
  580. this.height == that.height &&
  581. this.numBands == that.numBands &&
  582. this.dataType == that.dataType &&
  583. this.pixelBitStride == that.pixelBitStride &&
  584. this.bitMask == that.bitMask &&
  585. this.pixelsPerDataElement == that.pixelsPerDataElement &&
  586. this.dataElementSize == that.dataElementSize &&
  587. this.dataBitOffset == that.dataBitOffset &&
  588. this.scanlineStride == that.scanlineStride;
  589. }
  590. // If we implement equals() we must also implement hashCode
  591. public int hashCode() {
  592. int hash = 0;
  593. hash = width;
  594. hash <<= 8;
  595. hash ^= height;
  596. hash <<= 8;
  597. hash ^= numBands;
  598. hash <<= 8;
  599. hash ^= dataType;
  600. hash <<= 8;
  601. hash ^= pixelBitStride;
  602. hash <<= 8;
  603. hash ^= bitMask;
  604. hash <<= 8;
  605. hash ^= pixelsPerDataElement;
  606. hash <<= 8;
  607. hash ^= dataElementSize;
  608. hash <<= 8;
  609. hash ^= dataBitOffset;
  610. hash <<= 8;
  611. hash ^= scanlineStride;
  612. return hash;
  613. }
  614. }