001/* Copyright (C) 2000, 2002, 2003, 2006,  Free Software Foundation
002
003This file is part of GNU Classpath.
004
005GNU Classpath is free software; you can redistribute it and/or modify
006it under the terms of the GNU General Public License as published by
007the Free Software Foundation; either version 2, or (at your option)
008any later version.
009
010GNU Classpath is distributed in the hope that it will be useful, but
011WITHOUT ANY WARRANTY; without even the implied warranty of
012MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013General Public License for more details.
014
015You should have received a copy of the GNU General Public License
016along with GNU Classpath; see the file COPYING.  If not, write to the
017Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01802110-1301 USA.
019
020Linking this library statically or dynamically with other modules is
021making a combined work based on this library.  Thus, the terms and
022conditions of the GNU General Public License cover the whole
023combination.
024
025As a special exception, the copyright holders of this library give you
026permission to link this library with independent modules to produce an
027executable, regardless of the license terms of these independent
028modules, and to copy and distribute the resulting executable under
029terms of your choice, provided that you also meet, for each linked
030independent module, the terms and conditions of the license of that
031module.  An independent module is a module which is not derived from
032or based on this library.  If you modify this library, you may extend
033this exception to your version of the library, but you are not
034obligated to do so.  If you do not wish to do so, delete this
035exception statement from your version. */
036
037
038package java.awt.image;
039
040import java.awt.Point;
041import java.awt.Rectangle;
042
043/**
044 * A raster with methods to support updating pixel values.
045 * 
046 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
047 */
048public class WritableRaster extends Raster
049{
050  /**
051   * Creates a new <code>WritableRaster</code>.
052   * 
053   * @param sampleModel  the sample model.
054   * @param origin  the origin.
055   */
056  protected WritableRaster(SampleModel sampleModel, Point origin) 
057  {
058    this(sampleModel, sampleModel.createDataBuffer(), origin);
059  }
060  
061  /**
062   * Creates a new <code>WritableRaster</code> instance.
063   * 
064   * @param sampleModel  the sample model.
065   * @param dataBuffer  the data buffer.
066   * @param origin  the origin.
067   */
068  protected WritableRaster(SampleModel sampleModel, DataBuffer dataBuffer, 
069                           Point origin)
070  {
071    this(sampleModel, dataBuffer,
072         new Rectangle(origin != null ? origin.x : 0,
073                       origin != null ? origin.y : 0,
074                       sampleModel.getWidth(), sampleModel.getHeight()),
075         origin, null);
076  }
077
078  /**
079   * Creates a new <code>WritableRaster</code> instance.
080   * 
081   * @param sampleModel  the sample model.
082   * @param dataBuffer  the data buffer.
083   * @param aRegion  the raster's bounds.
084   * @param sampleModelTranslate  the translation.
085   * @param parent  the parent.
086   */
087  protected WritableRaster(SampleModel sampleModel, 
088                           DataBuffer dataBuffer,
089                           Rectangle aRegion,
090                           Point sampleModelTranslate,
091                           WritableRaster parent)
092  {
093    super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, parent);
094  }
095
096  /**
097   * Returns the raster's parent, cast as a {@link WritableRaster}.
098   * 
099   * @return The raster's parent.
100   */
101  public WritableRaster getWritableParent()
102  {
103    return (WritableRaster) getParent();
104  }
105  
106  /**
107   * @param childMinX
108   * @param childMinY
109   * @return
110   */
111  public WritableRaster createWritableTranslatedChild(int childMinX,
112                                                      int childMinY)
113  {
114    return createWritableChild(minX, minY, width, height,
115                               childMinX, childMinY, null);
116  }
117
118  /**
119   * 
120   * @param parentX
121   * @param parentY
122   * @param w
123   * @param h
124   * @param childMinX
125   * @param childMinY
126   * @param bandList
127   * @return
128   */
129  public WritableRaster createWritableChild(int parentX, int parentY,
130      int w, int h, int childMinX, int childMinY, int[] bandList)
131  {
132    // This mirrors the code from the super class
133    
134    if (parentX < minX || parentX + w > minX + width
135        || parentY < minY || parentY + h > minY + height)
136      throw new RasterFormatException("Child raster extends beyond parent");
137    
138    SampleModel sm = (bandList == null) ?
139      sampleModel :
140      sampleModel.createSubsetSampleModel(bandList);
141
142    return new WritableRaster(sm, getDataBuffer(),
143                              new Rectangle(childMinX, childMinY, w, h),
144                              new Point(sampleModelTranslateX + childMinX -
145                                          parentX,
146                                        sampleModelTranslateY + childMinY -
147                                          parentY),
148                              this);
149  }
150  
151  public Raster createChild(int parentX, int parentY, int width,
152                            int height, int childMinX, int childMinY,
153                            int[] bandList)
154  {
155    if (parentX < minX || parentX + width > minX + this.width
156        || parentY < minY || parentY + height > minY + this.height)
157      throw new RasterFormatException("Child raster extends beyond parent");
158    
159    SampleModel sm = (bandList == null) ?
160      sampleModel :
161      sampleModel.createSubsetSampleModel(bandList);
162
163    return new WritableRaster(sm, dataBuffer,
164        new Rectangle(childMinX, childMinY, width, height),
165        new Point(sampleModelTranslateX + childMinX - parentX,
166                  sampleModelTranslateY + childMinY - parentY),
167        this);
168  }
169
170  public void setDataElements(int x, int y, Object inData)
171  {
172    sampleModel.setDataElements(x - sampleModelTranslateX, 
173        y - sampleModelTranslateY, inData, dataBuffer);
174  }
175
176  public void setDataElements(int x, int y, Raster inRaster)
177  {
178    Object dataElements = getDataElements(0, 0, inRaster.getWidth(),
179        inRaster.getHeight(), null);
180    setDataElements(x, y, dataElements);
181  }
182
183  public void setDataElements(int x, int y, int w, int h, Object inData)
184  {
185    sampleModel.setDataElements(x - sampleModelTranslateX,
186        y - sampleModelTranslateY, w, h, inData, dataBuffer);
187  }
188
189  /**
190   * 
191   * @param srcRaster
192   */
193  public void setRect(Raster srcRaster)
194  {
195    setRect(0, 0, srcRaster);
196  }
197
198  /**
199   * 
200   * @param dx
201   * @param dy
202   * @param srcRaster
203   */
204  public void setRect(int dx, int dy, Raster srcRaster) 
205  {
206    Rectangle targetUnclipped = new Rectangle(srcRaster.getMinX() + dx,
207        srcRaster.getMinY() + dy, srcRaster.getWidth(), srcRaster.getHeight());
208        
209    Rectangle target = getBounds().intersection(targetUnclipped);
210
211    if (target.isEmpty()) return;
212    
213    int sx = target.x - dx;
214    int sy = target.y - dy;
215    
216    // FIXME: Do tests on rasters and use get/set data instead.
217    
218    /* The JDK documentation seems to imply this implementation.
219       (the trucation of higher bits), but an implementation using
220       get/setDataElements would be more efficient. None of the
221       implementations would do anything sensible when the sample
222       models don't match.
223       
224       But this is probably not the place to consider such
225       optimizations.*/
226
227    int[] pixels = srcRaster.getPixels(sx, sy, target.width, target.height,
228                                       (int[]) null);
229
230    setPixels(target.x, target.y, target.width, target.height, pixels);
231  }
232
233  /**
234   * Sets the samples for the pixel at (x, y) in the raster to the specified 
235   * values. 
236   * 
237   * @param x  the x-coordinate of the pixel.
238   * @param y  the y-coordinate of the pixel.
239   * @param iArray  the sample values (<code>null</code> not permitted).
240   * 
241   * @throws NullPointerException if <code>iArray</code> is <code>null</code>.
242   */
243  public void setPixel(int x, int y, int[] iArray)
244  {
245    sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY,
246                         iArray, dataBuffer);
247  }
248
249  /**
250   * Sets the samples for the pixel at (x, y) in the raster to the specified 
251   * values. 
252   * 
253   * @param x  the x-coordinate of the pixel.
254   * @param y  the y-coordinate of the pixel.
255   * @param fArray  the sample values (<code>null</code> not permitted).
256   * 
257   * @throws NullPointerException if <code>fArray</code> is <code>null</code>.
258   */
259  public void setPixel(int x, int y, float[] fArray)
260  {
261    sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY,
262                         fArray, dataBuffer);
263  }
264
265  /**
266   * Sets the samples for the pixel at (x, y) in the raster to the specified 
267   * values. 
268   * 
269   * @param x  the x-coordinate of the pixel.
270   * @param y  the y-coordinate of the pixel.
271   * @param dArray  the sample values (<code>null</code> not permitted).
272   * 
273   * @throws NullPointerException if <code>dArray</code> is <code>null</code>.
274   */
275  public void setPixel(int x, int y, double[] dArray)
276  {
277    sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY,
278                         dArray, dataBuffer);
279  }
280
281  /**
282   * Sets the sample values for the pixels in the region specified by 
283   * (x, y, w, h) in the raster.  The array is ordered by pixels (that is, all 
284   * the samples for the first pixel are grouped together, followed by all the 
285   * samples for the second pixel, and so on). 
286   *  
287   * @param x  the x-coordinate of the top-left pixel.
288   * @param y  the y-coordinate of the top-left pixel.
289   * @param w  the width of the region of pixels.
290   * @param h  the height of the region of pixels.
291   * @param iArray  the pixel sample values (<code>null</code> not permitted).
292   * 
293   * @throws NullPointerException if <code>iArray</code> is <code>null</code>.
294   */
295  public void setPixels(int x, int y, int w, int h, int[] iArray)
296  {
297    sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY,
298                          w, h, iArray, dataBuffer);
299  }
300
301  /**
302   * Sets the sample values for the pixels in the region specified by 
303   * (x, y, w, h) in the raster.  The array is ordered by pixels (that is, all 
304   * the samples for the first pixel are grouped together, followed by all the 
305   * samples for the second pixel, and so on). 
306   *  
307   * @param x  the x-coordinate of the top-left pixel.
308   * @param y  the y-coordinate of the top-left pixel.
309   * @param w  the width of the region of pixels.
310   * @param h  the height of the region of pixels.
311   * @param fArray  the pixel sample values (<code>null</code> not permitted).
312   * 
313   * @throws NullPointerException if <code>fArray</code> is <code>null</code>.
314   */
315  public void setPixels(int x, int y, int w, int h, float[] fArray)
316  {
317    sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY,
318                          w, h, fArray, dataBuffer);
319  }
320
321  /**
322   * Sets the sample values for the pixels in the region specified by 
323   * (x, y, w, h) in the raster.  The array is ordered by pixels (that is, all 
324   * the samples for the first pixel are grouped together, followed by all the 
325   * samples for the second pixel, and so on). 
326   *  
327   * @param x  the x-coordinate of the top-left pixel.
328   * @param y  the y-coordinate of the top-left pixel.
329   * @param w  the width of the region of pixels.
330   * @param h  the height of the region of pixels.
331   * @param dArray  the pixel sample values (<code>null</code> not permitted).
332   * 
333   * @throws NullPointerException if <code>dArray</code> is <code>null</code>.
334   */
335  public void setPixels(int x, int y, int w, int h, double[] dArray)
336  {
337    sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY,
338                          w, h, dArray, dataBuffer);
339  }
340
341  /**
342   * Sets the sample value for a band for the pixel at (x, y) in the raster. 
343   * 
344   * @param x  the x-coordinate of the pixel.
345   * @param y  the y-coordinate of the pixel.
346   * @param b  the band (in the range <code>0</code> to 
347   *     <code>getNumBands() - 1</code>).
348   * @param s  the sample value.
349   */
350  public void setSample(int x, int y, int b, int s)
351  {
352    sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY,
353                          b, s, dataBuffer);
354  }
355
356  /**
357   * Sets the sample value for a band for the pixel at (x, y) in the raster. 
358   * 
359   * @param x  the x-coordinate of the pixel.
360   * @param y  the y-coordinate of the pixel.
361   * @param b  the band (in the range <code>0</code> to 
362   *     <code>getNumBands() - 1</code>).
363   * @param s  the sample value.
364   */
365  public void setSample(int x, int y, int b, float s)
366  {
367    sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY,
368                          b, s, dataBuffer);
369  }
370
371  /**
372   * Sets the sample value for a band for the pixel at (x, y) in the raster. 
373   * 
374   * @param x  the x-coordinate of the pixel.
375   * @param y  the y-coordinate of the pixel.
376   * @param b  the band (in the range <code>0</code> to 
377   *     <code>getNumBands() - 1</code>).
378   * @param s  the sample value.
379   */
380  public void setSample(int x, int y, int b, double s)
381  {
382    sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY,
383                          b, s, dataBuffer);
384  }
385
386  /**
387   * Sets the sample values for one band for the pixels in the region 
388   * specified by (x, y, w, h) in the raster. 
389   * 
390   * @param x  the x-coordinate of the top-left pixel.
391   * @param y  the y-coordinate of the top-left pixel.
392   * @param w  the width of the region of pixels.
393   * @param h  the height of the region of pixels.
394   * @param b  the band (in the range <code>0</code> to 
395   *     </code>getNumBands() - 1</code>).
396   * @param iArray  the sample values (<code>null</code> not permitted).
397   * 
398   * @throws NullPointerException if <code>iArray</code> is <code>null</code>.
399   */
400  public void setSamples(int x, int y, int w, int h, int b,
401                         int[] iArray)
402  {
403    sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY,
404                           w, h, b, iArray, dataBuffer);
405  }
406
407  /**
408   * Sets the sample values for one band for the pixels in the region 
409   * specified by (x, y, w, h) in the raster. 
410   * 
411   * @param x  the x-coordinate of the top-left pixel.
412   * @param y  the y-coordinate of the top-left pixel.
413   * @param w  the width of the region of pixels.
414   * @param h  the height of the region of pixels.
415   * @param b  the band (in the range <code>0</code> to 
416   *     </code>getNumBands() - 1</code>).
417   * @param fArray  the sample values (<code>null</code> not permitted).
418   * 
419   * @throws NullPointerException if <code>fArray</code> is <code>null</code>.
420   */
421  public void setSamples(int x, int y, int w, int h, int b,
422                         float[] fArray)
423  {
424    sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY,
425                           w, h, b, fArray, dataBuffer);
426  }
427
428  /**
429   * Sets the sample values for one band for the pixels in the region 
430   * specified by (x, y, w, h) in the raster. 
431   * 
432   * @param x  the x-coordinate of the top-left pixel.
433   * @param y  the y-coordinate of the top-left pixel.
434   * @param w  the width of the region of pixels.
435   * @param h  the height of the region of pixels.
436   * @param b  the band (in the range <code>0</code> to 
437   *     </code>getNumBands() - 1</code>).
438   * @param dArray  the sample values (<code>null</code> not permitted).
439   * 
440   * @throws NullPointerException if <code>dArray</code> is <code>null</code>.
441   */
442  public void setSamples(int x, int y, int w, int h, int b,
443                         double[] dArray)
444  {
445    sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY,
446                           w, h, b, dArray, dataBuffer);
447  }
448}