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