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 rectangular collection of pixels composed from a {@link DataBuffer} which
045     * stores the pixel values, and a {@link SampleModel} which is used to retrieve
046     * the pixel values.
047     * 
048     * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
049     */
050    public class Raster
051    {
052      /** The sample model used to access the pixel values. */
053      protected SampleModel sampleModel;
054      
055      /** The data buffer used to store the pixel values. */
056      protected DataBuffer dataBuffer;
057      
058      /** The x-coordinate of the top left corner of the raster. */
059      protected int minX;
060      
061      /** The y-coordinate of the top left corner of the raster. */
062      protected int minY;
063      
064      /** The width of the raster. */
065      protected int width;
066      
067      /** The height of the raster. */
068      protected int height;
069      
070      protected int sampleModelTranslateX;
071      
072      protected int sampleModelTranslateY;
073      
074      /** The number of bands. */
075      protected int numBands;
076      
077      protected int numDataElements;
078      
079      /** The raster's parent. */
080      protected Raster parent;
081      
082      /**
083       * Creates a new raster.
084       * 
085       * @param sampleModel  the sample model.
086       * @param origin  the origin.
087       */
088      protected Raster(SampleModel sampleModel, Point origin)
089      {
090        this(sampleModel, sampleModel.createDataBuffer(), origin);
091      }
092      
093      /**
094       * Creates a new raster.
095       * 
096       * @param sampleModel  the sample model.
097       * @param dataBuffer  the data buffer.
098       * @param origin  the origin.
099       */
100      protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
101                       Point origin)
102      {
103        this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y,
104             sampleModel.getWidth(), sampleModel.getHeight()), origin, null);
105      }
106    
107      /**
108       * Creates a new raster.
109       * 
110       * @param sampleModel  the sample model.
111       * @param dataBuffer  the data buffer.
112       * @param aRegion  the raster's bounds.
113       * @param sampleModelTranslate  the translation (<code>null</code> permitted).
114       * @param parent  the raster's parent.
115       */
116      protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
117          Rectangle aRegion, Point sampleModelTranslate, Raster parent)
118      {
119        this.sampleModel = sampleModel;
120        this.dataBuffer = dataBuffer;
121        this.minX = aRegion.x;
122        this.minY = aRegion.y;
123        this.width = aRegion.width;
124        this.height = aRegion.height;
125        
126        // If sampleModelTranslate is null, use (0,0).  Methods such as
127        // Raster.createRaster are specified to allow for a null argument.
128        if (sampleModelTranslate != null)
129        {
130          this.sampleModelTranslateX = sampleModelTranslate.x;
131          this.sampleModelTranslateY = sampleModelTranslate.y;
132        }
133    
134        this.numBands = sampleModel.getNumBands();
135        this.numDataElements = sampleModel.getNumDataElements();
136        this.parent = parent;
137      }
138        
139      /**
140       * Creates an interleaved raster using the specified data type.
141       * 
142       * @param dataType  the data type.
143       * @param w  the width.
144       * @param h  the height.
145       * @param bands  the number of bands.
146       * @param location
147       * 
148       * @return The new raster.
149       */
150      public static WritableRaster createInterleavedRaster(int dataType,
151          int w, int h, int bands, Point location)
152      {
153        int[] bandOffsets = new int[bands];
154        // TODO: Maybe not generate this every time.
155        for (int b = 0; b < bands; b++) 
156          bandOffsets[b] = b;
157        
158        int scanlineStride = bands * w;
159        return createInterleavedRaster(dataType, w, h, scanlineStride, bands,
160                                       bandOffsets, location);
161      }
162    
163      /**
164       * Creates an interleaved raster.
165       * 
166       * @param dataType  the data type.
167       * @param w  the width.
168       * @param h  the height.
169       * @param scanlineStride  the number of data elements from a sample on one 
170       *     row to the corresponding sample on the next row.
171       * @param pixelStride  the number of elements from a sample in one pixel to
172       *     the corresponding sample in the next pixel.
173       * @param bandOffsets  the band offsets.
174       * @param location
175       * 
176       * @return The new raster.
177       */
178      public static WritableRaster createInterleavedRaster(int dataType, 
179          int w, int h, int scanlineStride, int pixelStride, int[] bandOffsets,
180          Point location)
181      {
182        SampleModel sm = new ComponentSampleModel(dataType, w, h, pixelStride,
183            scanlineStride, bandOffsets);
184        return createWritableRaster(sm, location);
185      }
186    
187      /**
188       * Creates a new banded raster.
189       * 
190       * @param dataType  the data type.
191       * @param w  the width.
192       * @param h  the height.
193       * @param bands  the number of bands.
194       * @param location  
195       * 
196       * @return The new raster.
197       */
198      public static WritableRaster createBandedRaster(int dataType, int w, int h, 
199          int bands, Point location)
200      {
201        SampleModel sm = new BandedSampleModel(dataType, w, h, bands);
202        return createWritableRaster(sm, location);
203      }
204    
205      /**
206       * Creates a new banded raster.
207       * 
208       * @param dataType  the data type.
209       * @param w  the width.
210       * @param h  the height.
211       * @param scanlineStride  the number of data elements from a sample on one 
212       *     row to the corresponding sample on the next row.
213       * @param bankIndices  the index for each bank.
214       * @param bandOffsets  the offset for each band.
215       * @param location
216       * 
217       * @return The new raster.
218       */
219      public static WritableRaster createBandedRaster(int dataType, int w, int h,
220          int scanlineStride, int[] bankIndices, int[] bandOffsets, Point location)
221      {
222        SampleModel sm = new BandedSampleModel(dataType, w, h, scanlineStride,
223                                               bankIndices, bandOffsets);
224        return createWritableRaster(sm, location);
225      }
226      
227      /**
228       * Creates a new packed raster.
229       * 
230       * @param dataType  the data type.
231       * @param w  the width.
232       * @param h  the height.
233       * @param bandMasks  the bit mask for each band.
234       * @param location 
235       * 
236       * @return The new raster.
237       */
238      public static WritableRaster createPackedRaster(int dataType, int w, int h,
239          int[] bandMasks, Point location)
240      {
241        SampleModel sm = new SinglePixelPackedSampleModel(dataType, w, h,
242                                                         bandMasks);
243        return createWritableRaster(sm, location);
244      }
245    
246      /**
247       * Creates a new raster.
248       * 
249       * @param dataType  the data type.
250       * @param w  the width.
251       * @param h  the height.
252       * @param bands  the number of bands.
253       * @param bitsPerBand  the number of bits per band.
254       * @param location
255       * 
256       * @return The new raster.
257       */
258      public static WritableRaster createPackedRaster(int dataType,
259          int w, int h, int bands, int bitsPerBand, Point location)
260      {
261        if (bands <= 0 || (bands * bitsPerBand > getTypeBits(dataType)))
262          throw new IllegalArgumentException();
263    
264        SampleModel sm;
265    
266        if (bands == 1)
267          sm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerBand);
268        else
269          {
270            int[] bandMasks = new int[bands];
271            int mask = 0x1;
272            for (int bits = bitsPerBand; --bits != 0;)
273              mask = (mask << 1) | 0x1;
274            for (int i = 0; i < bands; i++)
275              {
276                bandMasks[i] = mask;
277                mask <<= bitsPerBand;
278              }
279              
280            sm = new SinglePixelPackedSampleModel(dataType, w, h, bandMasks);
281          }
282        return createWritableRaster(sm, location);
283      }
284    
285      /**
286       * Creates a new interleaved raster.
287       * 
288       * @param dataBuffer  the data buffer.
289       * @param w  the width.
290       * @param h  the height.
291       * @param scanlineStride  the number of data elements from a sample on one 
292       *     row to the corresponding sample on the next row.
293       * @param pixelStride  the number of elements from a sample in one pixel to
294       *     the corresponding sample in the next pixel.
295       * @param bandOffsets  the offset for each band.
296       * @param location
297       * 
298       * @return The new raster.
299       */
300      public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer, 
301          int w, int h, int scanlineStride, int pixelStride, int[] bandOffsets, 
302          Point location)
303      {
304        SampleModel sm = new ComponentSampleModel(dataBuffer.getDataType(),
305            w, h, scanlineStride, pixelStride, bandOffsets);
306        return createWritableRaster(sm, dataBuffer, location);
307      }
308    
309      /**
310       * Creates a new banded raster.
311       * 
312       * @param dataBuffer  the data buffer.
313       * @param w  the width.
314       * @param h  the height.
315       * @param scanlineStride  the number of data elements from a sample on one 
316       *     row to the corresponding sample on the next row.
317       * @param bankIndices  the index for each bank.
318       * @param bandOffsets  the band offsets.
319       * @param location
320       * 
321       * @return The new raster.
322       */
323      public static WritableRaster createBandedRaster(DataBuffer dataBuffer,
324          int w, int h, int scanlineStride, int[] bankIndices, int[] bandOffsets,
325          Point location)
326      {
327        SampleModel sm = new BandedSampleModel(dataBuffer.getDataType(),
328            w, h, scanlineStride, bankIndices, bandOffsets);
329        return createWritableRaster(sm, dataBuffer, location);
330      }
331      
332      /**
333       * Creates a new packed raster.
334       * 
335       * @param dataBuffer  the data buffer.
336       * @param w  the width.
337       * @param h  the height.
338       * @param scanlineStride  the number of data elements from a sample on one 
339       *     row to the corresponding sample on the next row.
340       * @param bandMasks  the bit mask for each band.
341       * @param location
342       * 
343       * @return The new raster.
344       */
345      public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
346          int w, int h, int scanlineStride, int[] bandMasks, Point location)
347     {
348        SampleModel sm = new SinglePixelPackedSampleModel(dataBuffer.getDataType(),
349            w, h, scanlineStride, bandMasks);
350        return createWritableRaster(sm, dataBuffer, location);
351      }
352      
353      /**
354       * Creates a new packed raster.
355       * 
356       * @param dataBuffer  the data buffer.
357       * @param w  the width.
358       * @param h  the height.
359       * @param bitsPerPixel  the number of bits per pixel.
360       * @param location
361       * 
362       * @return The new raster.
363       */
364      public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
365          int w, int h, int bitsPerPixel, Point location)
366      {
367        SampleModel sm = new MultiPixelPackedSampleModel(dataBuffer.getDataType(),
368            w, h, bitsPerPixel);
369        return createWritableRaster(sm, dataBuffer, location);
370      }
371        
372      /**
373       * Creates a new raster.
374       * 
375       * @param sm  the sample model.
376       * @param db  the data buffer.
377       * @param location
378       * 
379       * @return The new raster.
380       */
381      public static Raster createRaster(SampleModel sm, DataBuffer db,
382                                        Point location)
383      {
384        return new Raster(sm, db, location);
385      }
386    
387      /**
388       * Creates a new writable raster.
389       * 
390       * @param sm  the sample model.
391       * @param location
392       * 
393       * @return The new writable raster.
394       */
395      public static WritableRaster createWritableRaster(SampleModel sm,
396                                                        Point location)
397      {
398        return new WritableRaster(sm, location);
399      }
400    
401      /**
402       * Creates a new writable raster.
403       * 
404       * @param sm  the sample model.
405       * @param db  the data buffer.
406       * @param location 
407       * 
408       * @return The new writable raster.
409       */
410      public static WritableRaster createWritableRaster(SampleModel sm,
411          DataBuffer db, Point location)
412      {
413        return new WritableRaster(sm, db, location);
414      }
415    
416      /**
417       * Returns the raster's parent.
418       * 
419       * @return The raster's parent.
420       */
421      public Raster getParent()
422      {
423        return parent;
424      }
425    
426      /**
427       * Returns the x-translation.
428       * 
429       * @return The x-translation.
430       */
431      public final int getSampleModelTranslateX()
432      {
433        return sampleModelTranslateX;
434      }
435    
436      /**
437       * Returns the y-translation.
438       * 
439       * @return The y-translation.
440       */
441      public final int getSampleModelTranslateY()
442      {
443        return sampleModelTranslateY;
444      }
445    
446      /**
447       * Creates a new writable raster that is compatible with this raster.
448       * 
449       * @return A new writable raster.
450       */
451      public WritableRaster createCompatibleWritableRaster()
452      {
453        return new WritableRaster(getSampleModel(), new Point(minX, minY));
454      }
455    
456      /**
457       * Creates a new writable raster that is compatible with this raster.
458       * 
459       * @param w  the width.
460       * @param h  the height.
461       * 
462       * @return A new writable raster.
463       */
464      public WritableRaster createCompatibleWritableRaster(int w, int h)
465      {
466        return createCompatibleWritableRaster(minX, minY, w, h);
467      }
468    
469      /**
470       * Creates a new writable raster that is compatible with this raster, with
471       * the specified bounds.
472       * 
473       * @param rect  the raster bounds.
474       * 
475       * @return A new writable raster.
476       */
477      public WritableRaster createCompatibleWritableRaster(Rectangle rect)
478      {
479        return createCompatibleWritableRaster(rect.x, rect.y,
480                                              rect.width, rect.height);
481      }
482    
483      /**
484       * Creates a new writable raster that is compatible with this raster, with
485       * the specified bounds.
486       * 
487       * @param x  the x-coordinate of the top-left corner of the raster.
488       * @param y  the y-coordinate of the top-left corner of the raster.
489       * @param w  the raster width.
490       * @param h  the raster height.
491       * 
492       * @return A new writable raster.
493       */
494      public WritableRaster createCompatibleWritableRaster(int x, int y,
495                                                           int w, int h)
496      {
497        SampleModel sm = getSampleModel().createCompatibleSampleModel(w, h);
498        return new WritableRaster(sm, sm.createDataBuffer(), new Point(x, y));
499      }
500    
501      public Raster createTranslatedChild(int childMinX, int childMinY) {
502        int tcx = sampleModelTranslateX - minX + childMinX;
503        int tcy = sampleModelTranslateY - minY + childMinY;
504        
505        return new Raster(sampleModel, dataBuffer,
506                          new Rectangle(childMinX, childMinY, width, height),
507                          new Point(tcx, tcy), this);
508      }
509    
510      public Raster createChild(int parentX, int parentY, int width,
511                                int height, int childMinX, int childMinY,
512                                int[] bandList)
513      {
514        if (parentX < minX || parentX + width > minX + this.width
515            || parentY < minY || parentY + height > minY + this.height)
516          throw new RasterFormatException("Child raster extends beyond parent");
517        
518        SampleModel sm = (bandList == null) ?
519          sampleModel :
520          sampleModel.createSubsetSampleModel(bandList);
521    
522        /*
523            data origin
524           /
525          +-------------------------
526          |\. __ parent trans
527          | \`.  
528          |  \ `.    parent origin
529          |   \  `. /
530          |   /\   +-------- - -
531          |trans\ /<\-- deltaTrans
532          |child +-+-\---- - - 
533          |     /|`|  \__ parent [x, y]
534          |child | |`. \
535          |origin| :  `.\
536          |      |    / `\
537          |      :   /    +
538          | child [x, y] 
539    
540          parent_xy - parent_trans = child_xy - child_trans
541    
542          child_trans = parent_trans + child_xy - parent_xy
543        */
544    
545        return new Raster(sm, dataBuffer,
546            new Rectangle(childMinX, childMinY, width, height),
547            new Point(sampleModelTranslateX + childMinX - parentX,
548                      sampleModelTranslateY + childMinY - parentY),
549            this);
550      }
551    
552      /**
553       * Returns a new rectangle containing the bounds of this raster.
554       * 
555       * @return A new rectangle containing the bounds of this raster.
556       */
557      public Rectangle getBounds()
558      {
559        return new Rectangle(minX, minY, width, height);
560      }
561    
562      /**
563       * Returns the x-coordinate of the top left corner of the raster.
564       * 
565       * @return The x-coordinate of the top left corner of the raster.
566       */
567      public final int getMinX()
568      {
569        return minX;
570      }
571    
572      /**
573       * Returns the t-coordinate of the top left corner of the raster.
574       * 
575       * @return The t-coordinate of the top left corner of the raster.
576       */
577      public final int getMinY()
578      {
579        return minY;
580      }
581    
582      /**
583       * Returns the width of the raster.
584       * 
585       * @return The width of the raster.
586       */
587      public final int getWidth()
588      {
589        return width;
590      }
591    
592      /**
593       * Returns the height of the raster.
594       * 
595       * @return The height of the raster.
596       */
597      public final int getHeight()
598      {
599        return height;
600      }
601    
602      /**
603       * Returns the number of bands for this raster.
604       * 
605       * @return The number of bands.
606       */
607      public final int getNumBands()
608      {
609        return numBands;
610      }
611        
612      public final int getNumDataElements()
613      {
614        return numDataElements;
615      }
616      
617      /**
618       * Returns the transfer type for the raster (this is determined by the 
619       * raster's sample model).
620       * 
621       * @return The transfer type.
622       */
623      public final int getTransferType()
624      {
625        return sampleModel.getTransferType();
626      }
627    
628      /**
629       * Returns the data buffer that stores the pixel data for this raster.
630       * 
631       * @return The data buffer.
632       */
633      public DataBuffer getDataBuffer()
634      {
635        return dataBuffer;
636      }
637    
638      /**
639       * Returns the sample model that accesses the data buffer (to extract pixel
640       * data) for this raster.
641       * 
642       * @return The sample model.
643       */
644      public SampleModel getSampleModel()
645      {
646        return sampleModel;
647      }
648    
649      public Object getDataElements(int x, int y, Object outData)
650      {
651        return sampleModel.getDataElements(x - sampleModelTranslateX,
652            y - sampleModelTranslateY, outData, dataBuffer);
653      }
654    
655      public Object getDataElements(int x, int y, int w, int h, Object outData)
656      {
657        return sampleModel.getDataElements(x - sampleModelTranslateX,
658            y - sampleModelTranslateY, w, h, outData, dataBuffer);
659      }
660    
661      /**
662       * Returns an array containing the samples for the pixel at (x, y) in the
663       * raster.  If <code>iArray</code> is not <code>null</code>, it will be 
664       * populated with the sample values and returned as the result of
665       * this function (this avoids allocating a new array instance).
666       * 
667       * @param x  the x-coordinate of the pixel.
668       * @param y  the y-coordinate of the pixel.
669       * @param iArray  an array to populate with the sample values and return as 
670       *     the result (if <code>null</code>, a new array will be allocated).
671       * 
672       * @return The pixel sample values.
673       */
674      public int[] getPixel(int x, int y, int[] iArray)
675      {
676        return sampleModel.getPixel(x - sampleModelTranslateX,
677            y - sampleModelTranslateY, iArray, dataBuffer);
678      }
679    
680      /**
681       * Returns an array containing the samples for the pixel at (x, y) in the
682       * raster.  If <code>fArray</code> is not <code>null</code>, it will be 
683       * populated with the sample values and returned as the result of
684       * this function (this avoids allocating a new array instance).
685       * 
686       * @param x  the x-coordinate of the pixel.
687       * @param y  the y-coordinate of the pixel.
688       * @param fArray  an array to populate with the sample values and return as 
689       *     the result (if <code>null</code>, a new array will be allocated).
690       * 
691       * @return The pixel sample values.
692       */
693      public float[] getPixel(int x, int y, float[] fArray)
694      {
695        return sampleModel.getPixel(x - sampleModelTranslateX,
696            y - sampleModelTranslateY, fArray, dataBuffer);
697      }
698    
699      /**
700       * Returns an array containing the samples for the pixel at (x, y) in the
701       * raster.  If <code>dArray</code> is not <code>null</code>, it will be 
702       * populated with the sample values and returned as the result of
703       * this function (this avoids allocating a new array instance).
704       * 
705       * @param x  the x-coordinate of the pixel.
706       * @param y  the y-coordinate of the pixel.
707       * @param dArray  an array to populate with the sample values and return as 
708       *     the result (if <code>null</code>, a new array will be allocated).
709       * 
710       * @return The pixel sample values.
711       */
712      public double[] getPixel(int x, int y, double[] dArray)
713      {
714        return sampleModel.getPixel(x - sampleModelTranslateX,
715            y - sampleModelTranslateY, dArray, dataBuffer);
716      }
717    
718      /**
719       * Returns an array containing the samples for the pixels in the region 
720       * specified by (x, y, w, h) in the raster.  The array is ordered by pixels 
721       * (that is, all the samples for the first pixel are grouped together, 
722       * followed by all the samples for the second pixel, and so on).  
723       * If <code>iArray</code> is not <code>null</code>, it will be populated 
724       * with the sample values and returned as the result of this function (this 
725       * avoids allocating a new array instance).
726       * 
727       * @param x  the x-coordinate of the top-left pixel.
728       * @param y  the y-coordinate of the top-left pixel.
729       * @param w  the width of the region of pixels.
730       * @param h  the height of the region of pixels.
731       * @param iArray  an array to populate with the sample values and return as 
732       *     the result (if <code>null</code>, a new array will be allocated).
733       * 
734       * @return The pixel sample values.
735       */
736      public int[] getPixels(int x, int y, int w, int h, int[] iArray)
737      {
738        return sampleModel.getPixels(x - sampleModelTranslateX,
739            y - sampleModelTranslateY, w, h, iArray, dataBuffer);
740      }
741    
742      /**
743       * Returns an array containing the samples for the pixels in the region 
744       * specified by (x, y, w, h) in the raster.  The array is ordered by pixels 
745       * (that is, all the samples for the first pixel are grouped together, 
746       * followed by all the samples for the second pixel, and so on).  
747       * If <code>fArray</code> is not <code>null</code>, it will be populated 
748       * with the sample values and returned as the result of this function (this 
749       * avoids allocating a new array instance).
750       * 
751       * @param x  the x-coordinate of the top-left pixel.
752       * @param y  the y-coordinate of the top-left pixel.
753       * @param w  the width of the region of pixels.
754       * @param h  the height of the region of pixels.
755       * @param fArray  an array to populate with the sample values and return as 
756       *     the result (if <code>null</code>, a new array will be allocated).
757       * 
758       * @return The pixel sample values.
759       */
760      public float[] getPixels(int x, int y, int w, int h, float[] fArray)
761      {
762        return sampleModel.getPixels(x - sampleModelTranslateX,
763            y - sampleModelTranslateY, w, h, fArray, dataBuffer);
764      }
765    
766      /**
767       * Returns an array containing the samples for the pixels in the region 
768       * specified by (x, y, w, h) in the raster.  The array is ordered by pixels 
769       * (that is, all the samples for the first pixel are grouped together, 
770       * followed by all the samples for the second pixel, and so on).  
771       * If <code>dArray</code> is not <code>null</code>, it will be populated 
772       * with the sample values and returned as the result of this function (this 
773       * avoids allocating a new array instance).
774       * 
775       * @param x  the x-coordinate of the top-left pixel.
776       * @param y  the y-coordinate of the top-left pixel.
777       * @param w  the width of the region of pixels.
778       * @param h  the height of the region of pixels.
779       * @param dArray  an array to populate with the sample values and return as 
780       *     the result (if <code>null</code>, a new array will be allocated).
781       * 
782       * @return The pixel sample values.
783       */
784      public double[] getPixels(int x, int y, int w, int h, double[] dArray)
785      {
786        return sampleModel.getPixels(x - sampleModelTranslateX,
787            y - sampleModelTranslateY, w, h, dArray, dataBuffer);
788      }
789    
790      /**
791       * Returns the sample value for the pixel at (x, y) in the raster.
792       * 
793       * @param x  the x-coordinate of the pixel.
794       * @param y  the y-coordinate of the pixel.
795       * @param b  the band (in the range <code>0</code> to 
796       *     <code>getNumBands() - 1</code>).
797       * 
798       * @return The sample value.
799       */
800      public int getSample(int x, int y, int b)
801      {
802        return sampleModel.getSample(x - sampleModelTranslateX,
803            y - sampleModelTranslateY, b, dataBuffer);
804      }
805    
806      /**
807       * Returns the sample value for the pixel at (x, y) in the raster.
808       * 
809       * @param x  the x-coordinate of the pixel.
810       * @param y  the y-coordinate of the pixel.
811       * @param b  the band (in the range <code>0</code> to 
812       *     <code>getNumBands() - 1</code>).
813       * 
814       * @return The sample value.
815       * 
816       * @see #getSample(int, int, int)
817       */
818      public float getSampleFloat(int x, int y, int b)
819      {
820        return sampleModel.getSampleFloat(x - sampleModelTranslateX,
821            y - sampleModelTranslateY, b, dataBuffer);
822      }
823    
824      /**
825       * Returns the sample value for the pixel at (x, y) in the raster.
826       * 
827       * @param x  the x-coordinate of the pixel.
828       * @param y  the y-coordinate of the pixel.
829       * @param b  the band (in the range <code>0</code> to 
830       *     <code>getNumBands() - 1</code>).
831       * 
832       * @return The sample value.
833       * 
834       * @see #getSample(int, int, int)
835       */
836      public double getSampleDouble(int x, int y, int b)
837      {
838        return sampleModel.getSampleDouble(x - sampleModelTranslateX,
839            y - sampleModelTranslateY, b, dataBuffer);
840      }
841    
842      /**
843       * Returns an array containing the samples from one band for the pixels in 
844       * the region specified by (x, y, w, h) in the raster.  If 
845       * <code>iArray</code> is not <code>null</code>, it will be 
846       * populated with the sample values and returned as the result of this 
847       * function (this avoids allocating a new array instance).
848       * 
849       * @param x  the x-coordinate of the top-left pixel.
850       * @param y  the y-coordinate of the top-left pixel.
851       * @param w  the width of the region of pixels.
852       * @param h  the height of the region of pixels.
853       * @param b  the band (in the range <code>0</code> to 
854       *     </code>getNumBands() - 1</code>).
855       * @param iArray  an array to populate with the sample values and return as 
856       *     the result (if <code>null</code>, a new array will be allocated).
857       * 
858       * @return The sample values.
859       */
860      public int[] getSamples(int x, int y, int w, int h, int b,
861                              int[] iArray)
862      {
863        return sampleModel.getSamples(x - sampleModelTranslateX,
864            y - sampleModelTranslateY, w, h, b, iArray, dataBuffer);
865      }
866    
867      /**
868       * Returns an array containing the samples from one band for the pixels in 
869       * the region specified by (x, y, w, h) in the raster.  If 
870       * <code>fArray</code> is not <code>null</code>, it will be 
871       * populated with the sample values and returned as the result of this 
872       * function (this avoids allocating a new array instance).
873       *
874       * @param x  the x-coordinate of the top-left pixel.
875       * @param y  the y-coordinate of the top-left pixel.
876       * @param w  the width of the region of pixels.
877       * @param h  the height of the region of pixels.
878       * @param b  the band (in the range <code>0</code> to 
879       *     </code>getNumBands() - 1</code>).
880       * @param fArray  an array to populate with the sample values and return as 
881       *     the result (if <code>null</code>, a new array will be allocated).
882       * 
883       * @return The sample values.
884       */  
885      public float[] getSamples(int x, int y, int w, int h, int b, float[] fArray)
886      {
887        return sampleModel.getSamples(x - sampleModelTranslateX,
888            y - sampleModelTranslateY, w, h, b, fArray, dataBuffer);
889      }
890    
891      /**
892       * Returns an array containing the samples from one band for the pixels in 
893       * the region specified by (x, y, w, h) in the raster.  If 
894       * <code>dArray</code> is not <code>null</code>, it will be 
895       * populated with the sample values and returned as the result of this 
896       * function (this avoids allocating a new array instance).
897       * 
898       * @param x  the x-coordinate of the top-left pixel.
899       * @param y  the y-coordinate of the top-left pixel.
900       * @param w  the width of the region of pixels.
901       * @param h  the height of the region of pixels.
902       * @param b  the band (in the range <code>0</code> to 
903       *     </code>getNumBands() - 1</code>).
904       * @param dArray  an array to populate with the sample values and return as 
905       *     the result (if <code>null</code>, a new array will be allocated).
906       * 
907       * @return The sample values.
908       */
909      public double[] getSamples(int x, int y, int w, int h, int b, 
910                                 double[] dArray)
911      {
912        return sampleModel.getSamples(x - sampleModelTranslateX,
913            y - sampleModelTranslateY, w, h, b, dArray, dataBuffer);
914      }
915      
916      /**
917       * Create a String representing the state of this Raster.
918       * 
919       * @return A String representing the stat of this Raster.
920       */
921      public String toString()
922      {
923        StringBuffer result = new StringBuffer();
924        
925        result.append(getClass().getName());
926        result.append("[(");
927        result.append(minX).append(",").append(minY).append("), ");
928        result.append(width).append(" x ").append(height).append(",");
929        result.append(sampleModel).append(",");
930        result.append(dataBuffer);
931        result.append("]");
932        
933        return result.toString();
934      }
935    
936      /**
937       * Returns the number of bits used to represent the specified data type.  
938       * Valid types are:
939       * <ul>
940       *   <li>{@link DataBuffer#TYPE_BYTE};</li>
941       *   <li>{@link DataBuffer#TYPE_USHORT};</li>
942       *   <li>{@link DataBuffer#TYPE_SHORT};</li>
943       *   <li>{@link DataBuffer#TYPE_INT};</li>
944       *   <li>{@link DataBuffer#TYPE_FLOAT};</li>
945       *   <li>{@link DataBuffer#TYPE_DOUBLE};</li>
946       * </ul>
947       * This method returns 0 for invalid data types.
948       * 
949       * @param dataType  the data type.
950       * 
951       * @return The number of bits used to represent the specified data type.
952       */
953      private static int getTypeBits(int dataType)
954      {
955        switch (dataType)
956          {
957          case DataBuffer.TYPE_BYTE:
958            return 8;
959          case DataBuffer.TYPE_USHORT:
960          case DataBuffer.TYPE_SHORT:
961            return 16;
962          case DataBuffer.TYPE_INT:
963          case DataBuffer.TYPE_FLOAT:
964            return 32;
965          case DataBuffer.TYPE_DOUBLE:
966            return 64;
967          default:
968            return 0;
969          }
970      }
971    }