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