1. /*
  2. * @(#)WritableRaster.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. import java.awt.Rectangle;
  21. import java.awt.Point;
  22. /**
  23. * This class extends Raster to provide pixel writing capabilities.
  24. * Refer to the class comment for Raster for descriptions of how
  25. * a Raster stores pixels.
  26. *
  27. * <p> The constructors of this class are protected. To instantiate
  28. * a WritableRaster, use one of the createWritableRaster factory methods
  29. * in the Raster class.
  30. */
  31. public class WritableRaster extends Raster {
  32. /**
  33. * Constructs a WritableRaster with the given SampleModel. The
  34. * WritableRaster's upper left corner is origin and it is the
  35. * same size as the SampleModel. A DataBuffer large enough to
  36. * describe the WritableRaster is automatically created.
  37. * @param sampleModel The SampleModel that specifies the layout.
  38. * @param origin The Point that specifies the origin.
  39. */
  40. protected WritableRaster(SampleModel sampleModel,
  41. Point origin) {
  42. this(sampleModel,
  43. sampleModel.createDataBuffer(),
  44. new Rectangle(origin.x,
  45. origin.y,
  46. sampleModel.getWidth(),
  47. sampleModel.getHeight()),
  48. origin,
  49. null);
  50. }
  51. /**
  52. * Constructs a WritableRaster with the given SampleModel and DataBuffer.
  53. * The WritableRaster's upper left corner is origin and it is the same
  54. * size as the SampleModel. The DataBuffer is not initialized and must
  55. * be compatible with SampleModel.
  56. * @param sampleModel The SampleModel that specifies the layout.
  57. * @param dataBuffer The DataBuffer that contains the image data.
  58. * @param origin The Point that specifies the origin.
  59. */
  60. protected WritableRaster(SampleModel sampleModel,
  61. DataBuffer dataBuffer,
  62. Point origin) {
  63. this(sampleModel,
  64. dataBuffer,
  65. new Rectangle(origin.x,
  66. origin.y,
  67. sampleModel.getWidth(),
  68. sampleModel.getHeight()),
  69. origin,
  70. null);
  71. }
  72. /**
  73. * Constructs a WritableRaster with the given SampleModel, DataBuffer,
  74. * and parent. aRegion specifies the bounding rectangle of the new
  75. * Raster. When translated into the base Raster's coordinate
  76. * system, aRegion must be contained by the base Raster.
  77. * (The base Raster is the Raster's ancestor which has no parent.)
  78. * sampleModelTranslate specifies the sampleModelTranslateX and
  79. * sampleModelTranslateY values of the new Raster.
  80. *
  81. * Note that this constructor should generally be called by other
  82. * constructors or create methods, it should not be used directly.
  83. * @param sampleModel The SampleModel that specifies the layout.
  84. * @param dataBuffer The DataBuffer that contains the image data.
  85. * @param aRegion The Rectangle that specifies the image area.
  86. * @param sampleModelTranslate The Point that specifies the translation
  87. * from SampleModel to Raster coordinates.
  88. * @param parent The parent (if any) of this raster.
  89. */
  90. protected WritableRaster(SampleModel sampleModel,
  91. DataBuffer dataBuffer,
  92. Rectangle aRegion,
  93. Point sampleModelTranslate,
  94. WritableRaster parent){
  95. super(sampleModel,dataBuffer,aRegion,sampleModelTranslate,parent);
  96. }
  97. /** Returns the parent WritableRaster (if any) of this WritableRaster,
  98. * or else null.
  99. */
  100. public WritableRaster getWritableParent() {
  101. return (WritableRaster)parent;
  102. }
  103. /**
  104. * Create a WritableRaster with the same size, SampleModel and DataBuffer
  105. * as this one, but with a different location. The new WritableRaster
  106. * will possess a reference to the current WritableRaster, accessible
  107. * through its getParent() and getWritableParent() methods.
  108. *
  109. * @param childMinX X coord of the upper left corner of the new Raster.
  110. * @param childMinY Y coord of the upper left corner of the new Raster.
  111. */
  112. public WritableRaster createWritableTranslatedChild(int childMinX,
  113. int childMinY) {
  114. return createWritableChild(minX,minY,width,height,
  115. childMinX,childMinY,null);
  116. }
  117. /**
  118. * Returns a new WritableRaster which shares all or part of this
  119. * WritableRaster's DataBuffer. The new WritableRaster will
  120. * possess a reference to the current WritableRaster, accessible
  121. * through its getParent() and getWritableParent() methods.
  122. *
  123. * <p> The parentX, parentY, width and height parameters form a
  124. * Rectangle in this WritableRaster's coordinate space, indicating
  125. * the area of pixels to be shared. An error will be thrown if
  126. * this Rectangle is not contained with the bounds of the current
  127. * WritableRaster.
  128. *
  129. * <p> The new WritableRaster may additionally be translated to a
  130. * different coordinate system for the plane than that used by the current
  131. * WritableRaster. The childMinX and childMinY parameters give
  132. * the new (x, y) coordinate of the upper-left pixel of the
  133. * returned WritableRaster; the coordinate (childMinX, childMinY)
  134. * in the new WritableRaster will map to the same pixel as the
  135. * coordinate (parentX, parentY) in the current WritableRaster.
  136. *
  137. * <p> The new WritableRaster may be defined to contain only a
  138. * subset of the bands of the current WritableRaster, possibly
  139. * reordered, by means of the bandList parameter. If bandList is
  140. * null, it is taken to include all of the bands of the current
  141. * WritableRaster in their current order.
  142. *
  143. * <p> To create a new WritableRaster that contains a subregion of
  144. * the current WritableRaster, but shares its coordinate system
  145. * and bands, this method should be called with childMinX equal to
  146. * parentX, childMinY equal to parentY, and bandList equal to
  147. * null.
  148. *
  149. * @param parentX X coordinate of the upper left corner in this
  150. * WritableRaster's coordinates.
  151. * @param parentY Y coordinate of the upper left corner in this
  152. * WritableRaster's coordinates.
  153. * @param width Width of the region starting at (parentX, parentY).
  154. * @param height Height of the region starting at (parentX, parentY).
  155. * @param childMinX X coordinate of the upper left corner of
  156. * the returned WritableRaster.
  157. * @param childMinY Y coordinate of the upper left corner of
  158. * the returned WritableRaster.
  159. * @param bandList Array of band indices, or null to use all bands.
  160. * @exception RasterFormatException if the subregion is outside of the
  161. * raster bounds.
  162. */
  163. public WritableRaster createWritableChild(int parentX, int parentY,
  164. int w, int h,
  165. int childMinX, int childMinY,
  166. int bandList[]) {
  167. if (parentX < this.minX) {
  168. throw new RasterFormatException("parentX lies outside raster");
  169. }
  170. if (parentY < this.minY) {
  171. throw new RasterFormatException("parentY lies outside raster");
  172. }
  173. if (parentX+w > this.width + this.minX) {
  174. throw new RasterFormatException("(parentX + width) is outside raster");
  175. }
  176. if (parentY+h > this.height + this.minY) {
  177. throw new RasterFormatException("(parentY + height) is outside raster");
  178. }
  179. SampleModel sm;
  180. if (bandList != null) {
  181. sm = sampleModel.createCompatibleSampleModel(sampleModel.width,
  182. sampleModel.height);
  183. sm = sm.createSubsetSampleModel(bandList);
  184. }
  185. else {
  186. sm = sampleModel;
  187. }
  188. int deltaX = childMinX - parentX;
  189. int deltaY = childMinY - parentY;
  190. return new WritableRaster(sm,
  191. dataBuffer,
  192. new Rectangle(childMinX,childMinY,
  193. w, h),
  194. new Point(sampleModelTranslateX+deltaX,
  195. sampleModelTranslateY+deltaY),
  196. this);
  197. }
  198. /**
  199. * Sets the data for a single pixel from a
  200. * primitive array of type TransferType. For image data supported by
  201. * the Java 2D(tm) API, this will be one of DataBuffer.TYPE_BYTE,
  202. * DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT. Data in the array
  203. * may be in a packed format, thus increasing efficiency for data
  204. * transfers.
  205. * There will be no explicit bounds checking on the parameters.
  206. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  207. * not in bounds, or if inData is not large enough to hold the pixel data.
  208. * A ClassCastException will be thrown if the input object is not null
  209. * and references anything other than an array of TransferType.
  210. * @see java.awt.image.SampleModel#setDataElements(int, int, Object, DataBuffer)
  211. * @param x The X coordinate of the pixel location.
  212. * @param y The Y coordinate of the pixel location.
  213. * @param inData An object reference to an array of type defined by
  214. * getTransferType() and length getNumDataElements()
  215. * containing the pixel data to place at x,y.
  216. */
  217. public void setDataElements(int x, int y, Object inData) {
  218. sampleModel.setDataElements(x-sampleModelTranslateX,
  219. y-sampleModelTranslateY,
  220. inData, dataBuffer);
  221. }
  222. /**
  223. * Sets the data for a rectangle of pixels from an input Raster.
  224. * The input Raster must be compatible with this WritableRaster
  225. * in that they must have the same number of bands, corresponding bands
  226. * must have the same number of bits per sample, the TransferTypes
  227. * and NumDataElements must be the same, and the packing used by
  228. * the getDataElements/setDataElements must be identical.
  229. * There will be no explicit bounds checking on the parameters.
  230. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  231. * not in bounds.
  232. * @param x The X coordinate of the pixel location.
  233. * @param y The Y coordinate of the pixel location.
  234. * @param inRaster Raster containing data to place at x,y.
  235. */
  236. public void setDataElements(int x, int y, Raster inRaster) {
  237. int width = inRaster.getWidth();
  238. int height = inRaster.getHeight();
  239. int srcOffX = inRaster.getMinX();
  240. int srcOffY = inRaster.getMinY();
  241. int dstOffX = x+inRaster.getMinX();
  242. int dstOffY = y+inRaster.getMinY();
  243. Object tdata = null;
  244. for (int startY=0; startY < height; startY++) {
  245. tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
  246. width, 1, tdata);
  247. setDataElements(dstOffX, dstOffY+startY,
  248. width, 1, tdata);
  249. }
  250. }
  251. /**
  252. * Sets the data for a rectangle of pixels from a
  253. * primitive array of type TransferType. For image data supported by
  254. * the Java 2D API, this will be one of DataBuffer.TYPE_BYTE,
  255. * DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT. Data in the array
  256. * may be in a packed format, thus increasing efficiency for data
  257. * transfers.
  258. * There will be no explicit bounds checking on the parameters.
  259. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  260. * not in bounds, or if inData is not large enough to hold the pixel data.
  261. * A ClassCastException will be thrown if the input object is not null
  262. * and references anything other than an array of TransferType.
  263. * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, Object, DataBuffer)
  264. * @param x The X coordinate of the upper left pixel location.
  265. * @param y The Y coordinate of the upper left pixel location.
  266. * @param w Width of the pixel rectangle.
  267. * @param h Height of the pixel rectangle.
  268. * @param inData An object reference to an array of type defined by
  269. * getTransferType() and length w*h*getNumDataElements()
  270. * containing the pixel data to place between x,y and
  271. * x+w-1, y+h-1.
  272. */
  273. public void setDataElements(int x, int y, int w, int h, Object inData) {
  274. sampleModel.setDataElements(x-sampleModelTranslateX,
  275. y-sampleModelTranslateY,
  276. w,h,inData,dataBuffer);
  277. }
  278. /**
  279. * Copies pixels from Raster srcRaster to this WritableRaster. Each pixel
  280. * in srcRaster is copied to the same x,y address in this raster, unless
  281. * the address falls outside the bounds of this raster. srcRaster
  282. * must have the same number of bands as this WritableRaster. The
  283. * copy is a simple copy of source samples to the corresponding destination
  284. * samples.
  285. * <p>
  286. * If all samples of both source and destination Rasters are of
  287. * integral type and less than or equal to 32 bits in size, then calling
  288. * this method is equivalent to executing the following code for all
  289. * <code>x,y</code> addresses valid in both Rasters.
  290. * <pre>
  291. * Raster srcRaster;
  292. * WritableRaster dstRaster;
  293. * for (int b = 0; b < srcRaster.getNumBands(); b++) {
  294. * dstRaster.setSample(x, y, b, srcRaster.getSample(x, y, b));
  295. * }
  296. * </pre>
  297. * Thus, if the source sample size is greater than the destination
  298. * sample size for a particular band, the high order bits of the source
  299. * sample are truncated. If the source sample size is less than the
  300. * destination size for a particular band, the high order bits of the
  301. * destination are zero-extended or sign-extended depending on whether
  302. * srcRaster's SampleModel treats the sample as a signed or unsigned
  303. * quantity.
  304. * <p>
  305. * @param srcRaster The Raster from which to copy pixels.
  306. */
  307. public void setRect(Raster srcRaster) {
  308. setRect(0,0,srcRaster);
  309. }
  310. /**
  311. * Copies pixels from Raster srcRaster to this WritableRaster.
  312. * For each (x, y) address in srcRaster, the corresponding pixel
  313. * is copied to address (x+dx, y+dy) in this WritableRaster,
  314. * unless (x+dx, y+dy) falls outside the bounds of this raster.
  315. * srcRaster must have the same number of bands as this WritableRaster.
  316. * The copy is a simple copy of source samples to the corresponding
  317. * destination samples. For details, see
  318. * {@link WritableRaster#setRect(Raster)}.
  319. *
  320. * @param dx The X translation factor from src space to dst space
  321. * of the copy.
  322. * @param dy The Y translation factor from src space to dst space
  323. * of the copy.
  324. * @param srcRaster The Raster from which to copy pixels.
  325. */
  326. public void setRect(int dx, int dy, Raster srcRaster) {
  327. int width = srcRaster.getWidth();
  328. int height = srcRaster.getHeight();
  329. int srcOffX = srcRaster.getMinX();
  330. int srcOffY = srcRaster.getMinY();
  331. int dstOffX = dx+srcOffX;
  332. int dstOffY = dy+srcOffY;
  333. // Clip to this raster
  334. if (dstOffX+width > this.minX+this.width) {
  335. width = this.minX + this.width - dstOffX;
  336. }
  337. if (dstOffY+height > this.minY+this.height) {
  338. height = this.minY + this.height - dstOffY;
  339. }
  340. switch (srcRaster.getSampleModel().getDataType()) {
  341. case DataBuffer.TYPE_BYTE:
  342. case DataBuffer.TYPE_SHORT:
  343. case DataBuffer.TYPE_USHORT:
  344. case DataBuffer.TYPE_INT:
  345. int[] iData = null;
  346. for (int startY=0; startY < height; startY++) {
  347. // Grab one scanline at a time
  348. iData =
  349. srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
  350. iData);
  351. setPixels(dstOffX, dstOffY+startY, width, 1, iData);
  352. }
  353. break;
  354. case DataBuffer.TYPE_FLOAT:
  355. float[] fData = null;
  356. for (int startY=0; startY < height; startY++) {
  357. fData =
  358. srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
  359. fData);
  360. setPixels(dstOffX, dstOffY+startY, width, 1, fData);
  361. }
  362. break;
  363. case DataBuffer.TYPE_DOUBLE:
  364. double[] dData = null;
  365. for (int startY=0; startY < height; startY++) {
  366. // Grab one scanline at a time
  367. dData =
  368. srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
  369. dData);
  370. setPixels(dstOffX, dstOffY+startY, width, 1, dData);
  371. }
  372. break;
  373. }
  374. }
  375. /**
  376. * Sets a pixel in the DataBuffer using an int array of samples for input.
  377. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  378. * not in bounds.
  379. * @param x The X coordinate of the pixel location.
  380. * @param y The Y coordinate of the pixel location.
  381. * @param iArray The input samples in a int array.
  382. */
  383. public void setPixel(int x, int y, int iArray[]) {
  384. sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
  385. iArray,dataBuffer);
  386. }
  387. /**
  388. * Sets a pixel in the DataBuffer using a float array of samples for input.
  389. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  390. * not in bounds.
  391. * @param x The X coordinate of the pixel location.
  392. * @param y The Y coordinate of the pixel location.
  393. * @param fArray The input samples in a float array.
  394. */
  395. public void setPixel(int x, int y, float fArray[]) {
  396. sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
  397. fArray,dataBuffer);
  398. }
  399. /**
  400. * Sets a pixel in the DataBuffer using a double array of samples for input.
  401. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  402. * not in bounds.
  403. * @param x The X coordinate of the pixel location.
  404. * @param y The Y coordinate of the pixel location.
  405. * @param dArray The input samples in a double array.
  406. */
  407. public void setPixel(int x, int y, double dArray[]) {
  408. sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
  409. dArray,dataBuffer);
  410. }
  411. /**
  412. * Sets all samples for a rectangle of pixels from an int array containing
  413. * one sample per array element.
  414. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  415. * not in bounds.
  416. * @param x The X coordinate of the upper left pixel location.
  417. * @param y The Y coordinate of the upper left pixel location.
  418. * @param w Width of the pixel rectangle.
  419. * @param h Height of the pixel rectangle.
  420. * @param iArray The input int pixel array.
  421. */
  422. public void setPixels(int x, int y, int w, int h, int iArray[]) {
  423. sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
  424. w,h,iArray,dataBuffer);
  425. }
  426. /**
  427. * Sets all samples for a rectangle of pixels from a float array containing
  428. * one sample per array element.
  429. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  430. * not in bounds.
  431. * @param x The X coordinate of the upper left pixel location.
  432. * @param y The Y coordinate of the upper left pixel location.
  433. * @param w Width of the pixel rectangle.
  434. * @param h Height of the pixel rectangle.
  435. * @param fArray The input float pixel array.
  436. */
  437. public void setPixels(int x, int y, int w, int h, float fArray[]) {
  438. sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
  439. w,h,fArray,dataBuffer);
  440. }
  441. /**
  442. * Sets all samples for a rectangle of pixels from a double array containing
  443. * one sample per array element.
  444. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  445. * not in bounds.
  446. * @param x The X coordinate of the upper left pixel location.
  447. * @param y The Y coordinate of the upper left pixel location.
  448. * @param w Width of the pixel rectangle.
  449. * @param h Height of the pixel rectangle.
  450. * @param dArray The input double pixel array.
  451. */
  452. public void setPixels(int x, int y, int w, int h, double dArray[]) {
  453. sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
  454. w,h,dArray,dataBuffer);
  455. }
  456. /**
  457. * Sets a sample in the specified band for the pixel located at (x,y)
  458. * in the DataBuffer using an int for input.
  459. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  460. * not in bounds.
  461. * @param x The X coordinate of the pixel location.
  462. * @param y The Y coordinate of the pixel location.
  463. * @param b The band to set.
  464. * @param s The input sample.
  465. */
  466. public void setSample(int x, int y, int b, int s) {
  467. sampleModel.setSample(x-sampleModelTranslateX,
  468. y-sampleModelTranslateY, b, s,
  469. dataBuffer);
  470. }
  471. /**
  472. * Sets a sample in the specified band for the pixel located at (x,y)
  473. * in the DataBuffer using a float for input.
  474. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  475. * not in bounds.
  476. * @param x The X coordinate of the pixel location.
  477. * @param y The Y coordinate of the pixel location.
  478. * @param b The band to set.
  479. * @param s The input sample as a float.
  480. */
  481. public void setSample(int x, int y, int b, float s){
  482. sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY,
  483. b,s,dataBuffer);
  484. }
  485. /**
  486. * Sets a sample in the specified band for the pixel located at (x,y)
  487. * in the DataBuffer using a double for input.
  488. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  489. * not in bounds.
  490. * @param x The X coordinate of the pixel location.
  491. * @param y The Y coordinate of the pixel location.
  492. * @param b The band to set.
  493. * @param s The input sample as a double.
  494. */
  495. public void setSample(int x, int y, int b, double s){
  496. sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY,
  497. b,s,dataBuffer);
  498. }
  499. /**
  500. * Sets the samples in the specified band for the specified rectangle
  501. * of pixels from an int array containing one sample per array element.
  502. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  503. * not in bounds.
  504. * @param x The X coordinate of the upper left pixel location.
  505. * @param y The Y coordinate of the upper left pixel location.
  506. * @param w Width of the pixel rectangle.
  507. * @param h Height of the pixel rectangle.
  508. * @param b The band to set.
  509. * @param iArray The input int sample array.
  510. */
  511. public void setSamples(int x, int y, int w, int h, int b,
  512. int iArray[]) {
  513. sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
  514. w,h,b,iArray,dataBuffer);
  515. }
  516. /**
  517. * Sets the samples in the specified band for the specified rectangle
  518. * of pixels from a float array containing one sample per array element.
  519. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  520. * not in bounds.
  521. * @param x The X coordinate of the upper left pixel location.
  522. * @param y The Y coordinate of the upper left pixel location.
  523. * @param w Width of the pixel rectangle.
  524. * @param h Height of the pixel rectangle.
  525. * @param b The band to set.
  526. * @param fArray The input float sample array.
  527. */
  528. public void setSamples(int x, int y, int w, int h, int b,
  529. float fArray[]) {
  530. sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
  531. w,h,b,fArray,dataBuffer);
  532. }
  533. /**
  534. * Sets the samples in the specified band for the specified rectangle
  535. * of pixels from a double array containing one sample per array element.
  536. * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  537. * not in bounds.
  538. * @param x The X coordinate of the upper left pixel location.
  539. * @param y The Y coordinate of the upper left pixel location.
  540. * @param w Width of the pixel rectangle.
  541. * @param h Height of the pixel rectangle.
  542. * @param b The band to set.
  543. * @param dArray The input double sample array.
  544. */
  545. public void setSamples(int x, int y, int w, int h, int b,
  546. double dArray[]) {
  547. sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
  548. w,h,b,dArray,dataBuffer);
  549. }
  550. }