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