1. /*
  2. * @(#)ComponentSampleModel.java 1.31 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 image data which is stored such that each sample
  22. * of a pixel occupies one data element of the DataBuffer. It stores the
  23. * N samples which make up a pixel in N separate data array elements.
  24. * Different bands may be in different banks of the DataBuffer.
  25. * Accessor methods are provided so that image data can be manipulated
  26. * directly. This class can support different kinds of interleaving, e.g.
  27. * band interleaving, scanline interleaving, and pixel interleaving.
  28. * Pixel stride is the number of data array elements between two samples
  29. * for the same band on the same scanline. Scanline stride is the number
  30. * of data array elements between a given sample and the corresponding sample
  31. * in the same column of the next scanline. Band offsets denote the number
  32. * of data array elements from the first data array element of the bank
  33. * of the DataBuffer holding each band to the first sample of the band.
  34. * The bands are numbered from 0 to N-1. This class can represent image
  35. * data for which each sample is an integral number which can be
  36. * stored in 8, 16, or 32 bits (all samples of a given ComponentSampleModel
  37. * are stored with the same precision). All strides and offsets must be
  38. * non-negative. This class supports
  39. * {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
  40. * {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
  41. * {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
  42. * {@link DataBuffer#TYPE_INT TYPE_INT},
  43. * @see java.awt.image.PixelInterleavedSampleModel
  44. * @see java.awt.image.BandedSampleModel
  45. */
  46. public class ComponentSampleModel extends SampleModel
  47. {
  48. /** Offsets for all bands in data array elements. */
  49. protected int bandOffsets[];
  50. /** Index for each bank storing a band of image data. */
  51. protected int[] bankIndices;
  52. /**
  53. * The number of bands in this
  54. * <code>ComponentSampleModel</code>.
  55. */
  56. protected int numBands = 1;
  57. /**
  58. * The number of banks in this
  59. * <code>ComponentSampleModel</code>.
  60. */
  61. protected int numBanks = 1;
  62. /**
  63. * Line stride (in data array elements) of the region of image
  64. * data described by this ComponentSampleModel.
  65. */
  66. protected int scanlineStride;
  67. /** Pixel stride (in data array elements) of the region of image
  68. * data described by this ComponentSampleModel.
  69. */
  70. protected int pixelStride;
  71. static private native void initIDs();
  72. static {
  73. ColorModel.loadLibraries();
  74. initIDs();
  75. }
  76. /**
  77. * Constructs a ComponentSampleModel with the specified parameters.
  78. * The number of bands will be given by the length of the bandOffsets array.
  79. * All bands will be stored in the first bank of the DataBuffer.
  80. * @param dataType The data type for storing samples.
  81. * @param w The width (in pixels) of the region of
  82. * image data described.
  83. * @param h The height (in pixels) of the region of
  84. * image data described.
  85. * @param pixelStride The pixel stride of the region of image
  86. * data described.
  87. * @param scanlineStride The line stride of the region of image
  88. * data described.
  89. * @param bandOffsets The offsets of all bands.
  90. * @throws IllegalArgumentException if <code>w</code> or
  91. * <code>h</code> is not greater than 0
  92. * @throws IllegalArgumentException if <code>pixelStride</code>
  93. * is less than 0
  94. * @throws IllegalArgumentException if <code>scanlineStride</code>
  95. * is less than 0
  96. * @throws IllegalArgumentException if <code>numBands</code>
  97. * is less than 1
  98. * @throws IllegalArgumentException if the product of <code>w</code>
  99. * and <code>h</code> is greater than
  100. * <code>Integer.MAX_VALUE</code>
  101. * @throws IllegalArgumentException if <code>dataType</code> is not
  102. * one of the supported data types
  103. */
  104. public ComponentSampleModel(int dataType,
  105. int w, int h,
  106. int pixelStride,
  107. int scanlineStride,
  108. int bandOffsets[]) {
  109. super(dataType, w, h, bandOffsets.length);
  110. this.dataType = dataType;
  111. this.pixelStride = pixelStride;
  112. this.scanlineStride = scanlineStride;
  113. this.bandOffsets = (int[])bandOffsets.clone();
  114. numBands = bandOffsets.length;
  115. if (pixelStride < 0) {
  116. throw new IllegalArgumentException("Pixel stride must be >= 0");
  117. }
  118. if (scanlineStride < 0) {
  119. throw new IllegalArgumentException("Scanline stride must be >= 0");
  120. }
  121. if (numBands < 1) {
  122. throw new IllegalArgumentException("Must have at least one band.");
  123. }
  124. bankIndices = new int[numBands];
  125. for (int i=0; i<numBands; i++) {
  126. bankIndices[i] = 0;
  127. }
  128. }
  129. /**
  130. * Constructs a ComponentSampleModel with the specified parameters.
  131. * The number of bands will be given by the length of the bandOffsets array.
  132. * Different bands may be stored in different banks of the DataBuffer.
  133. * @param dataType The data type for storing samples.
  134. * @param w The width (in pixels) of the region of
  135. * image data described.
  136. * @param h The height (in pixels) of the region of
  137. * image data described.
  138. * @param pixelStride The pixel stride of the region of image
  139. * data described.
  140. * @param scanlineStride The line stride of the region of image
  141. * data described.
  142. * @param bandIndices The bank indices of all bands.
  143. * @param bandOffsets The band offsets of all bands.
  144. * @throws IllegalArgumentException if <code>w</code> or
  145. * <code>h</code> is not greater than 0
  146. * @throws IllegalArgumentException if <code>pixelStride</code>
  147. * is less than 0
  148. * @throws IllegalArgumentException if <code>scanlineStride</code>
  149. * is less than 0
  150. * @throws IllegalArgumentException if the length of
  151. * <code>bankIndices</code> does not equal the length of
  152. * <code>bankOffsets</code>
  153. * @throws IllegalArgumentException if any of the bank indices
  154. * of <code>bandIndices</code> is less than 0
  155. */
  156. public ComponentSampleModel(int dataType,
  157. int w, int h,
  158. int pixelStride,
  159. int scanlineStride,
  160. int bankIndices[],
  161. int bandOffsets[]) {
  162. super(dataType, w, h, bandOffsets.length);
  163. this.dataType = dataType;
  164. this.pixelStride = pixelStride;
  165. this.scanlineStride = scanlineStride;
  166. this.bandOffsets = (int[])bandOffsets.clone();
  167. this.bankIndices = (int[]) bankIndices.clone();
  168. if (pixelStride < 0) {
  169. throw new IllegalArgumentException("Pixel stride must be >= 0");
  170. }
  171. if (scanlineStride < 0) {
  172. throw new IllegalArgumentException("Scanline stride must be >= 0");
  173. }
  174. int maxBank = bankIndices[0];
  175. if (maxBank < 0) {
  176. throw new IllegalArgumentException("Index of bank 0 is less than "+
  177. "0 ("+maxBank+")");
  178. }
  179. for (int i=1; i < bankIndices.length; i++) {
  180. if (bankIndices[i] > maxBank) {
  181. maxBank = bankIndices[i];
  182. }
  183. else if (bankIndices[i] < 0) {
  184. throw new IllegalArgumentException("Index of bank "+i+
  185. " is less than 0 ("+
  186. maxBank+")");
  187. }
  188. }
  189. numBanks = maxBank+1;
  190. numBands = bandOffsets.length;
  191. if (bandOffsets.length != bankIndices.length) {
  192. throw new IllegalArgumentException("Length of bandOffsets must "+
  193. "equal length of bankIndices.");
  194. }
  195. }
  196. /**
  197. * Returns the size of the data buffer (in data elements) needed
  198. * for a data buffer that matches this ComponentSampleModel.
  199. */
  200. private long getBufferSize() {
  201. int maxBandOff=bandOffsets[0];
  202. for (int i=1; i<bandOffsets.length; i++)
  203. maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
  204. long size = 0;
  205. if (maxBandOff >= 0)
  206. size += maxBandOff+1;
  207. if (pixelStride > 0)
  208. size += pixelStride * (width-1);
  209. if (scanlineStride > 0)
  210. size += scanlineStride*(height-1);
  211. return size;
  212. }
  213. /**
  214. * Preserves band ordering with new step factor...
  215. */
  216. int []orderBands(int orig[], int step) {
  217. int map[] = new int[orig.length];
  218. int ret[] = new int[orig.length];
  219. for (int i=0; i<map.length; i++) map[i] = i;
  220. for (int i = 0; i < ret.length; i++) {
  221. int index = i;
  222. for (int j = i+1; j < ret.length; j++) {
  223. if (orig[map[index]] > orig[map[j]]) {
  224. index = j;
  225. }
  226. }
  227. ret[map[index]] = i*step;
  228. map[index] = map[i];
  229. }
  230. return ret;
  231. }
  232. /**
  233. * Creates a new ComponentSampleModel with the specified
  234. * width and height. The new SampleModel will have the same
  235. * number of bands, storage data type, interleaving scheme, and
  236. * pixel stride as this SampleModel.
  237. * @param w the width of the resulting <code>SampleModel</code>
  238. * @param h the height of the resulting <code>SampleModel</code>
  239. * @throws IllegalArgumentException if <code>w</code> or
  240. * <code>h</code> is not greater than 0
  241. */
  242. public SampleModel createCompatibleSampleModel(int w, int h) {
  243. SampleModel ret=null;
  244. long size;
  245. int minBandOff=bandOffsets[0];
  246. int maxBandOff=bandOffsets[0];
  247. for (int i=1; i<bandOffsets.length; i++) {
  248. minBandOff = Math.min(minBandOff,bandOffsets[i]);
  249. maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
  250. }
  251. maxBandOff -= minBandOff;
  252. int bands = bandOffsets.length;
  253. int bandOff[];
  254. int pStride = Math.abs(pixelStride);
  255. int lStride = Math.abs(scanlineStride);
  256. int bStride = Math.abs(maxBandOff);
  257. if (pStride > lStride) {
  258. if (pStride > bStride) {
  259. if (lStride > bStride) { // pix > line > band
  260. bandOff = new int[bandOffsets.length];
  261. for (int i=0; i<bands; i++)
  262. bandOff[i] = bandOffsets[i]-minBandOff;
  263. lStride = bStride+1;
  264. pStride = lStride*h;
  265. } else { // pix > band > line
  266. bandOff = orderBands(bandOffsets,lStride*h);
  267. pStride = bands*lStride*h;
  268. }
  269. } else { // band > pix > line
  270. pStride = lStride*h;
  271. bandOff = orderBands(bandOffsets,pStride*w);
  272. }
  273. } else {
  274. if (pStride > bStride) { // line > pix > band
  275. bandOff = new int[bandOffsets.length];
  276. for (int i=0; i<bands; i++)
  277. bandOff[i] = bandOffsets[i]-minBandOff;
  278. pStride = bStride+1;
  279. lStride = pStride*w;
  280. } else {
  281. if (lStride > bStride) { // line > band > pix
  282. bandOff = orderBands(bandOffsets,pStride*w);
  283. lStride = bands*pStride*w;
  284. } else { // band > line > pix
  285. lStride = pStride*w;
  286. bandOff = orderBands(bandOffsets,lStride*h);
  287. }
  288. }
  289. }
  290. // make sure we make room for negative offsets...
  291. int base = 0;
  292. if (scanlineStride < 0) {
  293. base += lStride*h;
  294. lStride *= -1;
  295. }
  296. if (pixelStride < 0) {
  297. base += pStride*w;
  298. pStride *= -1;
  299. }
  300. for (int i=0; i<bands; i++)
  301. bandOff[i] += base;
  302. return new ComponentSampleModel(dataType, w, h, pStride,
  303. lStride, bandOff);
  304. }
  305. /**
  306. * This creates a new ComponentSampleModel with a subset of the bands
  307. * of this ComponentSampleModel. The new ComponentSampleModel can be
  308. * used with any DataBuffer that the existing ComponentSampleModel
  309. * can be used with. The new ComponentSampleModel/DataBuffer
  310. * combination will represent an image with a subset of the bands
  311. * of the original ComponentSampleModel/DataBuffer combination.
  312. */
  313. public SampleModel createSubsetSampleModel(int bands[]) {
  314. if (bands.length > bankIndices.length)
  315. throw new RasterFormatException("There are only " +
  316. bankIndices.length +
  317. " bands");
  318. int newBankIndices[] = new int[bands.length];
  319. int newBandOffsets[] = new int[bands.length];
  320. for (int i=0; i<bands.length; i++) {
  321. newBankIndices[i] = bankIndices[bands[i]];
  322. newBandOffsets[i] = bandOffsets[bands[i]];
  323. }
  324. return new ComponentSampleModel(this.dataType, width, height,
  325. this.pixelStride,
  326. this.scanlineStride,
  327. newBankIndices, newBandOffsets);
  328. }
  329. /**
  330. * Creates a DataBuffer that corresponds to this ComponentSampleModel.
  331. * The DataBuffer's data type, number of banks, and size
  332. * will be consistent with this ComponentSampleModel.
  333. */
  334. public DataBuffer createDataBuffer() {
  335. DataBuffer dataBuffer = null;
  336. int size = (int)getBufferSize();
  337. switch (dataType) {
  338. case DataBuffer.TYPE_BYTE:
  339. dataBuffer = new DataBufferByte(size, numBanks);
  340. break;
  341. case DataBuffer.TYPE_USHORT:
  342. dataBuffer = new DataBufferUShort(size, numBanks);
  343. break;
  344. case DataBuffer.TYPE_SHORT:
  345. dataBuffer = new DataBufferShort(size, numBanks);
  346. break;
  347. case DataBuffer.TYPE_INT:
  348. dataBuffer = new DataBufferInt(size, numBanks);
  349. break;
  350. }
  351. return dataBuffer;
  352. }
  353. /** Gets the offset for the first band of pixel (x,y).
  354. * A sample of the first band can be retrieved from a DataBuffer
  355. * <code>data</code> with a ComponentSampleModel <code>csm</code> as
  356. * <pre>
  357. * data.getElem(csm.getOffset(x, y));
  358. * </pre>
  359. */
  360. public int getOffset(int x, int y) {
  361. int offset = y*scanlineStride + x*pixelStride + bandOffsets[0];
  362. return offset;
  363. }
  364. /** Gets the offset for band b of pixel (x,y).
  365. * A sample of band <code>b</code> can be retrieved from a
  366. * DataBuffer <code>data</code>
  367. * with a ComponentSampleModel <code>csm</code> as
  368. * <pre>
  369. * data.getElem(csm.getOffset(x, y, b));
  370. * </pre>
  371. */
  372. public int getOffset(int x, int y, int b) {
  373. int offset = y*scanlineStride + x*pixelStride + bandOffsets[b];
  374. return offset;
  375. }
  376. /** Returns the number of bits per sample for all bands. */
  377. public final int[] getSampleSize() {
  378. int sampleSize[] = new int [numBands];
  379. int sizeInBits = getSampleSize(0);
  380. for (int i=0; i<numBands; i++)
  381. sampleSize[i] = sizeInBits;
  382. return sampleSize;
  383. }
  384. /** Returns the number of bits per sample for the specified band. */
  385. public final int getSampleSize(int band) {
  386. return DataBuffer.getDataTypeSize(dataType);
  387. }
  388. /** Returns the bank indices for all bands. */
  389. public final int [] getBankIndices() {
  390. return (int[]) bankIndices.clone();
  391. }
  392. /** Returns the band offset for all bands. */
  393. public final int [] getBandOffsets() {
  394. return (int[])bandOffsets.clone();
  395. }
  396. /** Returns the scanline stride of this ComponentSampleModel. */
  397. public final int getScanlineStride() {
  398. return scanlineStride;
  399. }
  400. /** Returns the pixel stride of this ComponentSampleModel. */
  401. public final int getPixelStride() {
  402. return pixelStride;
  403. }
  404. /**
  405. * Returns the number of data elements needed to transfer a pixel
  406. * via the getDataElements and setDataElements methods.
  407. * For a ComponentSampleModel this is identical to the
  408. * number of bands.
  409. * @see java.awt.image.SampleModel#getNumDataElements
  410. */
  411. public final int getNumDataElements() {
  412. return getNumBands();
  413. }
  414. /**
  415. * Returns data for a single pixel in a primitive array of type
  416. * TransferType. For a ComponentSampleModel, this will be the same
  417. * as the data type, and samples will be returned one per array
  418. * element. Generally, obj
  419. * should be passed in as null, so that the Object will be created
  420. * automatically and will be of the right primitive data type.
  421. * <p>
  422. * The following code illustrates transferring data for one pixel from
  423. * DataBuffer <code>db1</code>, whose storage layout is described by
  424. * ComponentSampleModel <code>csm1</code>, to DataBuffer <code>db2</code>,
  425. * whose storage layout is described by
  426. * ComponentSampleModel <code>csm2</code>.
  427. * The transfer will generally be more efficient than using
  428. * getPixel/setPixel.
  429. * <pre>
  430. * ComponentSampleModel csm1, csm2;
  431. * DataBufferInt db1, db2;
  432. * csm2.setDataElements(x, y,
  433. * csm1.getDataElements(x, y, null, db1), db2);
  434. * </pre>
  435. * Using getDataElements/setDataElements to transfer between two
  436. * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
  437. * the same number of bands, corresponding bands have the same number of
  438. * bits per sample, and the TransferTypes are the same.
  439. * <p>
  440. * If obj is non-null, it should be a primitive array of type TransferType.
  441. * Otherwise, a ClassCastException is thrown. An
  442. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  443. * not in bounds, or if obj is non-null and is not large enough to hold
  444. * the pixel data.
  445. * @param x The X coordinate of the pixel location.
  446. * @param y The Y coordinate of the pixel location.
  447. * @param obj If non-null, a primitive array in which to return
  448. * the pixel data.
  449. * @param data The DataBuffer containing the image data.
  450. */
  451. public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
  452. int type = getTransferType();
  453. int numDataElems = getNumDataElements();
  454. int pixelOffset = y*scanlineStride + x*pixelStride;
  455. switch(type) {
  456. case DataBuffer.TYPE_BYTE:
  457. byte[] bdata;
  458. if (obj == null)
  459. bdata = new byte[numDataElems];
  460. else
  461. bdata = (byte[])obj;
  462. for (int i=0; i<numDataElems; i++) {
  463. bdata[i] = (byte)data.getElem(bankIndices[i],
  464. pixelOffset + bandOffsets[i]);
  465. }
  466. obj = (Object)bdata;
  467. break;
  468. case DataBuffer.TYPE_USHORT:
  469. case DataBuffer.TYPE_SHORT:
  470. short[] sdata;
  471. if (obj == null)
  472. sdata = new short[numDataElems];
  473. else
  474. sdata = (short[])obj;
  475. for (int i=0; i<numDataElems; i++) {
  476. sdata[i] = (short)data.getElem(bankIndices[i],
  477. pixelOffset + bandOffsets[i]);
  478. }
  479. obj = (Object)sdata;
  480. break;
  481. case DataBuffer.TYPE_INT:
  482. int[] idata;
  483. if (obj == null)
  484. idata = new int[numDataElems];
  485. else
  486. idata = (int[])obj;
  487. for (int i=0; i<numDataElems; i++) {
  488. idata[i] = data.getElem(bankIndices[i],
  489. pixelOffset + bandOffsets[i]);
  490. }
  491. obj = (Object)idata;
  492. break;
  493. }
  494. return obj;
  495. }
  496. /**
  497. * Returns all samples for the specified pixel in an int array,
  498. * one sample per array element.
  499. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  500. * not in bounds.
  501. * @param x The X coordinate of the pixel location.
  502. * @param y The Y coordinate of the pixel location.
  503. * @param iArray If non-null, returns the samples in this array.
  504. * @param data The DataBuffer containing the image data.
  505. */
  506. public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
  507. int pixels[];
  508. if (iArray != null) {
  509. pixels = iArray;
  510. } else {
  511. pixels = new int [numBands];
  512. }
  513. int pixelOffset = y*scanlineStride + x*pixelStride;
  514. for (int i=0; i<numBands; i++) {
  515. pixels[i] = data.getElem(bankIndices[i],
  516. pixelOffset + bandOffsets[i]);
  517. }
  518. return pixels;
  519. }
  520. /**
  521. * Returns all samples for the specified rectangle of pixels in
  522. * an int array, one sample per array element.
  523. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  524. * not in bounds.
  525. * @param x The X coordinate of the upper left pixel location.
  526. * @param y The Y coordinate of the upper left pixel location.
  527. * @param w The width of the pixel rectangle.
  528. * @param h The height of the pixel rectangle.
  529. * @param iArray If non-null, returns the samples in this array.
  530. * @param data The DataBuffer containing the image data.
  531. */
  532. public int[] getPixels(int x, int y, int w, int h,
  533. int iArray[], DataBuffer data) {
  534. int pixels[];
  535. if (iArray != null) {
  536. pixels = iArray;
  537. } else {
  538. pixels = new int [w*h*numBands];
  539. }
  540. int lineOffset = y*scanlineStride + x*pixelStride;
  541. int srcOffset = 0;
  542. for (int i = 0; i < h; i++) {
  543. int pixelOffset = lineOffset;
  544. for (int j = 0; j < w; j++) {
  545. for (int k=0; k < numBands; k++) {
  546. pixels[srcOffset++] =
  547. data.getElem(bankIndices[k], pixelOffset + bandOffsets[k]);
  548. }
  549. pixelOffset += pixelStride;
  550. }
  551. lineOffset += scanlineStride;
  552. }
  553. return pixels;
  554. }
  555. /**
  556. * Returns as int the sample in a specified band for the pixel
  557. * located at (x,y).
  558. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  559. * not in bounds.
  560. * @param x The X coordinate of the pixel location.
  561. * @param y The Y coordinate of the pixel location.
  562. * @param b The band to return.
  563. * @param data The DataBuffer containing the image data.
  564. */
  565. public int getSample(int x, int y, int b, DataBuffer data) {
  566. int sample = data.getElem(bankIndices[b],
  567. y*scanlineStride + x*pixelStride +
  568. bandOffsets[b]);
  569. return sample;
  570. }
  571. /**
  572. * Returns the sample in a specified band
  573. * for the pixel located at (x,y) as a float.
  574. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  575. * not in bounds.
  576. * @param x The X coordinate of the pixel location.
  577. * @param y The Y coordinate of the pixel location.
  578. * @param b The band to return.
  579. * @param data The DataBuffer containing the image data.
  580. */
  581. public float getSampleFloat(int x, int y, int b, DataBuffer data) {
  582. float sample = data.getElemFloat(bankIndices[b],
  583. y*scanlineStride + x*pixelStride +
  584. bandOffsets[b]);
  585. return sample;
  586. }
  587. /**
  588. * Returns the sample in a specified band
  589. * for a pixel located at (x,y) as a double.
  590. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  591. * not in bounds.
  592. * @param x The X coordinate of the pixel location.
  593. * @param y The Y coordinate of the pixel location.
  594. * @param b The band to return.
  595. * @param data The DataBuffer containing the image data.
  596. */
  597. public double getSampleDouble(int x, int y, int b, DataBuffer data) {
  598. double sample = data.getElemDouble(bankIndices[b],
  599. y*scanlineStride + x*pixelStride +
  600. bandOffsets[b]);
  601. return sample;
  602. }
  603. /**
  604. * Returns the samples in a specified band for the specified rectangle
  605. * of pixels in an int array, one sample per data array element.
  606. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  607. * not in bounds.
  608. * @param x The X coordinate of the upper left pixel location.
  609. * @param y The Y coordinate of the upper left pixel location.
  610. * @param w The width of the pixel rectangle.
  611. * @param h The height of the pixel rectangle.
  612. * @param b The band to return.
  613. * @param iArray If non-null, returns the samples in this array.
  614. * @param data The DataBuffer containing the image data.
  615. */
  616. public int[] getSamples(int x, int y, int w, int h, int b,
  617. int iArray[], DataBuffer data) {
  618. int samples[];
  619. if (iArray != null) {
  620. samples = iArray;
  621. } else {
  622. samples = new int [w*h];
  623. }
  624. int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
  625. int srcOffset = 0;
  626. for (int i = 0; i < h; i++) {
  627. int sampleOffset = lineOffset;
  628. for (int j = 0; j < w; j++) {
  629. samples[srcOffset++] = data.getElem(bankIndices[b],
  630. sampleOffset);
  631. sampleOffset += pixelStride;
  632. }
  633. lineOffset += scanlineStride;
  634. }
  635. return samples;
  636. }
  637. /**
  638. * Sets the data for a single pixel in the specified DataBuffer from a
  639. * primitive array of type TransferType. For a ComponentSampleModel,
  640. * this will be the same as the data type, and samples are transferred
  641. * one per array element.
  642. * <p>
  643. * The following code illustrates transferring data for one pixel from
  644. * DataBuffer <code>db1</code>, whose storage layout is described by
  645. * ComponentSampleModel <code>csm1</code>, to DataBuffer <code>db2</code>,
  646. * whose storage layout is described by
  647. * ComponentSampleModel <code>csm2</code>.
  648. * The transfer will generally be more efficient than using
  649. * getPixel/setPixel.
  650. * <pre>
  651. * ComponentSampleModel csm1, csm2;
  652. * DataBufferInt db1, db2;
  653. * csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
  654. * db2);
  655. * </pre>
  656. * Using getDataElements/setDataElements to transfer between two
  657. * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
  658. * the same number of bands, corresponding bands have the same number of
  659. * bits per sample, and the TransferTypes are the same.
  660. * <p>
  661. * obj must be a primitive array of type TransferType. Otherwise,
  662. * a ClassCastException is thrown. An
  663. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  664. * not in bounds, or if obj is not large enough to hold the pixel data.
  665. * @param x The X coordinate of the pixel location.
  666. * @param y The Y coordinate of the pixel location.
  667. * @param obj A primitive array containing pixel data.
  668. * @param data The DataBuffer containing the image data.
  669. */
  670. public void setDataElements(int x, int y, Object obj, DataBuffer data) {
  671. int type = getTransferType();
  672. int numDataElems = getNumDataElements();
  673. int pixelOffset = y*scanlineStride + x*pixelStride;
  674. switch(type) {
  675. case DataBuffer.TYPE_BYTE:
  676. byte[] barray = (byte[])obj;
  677. for (int i=0; i<numDataElems; i++) {
  678. data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
  679. ((int)barray[i])&0xff);
  680. }
  681. break;
  682. case DataBuffer.TYPE_USHORT:
  683. case DataBuffer.TYPE_SHORT:
  684. short[] sarray = (short[])obj;
  685. for (int i=0; i<numDataElems; i++) {
  686. data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
  687. ((int)sarray[i])&0xffff);
  688. }
  689. break;
  690. case DataBuffer.TYPE_INT:
  691. int[] iarray = (int[])obj;
  692. for (int i=0; i<numDataElems; i++) {
  693. data.setElem(bankIndices[i],
  694. pixelOffset + bandOffsets[i], iarray[i]);
  695. }
  696. break;
  697. case DataBuffer.TYPE_FLOAT:
  698. float[] farray = (float[])obj;
  699. for (int i=0; i<numDataElems; i++) {
  700. data.setElemFloat(bankIndices[i],
  701. pixelOffset + bandOffsets[i], farray[i]);
  702. }
  703. break;
  704. case DataBuffer.TYPE_DOUBLE:
  705. double[] darray = (double[])obj;
  706. for (int i=0; i<numDataElems; i++) {
  707. data.setElemDouble(bankIndices[i],
  708. pixelOffset + bandOffsets[i], darray[i]);
  709. }
  710. break;
  711. }
  712. }
  713. /**
  714. * Sets a pixel in the DataBuffer using an int array of samples for input.
  715. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  716. * not in bounds.
  717. * @param x The X coordinate of the pixel location.
  718. * @param y The Y coordinate of the pixel location.
  719. * @param iArray The input samples in an int array.
  720. * @param data The DataBuffer containing the image data.
  721. */
  722. public void setPixel(int x, int y, int iArray[], DataBuffer data) {
  723. int pixelOffset = y*scanlineStride + x*pixelStride;
  724. for (int i=0; i<numBands; i++) {
  725. data.setElem(bankIndices[i],
  726. pixelOffset + bandOffsets[i],iArray[i]);
  727. }
  728. }
  729. /**
  730. * Sets all samples for a rectangle of pixels from an int array containing
  731. * one sample per array element.
  732. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  733. * not in bounds.
  734. * @param x The X coordinate of the upper left pixel location.
  735. * @param y The Y coordinate of the upper left pixel location.
  736. * @param w The width of the pixel rectangle.
  737. * @param h The height of the pixel rectangle.
  738. * @param iArray The input samples in an int array.
  739. * @param data The DataBuffer containing the image data.
  740. */
  741. public void setPixels(int x, int y, int w, int h,
  742. int iArray[], DataBuffer data) {
  743. int lineOffset = y*scanlineStride + x*pixelStride;
  744. int srcOffset = 0;
  745. for (int i = 0; i < h; i++) {
  746. int pixelOffset = lineOffset;
  747. for (int j = 0; j < w; j++) {
  748. for (int k=0; k < numBands; k++) {
  749. data.setElem(bankIndices[k], pixelOffset + bandOffsets[k],
  750. iArray[srcOffset++]);
  751. }
  752. pixelOffset += pixelStride;
  753. }
  754. lineOffset += scanlineStride;
  755. }
  756. }
  757. /**
  758. * Sets a sample in the specified band for the pixel located at (x,y)
  759. * in the DataBuffer using an int for input.
  760. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  761. * not in bounds.
  762. * @param x The X coordinate of the pixel location.
  763. * @param y The Y coordinate of the pixel location.
  764. * @param b The band to set.
  765. * @param s The input sample as an int.
  766. * @param data The DataBuffer containing the image data.
  767. */
  768. public void setSample(int x, int y, int b, int s,
  769. DataBuffer data) {
  770. data.setElem(bankIndices[b],
  771. y*scanlineStride + x*pixelStride + bandOffsets[b], s);
  772. }
  773. /**
  774. * Sets a sample in the specified band for the pixel located at (x,y)
  775. * in the DataBuffer using a float for input.
  776. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  777. * not in bounds.
  778. * @param x The X coordinate of the pixel location.
  779. * @param y The Y coordinate of the pixel location.
  780. * @param b The band to set.
  781. * @param s The input sample as a float.
  782. * @param data The DataBuffer containing the image data.
  783. */
  784. public void setSample(int x, int y, int b,
  785. float s ,
  786. DataBuffer data) {
  787. data.setElemFloat(bankIndices[b],
  788. y*scanlineStride + x*pixelStride + bandOffsets[b],
  789. s);
  790. }
  791. /**
  792. * Sets a sample in the specified band for the pixel located at (x,y)
  793. * in the DataBuffer using a double for input.
  794. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  795. * not in bounds.
  796. * @param x The X coordinate of the pixel location.
  797. * @param y The Y coordinate of the pixel location.
  798. * @param b The band to set.
  799. * @param s The input sample as a double.
  800. * @param data The DataBuffer containing the image data.
  801. */
  802. public void setSample(int x, int y, int b,
  803. double s,
  804. DataBuffer data) {
  805. data.setElemDouble(bankIndices[b],
  806. y*scanlineStride + x*pixelStride + bandOffsets[b],
  807. s);
  808. }
  809. /**
  810. * Sets the samples in the specified band for the specified rectangle
  811. * of pixels from an int array containing one sample per data array element.
  812. * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  813. * not in bounds.
  814. * @param x The X coordinate of the upper left pixel location.
  815. * @param y The Y coordinate of the upper left pixel location.
  816. * @param w The width of the pixel rectangle.
  817. * @param h The height of the pixel rectangle.
  818. * @param b The band to set.
  819. * @param iArray The input samples in an int array.
  820. * @param data The DataBuffer containing the image data.
  821. */
  822. public void setSamples(int x, int y, int w, int h, int b,
  823. int iArray[], DataBuffer data) {
  824. int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
  825. int srcOffset = 0;
  826. for (int i = 0; i < h; i++) {
  827. int sampleOffset = lineOffset;
  828. for (int j = 0; j < w; j++) {
  829. data.setElem(bankIndices[b], sampleOffset, iArray[srcOffset++]);
  830. sampleOffset += pixelStride;
  831. }
  832. lineOffset += scanlineStride;
  833. }
  834. }
  835. }