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