View Javadoc
1   /*
2    * Copyright (c) 1997, 2013, 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  /* ****************************************************************
27   ******************************************************************
28   ******************************************************************
29   *** COPYRIGHT (c) Eastman Kodak Company, 1997
30   *** As  an unpublished  work pursuant to Title 17 of the United
31   *** States Code.  All rights reserved.
32   ******************************************************************
33   ******************************************************************
34   ******************************************************************/
35  
36  package java.awt.image;
37  
38  /**
39   *  This class represents image data which is stored in a band interleaved
40   *  fashion and for
41   *  which each sample of a pixel occupies one data element of the DataBuffer.
42   *  It subclasses ComponentSampleModel but provides a more efficient
43   *  implementation for accessing band interleaved image data than is provided
44   *  by ComponentSampleModel.  This class should typically be used when working
45   *  with images which store sample data for each band in a different bank of the
46   *  DataBuffer. Accessor methods are provided so that image data can be
47   *  manipulated directly. Pixel stride is the number of
48   *  data array elements between two samples for the same band on the same
49   *  scanline. The pixel stride for a BandedSampleModel is one.
50   *  Scanline stride is the number of data array elements between
51   *  a given sample and the corresponding sample in the same column of the next
52   *  scanline.  Band offsets denote the number
53   *  of data array elements from the first data array element of the bank
54   *  of the DataBuffer holding each band to the first sample of the band.
55   *  The bands are numbered from 0 to N-1.
56   *  Bank indices denote the correspondence between a bank of the data buffer
57   *  and a band of image data.  This class supports
58   *  {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
59   *  {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
60   *  {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
61   *  {@link DataBuffer#TYPE_INT TYPE_INT},
62   *  {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, and
63   *  {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes
64   */
65  
66  
67  public final class BandedSampleModel extends ComponentSampleModel
68  {
69  
70      /**
71       * Constructs a BandedSampleModel with the specified parameters.
72       * The pixel stride will be one data element.  The scanline stride
73       * will be the same as the width.  Each band will be stored in
74       * a separate bank and all band offsets will be zero.
75       * @param dataType  The data type for storing samples.
76       * @param w         The width (in pixels) of the region of
77       *                  image data described.
78       * @param h         The height (in pixels) of the region of image
79       *                  data described.
80       * @param numBands  The number of bands for the image data.
81       * @throws IllegalArgumentException if <code>dataType</code> is not
82       *         one of the supported data types
83       */
84      public BandedSampleModel(int dataType, int w, int h, int numBands) {
85          super(dataType, w, h, 1, w,
86                BandedSampleModel.createIndicesArray(numBands),
87                BandedSampleModel.createOffsetArray(numBands));
88      }
89  
90      /**
91       * Constructs a BandedSampleModel with the specified parameters.
92       * The number of bands will be inferred from the lengths of the
93       * bandOffsets bankIndices arrays, which must be equal.  The pixel
94       * stride will be one data element.
95       * @param dataType  The data type for storing samples.
96       * @param w         The width (in pixels) of the region of
97       *                  image data described.
98       * @param h         The height (in pixels) of the region of
99       *                  image data described.
100      * @param scanlineStride The line stride of the of the image data.
101      * @param bankIndices The bank index for each band.
102      * @param bandOffsets The band offset for each band.
103      * @throws IllegalArgumentException if <code>dataType</code> is not
104      *         one of the supported data types
105      */
106     public BandedSampleModel(int dataType,
107                              int w, int h,
108                              int scanlineStride,
109                              int bankIndices[],
110                              int bandOffsets[]) {
111 
112         super(dataType, w, h, 1,scanlineStride, bankIndices, bandOffsets);
113     }
114 
115     /**
116      * Creates a new BandedSampleModel with the specified
117      * width and height.  The new BandedSampleModel will have the same
118      * number of bands, storage data type, and bank indices
119      * as this BandedSampleModel.  The band offsets will be compressed
120      * such that the offset between bands will be w*pixelStride and
121      * the minimum of all of the band offsets is zero.
122      * @param w the width of the resulting <code>BandedSampleModel</code>
123      * @param h the height of the resulting <code>BandedSampleModel</code>
124      * @return a new <code>BandedSampleModel</code> with the specified
125      *         width and height.
126      * @throws IllegalArgumentException if <code>w</code> or
127      *         <code>h</code> equals either
128      *         <code>Integer.MAX_VALUE</code> or
129      *         <code>Integer.MIN_VALUE</code>
130      * @throws IllegalArgumentException if <code>dataType</code> is not
131      *         one of the supported data types
132      */
133     public SampleModel createCompatibleSampleModel(int w, int h) {
134         int[] bandOffs;
135 
136         if (numBanks == 1) {
137             bandOffs = orderBands(bandOffsets, w*h);
138         }
139         else {
140             bandOffs = new int[bandOffsets.length];
141         }
142 
143         SampleModel sampleModel =
144             new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffs);
145         return sampleModel;
146     }
147 
148     /**
149      * Creates a new BandedSampleModel with a subset of the bands of this
150      * BandedSampleModel.  The new BandedSampleModel can be
151      * used with any DataBuffer that the existing BandedSampleModel
152      * can be used with.  The new BandedSampleModel/DataBuffer
153      * combination will represent an image with a subset of the bands
154      * of the original BandedSampleModel/DataBuffer combination.
155      * @throws RasterFormatException if the number of bands is greater than
156      *                               the number of banks in this sample model.
157      * @throws IllegalArgumentException if <code>dataType</code> is not
158      *         one of the supported data types
159      */
160     public SampleModel createSubsetSampleModel(int bands[]) {
161         if (bands.length > bankIndices.length)
162             throw new RasterFormatException("There are only " +
163                                             bankIndices.length +
164                                             " bands");
165         int newBankIndices[] = new int[bands.length];
166         int newBandOffsets[] = new int[bands.length];
167 
168         for (int i=0; i<bands.length; i++) {
169             newBankIndices[i] = bankIndices[bands[i]];
170             newBandOffsets[i] = bandOffsets[bands[i]];
171         }
172 
173         return new BandedSampleModel(this.dataType, width, height,
174                                      this.scanlineStride,
175                                      newBankIndices, newBandOffsets);
176     }
177 
178     /**
179      * Creates a DataBuffer that corresponds to this BandedSampleModel,
180      * The DataBuffer's data type, number of banks, and size
181      * will be consistent with this BandedSampleModel.
182      * @throws IllegalArgumentException if <code>dataType</code> is not
183      *         one of the supported types.
184      */
185     public DataBuffer createDataBuffer() {
186         DataBuffer dataBuffer = null;
187 
188         int size = scanlineStride * height;
189         switch (dataType) {
190         case DataBuffer.TYPE_BYTE:
191             dataBuffer = new DataBufferByte(size, numBanks);
192             break;
193         case DataBuffer.TYPE_USHORT:
194             dataBuffer = new DataBufferUShort(size, numBanks);
195             break;
196         case DataBuffer.TYPE_SHORT:
197             dataBuffer = new DataBufferShort(size, numBanks);
198             break;
199         case DataBuffer.TYPE_INT:
200             dataBuffer = new DataBufferInt(size, numBanks);
201             break;
202         case DataBuffer.TYPE_FLOAT:
203             dataBuffer = new DataBufferFloat(size, numBanks);
204             break;
205         case DataBuffer.TYPE_DOUBLE:
206             dataBuffer = new DataBufferDouble(size, numBanks);
207             break;
208         default:
209             throw new IllegalArgumentException("dataType is not one " +
210                 "of the supported types.");
211         }
212 
213         return dataBuffer;
214     }
215 
216 
217     /**
218      * Returns data for a single pixel in a primitive array of type
219      * TransferType.  For a BandedSampleModel, this will be the same
220      * as the data type, and samples will be returned one per array
221      * element.  Generally, obj
222      * should be passed in as null, so that the Object will be created
223      * automatically and will be of the right primitive data type.
224      * <p>
225      * The following code illustrates transferring data for one pixel from
226      * DataBuffer <code>db1</code>, whose storage layout is described by
227      * BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
228      * whose storage layout is described by
229      * BandedSampleModel <code>bsm2</code>.
230      * The transfer will generally be more efficient than using
231      * getPixel/setPixel.
232      * <pre>
233      *       BandedSampleModel bsm1, bsm2;
234      *       DataBufferInt db1, db2;
235      *       bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
236      *                            db2);
237      * </pre>
238      * Using getDataElements/setDataElements to transfer between two
239      * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
240      * the same number of bands, corresponding bands have the same number of
241      * bits per sample, and the TransferTypes are the same.
242      * <p>
243      * If obj is non-null, it should be a primitive array of type TransferType.
244      * Otherwise, a ClassCastException is thrown.  An
245      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
246      * not in bounds, or if obj is non-null and is not large enough to hold
247      * the pixel data.
248      * @param x         The X coordinate of the pixel location
249      * @param y         The Y coordinate of the pixel location
250      * @param obj       If non-null, a primitive array in which to return
251      *                  the pixel data.
252      * @param data      The DataBuffer containing the image data.
253      * @return the data for the specified pixel.
254      * @see #setDataElements(int, int, Object, DataBuffer)
255      */
256     public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
257         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
258             throw new ArrayIndexOutOfBoundsException
259                 ("Coordinate out of bounds!");
260         }
261         int type = getTransferType();
262         int numDataElems = getNumDataElements();
263         int pixelOffset = y*scanlineStride + x;
264 
265         switch(type) {
266 
267         case DataBuffer.TYPE_BYTE:
268 
269             byte[] bdata;
270 
271             if (obj == null) {
272                 bdata = new byte[numDataElems];
273             } else {
274                 bdata = (byte[])obj;
275             }
276 
277             for (int i=0; i<numDataElems; i++) {
278                 bdata[i] = (byte)data.getElem(bankIndices[i],
279                                               pixelOffset + bandOffsets[i]);
280             }
281 
282             obj = (Object)bdata;
283             break;
284 
285         case DataBuffer.TYPE_USHORT:
286         case DataBuffer.TYPE_SHORT:
287 
288             short[] sdata;
289 
290             if (obj == null) {
291                 sdata = new short[numDataElems];
292             } else {
293                 sdata = (short[])obj;
294             }
295 
296             for (int i=0; i<numDataElems; i++) {
297                 sdata[i] = (short)data.getElem(bankIndices[i],
298                                                pixelOffset + bandOffsets[i]);
299             }
300 
301             obj = (Object)sdata;
302             break;
303 
304         case DataBuffer.TYPE_INT:
305 
306             int[] idata;
307 
308             if (obj == null) {
309                 idata = new int[numDataElems];
310             } else {
311                 idata = (int[])obj;
312             }
313 
314             for (int i=0; i<numDataElems; i++) {
315                 idata[i] = data.getElem(bankIndices[i],
316                                         pixelOffset + bandOffsets[i]);
317             }
318 
319             obj = (Object)idata;
320             break;
321 
322         case DataBuffer.TYPE_FLOAT:
323 
324             float[] fdata;
325 
326             if (obj == null) {
327                 fdata = new float[numDataElems];
328             } else {
329                 fdata = (float[])obj;
330             }
331 
332             for (int i=0; i<numDataElems; i++) {
333                 fdata[i] = data.getElemFloat(bankIndices[i],
334                                              pixelOffset + bandOffsets[i]);
335             }
336 
337             obj = (Object)fdata;
338             break;
339 
340         case DataBuffer.TYPE_DOUBLE:
341 
342             double[] ddata;
343 
344             if (obj == null) {
345                 ddata = new double[numDataElems];
346             } else {
347                 ddata = (double[])obj;
348             }
349 
350             for (int i=0; i<numDataElems; i++) {
351                 ddata[i] = data.getElemDouble(bankIndices[i],
352                                               pixelOffset + bandOffsets[i]);
353             }
354 
355             obj = (Object)ddata;
356             break;
357         }
358 
359         return obj;
360     }
361 
362     /**
363      * Returns all samples for the specified pixel in an int array.
364      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
365      * not in bounds.
366      * @param x         The X coordinate of the pixel location
367      * @param y         The Y coordinate of the pixel location
368      * @param iArray    If non-null, returns the samples in this array
369      * @param data      The DataBuffer containing the image data
370      * @return the samples for the specified pixel.
371      * @see #setPixel(int, int, int[], DataBuffer)
372      */
373     public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
374         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
375             throw new ArrayIndexOutOfBoundsException
376                 ("Coordinate out of bounds!");
377         }
378 
379         int[] pixels;
380 
381         if (iArray != null) {
382            pixels = iArray;
383         } else {
384            pixels = new int [numBands];
385         }
386 
387         int pixelOffset = y*scanlineStride + x;
388         for (int i=0; i<numBands; i++) {
389             pixels[i] = data.getElem(bankIndices[i],
390                                      pixelOffset + bandOffsets[i]);
391         }
392         return pixels;
393     }
394 
395     /**
396      * Returns all samples for the specified rectangle of pixels in
397      * an int array, one sample per data array element.
398      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
399      * not in bounds.
400      * @param x         The X coordinate of the upper left pixel location
401      * @param y         The Y coordinate of the upper left pixel location
402      * @param w         The width of the pixel rectangle
403      * @param h         The height of the pixel rectangle
404      * @param iArray    If non-null, returns the samples in this array
405      * @param data      The DataBuffer containing the image data
406      * @return the samples for the pixels within the specified region.
407      * @see #setPixels(int, int, int, int, int[], DataBuffer)
408      */
409     public int[] getPixels(int x, int y, int w, int h,
410                            int iArray[], DataBuffer data) {
411         int x1 = x + w;
412         int y1 = y + h;
413 
414         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
415             y < 0 || y >= height || h > height || y1 < 0 || y1 >  height)
416         {
417             throw new ArrayIndexOutOfBoundsException
418                 ("Coordinate out of bounds!");
419         }
420         int[] pixels;
421 
422         if (iArray != null) {
423            pixels = iArray;
424         } else {
425            pixels = new int[w*h*numBands];
426         }
427 
428         for (int k = 0; k < numBands; k++) {
429             int lineOffset = y*scanlineStride + x + bandOffsets[k];
430             int srcOffset = k;
431             int bank = bankIndices[k];
432 
433             for (int i = 0; i < h; i++) {
434                 int pixelOffset = lineOffset;
435                 for (int j = 0; j < w; j++) {
436                     pixels[srcOffset] = data.getElem(bank, pixelOffset++);
437                     srcOffset += numBands;
438                 }
439                 lineOffset += scanlineStride;
440             }
441         }
442         return pixels;
443     }
444 
445     /**
446      * Returns as int the sample in a specified band for the pixel
447      * located at (x,y).
448      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
449      * not in bounds.
450      * @param x         The X coordinate of the pixel location
451      * @param y         The Y coordinate of the pixel location
452      * @param b         The band to return
453      * @param data      The DataBuffer containing the image data
454      * @return the sample in the specified band for the specified pixel.
455      * @see #setSample(int, int, int, int, DataBuffer)
456      */
457     public int getSample(int x, int y, int b, DataBuffer data) {
458         // Bounds check for 'b' will be performed automatically
459         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
460             throw new ArrayIndexOutOfBoundsException
461                 ("Coordinate out of bounds!");
462         }
463         int sample =
464             data.getElem(bankIndices[b],
465                          y*scanlineStride + x + bandOffsets[b]);
466         return sample;
467     }
468 
469     /**
470      * Returns the sample in a specified band
471      * for the pixel located at (x,y) as a float.
472      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
473      * not in bounds.
474      * @param x         The X coordinate of the pixel location
475      * @param y         The Y coordinate of the pixel location
476      * @param b         The band to return
477      * @param data      The DataBuffer containing the image data
478      * @return a float value that represents the sample in the specified
479      * band for the specified pixel.
480      */
481     public float getSampleFloat(int x, int y, int b, DataBuffer data) {
482         // Bounds check for 'b' will be performed automatically
483         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
484             throw new ArrayIndexOutOfBoundsException
485                 ("Coordinate out of bounds!");
486         }
487 
488         float sample = data.getElemFloat(bankIndices[b],
489                                     y*scanlineStride + x + bandOffsets[b]);
490         return sample;
491     }
492 
493     /**
494      * Returns the sample in a specified band
495      * for a pixel located at (x,y) as a double.
496      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
497      * not in bounds.
498      * @param x         The X coordinate of the pixel location
499      * @param y         The Y coordinate of the pixel location
500      * @param b         The band to return
501      * @param data      The DataBuffer containing the image data
502      * @return a double value that represents the sample in the specified
503      * band for the specified pixel.
504      */
505     public double getSampleDouble(int x, int y, int b, DataBuffer data) {
506         // Bounds check for 'b' will be performed automatically
507         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
508             throw new ArrayIndexOutOfBoundsException
509                 ("Coordinate out of bounds!");
510         }
511 
512         double sample = data.getElemDouble(bankIndices[b],
513                                        y*scanlineStride + x + bandOffsets[b]);
514         return sample;
515     }
516 
517     /**
518      * Returns the samples in a specified band for the specified rectangle
519      * of pixels in an int array, one sample per data array element.
520      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
521      * not in bounds.
522      * @param x         The X coordinate of the upper left pixel location
523      * @param y         The Y coordinate of the upper left pixel location
524      * @param w         The width of the pixel rectangle
525      * @param h         The height of the pixel rectangle
526      * @param b         The band to return
527      * @param iArray    If non-null, returns the samples in this array
528      * @param data      The DataBuffer containing the image data
529      * @return the samples in the specified band for the pixels within
530      * the specified region.
531      * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
532      */
533     public int[] getSamples(int x, int y, int w, int h, int b,
534                             int iArray[], DataBuffer data) {
535         // Bounds check for 'b' will be performed automatically
536         if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
537             throw new ArrayIndexOutOfBoundsException
538                 ("Coordinate out of bounds!");
539         }
540         int samples[];
541         if (iArray != null) {
542            samples = iArray;
543         } else {
544            samples = new int [w*h];
545         }
546 
547         int lineOffset = y*scanlineStride + x + bandOffsets[b];
548         int srcOffset = 0;
549         int bank = bankIndices[b];
550 
551         for (int i = 0; i < h; i++) {
552            int sampleOffset = lineOffset;
553            for (int j = 0; j < w; j++) {
554                samples[srcOffset++] = data.getElem(bank, sampleOffset++);
555            }
556            lineOffset += scanlineStride;
557         }
558         return samples;
559     }
560 
561     /**
562      * Sets the data for a single pixel in the specified DataBuffer from a
563      * primitive array of type TransferType.  For a BandedSampleModel,
564      * this will be the same as the data type, and samples are transferred
565      * one per array element.
566      * <p>
567      * The following code illustrates transferring data for one pixel from
568      * DataBuffer <code>db1</code>, whose storage layout is described by
569      * BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
570      * whose storage layout is described by
571      * BandedSampleModel <code>bsm2</code>.
572      * The transfer will generally be more efficient than using
573      * getPixel/setPixel.
574      * <pre>
575      *       BandedSampleModel bsm1, bsm2;
576      *       DataBufferInt db1, db2;
577      *       bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
578      *                            db2);
579      * </pre>
580      * Using getDataElements/setDataElements to transfer between two
581      * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
582      * the same number of bands, corresponding bands have the same number of
583      * bits per sample, and the TransferTypes are the same.
584      * <p>
585      * obj must be a primitive array of type TransferType.  Otherwise,
586      * a ClassCastException is thrown.  An
587      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
588      * not in bounds, or if obj is not large enough to hold the pixel data.
589      * @param x         The X coordinate of the pixel location
590      * @param y         The Y coordinate of the pixel location
591      * @param obj       If non-null, returns the primitive array in this
592      *                  object
593      * @param data      The DataBuffer containing the image data
594      * @see #getDataElements(int, int, Object, DataBuffer)
595      */
596     public void setDataElements(int x, int y, Object obj, DataBuffer data) {
597         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
598             throw new ArrayIndexOutOfBoundsException
599                 ("Coordinate out of bounds!");
600         }
601         int type = getTransferType();
602         int numDataElems = getNumDataElements();
603         int pixelOffset = y*scanlineStride + x;
604 
605         switch(type) {
606 
607         case DataBuffer.TYPE_BYTE:
608 
609             byte[] barray = (byte[])obj;
610 
611             for (int i=0; i<numDataElems; i++) {
612                 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
613                              barray[i] & 0xff);
614             }
615             break;
616 
617         case DataBuffer.TYPE_USHORT:
618         case DataBuffer.TYPE_SHORT:
619 
620             short[] sarray = (short[])obj;
621 
622             for (int i=0; i<numDataElems; i++) {
623                 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
624                              sarray[i] & 0xffff);
625             }
626             break;
627 
628         case DataBuffer.TYPE_INT:
629 
630             int[] iarray = (int[])obj;
631 
632             for (int i=0; i<numDataElems; i++) {
633                 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
634                              iarray[i]);
635             }
636             break;
637 
638         case DataBuffer.TYPE_FLOAT:
639 
640             float[] farray = (float[])obj;
641 
642             for (int i=0; i<numDataElems; i++) {
643                 data.setElemFloat(bankIndices[i], pixelOffset + bandOffsets[i],
644                                   farray[i]);
645             }
646             break;
647 
648         case DataBuffer.TYPE_DOUBLE:
649 
650             double[] darray = (double[])obj;
651 
652             for (int i=0; i<numDataElems; i++) {
653                 data.setElemDouble(bankIndices[i], pixelOffset + bandOffsets[i],
654                                    darray[i]);
655             }
656             break;
657 
658         }
659     }
660 
661     /**
662      * Sets a pixel in the DataBuffer using an int array of samples for input.
663      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
664      * not in bounds.
665      * @param x         The X coordinate of the pixel location
666      * @param y         The Y coordinate of the pixel location
667      * @param iArray    The input samples in an int array
668      * @param data      The DataBuffer containing the image data
669      * @see #getPixel(int, int, int[], DataBuffer)
670      */
671     public void setPixel(int x, int y, int iArray[], DataBuffer data) {
672         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
673             throw new ArrayIndexOutOfBoundsException
674                 ("Coordinate out of bounds!");
675         }
676        int pixelOffset = y*scanlineStride + x;
677        for (int i=0; i<numBands; i++) {
678            data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
679                         iArray[i]);
680        }
681     }
682 
683     /**
684      * Sets all samples for a rectangle of pixels from an int array containing
685      * one sample per array element.
686      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
687      * not in bounds.
688      * @param x         The X coordinate of the upper left pixel location
689      * @param y         The Y coordinate of the upper left pixel location
690      * @param w         The width of the pixel rectangle
691      * @param h         The height of the pixel rectangle
692      * @param iArray    The input samples in an int array
693      * @param data      The DataBuffer containing the image data
694      * @see #getPixels(int, int, int, int, int[], DataBuffer)
695      */
696     public void setPixels(int x, int y, int w, int h,
697                           int iArray[], DataBuffer data) {
698         int x1 = x + w;
699         int y1 = y + h;
700 
701         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
702             y < 0 || y >= height || h > height || y1 < 0 || y1 >  height)
703         {
704             throw new ArrayIndexOutOfBoundsException
705                 ("Coordinate out of bounds!");
706         }
707 
708         for (int k = 0; k < numBands; k++) {
709             int lineOffset = y*scanlineStride + x + bandOffsets[k];
710             int srcOffset = k;
711             int bank = bankIndices[k];
712 
713             for (int i = 0; i < h; i++) {
714                 int pixelOffset = lineOffset;
715                 for (int j = 0; j < w; j++) {
716                     data.setElem(bank, pixelOffset++, iArray[srcOffset]);
717                     srcOffset += numBands;
718                 }
719                 lineOffset += scanlineStride;
720            }
721         }
722     }
723 
724     /**
725      * Sets a sample in the specified band for the pixel located at (x,y)
726      * in the DataBuffer using an int for input.
727      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
728      * not in bounds.
729      * @param x         The X coordinate of the pixel location
730      * @param y         The Y coordinate of the pixel location
731      * @param b         The band to set
732      * @param s         The input sample as an int
733      * @param data      The DataBuffer containing the image data
734      * @see #getSample(int, int, int, DataBuffer)
735      */
736     public void setSample(int x, int y, int b, int s,
737                           DataBuffer data) {
738         // Bounds check for 'b' will be performed automatically
739         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
740             throw new ArrayIndexOutOfBoundsException
741                 ("Coordinate out of bounds!");
742         }
743         data.setElem(bankIndices[b],
744                      y*scanlineStride + x + bandOffsets[b], s);
745     }
746 
747     /**
748      * Sets a sample in the specified band for the pixel located at (x,y)
749      * in the DataBuffer using a float for input.
750      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
751      * not in bounds.
752      * @param x         The X coordinate of the pixel location
753      * @param y         The Y coordinate of the pixel location
754      * @param b         The band to set
755      * @param s         The input sample as a float
756      * @param data      The DataBuffer containing the image data
757      * @see #getSample(int, int, int, DataBuffer)
758      */
759     public void setSample(int x, int y, int b,
760                           float s ,
761                           DataBuffer data) {
762         // Bounds check for 'b' will be performed automatically
763         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
764             throw new ArrayIndexOutOfBoundsException
765                 ("Coordinate out of bounds!");
766         }
767         data.setElemFloat(bankIndices[b],
768                           y*scanlineStride + x + bandOffsets[b], s);
769     }
770 
771     /**
772      * Sets a sample in the specified band for the pixel located at (x,y)
773      * in the DataBuffer using a double for input.
774      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
775      * not in bounds.
776      * @param x         The X coordinate of the pixel location
777      * @param y         The Y coordinate of the pixel location
778      * @param b         The band to set
779      * @param s         The input sample as a double
780      * @param data      The DataBuffer containing the image data
781      * @see #getSample(int, int, int, DataBuffer)
782      */
783     public void setSample(int x, int y, int b,
784                           double s,
785                           DataBuffer data) {
786         // Bounds check for 'b' will be performed automatically
787         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
788             throw new ArrayIndexOutOfBoundsException
789                 ("Coordinate out of bounds!");
790         }
791         data.setElemDouble(bankIndices[b],
792                           y*scanlineStride + x + bandOffsets[b], s);
793     }
794 
795     /**
796      * Sets the samples in the specified band for the specified rectangle
797      * of pixels from an int array containing one sample per data array element.
798      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
799      * not in bounds.
800      * @param x         The X coordinate of the upper left pixel location
801      * @param y         The Y coordinate of the upper left pixel location
802      * @param w         The width of the pixel rectangle
803      * @param h         The height of the pixel rectangle
804      * @param b         The band to set
805      * @param iArray    The input sample array
806      * @param data      The DataBuffer containing the image data
807      * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
808      */
809     public void setSamples(int x, int y, int w, int h, int b,
810                            int iArray[], DataBuffer data) {
811         // Bounds check for 'b' will be performed automatically
812         if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
813             throw new ArrayIndexOutOfBoundsException
814                 ("Coordinate out of bounds!");
815         }
816         int lineOffset = y*scanlineStride + x + bandOffsets[b];
817         int srcOffset = 0;
818         int bank = bankIndices[b];
819 
820         for (int i = 0; i < h; i++) {
821            int sampleOffset = lineOffset;
822            for (int j = 0; j < w; j++) {
823               data.setElem(bank, sampleOffset++, iArray[srcOffset++]);
824            }
825            lineOffset += scanlineStride;
826         }
827     }
828 
829     private static int[] createOffsetArray(int numBands) {
830         int[] bandOffsets = new int[numBands];
831         for (int i=0; i < numBands; i++) {
832             bandOffsets[i] = 0;
833         }
834         return bandOffsets;
835     }
836 
837     private static int[] createIndicesArray(int numBands) {
838         int[] bankIndices = new int[numBands];
839         for (int i=0; i < numBands; i++) {
840             bankIndices[i] = i;
841         }
842         return bankIndices;
843     }
844 
845     // Differentiate hash code from other ComponentSampleModel subclasses
846     public int hashCode() {
847         return super.hashCode() ^ 0x2;
848     }
849 }