1. /*
  2. * @(#)SinglePixelPackedSampleModel.java 1.42 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. import java.util.Arrays;
  18. /**
  19. * This class represents pixel data packed such that the N samples which make
  20. * up a single pixel are stored in a single data array element, and each data
  21. * data array element holds samples for only one pixel.
  22. * This class supports
  23. * {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
  24. * {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
  25. * {@link DataBuffer#TYPE_INT TYPE_INT} data types.
  26. * All data array elements reside
  27. * in the first bank of a DataBuffer. Accessor methods are provided so
  28. * that the image data can be manipulated directly. Scanline stride is the
  29. * number of data array elements between a given sample and the corresponding
  30. * sample in the same column of the next scanline. Bit masks are the masks
  31. * required to extract the samples representing the bands of the pixel.
  32. * Bit offsets are the offsets in bits into the data array
  33. * element of the samples representing the bands of the pixel.
  34. * <p>
  35. * The following code illustrates extracting the bits of the sample
  36. * representing band <code>b</code> for pixel <code>x,y</code>
  37. * from DataBuffer <code>data</code>:
  38. * <pre>
  39. * int sample = data.getElem(y * scanlineStride + x);
  40. * sample = (sample & bitMasks[b]) >>> bitOffsets[b];
  41. * </pre>
  42. */
  43. public class SinglePixelPackedSampleModel extends SampleModel
  44. {
  45. /** Bit masks for all bands of the image data. */
  46. private int bitMasks[];
  47. /** Bit Offsets for all bands of the image data. */
  48. private int bitOffsets[];
  49. /** Bit sizes for all the bands of the image data. */
  50. private int bitSizes[];
  51. /** Maximum bit size. */
  52. private int maxBitSize;
  53. /** Line stride of the region of image data described by this
  54. * SinglePixelPackedSampleModel.
  55. */
  56. private int scanlineStride;
  57. private static native void initIDs();
  58. static {
  59. ColorModel.loadLibraries();
  60. initIDs();
  61. }
  62. /**
  63. * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands.
  64. * Each sample is stored in a data array element in the position of
  65. * its corresponding bit mask. Each bit mask must be contiguous and
  66. * masks must not overlap.
  67. * @param dataType The data type for storing samples.
  68. * @param w The width (in pixels) of the region of the
  69. * image data described.
  70. * @param h The height (in pixels) of the region of the
  71. * image data described.
  72. * @param bitMasks The bit masks for all bands.
  73. * @throws IllegalArgumentException if <code>dataType</code> is not
  74. * either <code>DataBuffer.TYPE_BYTE</code>,
  75. * <code>DataBuffer.TYPE_USHORT</code>, or
  76. * <code>DataBuffer.TYPE_INT</code>
  77. */
  78. public SinglePixelPackedSampleModel(int dataType, int w, int h,
  79. int bitMasks[]) {
  80. this(dataType, w, h, w, bitMasks);
  81. if (dataType != DataBuffer.TYPE_BYTE &&
  82. dataType != DataBuffer.TYPE_USHORT &&
  83. dataType != DataBuffer.TYPE_INT) {
  84. throw new IllegalArgumentException("Unsupported data type "+
  85. dataType);
  86. }
  87. }
  88. /**
  89. * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands
  90. * and a scanline stride equal to scanlineStride data array elements.
  91. * Each sample is stored in a data array element in the position of
  92. * its corresponding bit mask. Each bit mask must be contiguous and
  93. * masks must not overlap.
  94. * @param dataType The data type for storing samples.
  95. * @param w The width (in pixels) of the region of
  96. * image data described.
  97. * @param h The height (in pixels) of the region of
  98. * image data described.
  99. * @param scanlineStride The line stride of the image data.
  100. * @param bitMasks The bit masks for all bands.
  101. * @throws IllegalArgumentException if <code>w</code> or
  102. * <code>h</code> is not greater than 0
  103. * @throws IllegalArgumentException if any mask in
  104. * <code>bitMask</code> is not contiguous
  105. * @throws IllegalArgumentException if <code>dataType</code> is not
  106. * either <code>DataBuffer.TYPE_BYTE</code>,
  107. * <code>DataBuffer.TYPE_USHORT</code>, or
  108. * <code>DataBuffer.TYPE_INT</code>
  109. */
  110. public SinglePixelPackedSampleModel(int dataType, int w, int h,
  111. int scanlineStride, int bitMasks[]) {
  112. super(dataType, w, h, bitMasks.length);
  113. if (dataType != DataBuffer.TYPE_BYTE &&
  114. dataType != DataBuffer.TYPE_USHORT &&
  115. dataType != DataBuffer.TYPE_INT) {
  116. throw new IllegalArgumentException("Unsupported data type "+
  117. dataType);
  118. }
  119. this.dataType = dataType;
  120. this.bitMasks = (int[]) bitMasks.clone();
  121. this.scanlineStride = scanlineStride;
  122. this.bitOffsets = new int[numBands];
  123. this.bitSizes = new int[numBands];
  124. this.maxBitSize = 0;
  125. for (int i=0; i<numBands; i++) {
  126. int bitOffset = 0, bitSize = 0, mask;
  127. mask = bitMasks[i];
  128. if (mask != 0) {
  129. while ((mask & 1) == 0) {
  130. mask = mask >>> 1;
  131. bitOffset++;
  132. }
  133. while ((mask & 1) == 1) {
  134. mask = mask >>> 1;
  135. bitSize++;
  136. }
  137. if (mask != 0) {
  138. throw new IllegalArgumentException("Mask "+bitMasks[i]+
  139. " must be contiguous");
  140. }
  141. }
  142. bitOffsets[i] = bitOffset;
  143. bitSizes[i] = bitSize;
  144. if (bitSize > maxBitSize) {
  145. maxBitSize = bitSize;
  146. }
  147. }
  148. }
  149. /**
  150. * Returns the number of data elements needed to transfer one pixel
  151. * via the getDataElements and setDataElements methods.
  152. * For a SinglePixelPackedSampleModel, this is one.
  153. */
  154. public int getNumDataElements() {
  155. return 1;
  156. }
  157. /**
  158. * Returns the size of the buffer (in data array elements)
  159. * needed for a data buffer that matches this
  160. * SinglePixelPackedSampleModel.
  161. */
  162. private long getBufferSize() {
  163. long size = scanlineStride * (height-1) + width;
  164. return size;
  165. }
  166. /**
  167. * Creates a new SinglePixelPackedSampleModel with the specified
  168. * width and height. The new SinglePixelPackedSampleModel will have the
  169. * same storage data type and bit masks as this
  170. * SinglePixelPackedSampleModel.
  171. * @param w the width of the resulting <code>SampleModel</code>
  172. * @param h the height of the resulting <code>SampleModel</code>
  173. * @return a <code>SinglePixelPackedSampleModel</code> with the
  174. * specified width and height.
  175. * @throws IllegalArgumentException if <code>w</code> or
  176. * <code>h</code> is not greater than 0
  177. */
  178. public SampleModel createCompatibleSampleModel(int w, int h) {
  179. SampleModel sampleModel = new SinglePixelPackedSampleModel(dataType, w, h,
  180. bitMasks);
  181. return sampleModel;
  182. }
  183. /**
  184. * Creates a DataBuffer that corresponds to this
  185. * SinglePixelPackedSampleModel. The DataBuffer's data type and size
  186. * will be consistent with this SinglePixelPackedSampleModel. The
  187. * DataBuffer will have a single bank.
  188. */
  189. public DataBuffer createDataBuffer() {
  190. DataBuffer dataBuffer = null;
  191. int size = (int)getBufferSize();
  192. switch (dataType) {
  193. case DataBuffer.TYPE_BYTE:
  194. dataBuffer = new DataBufferByte(size);
  195. break;
  196. case DataBuffer.TYPE_USHORT:
  197. dataBuffer = new DataBufferUShort(size);
  198. break;
  199. case DataBuffer.TYPE_INT:
  200. dataBuffer = new DataBufferInt(size);
  201. break;
  202. }
  203. return dataBuffer;
  204. }
  205. /** Returns the number of bits per sample for all bands. */
  206. public int[] getSampleSize() {
  207. int mask;
  208. int sampleSize[] = new int [numBands];
  209. for (int i=0; i<numBands; i++) {
  210. sampleSize[i] = 0;
  211. mask = bitMasks[i] >>> bitOffsets[i];
  212. while ((mask & 1) != 0) {
  213. sampleSize[i] ++;
  214. mask = mask >>> 1;
  215. }
  216. }
  217. return sampleSize;
  218. }
  219. /** Returns the number of bits per sample for the specified band. */
  220. public int getSampleSize(int band) {
  221. int sampleSize = 0;
  222. int mask = bitMasks[band] >>> bitOffsets[band];
  223. while ((mask & 1) != 0) {
  224. sampleSize ++;
  225. mask = mask >>> 1;
  226. }
  227. return sampleSize;
  228. }
  229. /** Returns the offset (in data array elements) of pixel (x,y).
  230. * The data element containing pixel <code>x,y</code>
  231. * can be retrieved from a DataBuffer <code>data</code> with a
  232. * SinglePixelPackedSampleModel <code>sppsm</code> as:
  233. * <pre>
  234. * data.getElem(sppsm.getOffset(x, y));
  235. * </pre>
  236. * @param x, y the coordinates of the specified pixel
  237. * @return the offset of the specified pixel.
  238. */
  239. public int getOffset(int x, int y) {
  240. int offset = y * scanlineStride + x;
  241. return offset;
  242. }
  243. /** Returns the bit offsets into the data array element representing
  244. * a pixel for all bands.
  245. * @return the bit offsets representing a pixel for all bands.
  246. */
  247. public int [] getBitOffsets() {
  248. return (int[])bitOffsets.clone();
  249. }
  250. /** Returns the bit masks for all bands.
  251. * @return the bit masks for all bands.
  252. */
  253. public int [] getBitMasks() {
  254. return (int[])bitMasks.clone();
  255. }
  256. /** Returns the scanline stride of this SinglePixelPackedSampleModel.
  257. * @return the scanline stride of this
  258. * <code>SinglePixelPackedSampleModel</code>.
  259. */
  260. public int getScanlineStride() {
  261. return scanlineStride;
  262. }
  263. /**
  264. * This creates a new SinglePixelPackedSampleModel with a subset of the
  265. * bands of this SinglePixelPackedSampleModel. The new
  266. * SinglePixelPackedSampleModel can be used with any DataBuffer that the
  267. * existing SinglePixelPackedSampleModel can be used with. The new
  268. * SinglePixelPackedSampleModel/DataBuffer combination will represent
  269. * an image with a subset of the bands of the original
  270. * SinglePixelPackedSampleModel/DataBuffer combination.
  271. * @exception RasterFormatException if the length of the bands argument is
  272. * greater than the number of bands in
  273. * the sample model.
  274. */
  275. public SampleModel createSubsetSampleModel(int bands[]) {
  276. if (bands.length > numBands)
  277. throw new RasterFormatException("There are only " +
  278. numBands +
  279. " bands");
  280. int newBitMasks[] = new int[bands.length];
  281. for (int i=0; i<bands.length; i++)
  282. newBitMasks[i] = bitMasks[bands[i]];
  283. return new SinglePixelPackedSampleModel(this.dataType, width, height,
  284. this.scanlineStride, newBitMasks);
  285. }
  286. /**
  287. * Returns data for a single pixel in a primitive array of type
  288. * TransferType. For a SinglePixelPackedSampleModel, the array will
  289. * have one element, and the type will be the same as the storage
  290. * data type. Generally, obj
  291. * should be passed in as null, so that the Object will be created
  292. * automatically and will be of the right primitive data type.
  293. * <p>
  294. * The following code illustrates transferring data for one pixel from
  295. * DataBuffer <code>db1</code>, whose storage layout is described by
  296. * SinglePixelPackedSampleModel <code>sppsm1</code>, to
  297. * DataBuffer <code>db2</code>, whose storage layout is described by
  298. * SinglePixelPackedSampleModel <code>sppsm2</code>.
  299. * The transfer will generally be more efficient than using
  300. * getPixel/setPixel.
  301. * <pre>
  302. * SinglePixelPackedSampleModel sppsm1, sppsm2;
  303. * DataBufferInt db1, db2;
  304. * sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
  305. * db1), db2);
  306. * </pre>
  307. * Using getDataElements/setDataElements to transfer between two
  308. * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
  309. * the same number of bands, corresponding bands have the same number of
  310. * bits per sample, and the TransferTypes are the same.
  311. * <p>
  312. * If obj is non-null, it should be a primitive array of type TransferType.
  313. * Otherwise, a ClassCastException is thrown. An
  314. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  315. * not in bounds, or if obj is non-null and is not large enough to hold
  316. * the pixel data.
  317. * @param x The X coordinate of the pixel location.
  318. * @param y The Y coordinate of the pixel location.
  319. * @param obj If non-null, a primitive array in which to return
  320. * the pixel data.
  321. * @param data The DataBuffer containing the image data.
  322. * @return the data for the specified pixel.
  323. * @see #setDataElements(int, int, Object, DataBuffer)
  324. */
  325. public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
  326. // Bounds check for 'b' will be performed automatically
  327. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  328. throw new ArrayIndexOutOfBoundsException
  329. ("Coordinate out of bounds!");
  330. }
  331. int type = getTransferType();
  332. switch(type) {
  333. case DataBuffer.TYPE_BYTE:
  334. byte[] bdata;
  335. if (obj == null)
  336. bdata = new byte[1];
  337. else
  338. bdata = (byte[])obj;
  339. bdata[0] = (byte)data.getElem(y * scanlineStride + x);
  340. obj = (Object)bdata;
  341. break;
  342. case DataBuffer.TYPE_USHORT:
  343. short[] sdata;
  344. if (obj == null)
  345. sdata = new short[1];
  346. else
  347. sdata = (short[])obj;
  348. sdata[0] = (short)data.getElem(y * scanlineStride + x);
  349. obj = (Object)sdata;
  350. break;
  351. case DataBuffer.TYPE_INT:
  352. int[] idata;
  353. if (obj == null)
  354. idata = new int[1];
  355. else
  356. idata = (int[])obj;
  357. idata[0] = data.getElem(y * scanlineStride + x);
  358. obj = (Object)idata;
  359. break;
  360. }
  361. return obj;
  362. }
  363. /**
  364. * Returns all samples in for the specified pixel in an int array.
  365. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  366. * not in bounds.
  367. * @param x The X coordinate of the pixel location.
  368. * @param y The Y coordinate of the pixel location.
  369. * @param iArray If non-null, returns the samples in this array
  370. * @param data The DataBuffer containing the image data.
  371. * @return all samples for the specified pixel.
  372. * @see #setPixel(int, int, int[], DataBuffer)
  373. */
  374. public int [] getPixel(int x, int y, int iArray[], DataBuffer data) {
  375. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  376. throw new ArrayIndexOutOfBoundsException
  377. ("Coordinate out of bounds!");
  378. }
  379. int pixels[];
  380. if (iArray == null) {
  381. pixels = new int [numBands];
  382. } else {
  383. pixels = iArray;
  384. }
  385. int value = data.getElem(y * scanlineStride + x);
  386. for (int i=0; i<numBands; i++) {
  387. pixels[i] = (value & bitMasks[i]) >>> bitOffsets[i];
  388. }
  389. return pixels;
  390. }
  391. /**
  392. * Returns all samples for the specified rectangle of pixels in
  393. * an int array, one sample per array element.
  394. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  395. * not in bounds.
  396. * @param x The X coordinate of the upper left pixel location.
  397. * @param y The Y coordinate of the upper left pixel location.
  398. * @param w The width of the pixel rectangle.
  399. * @param h The height of the pixel rectangle.
  400. * @param iArray If non-null, returns the samples in this array.
  401. * @param data The DataBuffer containing the image data.
  402. * @return all samples for the specified region of pixels.
  403. * @see #setPixels(int, int, int, int, int[], DataBuffer)
  404. */
  405. public int[] getPixels(int x, int y, int w, int h,
  406. int iArray[], DataBuffer data) {
  407. if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
  408. throw new ArrayIndexOutOfBoundsException
  409. ("Coordinate out of bounds!");
  410. }
  411. int pixels[];
  412. if (iArray != null) {
  413. pixels = iArray;
  414. } else {
  415. pixels = new int [w*h*numBands];
  416. }
  417. int lineOffset = y*scanlineStride + x;
  418. int dstOffset = 0;
  419. for (int i = 0; i < h; i++) {
  420. for (int j = 0; j < w; j++) {
  421. int value = data.getElem(lineOffset+j);
  422. for (int k=0; k < numBands; k++) {
  423. pixels[dstOffset++] =
  424. ((value & bitMasks[k]) >>> bitOffsets[k]);
  425. }
  426. }
  427. lineOffset += scanlineStride;
  428. }
  429. return pixels;
  430. }
  431. /**
  432. * Returns as int the sample in a specified band for the pixel
  433. * located at (x,y).
  434. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  435. * not in bounds.
  436. * @param x The X coordinate of the pixel location.
  437. * @param y The Y coordinate of the pixel location.
  438. * @param b The band to return.
  439. * @param data The DataBuffer containing the image data.
  440. * @return the sample in a specified band for the specified
  441. * pixel.
  442. * @see #setSample(int, int, int, int, DataBuffer)
  443. */
  444. public int getSample(int x, int y, int b, DataBuffer data) {
  445. // Bounds check for 'b' will be performed automatically
  446. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  447. throw new ArrayIndexOutOfBoundsException
  448. ("Coordinate out of bounds!");
  449. }
  450. int sample = data.getElem(y * scanlineStride + x);
  451. return ((sample & bitMasks[b]) >>> bitOffsets[b]);
  452. }
  453. /**
  454. * Returns the samples for a specified band for the specified rectangle
  455. * of pixels in an int array, one sample per array element.
  456. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  457. * not in bounds.
  458. * @param x The X coordinate of the upper left pixel location.
  459. * @param y The Y coordinate of the upper left pixel location.
  460. * @param w The width of the pixel rectangle.
  461. * @param h The height of the pixel rectangle.
  462. * @param b The band to return.
  463. * @param iArray If non-null, returns the samples in this array.
  464. * @param data The DataBuffer containing the image data.
  465. * @return the samples for the specified band for the specified
  466. * region of pixels.
  467. * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
  468. */
  469. public int[] getSamples(int x, int y, int w, int h, int b,
  470. int iArray[], DataBuffer data) {
  471. // Bounds check for 'b' will be performed automatically
  472. if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
  473. throw new ArrayIndexOutOfBoundsException
  474. ("Coordinate out of bounds!");
  475. }
  476. int samples[];
  477. if (iArray != null) {
  478. samples = iArray;
  479. } else {
  480. samples = new int [w*h];
  481. }
  482. int lineOffset = y*scanlineStride + x;
  483. int dstOffset = 0;
  484. for (int i = 0; i < h; i++) {
  485. for (int j = 0; j < w; j++) {
  486. int value = data.getElem(lineOffset+j);
  487. samples[dstOffset++] =
  488. ((value & bitMasks[b]) >>> bitOffsets[b]);
  489. }
  490. lineOffset += scanlineStride;
  491. }
  492. return samples;
  493. }
  494. /**
  495. * Sets the data for a single pixel in the specified DataBuffer from a
  496. * primitive array of type TransferType. For a
  497. * SinglePixelPackedSampleModel, only the first element of the array
  498. * will hold valid data, and the type of the array must be the same as
  499. * the storage data type of the SinglePixelPackedSampleModel.
  500. * <p>
  501. * The following code illustrates transferring data for one pixel from
  502. * DataBuffer <code>db1</code>, whose storage layout is described by
  503. * SinglePixelPackedSampleModel <code>sppsm1</code>,
  504. * to DataBuffer <code>db2</code>, whose storage layout is described by
  505. * SinglePixelPackedSampleModel <code>sppsm2</code>.
  506. * The transfer will generally be more efficient than using
  507. * getPixel/setPixel.
  508. * <pre>
  509. * SinglePixelPackedSampleModel sppsm1, sppsm2;
  510. * DataBufferInt db1, db2;
  511. * sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
  512. * db1), db2);
  513. * </pre>
  514. * Using getDataElements/setDataElements to transfer between two
  515. * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
  516. * the same number of bands, corresponding bands have the same number of
  517. * bits per sample, and the TransferTypes are the same.
  518. * <p>
  519. * obj must be a primitive array of type TransferType. Otherwise,
  520. * a ClassCastException is thrown. An
  521. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  522. * not in bounds, or if obj is not large enough to hold the pixel data.
  523. * @param x The X coordinate of the pixel location.
  524. * @param y The Y coordinate of the pixel location.
  525. * @param obj A primitive array containing pixel data.
  526. * @param data The DataBuffer containing the image data.
  527. * @see #getDataElements(int, int, Object, DataBuffer)
  528. */
  529. public void setDataElements(int x, int y, Object obj, DataBuffer data) {
  530. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  531. throw new ArrayIndexOutOfBoundsException
  532. ("Coordinate out of bounds!");
  533. }
  534. int type = getTransferType();
  535. switch(type) {
  536. case DataBuffer.TYPE_BYTE:
  537. byte[] barray = (byte[])obj;
  538. data.setElem(y*scanlineStride+x, ((int)barray[0])&0xff);
  539. break;
  540. case DataBuffer.TYPE_USHORT:
  541. short[] sarray = (short[])obj;
  542. data.setElem(y*scanlineStride+x, ((int)sarray[0])&0xffff);
  543. break;
  544. case DataBuffer.TYPE_INT:
  545. int[] iarray = (int[])obj;
  546. data.setElem(y*scanlineStride+x, iarray[0]);
  547. break;
  548. }
  549. }
  550. /**
  551. * Sets a pixel in the DataBuffer using an int array of samples for input.
  552. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  553. * not in bounds.
  554. * @param x The X coordinate of the pixel location.
  555. * @param y The Y coordinate of the pixel location.
  556. * @param iArray The input samples in an int array.
  557. * @param data The DataBuffer containing the image data.
  558. * @see #getPixel(int, int, int[], DataBuffer)
  559. */
  560. public void setPixel(int x, int y,
  561. int iArray[],
  562. DataBuffer data) {
  563. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  564. throw new ArrayIndexOutOfBoundsException
  565. ("Coordinate out of bounds!");
  566. }
  567. int lineOffset = y * scanlineStride + x;
  568. int value = data.getElem(lineOffset);
  569. for (int i=0; i < numBands; i++) {
  570. value &= ~bitMasks[i];
  571. value |= ((iArray[i] << bitOffsets[i]) & bitMasks[i]);
  572. }
  573. data.setElem(lineOffset, value);
  574. }
  575. /**
  576. * Sets all samples for a rectangle of pixels from an int array containing
  577. * one sample per array element.
  578. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  579. * not in bounds.
  580. * @param x The X coordinate of the upper left pixel location.
  581. * @param y The Y coordinate of the upper left pixel location.
  582. * @param w The width of the pixel rectangle.
  583. * @param h The height of the pixel rectangle.
  584. * @param iArray The input samples in an int array.
  585. * @param data The DataBuffer containing the image data.
  586. * @see #getPixels(int, int, int, int, int[], DataBuffer)
  587. */
  588. public void setPixels(int x, int y, int w, int h,
  589. int iArray[], DataBuffer data) {
  590. if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
  591. throw new ArrayIndexOutOfBoundsException
  592. ("Coordinate out of bounds!");
  593. }
  594. int lineOffset = y*scanlineStride + x;
  595. int srcOffset = 0;
  596. for (int i = 0; i < h; i++) {
  597. for (int j = 0; j < w; j++) {
  598. int value = data.getElem(lineOffset+j);
  599. for (int k=0; k < numBands; k++) {
  600. value &= ~bitMasks[k];
  601. int srcValue = iArray[srcOffset++];
  602. value |= ((srcValue << bitOffsets[k])
  603. & bitMasks[k]);
  604. }
  605. data.setElem(lineOffset+j, value);
  606. }
  607. lineOffset += scanlineStride;
  608. }
  609. }
  610. /**
  611. * Sets a sample in the specified band for the pixel located at (x,y)
  612. * in the DataBuffer using an int for input.
  613. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  614. * not in bounds.
  615. * @param x The X coordinate of the pixel location.
  616. * @param y The Y coordinate of the pixel location.
  617. * @param b The band to set.
  618. * @param s The input sample as an int.
  619. * @param data The DataBuffer containing the image data.
  620. * @see #getSample(int, int, int, DataBuffer)
  621. */
  622. public void setSample(int x, int y, int b, int s,
  623. DataBuffer data) {
  624. // Bounds check for 'b' will be performed automatically
  625. if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  626. throw new ArrayIndexOutOfBoundsException
  627. ("Coordinate out of bounds!");
  628. }
  629. int value = data.getElem(y*scanlineStride + x);
  630. value &= ~bitMasks[b];
  631. value |= (s << bitOffsets[b]) & bitMasks[b];
  632. data.setElem(y*scanlineStride + x,value);
  633. }
  634. /**
  635. * Sets the samples in the specified band for the specified rectangle
  636. * of pixels from an int array containing one sample per array element.
  637. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  638. * not in bounds.
  639. * @param x The X coordinate of the upper left pixel location.
  640. * @param y The Y coordinate of the upper left pixel location.
  641. * @param w The width of the pixel rectangle.
  642. * @param h The height of the pixel rectangle.
  643. * @param b The band to set.
  644. * @param iArray The input samples in an int array.
  645. * @param data The DataBuffer containing the image data.
  646. * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
  647. */
  648. public void setSamples(int x, int y, int w, int h, int b,
  649. int iArray[], DataBuffer data) {
  650. // Bounds check for 'b' will be performed automatically
  651. if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
  652. throw new ArrayIndexOutOfBoundsException
  653. ("Coordinate out of bounds!");
  654. }
  655. int lineOffset = y*scanlineStride + x;
  656. int srcOffset = 0;
  657. for (int i = 0; i < h; i++) {
  658. for (int j = 0; j < w; j++) {
  659. int value = data.getElem(lineOffset+j);
  660. value &= ~bitMasks[b];
  661. int sample = iArray[srcOffset++];
  662. value |= ((int)sample << bitOffsets[b]) & bitMasks[b];
  663. data.setElem(lineOffset+j,value);
  664. }
  665. lineOffset += scanlineStride;
  666. }
  667. }
  668. public boolean equals(Object o) {
  669. if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
  670. return false;
  671. }
  672. SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel)o;
  673. return this.width == that.width &&
  674. this.height == that.height &&
  675. this.numBands == that.numBands &&
  676. this.dataType == that.dataType &&
  677. Arrays.equals(this.bitMasks, that.bitMasks) &&
  678. Arrays.equals(this.bitOffsets, that.bitOffsets) &&
  679. Arrays.equals(this.bitSizes, that.bitSizes) &&
  680. this.maxBitSize == that.maxBitSize &&
  681. this.scanlineStride == that.scanlineStride;
  682. }
  683. // If we implement equals() we must also implement hashCode
  684. public int hashCode() {
  685. int hash = 0;
  686. hash = width;
  687. hash <<= 8;
  688. hash ^= height;
  689. hash <<= 8;
  690. hash ^= numBands;
  691. hash <<= 8;
  692. hash ^= dataType;
  693. hash <<= 8;
  694. for (int i = 0; i < bitMasks.length; i++) {
  695. hash ^= bitMasks[i];
  696. hash <<= 8;
  697. }
  698. for (int i = 0; i < bitOffsets.length; i++) {
  699. hash ^= bitOffsets[i];
  700. hash <<= 8;
  701. }
  702. for (int i = 0; i < bitSizes.length; i++) {
  703. hash ^= bitSizes[i];
  704. hash <<= 8;
  705. }
  706. hash ^= maxBitSize;
  707. hash <<= 8;
  708. hash ^= scanlineStride;
  709. return hash;
  710. }
  711. }