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