View Javadoc
1   /*
2    * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package sun.awt.image;
27  import java.awt.image.Raster;
28  import java.awt.image.WritableRaster;
29  import java.awt.image.RasterFormatException;
30  import java.awt.image.SampleModel;
31  import java.awt.image.ComponentSampleModel;
32  import java.awt.image.PixelInterleavedSampleModel;
33  import java.awt.image.SinglePixelPackedSampleModel;
34  import java.awt.image.DataBuffer;
35  import java.awt.image.DataBufferByte;
36  import java.awt.Rectangle;
37  import java.awt.Point;
38  
39  /**
40   * This class defines a Raster with pixels consisting of one or more
41   * 8-bit data elements stored in close proximity to each other in a
42   * single byte array.
43   * <p>
44   * The bit precision per data element is that of the data type (that
45   * is, the bit precision for this Raster is 8).  There is only one
46   * pixel stride and one scanline stride for all bands.  This type of
47   * Raster can be used with a ComponentColorModel if there are multiple
48   * bands, or an IndexColorModel if there is only one band.
49   *
50   */
51  public class ByteInterleavedRaster extends ByteComponentRaster {
52  
53      /** True if the data offsets range from 0 to (pixelStride - 1) in order. */
54      boolean inOrder;
55  
56      /**
57       * The DataBuffer offset, minus sampleModelTranslateX*pixelStride,
58       * minus sampleModelTranslateY*scanlineStride, used to calculate
59       * pixel offsets.
60       */
61      int dbOffset;
62      int dbOffsetPacked;
63  
64      /** True if a SinglePixelPackedSampleModel is being used. */
65      boolean packed = false;
66  
67      /** If packed == true, the SampleModel's bit masks. */
68      int[] bitMasks;
69  
70      /** If packed == true, the SampleModel's bit offsets. */
71      int[] bitOffsets;
72  
73      /** A cached copy of minX + width for use in bounds checks. */
74      private int maxX;
75  
76      /** A cached copy of minY + height for use in bounds checks. */
77      private int maxY;
78  
79      /**
80       * Constructs a ByteInterleavedRaster with the given SampleModel.
81       * The Raster's upper left corner is origin and it is the same
82       * size as the SampleModel.  A DataBuffer large enough to describe the
83       * Raster is automatically created.  SampleModel must be of type
84       * SinglePixelPackedSampleModel or InterleavedSampleModel.
85       * @param sampleModel     The SampleModel that specifies the layout.
86       * @param origin          The Point that specified the origin.
87       */
88      public ByteInterleavedRaster(SampleModel sampleModel, Point origin) {
89          this(sampleModel,
90               sampleModel.createDataBuffer(),
91               new Rectangle(origin.x,
92                             origin.y,
93                             sampleModel.getWidth(),
94                             sampleModel.getHeight()),
95               origin,
96               null);
97      }
98  
99      /**
100      * Constructs a ByteInterleavedRaster with the given SampleModel
101      * and DataBuffer.  The Raster's upper left corner is origin and
102      * it is the same size as the SampleModel.  The DataBuffer is not
103      * initialized and must be a DataBufferByte compatible with SampleModel.
104      * SampleModel must be of type SinglePixelPackedSampleModel
105      * or InterleavedSampleModel.
106      * @param sampleModel     The SampleModel that specifies the layout.
107      * @param dataBuffer      The DataBufferShort that contains the image data.
108      * @param origin          The Point that specifies the origin.
109      */
110     public ByteInterleavedRaster(SampleModel sampleModel,
111                                   DataBuffer dataBuffer,
112                                   Point origin) {
113         this(sampleModel,
114              dataBuffer,
115              new Rectangle(origin.x,
116                            origin.y,
117                            sampleModel.getWidth(),
118                            sampleModel.getHeight()),
119              origin,
120              null);
121     }
122 
123     /*** Analyzes a ComponentSampleModel to determine if it can function
124      * as a PixelInterleavedSampleModel.  In order to do so, it must use
125      * only bank 0 of its DataBuffer, and the data offsets must span a range
126      * of less than pixelStride.
127      *
128      * <p> These properties are trivially true for a 1-banded SampleModel.
129      */
130     private boolean isInterleaved(ComponentSampleModel sm) {
131         // Analyze ComponentSampleModel to determine if it has the
132         // properties of a PixelInterleavedSampleModel
133 
134         int numBands = sampleModel.getNumBands();
135         if (numBands == 1) {
136             return true;
137         }
138 
139         // Determine banks used
140         int[] bankIndices = sm.getBankIndices();
141         for (int i = 0; i < numBands; i++) {
142             if (bankIndices[i] != 0) {
143                 return false;
144             }
145         }
146 
147         // Determine range of band offsets
148         int[] bandOffsets = sm.getBandOffsets();
149         int minOffset = bandOffsets[0];
150         int maxOffset = minOffset;
151         for (int i = 1; i < numBands; i++) {
152             int offset = bandOffsets[i];
153             if (offset < minOffset) {
154                 minOffset = offset;
155             }
156             if (offset > maxOffset) {
157                 maxOffset = offset;
158             }
159         }
160         if (maxOffset - minOffset >= sm.getPixelStride()) {
161             return false;
162         }
163 
164         return true;
165     }
166 
167     /**
168      * Constructs a ByteInterleavedRaster with the given SampleModel,
169      * DataBuffer, and parent.  DataBuffer must be a DataBufferByte and
170      * SampleModel must be of type SinglePixelPackedSampleModel
171      * or InterleavedSampleModel.
172      * When translated into the base Raster's
173      * coordinate system, aRegion must be contained by the base Raster.
174      * Origin is the coordinate in the new Raster's coordinate system of
175      * the origin of the base Raster.  (The base Raster is the Raster's
176      * ancestor which has no parent.)
177      *
178      * Note that this constructor should generally be called by other
179      * constructors or create methods, it should not be used directly.
180      * @param sampleModel     The SampleModel that specifies the layout.
181      * @param dataBuffer      The DataBufferShort that contains the image data.
182      * @param aRegion         The Rectangle that specifies the image area.
183      * @param origin          The Point that specifies the origin.
184      * @param parent          The parent (if any) of this raster.
185      */
186     public ByteInterleavedRaster(SampleModel sampleModel,
187                                   DataBuffer dataBuffer,
188                                   Rectangle aRegion,
189                                   Point origin,
190                                   ByteInterleavedRaster parent) {
191         super(sampleModel, dataBuffer, aRegion, origin, parent);
192         this.maxX = minX + width;
193         this.maxY = minY + height;
194 
195         if (!(dataBuffer instanceof DataBufferByte)) {
196             throw new RasterFormatException("ByteInterleavedRasters must have " +
197                                             "byte DataBuffers");
198         }
199 
200         DataBufferByte dbb = (DataBufferByte)dataBuffer;
201         this.data = stealData(dbb, 0);
202 
203         int xOffset = aRegion.x - origin.x;
204         int yOffset = aRegion.y - origin.y;
205         if (sampleModel instanceof PixelInterleavedSampleModel ||
206             (sampleModel instanceof ComponentSampleModel &&
207              isInterleaved((ComponentSampleModel)sampleModel))) {
208             ComponentSampleModel csm = (ComponentSampleModel)sampleModel;
209             this.scanlineStride = csm.getScanlineStride();
210             this.pixelStride = csm.getPixelStride();
211             this.dataOffsets = csm.getBandOffsets();
212             for (int i = 0; i < getNumDataElements(); i++) {
213                 dataOffsets[i] += xOffset*pixelStride+yOffset*scanlineStride;
214             }
215         } else if (sampleModel instanceof SinglePixelPackedSampleModel) {
216             SinglePixelPackedSampleModel sppsm =
217                     (SinglePixelPackedSampleModel)sampleModel;
218             this.packed = true;
219             this.bitMasks = sppsm.getBitMasks();
220             this.bitOffsets = sppsm.getBitOffsets();
221             this.scanlineStride = sppsm.getScanlineStride();
222             this.pixelStride = 1;
223             this.dataOffsets = new int[1];
224             this.dataOffsets[0] = dbb.getOffset();
225             dataOffsets[0] += xOffset*pixelStride+yOffset*scanlineStride;
226         } else {
227             throw new RasterFormatException("ByteInterleavedRasters must " +
228               "have PixelInterleavedSampleModel, SinglePixelPackedSampleModel"+
229               " or interleaved ComponentSampleModel.  Sample model is " +
230               sampleModel);
231         }
232         this.bandOffset = this.dataOffsets[0];
233 
234         this.dbOffsetPacked = dataBuffer.getOffset() -
235             sampleModelTranslateY*scanlineStride -
236             sampleModelTranslateX*pixelStride;
237         this.dbOffset = dbOffsetPacked -
238             (xOffset*pixelStride+yOffset*scanlineStride);
239 
240         // Set inOrder to true if the data elements are in order and
241         // have no gaps between them
242         this.inOrder = false;
243         if (numDataElements == pixelStride) {
244             inOrder = true;
245             for (int i = 1; i < numDataElements; i++) {
246                 if (dataOffsets[i] - dataOffsets[0] != i) {
247                     inOrder = false;
248                     break;
249                 }
250             }
251         }
252 
253         verify();
254     }
255 
256     /**
257      * Returns a copy of the data offsets array. For each band the data offset
258      * is the index into the band's data array, of the first sample of the
259      * band.
260      */
261     public int[] getDataOffsets() {
262         return (int[]) dataOffsets.clone();
263     }
264 
265     /**
266      * Returns the data offset for the specified band.  The data offset
267      * is the index into the data array
268      * in which the first sample of the first scanline is stored.
269      * @param band  The band whose offset is returned.
270      */
271     public int getDataOffset(int band) {
272         return dataOffsets[band];
273     }
274 
275     /**
276      * Returns the scanline stride -- the number of data array elements between
277      * a given sample and the sample in the same column of the next row in the
278      * same band.
279      */
280     public int getScanlineStride() {
281         return scanlineStride;
282     }
283 
284     /**
285      * Returns pixel stride -- the number of data array elements between two
286      * samples for the same band on the same scanline.
287      */
288     public int getPixelStride() {
289         return pixelStride;
290     }
291 
292     /**
293      * Returns a reference to the data array.
294      */
295     public byte[] getDataStorage() {
296         return data;
297     }
298 
299     /**
300      * Returns the data elements for all bands at the specified
301      * location.
302      * An ArrayIndexOutOfBounds exception will be thrown at runtime
303      * if the pixel coordinate is out of bounds.
304      * A ClassCastException will be thrown if the input object is non null
305      * and references anything other than an array of transferType.
306      * @param x        The X coordinate of the pixel location.
307      * @param y        The Y coordinate of the pixel location.
308      * @param outData  An object reference to an array of type defined by
309      *                 getTransferType() and length getNumDataElements().
310      *                 If null an array of appropriate type and size will be
311      *                 allocated.
312      * @return         An object reference to an array of type defined by
313      *                 getTransferType() with the request pixel data.
314      */
315     public Object getDataElements(int x, int y, Object obj) {
316         if ((x < this.minX) || (y < this.minY) ||
317             (x >= this.maxX) || (y >= this.maxY)) {
318             throw new ArrayIndexOutOfBoundsException
319                 ("Coordinate out of bounds!");
320         }
321         byte outData[];
322         if (obj == null) {
323             outData = new byte[numDataElements];
324         } else {
325             outData = (byte[])obj;
326         }
327         int off = (y-minY)*scanlineStride +
328                   (x-minX)*pixelStride;
329 
330         for (int band = 0; band < numDataElements; band++) {
331             outData[band] = data[dataOffsets[band] + off];
332         }
333 
334         return outData;
335     }
336 
337     /**
338      * Returns an array of data elements from the specified rectangular
339      * region.
340      * An ArrayIndexOutOfBounds exception will be thrown at runtime
341      * if the pixel coordinates are out of bounds.
342      * A ClassCastException will be thrown if the input object is non null
343      * and references anything other than an array of transferType.
344      * <pre>
345      *       byte[] bandData = (byte[])raster.getDataElements(x, y, w, h, null);
346      *       int numDataElements = raster.getNumDataElements();
347      *       byte[] pixel = new byte[numDataElements];
348      *       // To find a data element at location (x2, y2)
349      *       System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
350      *                        pixel, 0, numDataElements);
351      * </pre>
352      * @param x        The X coordinate of the upper left pixel location.
353      * @param y        The Y coordinate of the upper left pixel location.
354      * @param width    Width of the pixel rectangle.
355      * @param height   Height of the pixel rectangle.
356      * @param outData  An object reference to an array of type defined by
357      *                 getTransferType() and length w*h*getNumDataElements().
358      *                 If null an array of appropriate type and size will be
359      *                 allocated.
360      * @return         An object reference to an array of type defined by
361      *                 getTransferType() with the request pixel data.
362      */
363     public Object getDataElements(int x, int y, int w, int h, Object obj) {
364         return getByteData(x, y, w, h, (byte[])obj);
365     }
366 
367     /**
368      * Returns a byte array of data elements from the specified rectangular
369      * region for the specified band.
370      * An ArrayIndexOutOfBounds exception will be thrown at runtime
371      * if the pixel coordinates are out of bounds.
372      * <pre>
373      *       byte[] bandData = raster.getByteData(x, y, w, h, null);
374      *       // To find the data element at location (x2, y2)
375      *       byte bandElement = bandData[((y2-y)*w + (x2-x))];
376      * </pre>
377      * @param x        The X coordinate of the upper left pixel location.
378      * @param y        The Y coordinate of the upper left pixel location.
379      * @param width    Width of the pixel rectangle.
380      * @param height   Height of the pixel rectangle.
381      * @param band     The band to return.
382      * @param outData  If non-null, data elements for all bands
383      *                 at the specified location are returned in this array.
384      * @return         Data array with data elements for all bands.
385      */
386     public byte[] getByteData(int x, int y, int w, int h,
387                               int band, byte[] outData) {
388         // Bounds check for 'band' will be performed automatically
389         if ((x < this.minX) || (y < this.minY) ||
390             (x + w > this.maxX) || (y + h > this.maxY)) {
391             throw new ArrayIndexOutOfBoundsException
392                 ("Coordinate out of bounds!");
393         }
394         if (outData == null) {
395             outData = new byte[w*h];
396         }
397         int yoff = (y-minY)*scanlineStride +
398                    (x-minX)*pixelStride + dataOffsets[band];
399         int xoff;
400         int off = 0;
401         int xstart;
402         int ystart;
403 
404         if (pixelStride == 1) {
405             if (scanlineStride == w) {
406                 System.arraycopy(data, yoff, outData, 0, w*h);
407             } else {
408                 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
409                     System.arraycopy(data, yoff, outData, off, w);
410                     off += w;
411                 }
412             }
413         } else {
414             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
415                 xoff = yoff;
416                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
417                     outData[off++] = data[xoff];
418                 }
419             }
420         }
421 
422         return outData;
423     }
424 
425     /**
426      * Returns a byte array of data elements from the specified rectangular
427      * region.
428      * An ArrayIndexOutOfBounds exception will be thrown at runtime
429      * if the pixel coordinates are out of bounds.
430      * <pre>
431      *       byte[] bandData = raster.getByteData(x, y, w, h, null);
432      *       int numDataElements = raster.getnumDataElements();
433      *       byte[] pixel = new byte[numDataElements];
434      *       // To find a data element at location (x2, y2)
435      *       System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
436      *                        pixel, 0, numDataElements);
437      * </pre>
438      * @param x        The X coordinate of the upper left pixel location.
439      * @param y        The Y coordinate of the upper left pixel location.
440      * @param width    Width of the pixel rectangle.
441      * @param height   Height of the pixel rectangle.
442      * @param outData  If non-null, data elements for all bands
443      *                 at the specified location are returned in this array.
444      * @return         Data array with data elements for all bands.
445      */
446     public byte[] getByteData(int x, int y, int w, int h, byte[] outData) {
447         if ((x < this.minX) || (y < this.minY) ||
448             (x + w > this.maxX) || (y + h > this.maxY)) {
449             throw new ArrayIndexOutOfBoundsException
450                 ("Coordinate out of bounds!");
451         }
452         if (outData == null) {
453             outData = new byte[numDataElements*w*h];
454         }
455         int yoff = (y-minY)*scanlineStride +
456                    (x-minX)*pixelStride;
457         int xoff;
458         int off = 0;
459         int xstart;
460         int ystart;
461 
462         if (inOrder) {
463             yoff += dataOffsets[0];
464             int rowBytes = w*pixelStride;
465             if (scanlineStride == rowBytes) {
466                 System.arraycopy(data, yoff, outData, off, rowBytes*h);
467             } else {
468                 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
469                     System.arraycopy(data, yoff, outData, off, rowBytes);
470                     off += rowBytes;
471                 }
472             }
473         } else if (numDataElements == 1) {
474             yoff += dataOffsets[0];
475             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
476                 xoff = yoff;
477                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
478                     outData[off++] = data[xoff];
479                 }
480             }
481         } else if (numDataElements == 2) {
482             yoff += dataOffsets[0];
483             int d1 = dataOffsets[1] - dataOffsets[0];
484             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
485                 xoff = yoff;
486                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
487                     outData[off++] = data[xoff];
488                     outData[off++] = data[xoff + d1];
489                 }
490             }
491         } else if (numDataElements == 3) {
492             yoff += dataOffsets[0];
493             int d1 = dataOffsets[1] - dataOffsets[0];
494             int d2 = dataOffsets[2] - dataOffsets[0];
495             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
496                 xoff = yoff;
497                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
498                     outData[off++] = data[xoff];
499                     outData[off++] = data[xoff + d1];
500                     outData[off++] = data[xoff + d2];
501                 }
502             }
503         } else if (numDataElements == 4) {
504             yoff += dataOffsets[0];
505             int d1 = dataOffsets[1] - dataOffsets[0];
506             int d2 = dataOffsets[2] - dataOffsets[0];
507             int d3 = dataOffsets[3] - dataOffsets[0];
508             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
509                 xoff = yoff;
510                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
511                     outData[off++] = data[xoff];
512                     outData[off++] = data[xoff + d1];
513                     outData[off++] = data[xoff + d2];
514                     outData[off++] = data[xoff + d3];
515                 }
516             }
517         } else {
518             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
519                 xoff = yoff;
520                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
521                     for (int c = 0; c < numDataElements; c++) {
522                         outData[off++] = data[dataOffsets[c] + xoff];
523                     }
524                 }
525             }
526         }
527 
528         return outData;
529     }
530 
531     /**
532      * Stores the data elements for all bands at the specified location.
533      * An ArrayIndexOutOfBounds exception will be thrown at runtime
534      * if the pixel coordinate is out of bounds.
535      * A ClassCastException will be thrown if the input object is non null
536      * and references anything other than an array of transferType.
537      * @param x        The X coordinate of the pixel location.
538      * @param y        The Y coordinate of the pixel location.
539      * @param inData   An object reference to an array of type defined by
540      *                 getTransferType() and length getNumDataElements()
541      *                 containing the pixel data to place at x,y.
542      */
543     public void setDataElements(int x, int y, Object obj) {
544         if ((x < this.minX) || (y < this.minY) ||
545             (x >= this.maxX) || (y >= this.maxY)) {
546             throw new ArrayIndexOutOfBoundsException
547                 ("Coordinate out of bounds!");
548         }
549         byte inData[] = (byte[])obj;
550         int off = (y-minY)*scanlineStride +
551                   (x-minX)*pixelStride;
552 
553         for (int i = 0; i < numDataElements; i++) {
554             data[dataOffsets[i] + off] = inData[i];
555         }
556 
557         markDirty();
558     }
559 
560     /**
561      * Stores the Raster data at the specified location.
562      * An ArrayIndexOutOfBounds exception will be thrown at runtime
563      * if the pixel coordinates are out of bounds.
564      * @param x          The X coordinate of the pixel location.
565      * @param y          The Y coordinate of the pixel location.
566      * @param inRaster   Raster of data to place at x,y location.
567      */
568     public void setDataElements(int x, int y, Raster inRaster) {
569         int srcOffX = inRaster.getMinX();
570         int srcOffY = inRaster.getMinY();
571         int dstOffX = x + srcOffX;
572         int dstOffY = y + srcOffY;
573         int width  = inRaster.getWidth();
574         int height = inRaster.getHeight();
575         if ((dstOffX < this.minX) || (dstOffY < this.minY) ||
576             (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) {
577             throw new ArrayIndexOutOfBoundsException
578                 ("Coordinate out of bounds!");
579         }
580 
581         setDataElements(dstOffX, dstOffY, srcOffX, srcOffY,
582                         width, height, inRaster);
583     }
584 
585     /**
586      * Stores the Raster data at the specified location.
587      * @param dstX The absolute X coordinate of the destination pixel
588      * that will receive a copy of the upper-left pixel of the
589      * inRaster
590      * @param dstY The absolute Y coordinate of the destination pixel
591      * that will receive a copy of the upper-left pixel of the
592      * inRaster
593      * @param srcX The absolute X coordinate of the upper-left source
594      * pixel that will be copied into this Raster
595      * @param srcY The absolute Y coordinate of the upper-left source
596      * pixel that will be copied into this Raster
597      * @param width      The number of pixels to store horizontally
598      * @param height     The number of pixels to store vertically
599      * @param inRaster   Raster of data to place at x,y location.
600      */
601     private void setDataElements(int dstX, int dstY,
602                                  int srcX, int srcY,
603                                  int width, int height,
604                                  Raster inRaster) {
605         // Assume bounds checking has been performed previously
606         if (width <= 0 || height <= 0) {
607             return;
608         }
609 
610         // Write inRaster (minX, minY) to (dstX, dstY)
611 
612         int srcOffX = inRaster.getMinX();
613         int srcOffY = inRaster.getMinY();
614         Object tdata = null;
615 
616         if (inRaster instanceof ByteInterleavedRaster) {
617             ByteInterleavedRaster bct = (ByteInterleavedRaster) inRaster;
618             byte[] bdata = bct.getDataStorage();
619             // copy whole scanlines
620             if (inOrder && bct.inOrder && pixelStride == bct.pixelStride) {
621                 int toff = bct.getDataOffset(0);
622                 int tss  = bct.getScanlineStride();
623                 int tps  = bct.getPixelStride();
624 
625                 int srcOffset = toff +
626                     (srcY - srcOffY) * tss +
627                     (srcX - srcOffX) * tps;
628                 int dstOffset = dataOffsets[0] +
629                     (dstY - minY) * scanlineStride +
630                     (dstX - minX) * pixelStride;
631 
632                 int nbytes = width*pixelStride;
633                 for (int tmpY=0; tmpY < height; tmpY++) {
634                     System.arraycopy(bdata, srcOffset,
635                                      data, dstOffset, nbytes);
636                     srcOffset += tss;
637                     dstOffset += scanlineStride;
638                 }
639                 markDirty();
640                 return;
641             }
642         }
643 
644         for (int startY=0; startY < height; startY++) {
645             // Grab one scanline at a time
646             tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
647                                              width, 1, tdata);
648             setDataElements(dstX, dstY + startY, width, 1, tdata);
649         }
650     }
651 
652     /**
653      * Stores an array of data elements into the specified rectangular
654      * region.
655      * An ArrayIndexOutOfBounds exception will be thrown at runtime
656      * if the pixel coordinates are out of bounds.
657      * A ClassCastException will be thrown if the input object is non null
658      * and references anything other than an array of transferType.
659      * The data elements in the
660      * data array are assumed to be packed.  That is, a data element
661      * for the nth band at location (x2, y2) would be found at:
662      * <pre>
663      *      inData[((y2-y)*w + (x2-x))*numDataElements + n]
664      * </pre>
665      * @param x        The X coordinate of the upper left pixel location.
666      * @param y        The Y coordinate of the upper left pixel location.
667      * @param w        Width of the pixel rectangle.
668      * @param h        Height of the pixel rectangle.
669      * @param inData   An object reference to an array of type defined by
670      *                 getTransferType() and length w*h*getNumDataElements()
671      *                 containing the pixel data to place between x,y and
672      *                 x+h, y+h.
673      */
674     public void setDataElements(int x, int y, int w, int h, Object obj) {
675         putByteData(x, y, w, h, (byte[])obj);
676     }
677 
678     /**
679      * Stores a byte array of data elements into the specified rectangular
680      * region for the specified band.
681      * An ArrayIndexOutOfBounds exception will be thrown at runtime
682      * if the pixel coordinates are out of bounds.
683      * The data elements in the
684      * data array are assumed to be packed.  That is, a data element
685      * at location (x2, y2) would be found at:
686      * <pre>
687      *      inData[((y2-y)*w + (x2-x)) + n]
688      * </pre>
689      * @param x        The X coordinate of the upper left pixel location.
690      * @param y        The Y coordinate of the upper left pixel location.
691      * @param w        Width of the pixel rectangle.
692      * @param h        Height of the pixel rectangle.
693      * @param band     The band to set.
694      * @param inData   The data elements to be stored.
695      */
696     public void putByteData(int x, int y, int w, int h,
697                             int band, byte[] inData) {
698         // Bounds check for 'band' will be performed automatically
699         if ((x < this.minX) || (y < this.minY) ||
700             (x + w > this.maxX) || (y + h > this.maxY)) {
701             throw new ArrayIndexOutOfBoundsException
702                 ("Coordinate out of bounds!");
703         }
704         int yoff = (y-minY)*scanlineStride +
705                    (x-minX)*pixelStride + dataOffsets[band];
706         int xoff;
707         int off = 0;
708         int xstart;
709         int ystart;
710 
711         if (pixelStride == 1) {
712             if (scanlineStride == w) {
713                 System.arraycopy(inData, 0, data, yoff, w*h);
714             }
715             else {
716                 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
717                     System.arraycopy(inData, off, data, yoff, w);
718                     off += w;
719                 }
720             }
721         }
722         else {
723             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
724                 xoff = yoff;
725                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
726                     data[xoff] = inData[off++];
727                 }
728             }
729         }
730 
731         markDirty();
732     }
733 
734     /**
735      * Stores a byte array of data elements into the specified rectangular
736      * region.
737      * An ArrayIndexOutOfBounds exception will be thrown at runtime
738      * if the pixel coordinates are out of bounds.
739      * The data elements in the
740      * data array are assumed to be packed.  That is, a data element
741      * for the nth band at location (x2, y2) would be found at:
742      * <pre>
743      *      inData[((y2-y)*w + (x2-x))*numDataElements + n]
744      * </pre>
745      * @param x        The X coordinate of the upper left pixel location.
746      * @param y        The Y coordinate of the upper left pixel location.
747      * @param w        Width of the pixel rectangle.
748      * @param h        Height of the pixel rectangle.
749      * @param inData   The data elements to be stored.
750      */
751     public void putByteData(int x, int y, int w, int h, byte[] inData) {
752         if ((x < this.minX) || (y < this.minY) ||
753             (x + w > this.maxX) || (y + h > this.maxY)) {
754             throw new ArrayIndexOutOfBoundsException
755                 ("Coordinate out of bounds!");
756         }
757         int yoff = (y-minY)*scanlineStride +
758                    (x-minX)*pixelStride;
759 
760         int xoff;
761         int off = 0;
762         int xstart;
763         int ystart;
764 
765         if (inOrder) {
766             yoff += dataOffsets[0];
767             int rowBytes = w*pixelStride;
768             if (rowBytes == scanlineStride) {
769                 System.arraycopy(inData, 0, data, yoff, rowBytes*h);
770             } else {
771                 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
772                     System.arraycopy(inData, off, data, yoff, rowBytes);
773                     off += rowBytes;
774                 }
775             }
776         } else if (numDataElements == 1) {
777             yoff += dataOffsets[0];
778             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
779                 xoff = yoff;
780                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
781                     data[xoff] = inData[off++];
782                 }
783             }
784         } else if (numDataElements == 2) {
785             yoff += dataOffsets[0];
786             int d1 = dataOffsets[1] - dataOffsets[0];
787             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
788                 xoff = yoff;
789                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
790                     data[xoff] = inData[off++];
791                     data[xoff + d1] = inData[off++];
792                 }
793             }
794         } else if (numDataElements == 3) {
795             yoff += dataOffsets[0];
796             int d1 = dataOffsets[1] - dataOffsets[0];
797             int d2 = dataOffsets[2] - dataOffsets[0];
798             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
799                 xoff = yoff;
800                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
801                     data[xoff] = inData[off++];
802                     data[xoff + d1] = inData[off++];
803                     data[xoff + d2] = inData[off++];
804                 }
805             }
806         } else if (numDataElements == 4) {
807             yoff += dataOffsets[0];
808             int d1 = dataOffsets[1] - dataOffsets[0];
809             int d2 = dataOffsets[2] - dataOffsets[0];
810             int d3 = dataOffsets[3] - dataOffsets[0];
811             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
812                 xoff = yoff;
813                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
814                     data[xoff] = inData[off++];
815                     data[xoff + d1] = inData[off++];
816                     data[xoff + d2] = inData[off++];
817                     data[xoff + d3] = inData[off++];
818                 }
819             }
820         } else {
821             for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
822                 xoff = yoff;
823                 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
824                     for (int c = 0; c < numDataElements; c++) {
825                         data[dataOffsets[c] + xoff] = inData[off++];
826                     }
827                 }
828             }
829         }
830 
831         markDirty();
832     }
833 
834     public int getSample(int x, int y, int b) {
835         if ((x < this.minX) || (y < this.minY) ||
836             (x >= this.maxX) || (y >= this.maxY)) {
837             throw new ArrayIndexOutOfBoundsException
838                 ("Coordinate out of bounds!");
839         }
840         if (packed) {
841             int offset = y*scanlineStride + x + dbOffsetPacked;
842             byte sample = data[offset];
843             return (sample & bitMasks[b]) >>> bitOffsets[b];
844         } else {
845             int offset = y*scanlineStride + x*pixelStride + dbOffset;
846             return data[offset + dataOffsets[b]] & 0xff;
847         }
848     }
849 
850     public void setSample(int x, int y, int b, int s) {
851         if ((x < this.minX) || (y < this.minY) ||
852             (x >= this.maxX) || (y >= this.maxY)) {
853             throw new ArrayIndexOutOfBoundsException
854                 ("Coordinate out of bounds!");
855         }
856         if (packed) {
857             int offset = y*scanlineStride + x + dbOffsetPacked;
858             int bitMask = bitMasks[b];
859 
860             byte value = data[offset];
861             value &= ~bitMask;
862             value |= (s << bitOffsets[b]) & bitMask;
863             data[offset] = value;
864         } else {
865             int offset = y*scanlineStride + x*pixelStride + dbOffset;
866             data[offset + dataOffsets[b]] = (byte)s;
867         }
868 
869         markDirty();
870     }
871 
872     public int[] getSamples(int x, int y, int w, int h, int b,
873                             int[] iArray) {
874         if ((x < this.minX) || (y < this.minY) ||
875             (x + w > this.maxX) || (y + h > this.maxY)) {
876             throw new ArrayIndexOutOfBoundsException
877                 ("Coordinate out of bounds!");
878         }
879         int samples[];
880         if (iArray != null) {
881             samples = iArray;
882         } else {
883             samples = new int [w*h];
884         }
885 
886         int lineOffset = y*scanlineStride + x*pixelStride;
887         int dstOffset = 0;
888 
889         if (packed) {
890             lineOffset += dbOffsetPacked;
891             int bitMask = bitMasks[b];
892             int bitOffset = bitOffsets[b];
893 
894             for (int j = 0; j < h; j++) {
895                 int sampleOffset = lineOffset;
896                 for (int i = 0; i < w; i++) {
897                     int value = data[sampleOffset++];
898                     samples[dstOffset++] = ((value & bitMask) >>> bitOffset);
899                 }
900                 lineOffset += scanlineStride;
901             }
902         } else {
903             lineOffset += dbOffset + dataOffsets[b];
904             for (int j = 0; j < h; j++) {
905                 int sampleOffset = lineOffset;
906                 for (int i = 0; i < w; i++) {
907                     samples[dstOffset++] = data[sampleOffset] & 0xff;
908                     sampleOffset += pixelStride;
909                 }
910                 lineOffset += scanlineStride;
911             }
912         }
913 
914         return samples;
915     }
916 
917     public void setSamples(int x, int y, int w, int h, int b, int iArray[]) {
918         if ((x < this.minX) || (y < this.minY) ||
919             (x + w > this.maxX) || (y + h > this.maxY)) {
920             throw new ArrayIndexOutOfBoundsException
921                 ("Coordinate out of bounds!");
922         }
923         int lineOffset = y*scanlineStride + x*pixelStride;
924         int srcOffset = 0;
925 
926         if (packed) {
927             lineOffset += dbOffsetPacked;
928             int bitMask = bitMasks[b];
929 
930             for (int j = 0; j < h; j++) {
931                 int sampleOffset = lineOffset;
932                 for (int i = 0; i < w; i++) {
933                     byte value = data[sampleOffset];
934                     value &= ~bitMask;
935                     int sample = iArray[srcOffset++];
936                     value |= (sample << bitOffsets[b]) & bitMask;
937                     data[sampleOffset++] = value;
938                 }
939                 lineOffset += scanlineStride;
940             }
941         } else {
942             lineOffset += dbOffset + dataOffsets[b];
943             for (int i = 0; i < h; i++) {
944                 int sampleOffset = lineOffset;
945                 for (int j = 0; j < w; j++) {
946                     data[sampleOffset] = (byte)iArray[srcOffset++];
947                     sampleOffset += pixelStride;
948                 }
949                 lineOffset += scanlineStride;
950             }
951         }
952 
953         markDirty();
954     }
955 
956     public int[] getPixels(int x, int y, int w, int h, int[] iArray) {
957         if ((x < this.minX) || (y < this.minY) ||
958             (x + w > this.maxX) || (y + h > this.maxY)) {
959             throw new ArrayIndexOutOfBoundsException
960                 ("Coordinate out of bounds!");
961         }
962         int pixels[];
963         if (iArray != null) {
964             pixels = iArray;
965         } else {
966             pixels = new int[w*h*numBands];
967         }
968 
969         int lineOffset = y*scanlineStride + x*pixelStride;
970         int dstOffset = 0;
971 
972         if (packed) {
973             lineOffset += dbOffsetPacked;
974             for (int j = 0; j < h; j++) {
975                 for (int i = 0; i < w; i++) {
976                     int value = data[lineOffset + i];
977                     for (int k = 0; k < numBands; k++) {
978                         pixels[dstOffset++] =
979                             (value & bitMasks[k]) >>> bitOffsets[k];
980                     }
981                 }
982                 lineOffset += scanlineStride;
983             }
984         } else {
985             lineOffset += dbOffset;
986             int d0 = dataOffsets[0];
987 
988             if (numBands == 1) {
989                 for (int j = 0; j < h; j++) {
990                     int pixelOffset = lineOffset + d0;
991                     for (int i = 0; i < w; i++) {
992                         pixels[dstOffset++] = data[pixelOffset] & 0xff;
993                         pixelOffset += pixelStride;
994                     }
995                     lineOffset += scanlineStride;
996                 }
997             } else if (numBands == 2) {
998                 int d1 = dataOffsets[1] - d0;
999                 for (int j = 0; j < h; j++) {
1000                     int pixelOffset = lineOffset + d0;
1001                     for (int i = 0; i < w; i++) {
1002                         pixels[dstOffset++] = data[pixelOffset] & 0xff;
1003                         pixels[dstOffset++] = data[pixelOffset + d1] & 0xff;
1004                         pixelOffset += pixelStride;
1005                     }
1006                     lineOffset += scanlineStride;
1007                 }
1008             } else if (numBands == 3) {
1009                 int d1 = dataOffsets[1] - d0;
1010                 int d2 = dataOffsets[2] - d0;
1011                 for (int j = 0; j < h; j++) {
1012                     int pixelOffset = lineOffset + d0;
1013                     for (int i = 0; i < w; i++) {
1014                         pixels[dstOffset++] = data[pixelOffset] & 0xff;
1015                         pixels[dstOffset++] = data[pixelOffset + d1] & 0xff;
1016                         pixels[dstOffset++] = data[pixelOffset + d2] & 0xff;
1017                         pixelOffset += pixelStride;
1018                     }
1019                     lineOffset += scanlineStride;
1020                 }
1021             } else if (numBands == 4) {
1022                 int d1 = dataOffsets[1] - d0;
1023                 int d2 = dataOffsets[2] - d0;
1024                 int d3 = dataOffsets[3] - d0;
1025                 for (int j = 0; j < h; j++) {
1026                     int pixelOffset = lineOffset + d0;
1027                     for (int i = 0; i < w; i++) {
1028                         pixels[dstOffset++] = data[pixelOffset] & 0xff;
1029                         pixels[dstOffset++] = data[pixelOffset + d1] & 0xff;
1030                         pixels[dstOffset++] = data[pixelOffset + d2] & 0xff;
1031                         pixels[dstOffset++] = data[pixelOffset + d3] & 0xff;
1032                         pixelOffset += pixelStride;
1033                     }
1034                     lineOffset += scanlineStride;
1035                 }
1036             } else {
1037                 for (int j = 0; j < h; j++) {
1038                     int pixelOffset = lineOffset;
1039                     for (int i = 0; i < w; i++) {
1040                         for (int k = 0; k < numBands; k++) {
1041                             pixels[dstOffset++] =
1042                                 data[pixelOffset + dataOffsets[k]] & 0xff;
1043                         }
1044                         pixelOffset += pixelStride;
1045                     }
1046                     lineOffset += scanlineStride;
1047                 }
1048             }
1049         }
1050 
1051         return pixels;
1052     }
1053 
1054     public void setPixels(int x, int y, int w, int h, int[] iArray) {
1055         if ((x < this.minX) || (y < this.minY) ||
1056             (x + w > this.maxX) || (y + h > this.maxY)) {
1057             throw new ArrayIndexOutOfBoundsException
1058                 ("Coordinate out of bounds!");
1059         }
1060         int lineOffset = y*scanlineStride + x*pixelStride;
1061         int srcOffset = 0;
1062 
1063         if (packed) {
1064             lineOffset += dbOffsetPacked;
1065             for (int j = 0; j < h; j++) {
1066                 for (int i = 0; i < w; i++) {
1067                     int value = 0;
1068                     for (int k = 0; k < numBands; k++) {
1069                         int srcValue = iArray[srcOffset++];
1070                         value |= ((srcValue << bitOffsets[k])
1071                                   & bitMasks[k]);
1072                     }
1073                     data[lineOffset + i] = (byte)value;
1074                 }
1075                 lineOffset += scanlineStride;
1076             }
1077         } else {
1078             lineOffset += dbOffset;
1079             int d0 = dataOffsets[0];
1080 
1081             if (numBands == 1) {
1082                 for (int j = 0; j < h; j++) {
1083                     int pixelOffset = lineOffset + d0;
1084                     for (int i = 0; i < w; i++) {
1085                         data[pixelOffset] = (byte)iArray[srcOffset++];
1086                         pixelOffset += pixelStride;
1087                     }
1088                     lineOffset += scanlineStride;
1089                 }
1090             } else if (numBands == 2) {
1091                 int d1 = dataOffsets[1] - d0;
1092                 for (int j = 0; j < h; j++) {
1093                     int pixelOffset = lineOffset + d0;
1094                     for (int i = 0; i < w; i++) {
1095                         data[pixelOffset] = (byte)iArray[srcOffset++];
1096                         data[pixelOffset + d1] = (byte)iArray[srcOffset++];
1097                         pixelOffset += pixelStride;
1098                     }
1099                     lineOffset += scanlineStride;
1100                 }
1101             } else if (numBands == 3) {
1102                 int d1 = dataOffsets[1] - d0;
1103                 int d2 = dataOffsets[2] - d0;
1104                 for (int j = 0; j < h; j++) {
1105                     int pixelOffset = lineOffset + d0;
1106                     for (int i = 0; i < w; i++) {
1107                         data[pixelOffset] = (byte)iArray[srcOffset++];
1108                         data[pixelOffset + d1] = (byte)iArray[srcOffset++];
1109                         data[pixelOffset + d2] = (byte)iArray[srcOffset++];
1110                         pixelOffset += pixelStride;
1111                     }
1112                     lineOffset += scanlineStride;
1113                 }
1114             } else if (numBands == 4) {
1115                 int d1 = dataOffsets[1] - d0;
1116                 int d2 = dataOffsets[2] - d0;
1117                 int d3 = dataOffsets[3] - d0;
1118                 for (int j = 0; j < h; j++) {
1119                     int pixelOffset = lineOffset + d0;
1120                     for (int i = 0; i < w; i++) {
1121                         data[pixelOffset] = (byte)iArray[srcOffset++];
1122                         data[pixelOffset + d1] = (byte)iArray[srcOffset++];
1123                         data[pixelOffset + d2] = (byte)iArray[srcOffset++];
1124                         data[pixelOffset + d3] = (byte)iArray[srcOffset++];
1125                         pixelOffset += pixelStride;
1126                     }
1127                     lineOffset += scanlineStride;
1128                 }
1129             } else {
1130                 for (int j = 0; j < h; j++) {
1131                     int pixelOffset = lineOffset;
1132                     for (int i = 0; i < w; i++) {
1133                         for (int k = 0; k < numBands; k++) {
1134                             data[pixelOffset + dataOffsets[k]] =
1135                                 (byte)iArray[srcOffset++];
1136                         }
1137                         pixelOffset += pixelStride;
1138                     }
1139                     lineOffset += scanlineStride;
1140                 }
1141             }
1142         }
1143 
1144         markDirty();
1145     }
1146 
1147     public void setRect(int dx, int dy, Raster srcRaster) {
1148         if (!(srcRaster instanceof ByteInterleavedRaster)) {
1149             super.setRect(dx, dy, srcRaster);
1150             return;
1151         }
1152 
1153         int width  = srcRaster.getWidth();
1154         int height = srcRaster.getHeight();
1155         int srcOffX = srcRaster.getMinX();
1156         int srcOffY = srcRaster.getMinY();
1157         int dstOffX = dx+srcOffX;
1158         int dstOffY = dy+srcOffY;
1159 
1160         // Clip to this raster
1161         if (dstOffX < this.minX) {
1162             int skipX = minX - dstOffX;
1163             width -= skipX;
1164             srcOffX += skipX;
1165             dstOffX = this.minX;
1166         }
1167         if (dstOffY < this.minY) {
1168             int skipY = this.minY - dstOffY;
1169             height -= skipY;
1170             srcOffY += skipY;
1171             dstOffY = this.minY;
1172         }
1173         if (dstOffX+width > this.maxX) {
1174             width = this.maxX - dstOffX;
1175         }
1176         if (dstOffY+height > this.maxY) {
1177             height = this.maxY - dstOffY;
1178         }
1179 
1180         setDataElements(dstOffX, dstOffY,
1181                         srcOffX, srcOffY,
1182                         width, height, srcRaster);
1183     }
1184 
1185 
1186     /**
1187      * Creates a subraster given a region of the raster.  The x and y
1188      * coordinates specify the horizontal and vertical offsets
1189      * from the upper-left corner of this raster to the upper-left corner
1190      * of the subraster.  A subset of the bands of the parent Raster may
1191      * be specified.  If this is null, then all the bands are present in the
1192      * subRaster. A translation to the subRaster may also be specified.
1193      * Note that the subraster will reference the same
1194      * DataBuffer as the parent raster, but using different offsets.
1195      * @param x               X offset.
1196      * @param y               Y offset.
1197      * @param width           Width (in pixels) of the subraster.
1198      * @param height          Height (in pixels) of the subraster.
1199      * @param x0              Translated X origin of the subraster.
1200      * @param y0              Translated Y origin of the subraster.
1201      * @param bandList        Array of band indices.
1202      * @exception RasterFormatException
1203      *            if the specified bounding box is outside of the parent raster.
1204      */
1205     public Raster createChild(int x, int y,
1206                               int width, int height,
1207                               int x0, int y0, int[] bandList) {
1208         WritableRaster newRaster = createWritableChild(x, y,
1209                                                        width, height,
1210                                                        x0, y0,
1211                                                        bandList);
1212         return (Raster) newRaster;
1213     }
1214 
1215     /**
1216      * Creates a Writable subRaster given a region of the Raster. The x and y
1217      * coordinates specify the horizontal and vertical offsets
1218      * from the upper-left corner of this Raster to the upper-left corner
1219      * of the subRaster.  A subset of the bands of the parent Raster may
1220      * be specified.  If this is null, then all the bands are present in the
1221      * subRaster. A translation to the subRaster may also be specified.
1222      * Note that the subRaster will reference the same
1223      * DataBuffer as the parent Raster, but using different offsets.
1224      * @param x               X offset.
1225      * @param y               Y offset.
1226      * @param width           Width (in pixels) of the subraster.
1227      * @param height          Height (in pixels) of the subraster.
1228      * @param x0              Translated X origin of the subraster.
1229      * @param y0              Translated Y origin of the subraster.
1230      * @param bandList        Array of band indices.
1231      * @exception RasterFormatException
1232      *            if the specified bounding box is outside of the parent Raster.
1233      */
1234     public WritableRaster createWritableChild(int x, int y,
1235                                               int width, int height,
1236                                               int x0, int y0,
1237                                               int[] bandList) {
1238         if (x < this.minX) {
1239             throw new RasterFormatException("x lies outside the raster");
1240         }
1241         if (y < this.minY) {
1242             throw new RasterFormatException("y lies outside the raster");
1243         }
1244         if ((x+width < x) || (x+width > this.minX + this.width)) {
1245             throw new RasterFormatException("(x + width) is outside of Raster");
1246         }
1247         if ((y+height < y) || (y+height > this.minY + this.height)) {
1248             throw new RasterFormatException("(y + height) is outside of Raster");
1249         }
1250 
1251         SampleModel sm;
1252 
1253         if (bandList != null)
1254             sm = sampleModel.createSubsetSampleModel(bandList);
1255         else
1256             sm = sampleModel;
1257 
1258         int deltaX = x0 - x;
1259         int deltaY = y0 - y;
1260 
1261         return new ByteInterleavedRaster(sm,
1262                                        dataBuffer,
1263                                        new Rectangle(x0, y0, width, height),
1264                                        new Point(sampleModelTranslateX+deltaX,
1265                                                  sampleModelTranslateY+deltaY),
1266                                        this);
1267     }
1268 
1269     /**
1270      * Creates a Raster with the same layout but using a different
1271      * width and height, and with new zeroed data arrays.
1272      */
1273     public WritableRaster createCompatibleWritableRaster(int w, int h) {
1274         if (w <= 0 || h <=0) {
1275             throw new RasterFormatException("negative "+
1276                                           ((w <= 0) ? "width" : "height"));
1277         }
1278 
1279         SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
1280 
1281         return new ByteInterleavedRaster(sm, new Point(0,0));
1282 
1283     }
1284 
1285     /**
1286      * Creates a Raster with the same layout and the same
1287      * width and height, and with new zeroed data arrays.  If
1288      * the Raster is a subRaster, this will call
1289      * createCompatibleRaster(width, height).
1290      */
1291     public WritableRaster createCompatibleWritableRaster() {
1292         return createCompatibleWritableRaster(width,height);
1293     }
1294 
1295     public String toString() {
1296         return new String ("ByteInterleavedRaster: width = "+width+" height = "
1297                            + height
1298                            +" #numDataElements "+numDataElements
1299                            //  +" xOff = "+xOffset+" yOff = "+yOffset
1300                            +" dataOff[0] = "+dataOffsets[0]);
1301     }
1302 
1303 //    /**
1304 //     * For debugging...  prints a region of a one-band ByteInterleavedRaster
1305 //     */
1306 //    public void print(int x, int y, int w, int h) {
1307 //        // REMIND:  Only works for 1 band!
1308 //        System.out.println(this);
1309 //        int offset = dataOffsets[0] + y*scanlineStride + x*pixelStride;
1310 //        int off;
1311 //        for (int yoff=0; yoff < h; yoff++, offset += scanlineStride) {
1312 //            off = offset;
1313 //            System.out.print("Line "+(y+yoff)+": ");
1314 //            for (int xoff = 0; xoff < w; xoff++, off+= pixelStride) {
1315 //                String s = Integer.toHexString(data[off]);
1316 //                if (s.length() == 8) {
1317 //                    s = s.substring(6,8);
1318 //                }
1319 //                System.out.print(s+" ");
1320 //            }
1321 //            System.out.println("");
1322 //        }
1323 //    }
1324 }