1. /*
  2. * @(#)SinglePixelPackedSampleModel.java 1.33 00/02/02
  3. *
  4. * Copyright 1997-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. /* ****************************************************************
  11. ******************************************************************
  12. ******************************************************************
  13. *** COPYRIGHT (c) Eastman Kodak Company, 1997
  14. *** As an unpublished work pursuant to Title 17 of the United
  15. *** States Code. All rights reserved.
  16. ******************************************************************
  17. ******************************************************************
  18. ******************************************************************/
  19. package java.awt.image;
  20. /**
  21. * This class represents pixel data packed such that the N samples which make
  22. * up a single pixel are stored in a single data array element, and each data
  23. * data array element holds samples for only one pixel.
  24. * This class supports
  25. * {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
  26. * {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
  27. * {@link DataBuffer#TYPE_INT TYPE_INT} data types.
  28. * All data array elements reside
  29. * in the first bank of a DataBuffer. Accessor methods are provided so
  30. * that the image data can be manipulated directly. Scanline stride is the
  31. * number of data array elements between a given sample and the corresponding
  32. * sample in the same column of the next scanline. Bit masks are the masks
  33. * required to extract the samples representing the bands of the pixel.
  34. * Bit offsets are the offsets in bits into the data array
  35. * element of the samples representing the bands of the pixel.
  36. * <p>
  37. * The following code illustrates extracting the bits of the sample
  38. * representing band <code>b</code> for pixel <code>x,y</code>
  39. * from DataBuffer <code>data</code>:
  40. * <pre>
  41. * int sample = data.getElem(y * scanlineStride + x);
  42. * sample = (sample & bitMasks[b]) >>> bitOffsets[b];
  43. * </pre>
  44. */
  45. public class SinglePixelPackedSampleModel extends SampleModel
  46. {
  47. /** Bit masks for all bands of the image data. */
  48. private int bitMasks[];
  49. /** Bit Offsets for all bands of the image data. */
  50. private int bitOffsets[];
  51. /** Bit sizes for all the bands of the image data. */
  52. private int bitSizes[];
  53. /** Maximum bit size. */
  54. private int maxBitSize;
  55. /** Line stride of the region of image data described by this
  56. * SinglePixelPackedSampleModel.
  57. */
  58. private int scanlineStride;
  59. private static native void initIDs();
  60. static {
  61. ColorModel.loadLibraries();
  62. initIDs();
  63. }
  64. /**
  65. * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands.
  66. * Each sample is stored in a data array element in the position of
  67. * its corresponding bit mask. Each bit mask must be contiguous and
  68. * masks must not overlap.
  69. * @param dataType The data type for storing samples.
  70. * @param w The width (in pixels) of the region of the
  71. * image data described.
  72. * @param h The height (in pixels) of the region of the
  73. * image data described.
  74. * @param bitMasks The bit masks for all bands.
  75. * @throws IllegalArgumentException if <code>dataType</code> is not
  76. * either <code>DataBuffer.TYPE_BYTE</code>,
  77. * <code>DataBuffer.TYPE_USHORT</code>, or
  78. * <code>DataBuffer.TYPE_INT</code>
  79. */
  80. public SinglePixelPackedSampleModel(int dataType, int w, int h,
  81. int bitMasks[]) {
  82. this(dataType, w, h, w, bitMasks);
  83. if (dataType != DataBuffer.TYPE_BYTE &&
  84. dataType != DataBuffer.TYPE_USHORT &&
  85. dataType != DataBuffer.TYPE_INT) {
  86. throw new IllegalArgumentException("Unsupported data type "+
  87. dataType);
  88. }
  89. }
  90. /**
  91. * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands
  92. * and a scanline stride equal to scanlineStride data array elements.
  93. * Each sample is stored in a data array element in the position of
  94. * its corresponding bit mask. Each bit mask must be contiguous and
  95. * masks must not overlap.
  96. * @param dataType The data type for storing samples.
  97. * @param w The width (in pixels) of the region of
  98. * image data described.
  99. * @param h The height (in pixels) of the region of
  100. * image data described.
  101. * @param scanlineStride The line stride of the image data.
  102. * @param bitMasks The bit masks for all bands.
  103. * @throws IllegalArgumentException if <code>w</code> or
  104. * <code>h</code> is not greater than 0
  105. * @throws IllegalArgumentException if any mask in
  106. * <code>bitMask</code> is not contiguous
  107. * @throws IllegalArgumentException if <code>dataType</code> is not
  108. * either <code>DataBuffer.TYPE_BYTE</code>,
  109. * <code>DataBuffer.TYPE_USHORT</code>, or
  110. * <code>DataBuffer.TYPE_INT</code>
  111. */
  112. public SinglePixelPackedSampleModel(int dataType, int w, int h,
  113. int scanlineStride, int bitMasks[]) {
  114. super(dataType, w, h, bitMasks.length);
  115. if (dataType != DataBuffer.TYPE_BYTE &&
  116. dataType != DataBuffer.TYPE_USHORT &&
  117. dataType != DataBuffer.TYPE_INT) {
  118. throw new IllegalArgumentException("Unsupported data type "+
  119. dataType);
  120. }
  121. this.dataType = dataType;
  122. this.bitMasks = (int[]) bitMasks.clone();
  123. this.scanlineStride = scanlineStride;
  124. this.bitOffsets = new int[numBands];
  125. this.bitSizes = new int[numBands];
  126. this.maxBitSize = 0;
  127. for (int i=0; i<numBands; i++) {
  128. int bitOffset = 0, bitSize = 0, mask;
  129. mask = bitMasks[i];
  130. if (mask != 0) {
  131. while ((mask & 1) == 0) {
  132. mask = mask >>> 1;
  133. bitOffset++;
  134. }
  135. while ((mask & 1) == 1) {
  136. mask = mask >>> 1;
  137. bitSize++;
  138. }
  139. if (mask != 0) {
  140. throw new IllegalArgumentException("Mask "+bitMasks[i]+
  141. " must be contiguous");
  142. }
  143. }
  144. bitOffsets[i] = bitOffset;
  145. bitSizes[i] = bitSize;
  146. if (bitSize > maxBitSize) {
  147. maxBitSize = bitSize;
  148. }
  149. }
  150. }
  151. /**
  152. * Returns the number of data elements needed to transfer one pixel
  153. * via the getDataElements and setDataElements methods.
  154. * For a SinglePixelPackedSampleModel, this is one.
  155. */
  156. public int getNumDataElements() {
  157. return 1;
  158. }
  159. /**
  160. * Returns the size of the buffer (in data array elements)
  161. * needed for a data buffer that matches this
  162. * SinglePixelPackedSampleModel.
  163. */
  164. private long getBufferSize() {
  165. long size = scanlineStride * (height-1) + width;
  166. return size;
  167. }
  168. /**
  169. * This creates a new SinglePixelPackedSampleModel with the specified
  170. * width and height. The new SinglePixelPackedSampleModel will have the
  171. * same storage data type and bit masks as this
  172. * SinglePixelPackedSampleModel.
  173. * @param w the width of the resulting <code>SampleModel</code>
  174. * @param h the height of the resulting <code>SampleModel</code>
  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. */
  237. public int getOffset(int x, int y) {
  238. int offset = y * scanlineStride + x;
  239. return offset;
  240. }
  241. /** Returns the bit offsets into the data array element representing
  242. * a pixel for all bands. */
  243. public int [] getBitOffsets() {
  244. return (int[])bitOffsets.clone();
  245. }
  246. /** Returns the bit masks for all bands. */
  247. public int [] getBitMasks() {
  248. return (int[])bitMasks.clone();
  249. }
  250. /** Returns the scanline stride of this SinglePixelPackedSampleModel. */
  251. public int getScanlineStride() {
  252. return scanlineStride;
  253. }
  254. /**
  255. * This creates a new SinglePixelPackedSampleModel with a subset of the
  256. * bands of this SinglePixelPackedSampleModel. The new
  257. * SinglePixelPackedSampleModel can be used with any DataBuffer that the
  258. * existing SinglePixelPackedSampleModel can be used with. The new
  259. * SinglePixelPackedSampleModel/DataBuffer combination will represent
  260. * an image with a subset of the bands of the original
  261. * SinglePixelPackedSampleModel/DataBuffer combination.
  262. * @exception RasterFormatException if the length of the bands argument is
  263. * greater than the number of bands in
  264. * the sample model.
  265. */
  266. public SampleModel createSubsetSampleModel(int bands[]) {
  267. if (bands.length > numBands)
  268. throw new RasterFormatException("There are only " +
  269. numBands +
  270. " bands");
  271. int newBitMasks[] = new int[bands.length];
  272. for (int i=0; i<bands.length; i++)
  273. newBitMasks[i] = bitMasks[bands[i]];
  274. return new SinglePixelPackedSampleModel(this.dataType, width, height,
  275. this.scanlineStride, newBitMasks);
  276. }
  277. /**
  278. * Returns data for a single pixel in a primitive array of type
  279. * TransferType. For a SinglePixelPackedSampleModel, the array will
  280. * have one element, and the type will be the same as the storage
  281. * data type. Generally, obj
  282. * should be passed in as null, so that the Object will be created
  283. * automatically and will be of the right primitive data type.
  284. * <p>
  285. * The following code illustrates transferring data for one pixel from
  286. * DataBuffer <code>db1</code>, whose storage layout is described by
  287. * SinglePixelPackedSampleModel <code>sppsm1</code>, to
  288. * DataBuffer <code>db2</code>, whose storage layout is described by
  289. * SinglePixelPackedSampleModel <code>sppsm2</code>.
  290. * The transfer will generally be more efficient than using
  291. * getPixel/setPixel.
  292. * <pre>
  293. * SinglePixelPackedSampleModel sppsm1, sppsm2;
  294. * DataBufferInt db1, db2;
  295. * sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
  296. * db1), db2);
  297. * </pre>
  298. * Using getDataElements/setDataElements to transfer between two
  299. * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
  300. * the same number of bands, corresponding bands have the same number of
  301. * bits per sample, and the TransferTypes are the same.
  302. * <p>
  303. * If obj is non-null, it should be a primitive array of type TransferType.
  304. * Otherwise, a ClassCastException is thrown. An
  305. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  306. * not in bounds, or if obj is non-null and is not large enough to hold
  307. * the pixel data.
  308. * @param x The X coordinate of the pixel location.
  309. * @param y The Y coordinate of the pixel location.
  310. * @param obj If non-null, a primitive array in which to return
  311. * the pixel data.
  312. * @param data The DataBuffer containing the image data.
  313. */
  314. public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
  315. int type = getTransferType();
  316. switch(type) {
  317. case DataBuffer.TYPE_BYTE:
  318. byte[] bdata;
  319. if (obj == null)
  320. bdata = new byte[1];
  321. else
  322. bdata = (byte[])obj;
  323. bdata[0] = (byte)data.getElem(y * scanlineStride + x);
  324. obj = (Object)bdata;
  325. break;
  326. case DataBuffer.TYPE_USHORT:
  327. short[] sdata;
  328. if (obj == null)
  329. sdata = new short[1];
  330. else
  331. sdata = (short[])obj;
  332. sdata[0] = (short)data.getElem(y * scanlineStride + x);
  333. obj = (Object)sdata;
  334. break;
  335. case DataBuffer.TYPE_INT:
  336. int[] idata;
  337. if (obj == null)
  338. idata = new int[1];
  339. else
  340. idata = (int[])obj;
  341. idata[0] = data.getElem(y * scanlineStride + x);
  342. obj = (Object)idata;
  343. break;
  344. }
  345. return obj;
  346. }
  347. /**
  348. * Returns all samples in for the specified pixel in an int array.
  349. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  350. * not in bounds.
  351. * @param x The X coordinate of the pixel location.
  352. * @param y The Y coordinate of the pixel location.
  353. * @param iArray If non-null, returns the samples in this array
  354. * @param data The DataBuffer containing the image data.
  355. */
  356. public int [] getPixel(int x, int y, int iArray[], DataBuffer data) {
  357. int pixels[];
  358. if (iArray == null) {
  359. pixels = new int [numBands];
  360. } else {
  361. pixels = iArray;
  362. }
  363. int value = data.getElem(y * scanlineStride + x);
  364. for (int i=0; i<numBands; i++) {
  365. pixels[i] = (value & bitMasks[i]) >>> bitOffsets[i];
  366. }
  367. return pixels;
  368. }
  369. /**
  370. * Returns all samples for the specified rectangle of pixels in
  371. * an int array, one sample per array element.
  372. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  373. * not in bounds.
  374. * @param x The X coordinate of the upper left pixel location.
  375. * @param y The Y coordinate of the upper left pixel location.
  376. * @param w The width of the pixel rectangle.
  377. * @param h The height of the pixel rectangle.
  378. * @param iArray If non-null, returns the samples in this array.
  379. * @param data The DataBuffer containing the image data.
  380. */
  381. public int[] getPixels(int x, int y, int w, int h,
  382. int iArray[], DataBuffer data) {
  383. int pixels[];
  384. if (iArray != null) {
  385. pixels = iArray;
  386. } else {
  387. pixels = new int [w*h*numBands];
  388. }
  389. int lineOffset = y*scanlineStride + x;
  390. int dstOffset = 0;
  391. for (int i = 0; i < h; i++) {
  392. for (int j = 0; j < w; j++) {
  393. int value = data.getElem(lineOffset+j);
  394. for (int k=0; k < numBands; k++) {
  395. pixels[dstOffset++] =
  396. ((value & bitMasks[k]) >>> bitOffsets[k]);
  397. }
  398. }
  399. lineOffset += scanlineStride;
  400. }
  401. return pixels;
  402. }
  403. /**
  404. * Returns as int the sample in a specified band for the pixel
  405. * located at (x,y).
  406. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  407. * not in bounds.
  408. * @param x The X coordinate of the pixel location.
  409. * @param y The Y coordinate of the pixel location.
  410. * @param b The band to return.
  411. * @param data The DataBuffer containing the image data.
  412. */
  413. public int getSample(int x, int y, int b, DataBuffer data) {
  414. int sample = data.getElem(y * scanlineStride + x);
  415. return ((sample & bitMasks[b]) >>> bitOffsets[b]);
  416. }
  417. /**
  418. * Returns the samples for a specified band for the specified rectangle
  419. * of pixels in an int array, one sample per array element.
  420. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  421. * not in bounds.
  422. * @param x The X coordinate of the upper left pixel location.
  423. * @param y The Y coordinate of the upper left pixel location.
  424. * @param w The width of the pixel rectangle.
  425. * @param h The height of the pixel rectangle.
  426. * @param b The band to return.
  427. * @param iArray If non-null, returns the samples in this array.
  428. * @param data The DataBuffer containing the image data.
  429. */
  430. public int[] getSamples(int x, int y, int w, int h, int b,
  431. int iArray[], DataBuffer data) {
  432. int samples[];
  433. if (iArray != null) {
  434. samples = iArray;
  435. } else {
  436. samples = new int [w*h];
  437. }
  438. int lineOffset = y*scanlineStride + x;
  439. int dstOffset = 0;
  440. for (int i = 0; i < h; i++) {
  441. for (int j = 0; j < w; j++) {
  442. int value = data.getElem(lineOffset+j);
  443. samples[dstOffset++] =
  444. ((value & bitMasks[b]) >>> bitOffsets[b]);
  445. }
  446. lineOffset += scanlineStride;
  447. }
  448. return samples;
  449. }
  450. /**
  451. * Sets the data for a single pixel in the specified DataBuffer from a
  452. * primitive array of type TransferType. For a
  453. * SinglePixelPackedSampleModel, only the first element of the array
  454. * will hold valid data, and the type of the array must be the same as
  455. * the storage data type of the SinglePixelPackedSampleModel.
  456. * <p>
  457. * The following code illustrates transferring data for one pixel from
  458. * DataBuffer <code>db1</code>, whose storage layout is described by
  459. * SinglePixelPackedSampleModel <code>sppsm1</code>,
  460. * to DataBuffer <code>db2</code>, whose storage layout is described by
  461. * SinglePixelPackedSampleModel <code>sppsm2</code>.
  462. * The transfer will generally be more efficient than using
  463. * getPixel/setPixel.
  464. * <pre>
  465. * SinglePixelPackedSampleModel sppsm1, sppsm2;
  466. * DataBufferInt db1, db2;
  467. * sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
  468. * db1), db2);
  469. * </pre>
  470. * Using getDataElements/setDataElements to transfer between two
  471. * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
  472. * the same number of bands, corresponding bands have the same number of
  473. * bits per sample, and the TransferTypes are the same.
  474. * <p>
  475. * obj must be a primitive array of type TransferType. Otherwise,
  476. * a ClassCastException is thrown. An
  477. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  478. * not in bounds, or if obj is not large enough to hold the pixel data.
  479. * @param x The X coordinate of the pixel location.
  480. * @param y The Y coordinate of the pixel location.
  481. * @param obj A primitive array containing pixel data.
  482. * @param data The DataBuffer containing the image data.
  483. */
  484. public void setDataElements(int x, int y, Object obj, DataBuffer data) {
  485. int type = getTransferType();
  486. switch(type) {
  487. case DataBuffer.TYPE_BYTE:
  488. byte[] barray = (byte[])obj;
  489. data.setElem(y*scanlineStride+x, ((int)barray[0])&0xff);
  490. break;
  491. case DataBuffer.TYPE_USHORT:
  492. short[] sarray = (short[])obj;
  493. data.setElem(y*scanlineStride+x, ((int)sarray[0])&0xffff);
  494. break;
  495. case DataBuffer.TYPE_INT:
  496. int[] iarray = (int[])obj;
  497. data.setElem(y*scanlineStride+x, iarray[0]);
  498. break;
  499. }
  500. }
  501. /**
  502. * Sets a pixel in the DataBuffer using an int array of samples for input.
  503. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  504. * not in bounds.
  505. * @param x The X coordinate of the pixel location.
  506. * @param y The Y coordinate of the pixel location.
  507. * @param iArray The input samples in an int array.
  508. * @param data The DataBuffer containing the image data.
  509. */
  510. public void setPixel(int x, int y,
  511. int iArray[],
  512. DataBuffer data) {
  513. int value = 0;
  514. for (int i=0; i < numBands; i++) {
  515. value |= ((iArray[i] << bitOffsets[i]) & bitMasks[i]);
  516. }
  517. data.setElem(y*scanlineStride+x, value);
  518. }
  519. /**
  520. * Sets all samples for a rectangle of pixels from an int array containing
  521. * one sample per array element.
  522. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  523. * not in bounds.
  524. * @param x The X coordinate of the upper left pixel location.
  525. * @param y The Y coordinate of the upper left pixel location.
  526. * @param w The width of the pixel rectangle.
  527. * @param h The height of the pixel rectangle.
  528. * @param iArray The input samples in an int array.
  529. * @param data The DataBuffer containing the image data.
  530. */
  531. public void setPixels(int x, int y, int w, int h,
  532. int iArray[], DataBuffer data) {
  533. int lineOffset = y*scanlineStride + x;
  534. int srcOffset = 0;
  535. for (int i = 0; i < h; i++) {
  536. for (int j = 0; j < w; j++) {
  537. int value = 0;
  538. for (int k=0; k < numBands; k++) {
  539. int srcValue = iArray[srcOffset++];
  540. value |= ((srcValue << bitOffsets[k])
  541. & bitMasks[k]);
  542. }
  543. data.setElem(lineOffset+j,value);
  544. }
  545. lineOffset += scanlineStride;
  546. }
  547. }
  548. /**
  549. * Sets a sample in the specified band for the pixel located at (x,y)
  550. * in the DataBuffer using an int for input.
  551. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  552. * not in bounds.
  553. * @param x The X coordinate of the pixel location.
  554. * @param y The Y coordinate of the pixel location.
  555. * @param b The band to set.
  556. * @param s The input sample as an int.
  557. * @param data The DataBuffer containing the image data.
  558. */
  559. public void setSample(int x, int y, int b, int s,
  560. DataBuffer data) {
  561. int value = data.getElem(y*scanlineStride + x);
  562. value &= ~bitMasks[b];
  563. value |= (s << bitOffsets[b]) & bitMasks[b];
  564. data.setElem(y*scanlineStride + x,value);
  565. }
  566. /**
  567. * Sets the samples in the specified band for the specified rectangle
  568. * of pixels from an int array containing one sample per array element.
  569. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  570. * not in bounds.
  571. * @param x The X coordinate of the upper left pixel location.
  572. * @param y The Y coordinate of the upper left pixel location.
  573. * @param w The width of the pixel rectangle.
  574. * @param h The height of the pixel rectangle.
  575. * @param b The band to set.
  576. * @param iArray The input samples in an int array.
  577. * @param data The DataBuffer containing the image data.
  578. */
  579. public void setSamples(int x, int y, int w, int h, int b,
  580. int iArray[], DataBuffer data) {
  581. int lineOffset = y*scanlineStride + x;
  582. int srcOffset = 0;
  583. for (int i = 0; i < h; i++) {
  584. for (int j = 0; j < w; j++) {
  585. int value = data.getElem(lineOffset+j);
  586. value &= ~bitMasks[b];
  587. int sample = iArray[srcOffset++];
  588. value |= ((int)sample << bitOffsets[b]) & bitMasks[b];
  589. data.setElem(lineOffset+j,value);
  590. }
  591. lineOffset += scanlineStride;
  592. }
  593. }
  594. }