001/* Copyright (C) 2000, 2002, 2003, 2006,  Free Software Foundation
002
003This file is part of GNU Classpath.
004
005GNU Classpath is free software; you can redistribute it and/or modify
006it under the terms of the GNU General Public License as published by
007the Free Software Foundation; either version 2, or (at your option)
008any later version.
009
010GNU Classpath is distributed in the hope that it will be useful, but
011WITHOUT ANY WARRANTY; without even the implied warranty of
012MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013General Public License for more details.
014
015You should have received a copy of the GNU General Public License
016along with GNU Classpath; see the file COPYING.  If not, write to the
017Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01802110-1301 USA.
019
020Linking this library statically or dynamically with other modules is
021making a combined work based on this library.  Thus, the terms and
022conditions of the GNU General Public License cover the whole
023combination.
024
025As a special exception, the copyright holders of this library give you
026permission to link this library with independent modules to produce an
027executable, regardless of the license terms of these independent
028modules, and to copy and distribute the resulting executable under
029terms of your choice, provided that you also meet, for each linked
030independent module, the terms and conditions of the license of that
031module.  An independent module is a module which is not derived from
032or based on this library.  If you modify this library, you may extend
033this exception to your version of the library, but you are not
034obligated to do so.  If you do not wish to do so, delete this
035exception statement from your version. */
036
037
038package java.awt.image;
039
040import gnu.java.lang.CPStringBuilder;
041
042import java.awt.Point;
043import 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 */
052public 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}