001    /* Copyright (C) 2004, 2005, 2006, Free Software Foundation
002    
003    This file is part of GNU Classpath.
004    
005    GNU Classpath is free software; you can redistribute it and/or modify
006    it under the terms of the GNU General Public License as published by
007    the Free Software Foundation; either version 2, or (at your option)
008    any later version.
009    
010    GNU Classpath is distributed in the hope that it will be useful, but
011    WITHOUT ANY WARRANTY; without even the implied warranty of
012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013    General Public License for more details.
014    
015    You should have received a copy of the GNU General Public License
016    along with GNU Classpath; see the file COPYING.  If not, write to the
017    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
018    02110-1301 USA.
019    
020    Linking this library statically or dynamically with other modules is
021    making a combined work based on this library.  Thus, the terms and
022    conditions of the GNU General Public License cover the whole
023    combination.
024    
025    As a special exception, the copyright holders of this library give you
026    permission to link this library with independent modules to produce an
027    executable, regardless of the license terms of these independent
028    modules, and to copy and distribute the resulting executable under
029    terms of your choice, provided that you also meet, for each linked
030    independent module, the terms and conditions of the license of that
031    module.  An independent module is a module which is not derived from
032    or based on this library.  If you modify this library, you may extend
033    this exception to your version of the library, but you are not
034    obligated to do so.  If you do not wish to do so, delete this
035    exception statement from your version. */
036    
037    package java.awt.image;
038    
039    import gnu.java.awt.Buffers;
040    
041    /**
042     * A sample model that reads each sample value from a separate band in the
043     * {@link DataBuffer}.
044     *
045     * @author Jerry Quinn (jlquinn@optonline.net)
046     */
047    public final class BandedSampleModel extends ComponentSampleModel
048    {
049      private int[] bitMasks;
050      private int[] bitOffsets;
051      private int[] sampleSize;
052      private int dataBitOffset;
053      private int elemBits;
054      private int numberOfBits;
055      private int numElems;
056    
057      private static int[] createBankArray(int size) 
058      {
059        int[] result = new int[size];
060        for (int i = 0; i < size; i++)
061          result[i] = i;
062        return result;
063      }
064    
065      /**
066       * Creates a new <code>BandedSampleModel</code>.
067       * 
068       * @param dataType  the data buffer type.
069       * @param w  the width (in pixels).
070       * @param h  the height (in pixels).
071       * @param numBands  the number of bands.
072       */
073      public BandedSampleModel(int dataType, int w, int h, int numBands)
074      {
075        this(dataType, w, h, w, createBankArray(numBands), new int[numBands]);
076      }
077    
078      /**
079       * Creates a new <code>BandedSampleModel</code>.
080       * 
081       * @param dataType  the data buffer type.
082       * @param w  the width (in pixels).
083       * @param h  the height (in pixels).
084       * @param scanlineStride  the number of data elements from a pixel in one 
085       *     row to the corresponding pixel in the next row.
086       * @param bankIndices  the bank indices.
087       * @param bandOffsets  the band offsets.
088       */
089      public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
090                               int[] bankIndices, int[] bandOffsets)
091      {
092        super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
093      }
094      
095      /**
096       * Creates a new data buffer that is compatible with this sample model.
097       * 
098       * @return The new data buffer.
099       */
100      public DataBuffer createDataBuffer()
101      {
102        int size = scanlineStride * height;
103        return Buffers.createBuffer(getDataType(), size, numBanks);
104      }
105    
106      /**
107       * Creates a new <code>SampleModel</code> that is compatible with this
108       * model and has the specified width and height.
109       * 
110       * @param w  the width (in pixels, must be greater than zero).
111       * @param h  the height (in pixels, must be greater than zero).
112       * 
113       * @return The new sample model.
114       * 
115       * @throws IllegalArgumentException if <code>w</code> or <code>h</code> is
116       *     not greater than zero.
117       * @throws IllegalArgumentException if <code>w * h</code> exceeds 
118       *     <code>Integer.MAX_VALUE</code>.
119       */
120      public SampleModel createCompatibleSampleModel(int w, int h)
121      {
122        // NOTE: blackdown 1.4.1 sets all offsets to 0.  Sun's 1.4.2 docs
123        // disagree.
124    
125        // Compress offsets so minimum is 0, others w*scanlineStride
126        int[] newoffsets = new int[bandOffsets.length];
127        int[] order = new int[bandOffsets.length];
128        for (int i = 0; i < bandOffsets.length; i++)
129          order[i] = i;
130        // FIXME: This is N^2, but not a big issue, unless there's a lot of
131        // bands...
132        for (int i = 0; i < bandOffsets.length; i++)
133          for (int j = i + 1; j < bandOffsets.length; j++)
134            if (bankIndices[order[i]] > bankIndices[order[j]]
135                || (bankIndices[order[i]] == bankIndices[order[j]]
136                && bandOffsets[order[i]] > bandOffsets[order[j]]))
137              {
138                int t = order[i]; order[i] = order[j]; order[j] = t;
139              }
140        int bank = 0;
141        int offset = 0;
142        for (int i = 0; i < bandOffsets.length; i++)
143          {
144            if (bankIndices[order[i]] != bank)
145              {
146                bank = bankIndices[order[i]];
147                offset = 0;
148              }
149            newoffsets[order[i]] = offset;
150            offset += w * scanlineStride;
151          }
152        
153        return new BandedSampleModel(dataType, w, h, w, bankIndices, newoffsets);
154      }
155    
156    
157      public SampleModel createSubsetSampleModel(int[] bands)
158      {
159        if (bands.length > bankIndices.length)
160          throw new
161            RasterFormatException("BandedSampleModel createSubsetSampleModel too"
162                                  +" many bands");
163        int[] newoff = new int[bands.length];
164        int[] newbanks = new int[bands.length];
165        for (int i = 0; i < bands.length; i++)
166          {
167            int b = bands[i];
168            newoff[i] = bandOffsets[b];
169            newbanks[i] = bankIndices[b];
170          }
171    
172        return new BandedSampleModel(dataType, width, height, scanlineStride,
173                                     newbanks, newoff);
174      }
175    
176      /**
177       * Extract all samples of one pixel and return in an array of transfer type.
178       *
179       * Extracts the pixel at x, y from data and stores samples into the array
180       * obj.  If obj is null, a new array of getTransferType() is created.
181       *
182       * @param x The x-coordinate of the pixel rectangle to store in 
183       *     <code>obj</code>.
184       * @param y The y-coordinate of the pixel rectangle to store in 
185       *     <code>obj</code>.
186       * @param obj The primitive array to store the pixels into or null to force 
187       *     creation.
188       * @param data The DataBuffer that is the source of the pixel data.
189       * @return The primitive array containing the pixel data.
190       * @see java.awt.image.SampleModel#getDataElements(int, int, 
191       *     java.lang.Object, java.awt.image.DataBuffer)
192       */
193      public Object getDataElements(int x, int y, Object obj, DataBuffer data)
194      {
195        if (x < 0 || y < 0)
196          throw new ArrayIndexOutOfBoundsException(
197              "x and y must not be less than 0.");
198        int pixel = getSample(x, y, 0, data);
199        switch (getTransferType())
200        {
201        case DataBuffer.TYPE_BYTE:
202          {
203            byte[] b = (byte[]) obj;
204            if (b == null) b = new byte[numBands];
205            for (int i = 0; i < numBands; i++)
206              b[i] = (byte)getSample(x, y, i, data);
207            return b;
208          }
209        case DataBuffer.TYPE_SHORT:
210        case DataBuffer.TYPE_USHORT:
211          {
212            short[] b = (short[]) obj;
213            if (b == null) b = new short[numBands];
214            for (int i = 0; i < numBands; i++)
215              b[i] = (short)getSample(x, y, i, data);
216            return b;
217          }
218        case DataBuffer.TYPE_INT:
219          {
220            int[] b = (int[]) obj;
221            if (b == null) b = new int[numBands];
222            for (int i = 0; i < numBands; i++)
223              b[i] = getSample(x, y, i, data);
224            return b;
225          }
226        case DataBuffer.TYPE_FLOAT:
227          {
228            float[] b = (float[]) obj;
229            if (b == null) b = new float[numBands];
230            for (int i = 0; i < numBands; i++)
231              b[i] = getSampleFloat(x, y, i, data);
232            return b;
233          }
234        case DataBuffer.TYPE_DOUBLE:
235          {
236            double[] b = (double[]) obj;
237            if (b == null) 
238              b = new double[numBands];
239            for (int i = 0; i < numBands; i++)
240              b[i] = getSample(x, y, i, data);
241            return b;
242          }
243    
244        default:
245          // Seems like the only sensible thing to do.
246          throw new ClassCastException();
247        }
248      }
249    
250      /**
251       * Returns all the samples for the pixel at location <code>(x, y)</code>
252       * stored in the specified data buffer.
253       * 
254       * @param x  the x-coordinate.
255       * @param y  the y-coordinate.
256       * @param iArray  an array that will be populated with the sample values and
257       *   returned as the result.  The size of this array should be equal to the 
258       *   number of bands in the model.  If the array is <code>null</code>, a new
259       *   array is created.
260       * @param data  the data buffer (<code>null</code> not permitted).
261       * 
262       * @return The samples for the specified pixel.
263       * 
264       * @see #setPixel(int, int, int[], DataBuffer)
265       */
266      public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
267      {
268        if (iArray == null) 
269          iArray = new int[numBands];
270        for (int i = 0; i < numBands; i++)
271          iArray[i] = getSample(x, y, i, data);
272            
273        return iArray;
274      }
275    
276      /**
277       * Copy pixels from a region into an array.
278       *
279       * Copies the samples of the pixels in the rectangle starting at x, y that
280       * is w pixels wide and h scanlines high.  When there is more than one band,
281       * the samples stored in order before the next pixel.  This ordering isn't
282       * well specified in Sun's docs as of 1.4.2.
283       *
284       * If iArray is null, a new array is allocated, filled, and returned.
285       *
286       * @param x The x-coordinate of the pixel rectangle to store in
287       * <code>iArray</code>.
288       * @param y The y-coordinate of the pixel rectangle to store in
289       * <code>iArray</code>.
290       * @param w The width in pixels of the rectangle.
291       * @param h The height in pixels of the rectangle.
292       * @param iArray The int array to store the pixels into or null to force
293       * creation.
294       * @param data The DataBuffer that is the source of the pixel data.
295       * @return The primitive array containing the pixel data.
296       */
297      public int[] getPixels(int x, int y, int w, int h, int[] iArray,
298                             DataBuffer data)
299      {
300        if (x < 0 || y < 0)
301          throw new ArrayIndexOutOfBoundsException(
302              "x and y must not be less than 0.");
303        if (iArray == null) 
304          iArray = new int[w * h * numBands];
305        int outOffset = 0;
306        int maxX = x + w;
307        int maxY = y + h;
308        for (int yy = x; yy < maxY; yy++)
309          {
310            for (int xx = x; xx < maxX; xx++)
311              {
312                for (int b = 0; b < numBands; b++)
313                  {
314                    int offset = bandOffsets[b] + yy * scanlineStride + xx;
315                    iArray[outOffset++] =
316                      data.getElem(bankIndices[b], offset);
317                  }
318              }
319          }
320        return iArray;      
321      }
322    
323      /**
324       * Returns a sample value for the pixel at (x, y) in the specified data 
325       * buffer.
326       * 
327       * @param x  the x-coordinate of the pixel.
328       * @param y  the y-coordinate of the pixel.
329       * @param b  the band (in the range <code>0</code> to 
330       *     <code>getNumBands() - 1</code>).
331       * @param data  the data buffer (<code>null</code> not permitted).
332       * 
333       * @return The sample value.
334       * 
335       * @throws NullPointerException if <code>data</code> is <code>null</code>.
336       */
337      public int getSample(int x, int y, int b, DataBuffer data)
338      {
339        int offset = bandOffsets[b] + y * scanlineStride + x;
340        return data.getElem(bankIndices[b], offset);
341      }
342      
343      /**
344       * Returns a sample value for the pixel at (x, y) in the specified data 
345       * buffer.
346       * 
347       * @param x  the x-coordinate of the pixel.
348       * @param y  the y-coordinate of the pixel.
349       * @param b  the band (in the range <code>0</code> to 
350       *     <code>getNumBands() - 1</code>).
351       * @param data  the data buffer (<code>null</code> not permitted).
352       * 
353       * @return The sample value.
354       * 
355       * @throws NullPointerException if <code>data</code> is <code>null</code>.
356       * 
357       * @see #getSample(int, int, int, DataBuffer)
358       */
359      public float getSampleFloat(int x, int y, int b, DataBuffer data)
360      {
361        int offset = bandOffsets[b] + y * scanlineStride + x;
362        return data.getElemFloat(bankIndices[b], offset);
363      }
364      
365      /**
366       * Returns the sample value for the pixel at (x, y) in the specified data 
367       * buffer.
368       * 
369       * @param x  the x-coordinate of the pixel.
370       * @param y  the y-coordinate of the pixel.
371       * @param b  the band (in the range <code>0</code> to 
372       *     <code>getNumBands() - 1</code>).
373       * @param data  the data buffer (<code>null</code> not permitted).
374       * 
375       * @return The sample value.
376       * 
377       * @throws NullPointerException if <code>data</code> is <code>null</code>.
378       * 
379       * @see #getSample(int, int, int, DataBuffer)
380       */
381      public double getSampleDouble(int x, int y, int b, DataBuffer data)
382      {
383        int offset = bandOffsets[b] + y * scanlineStride + x;
384        return data.getElemDouble(bankIndices[b], offset);
385      }
386      
387      /**
388       * Copy one band's samples from a region into an array.
389       *
390       * Copies from one band the samples of the pixels in the rectangle starting
391       * at x, y that is w pixels wide and h scanlines high.
392       *
393       * If iArray is null, a new array is allocated, filled, and returned.
394       *
395       * @param x The x-coordinate of the pixel rectangle to store in
396       * <code>iArray</code>.
397       * @param y The y-coordinate of the pixel rectangle to store in
398       * <code>iArray</code>.
399       * @param w The width in pixels of the rectangle.
400       * @param h The height in pixels of the rectangle.
401       * @param b The band to retrieve.
402       * @param iArray The int array to store the pixels into or null to force
403       * creation.
404       * @param data The DataBuffer that is the source of the pixel data.
405       * @return The primitive array containing the pixel data.
406       */
407      public int[] getSamples(int x, int y, int w, int h, int b, int[] iArray,
408                              DataBuffer data)
409      {
410        if (x < 0 || y < 0)
411          throw new ArrayIndexOutOfBoundsException(
412              "x and y must not be less than 0.");
413        if (iArray == null) 
414          iArray = new int[w * h];
415        int outOffset = 0;
416        int maxX = x + w;
417        int maxY = y + h;
418        for (int yy = y; yy < maxY; yy++)
419          {
420            for (int xx = x; xx < maxX; xx++)
421              {
422                int offset = bandOffsets[b] + yy * scanlineStride + xx;
423                iArray[outOffset++] =
424                  data.getElem(bankIndices[b], offset);
425              }
426          }
427        return iArray;      
428      }
429    
430      /**
431       * Set the pixel at x, y to the value in the first element of the primitive
432       * array obj.
433       *
434       * @param x The x-coordinate of the data elements in <code>obj</code>.
435       * @param y The y-coordinate of the data elements in <code>obj</code>.
436       * @param obj The primitive array containing the data elements to set.
437       * @param data The DataBuffer to store the data elements into.
438       * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
439       */
440      public void setDataElements(int x, int y, Object obj, DataBuffer data)
441      {
442        int transferType = getTransferType();
443        if (getTransferType() != data.getDataType())
444          {
445            throw new IllegalArgumentException("transfer type ("+
446                                               getTransferType()+"), "+
447                                               "does not match data "+
448                                               "buffer type (" +
449                                               data.getDataType() +
450                                               ").");
451          }
452    
453        int offset = y * scanlineStride + x;
454        
455        try
456          {
457            switch (transferType)
458              {
459              case DataBuffer.TYPE_BYTE:
460                {
461                  DataBufferByte out = (DataBufferByte) data;
462                  byte[] in = (byte[]) obj;
463                  for (int i = 0; i < numBands; i++)
464                    out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
465                  return;
466                }
467              case DataBuffer.TYPE_SHORT:
468                {
469                  DataBufferShort out = (DataBufferShort) data;
470                  short[] in = (short[]) obj;
471                  for (int i = 0; i < numBands; i++)
472                    out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
473                  return;
474                }
475              case DataBuffer.TYPE_USHORT:
476                {
477                  DataBufferUShort out = (DataBufferUShort) data;
478                  short[] in = (short[]) obj;
479                  for (int i = 0; i < numBands; i++)
480                    out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
481                  return;
482                }
483              case DataBuffer.TYPE_INT:
484                {
485                  DataBufferInt out = (DataBufferInt) data;
486                  int[] in = (int[]) obj;
487                  for (int i = 0; i < numBands; i++)
488                    out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
489                  return;
490                }
491              case DataBuffer.TYPE_FLOAT:
492                {
493                  DataBufferFloat out = (DataBufferFloat) data;
494                  float[] in = (float[]) obj;
495                  for (int i = 0; i < numBands; i++)
496                    out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
497                  return;
498                }
499              case DataBuffer.TYPE_DOUBLE:
500                {
501                  DataBufferDouble out = (DataBufferDouble) data;
502                  double[] in = (double[]) obj;
503                  for (int i = 0; i < numBands; i++)
504                    out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
505                  return;
506                }
507              default:
508                throw new ClassCastException("Unsupported data type");
509              }
510          }
511        catch (ArrayIndexOutOfBoundsException aioobe)
512          {
513            String msg = "While writing data elements" 
514          + ", x=" + x + ", y=" + y 
515          + ", width=" + width + ", height=" + height 
516          + ", scanlineStride=" + scanlineStride 
517          + ", offset=" + offset 
518          + ", data.getSize()=" + data.getSize() 
519          + ", data.getOffset()=" + data.getOffset() 
520          + ": " + aioobe;
521            throw new ArrayIndexOutOfBoundsException(msg);
522          }
523        }
524    
525      /**
526       * Sets the samples for the pixel at (x, y) in the specified data buffer to
527       * the specified values. 
528       * 
529       * @param x  the x-coordinate of the pixel.
530       * @param y  the y-coordinate of the pixel.
531       * @param iArray  the sample values (<code>null</code> not permitted).
532       * @param data  the data buffer (<code>null</code> not permitted).
533       * 
534       * @throws NullPointerException if either <code>iArray</code> or 
535       *     <code>data</code> is <code>null</code>.
536       */
537      public void setPixel(int x, int y, int[] iArray, DataBuffer data)
538      {
539        for (int b = 0; b < numBands; b++)
540          data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
541                       iArray[b]);
542      }
543    
544      /**
545       * Sets the sample values for the pixels in the region specified by 
546       * (x, y, w, h) in the specified data buffer.  The array is
547       * ordered by pixels (that is, all the samples for the first pixel are 
548       * grouped together, followed by all the samples for the second pixel, and so
549       * on). 
550       *  
551       * @param x  the x-coordinate of the top-left pixel.
552       * @param y  the y-coordinate of the top-left pixel.
553       * @param w  the width of the region of pixels.
554       * @param h  the height of the region of pixels.
555       * @param iArray  the pixel sample values (<code>null</code> not permitted).
556       * @param data  the data buffer (<code>null</code> not permitted).
557       * 
558       * @throws NullPointerException if either <code>iArray</code> or 
559       *     <code>data</code> is <code>null</code>.
560       */
561      public void setPixels(int x, int y, int w, int h, int[] iArray,
562                            DataBuffer data)
563      {
564        int inOffset = 0;
565        for (int hh = 0; hh < h; hh++)
566          {
567            for (int ww = 0; ww < w; ww++)
568              {
569                int offset = y * scanlineStride + (x + ww);
570                for (int b = 0; b < numBands; b++)
571                  data.setElem(bankIndices[b], bandOffsets[b] + offset,
572                               iArray[inOffset++]);
573              }
574            y++;
575          }
576      }
577    
578      /**
579       * Sets the sample value for band <code>b</code> of the pixel at location
580       * <code>(x, y)</code> in the specified data buffer.
581       * 
582       * @param x  the x-coordinate.
583       * @param y  the y-coordinate.
584       * @param b  the band index.
585       * @param s  the sample value.
586       * @param data  the data buffer (<code>null</code> not permitted).
587       * 
588       * @see #getSample(int, int, int, DataBuffer)
589       */
590      public void setSample(int x, int y, int b, int s, DataBuffer data)
591      {
592        data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
593      }
594      
595      /**
596       * Sets the sample value for a band for the pixel at (x, y) in the 
597       * specified data buffer. 
598       * 
599       * @param x  the x-coordinate of the pixel.
600       * @param y  the y-coordinate of the pixel.
601       * @param b  the band (in the range <code>0</code> to 
602       *     <code>getNumBands() - 1</code>).
603       * @param s  the sample value.
604       * @param data  the data buffer (<code>null</code> not permitted).
605       * 
606       * @throws NullPointerException if <code>data</code> is <code>null</code>.
607       */
608      public void setSample(int x, int y, int b, float s, DataBuffer data)
609      {
610        data.setElemFloat(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, 
611                          s);
612      }
613      
614      /**
615       * Sets the sample value for a band for the pixel at (x, y) in the 
616       * specified data buffer. 
617       * 
618       * @param x  the x-coordinate of the pixel.
619       * @param y  the y-coordinate of the pixel.
620       * @param b  the band (in the range <code>0</code> to 
621       *     <code>getNumBands() - 1</code>).
622       * @param s  the sample value.
623       * @param data  the data buffer (<code>null</code> not permitted).
624       * 
625       * @throws NullPointerException if <code>data</code> is <code>null</code>.
626       */
627      public void setSample(int x, int y, int b, double s, DataBuffer data)
628      {
629        data.setElemDouble(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
630                           s);
631      }
632      
633      /**
634       * Sets the sample values for one band for the pixels in the region 
635       * specified by (x, y, w, h) in the specified data buffer. 
636       * 
637       * @param x  the x-coordinate of the top-left pixel.
638       * @param y  the y-coordinate of the top-left pixel.
639       * @param w  the width of the region of pixels.
640       * @param h  the height of the region of pixels.
641       * @param b  the band (in the range <code>0</code> to 
642       *     </code>getNumBands() - 1</code>).
643       * @param iArray  the sample values (<code>null</code> not permitted).
644       * @param data  the data buffer (<code>null</code> not permitted).
645       * 
646       * @throws NullPointerException if either <code>iArray</code> or 
647       *     <code>data</code> is <code>null</code>.
648       */
649      public void setSamples(int x, int y, int w, int h, int b, int[] iArray,
650                             DataBuffer data)
651      {
652        if (x < 0 || y < 0)
653          throw new ArrayIndexOutOfBoundsException(
654              "x and y must not be less than 0.");
655        int inOffset = 0;
656    
657        switch (getTransferType())
658          {
659          case DataBuffer.TYPE_BYTE:
660            {
661              DataBufferByte out = (DataBufferByte) data;
662              byte[] bank = out.getData(bankIndices[b]);
663              for (int hh = 0; hh < h; hh++)
664                {
665                  for (int ww = 0; ww < w; ww++)
666                    {
667                      int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
668                      bank[offset] = (byte)iArray[inOffset++];
669                    }
670                  y++;
671                }
672              return;
673            }
674          case DataBuffer.TYPE_SHORT:
675            {
676              DataBufferShort out = (DataBufferShort) data;
677              short[] bank = out.getData(bankIndices[b]);
678              for (int hh = 0; hh < h; hh++)
679                {
680                  for (int ww = 0; ww < w; ww++)
681                    {
682                      int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
683                      bank[offset] = (short)iArray[inOffset++];
684                    }
685                  y++;
686                }
687              return;
688            }
689          case DataBuffer.TYPE_USHORT:
690            {
691              DataBufferShort out = (DataBufferShort) data;
692              short[] bank = out.getData(bankIndices[b]);
693              for (int hh = 0; hh < h; hh++)
694                {
695                  for (int ww = 0; ww < w; ww++)
696                    {
697                      int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
698                      bank[offset] = (short)iArray[inOffset++];
699                    }
700                  y++;
701                }
702              return;
703            }
704          case DataBuffer.TYPE_INT:
705            {
706              DataBufferInt out = (DataBufferInt) data;
707              int[] bank = out.getData(bankIndices[b]);
708              for (int hh = 0; hh < h; hh++)
709                {
710                  for (int ww = 0; ww < w; ww++)
711                    {
712                      int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
713                      bank[offset] = iArray[inOffset++];
714                    }
715                  y++;
716                }
717              return;
718            }
719          case DataBuffer.TYPE_FLOAT:
720          case DataBuffer.TYPE_DOUBLE:
721            break;
722          default:
723            throw new ClassCastException("Unsupported data type");
724          }
725    
726        // Default implementation probably slower for float and double
727        for (int hh = 0; hh < h; hh++)
728          {
729            for (int ww = 0; ww < w; ww++)
730              {
731                int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
732                data.setElem(bankIndices[b], offset, iArray[inOffset++]);
733              }
734            y++;
735          }
736      }
737    
738      /**
739       * Creates a String with some information about this SampleModel.
740       * @return A String describing this SampleModel.
741       * @see java.lang.Object#toString()
742       */
743      public String toString()
744      {
745        StringBuffer result = new StringBuffer();
746        result.append(getClass().getName());
747        result.append("[");
748        result.append("scanlineStride=").append(scanlineStride);
749        for(int i = 0; i < bitMasks.length; i+=1)
750        {
751          result.append(", mask[").append(i).append("]=0x").append(
752              Integer.toHexString(bitMasks[i]));
753        }
754        
755        result.append("]");
756        return result.toString();
757      }
758    }