BandedSampleModel.java 25.6 KB
Newer Older
1
/* Copyright (C) 2004, 2005, 2006, Free Software Foundation
Tom Tromey committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.awt.image;

39
import gnu.java.awt.Buffers;
40
import gnu.java.lang.CPStringBuilder;
41

Tom Tromey committed
42
/**
43 44
 * A sample model that reads each sample value from a separate band in the
 * {@link DataBuffer}.
Tom Tromey committed
45 46 47 48 49 50 51 52 53 54 55 56 57
 *
 * @author Jerry Quinn (jlquinn@optonline.net)
 */
public final class BandedSampleModel extends ComponentSampleModel
{
  private int[] bitMasks;
  private int[] bitOffsets;
  private int[] sampleSize;
  private int dataBitOffset;
  private int elemBits;
  private int numberOfBits;
  private int numElems;

58
  private static int[] createBankArray(int size)
Tom Tromey committed
59 60 61 62 63 64 65
  {
    int[] result = new int[size];
    for (int i = 0; i < size; i++)
      result[i] = i;
    return result;
  }

66 67
  /**
   * Creates a new <code>BandedSampleModel</code>.
68
   *
69 70 71 72 73
   * @param dataType  the data buffer type.
   * @param w  the width (in pixels).
   * @param h  the height (in pixels).
   * @param numBands  the number of bands.
   */
Tom Tromey committed
74 75 76 77 78
  public BandedSampleModel(int dataType, int w, int h, int numBands)
  {
    this(dataType, w, h, w, createBankArray(numBands), new int[numBands]);
  }

79 80
  /**
   * Creates a new <code>BandedSampleModel</code>.
81
   *
82 83 84
   * @param dataType  the data buffer type.
   * @param w  the width (in pixels).
   * @param h  the height (in pixels).
85
   * @param scanlineStride  the number of data elements from a pixel in one
86 87 88 89
   *     row to the corresponding pixel in the next row.
   * @param bankIndices  the bank indices.
   * @param bandOffsets  the band offsets.
   */
Tom Tromey committed
90
  public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
91
                           int[] bankIndices, int[] bandOffsets)
Tom Tromey committed
92 93 94
  {
    super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
  }
95

96 97
  /**
   * Creates a new data buffer that is compatible with this sample model.
98
   *
99 100 101 102 103 104 105
   * @return The new data buffer.
   */
  public DataBuffer createDataBuffer()
  {
    int size = scanlineStride * height;
    return Buffers.createBuffer(getDataType(), size, numBanks);
  }
Tom Tromey committed
106

107 108 109
  /**
   * Creates a new <code>SampleModel</code> that is compatible with this
   * model and has the specified width and height.
110
   *
111 112
   * @param w  the width (in pixels, must be greater than zero).
   * @param h  the height (in pixels, must be greater than zero).
113
   *
114
   * @return The new sample model.
115
   *
116 117
   * @throws IllegalArgumentException if <code>w</code> or <code>h</code> is
   *     not greater than zero.
118
   * @throws IllegalArgumentException if <code>w * h</code> exceeds
119 120
   *     <code>Integer.MAX_VALUE</code>.
   */
Tom Tromey committed
121 122 123 124 125 126 127 128
  public SampleModel createCompatibleSampleModel(int w, int h)
  {
    // NOTE: blackdown 1.4.1 sets all offsets to 0.  Sun's 1.4.2 docs
    // disagree.

    // Compress offsets so minimum is 0, others w*scanlineStride
    int[] newoffsets = new int[bandOffsets.length];
    int[] order = new int[bandOffsets.length];
129
    for (int i = 0; i < bandOffsets.length; i++)
Tom Tromey committed
130 131 132
      order[i] = i;
    // FIXME: This is N^2, but not a big issue, unless there's a lot of
    // bands...
133 134 135 136 137 138 139 140
    for (int i = 0; i < bandOffsets.length; i++)
      for (int j = i + 1; j < bandOffsets.length; j++)
        if (bankIndices[order[i]] > bankIndices[order[j]]
            || (bankIndices[order[i]] == bankIndices[order[j]]
            && bandOffsets[order[i]] > bandOffsets[order[j]]))
          {
            int t = order[i]; order[i] = order[j]; order[j] = t;
          }
Tom Tromey committed
141 142
    int bank = 0;
    int offset = 0;
143
    for (int i = 0; i < bandOffsets.length; i++)
Tom Tromey committed
144
      {
145 146 147 148 149 150 151
        if (bankIndices[order[i]] != bank)
          {
            bank = bankIndices[order[i]];
            offset = 0;
          }
        newoffsets[order[i]] = offset;
        offset += w * scanlineStride;
Tom Tromey committed
152
      }
153

154
    return new BandedSampleModel(dataType, w, h, w, bankIndices, newoffsets);
Tom Tromey committed
155 156 157 158 159 160 161
  }


  public SampleModel createSubsetSampleModel(int[] bands)
  {
    if (bands.length > bankIndices.length)
      throw new
162 163
        RasterFormatException("BandedSampleModel createSubsetSampleModel too"
                              +" many bands");
Tom Tromey committed
164 165
    int[] newoff = new int[bands.length];
    int[] newbanks = new int[bands.length];
166
    for (int i = 0; i < bands.length; i++)
Tom Tromey committed
167
      {
168 169 170
        int b = bands[i];
        newoff[i] = bandOffsets[b];
        newbanks[i] = bankIndices[b];
Tom Tromey committed
171 172 173
      }

    return new BandedSampleModel(dataType, width, height, scanlineStride,
174
                                 newbanks, newoff);
Tom Tromey committed
175 176 177 178 179 180 181 182
  }

  /**
   * Extract all samples of one pixel and return in an array of transfer type.
   *
   * Extracts the pixel at x, y from data and stores samples into the array
   * obj.  If obj is null, a new array of getTransferType() is created.
   *
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.
Tom Tromey committed
189 190
   * @param data The DataBuffer that is the source of the pixel data.
   * @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)
Tom Tromey committed
193
   */
194
  public Object getDataElements(int x, int y, Object obj, DataBuffer data)
Tom Tromey committed
195
  {
196 197 198
    if (x < 0 || y < 0)
      throw new ArrayIndexOutOfBoundsException(
          "x and y must not be less than 0.");
Tom Tromey committed
199 200 201 202 203
    int pixel = getSample(x, y, 0, data);
    switch (getTransferType())
    {
    case DataBuffer.TYPE_BYTE:
      {
204 205 206 207 208
        byte[] b = (byte[]) obj;
        if (b == null) b = new byte[numBands];
        for (int i = 0; i < numBands; i++)
          b[i] = (byte)getSample(x, y, i, data);
        return b;
Tom Tromey committed
209 210 211 212
      }
    case DataBuffer.TYPE_SHORT:
    case DataBuffer.TYPE_USHORT:
      {
213 214 215 216 217
        short[] b = (short[]) obj;
        if (b == null) b = new short[numBands];
        for (int i = 0; i < numBands; i++)
          b[i] = (short)getSample(x, y, i, data);
        return b;
Tom Tromey committed
218 219 220
      }
    case DataBuffer.TYPE_INT:
      {
221 222 223 224 225
        int[] b = (int[]) obj;
        if (b == null) b = new int[numBands];
        for (int i = 0; i < numBands; i++)
          b[i] = getSample(x, y, i, data);
        return b;
Tom Tromey committed
226 227 228
      }
    case DataBuffer.TYPE_FLOAT:
      {
229 230 231 232 233
        float[] b = (float[]) obj;
        if (b == null) b = new float[numBands];
        for (int i = 0; i < numBands; i++)
          b[i] = getSampleFloat(x, y, i, data);
        return b;
Tom Tromey committed
234 235 236
      }
    case DataBuffer.TYPE_DOUBLE:
      {
237 238
        double[] b = (double[]) obj;
        if (b == null)
239
          b = new double[numBands];
240 241 242
        for (int i = 0; i < numBands; i++)
          b[i] = getSample(x, y, i, data);
        return b;
Tom Tromey committed
243 244 245 246 247 248 249 250
      }

    default:
      // Seems like the only sensible thing to do.
      throw new ClassCastException();
    }
  }

251 252 253
  /**
   * Returns all the samples for the pixel at location <code>(x, y)</code>
   * stored in the specified data buffer.
254
   *
255 256 257
   * @param x  the x-coordinate.
   * @param y  the y-coordinate.
   * @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 260 261
   *   number of bands in the model.  If the array is <code>null</code>, a new
   *   array is created.
   * @param data  the data buffer (<code>null</code> not permitted).
262
   *
263
   * @return The samples for the specified pixel.
264
   *
265 266
   * @see #setPixel(int, int, int[], DataBuffer)
   */
Tom Tromey committed
267 268
  public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
  {
269
    if (iArray == null)
270 271
      iArray = new int[numBands];
    for (int i = 0; i < numBands; i++)
Tom Tromey committed
272
      iArray[i] = getSample(x, y, i, data);
273

Tom Tromey committed
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
    return iArray;
  }

  /**
   * Copy pixels from a region into an array.
   *
   * Copies the samples of the pixels in the rectangle starting at x, y that
   * is w pixels wide and h scanlines high.  When there is more than one band,
   * the samples stored in order before the next pixel.  This ordering isn't
   * well specified in Sun's docs as of 1.4.2.
   *
   * If iArray is null, a new array is allocated, filled, and returned.
   *
   * @param x The x-coordinate of the pixel rectangle to store in
   * <code>iArray</code>.
   * @param y The y-coordinate of the pixel rectangle to store in
   * <code>iArray</code>.
   * @param w The width in pixels of the rectangle.
   * @param h The height in pixels of the rectangle.
   * @param iArray The int array to store the pixels into or null to force
   * creation.
   * @param data The DataBuffer that is the source of the pixel data.
   * @return The primitive array containing the pixel data.
   */
  public int[] getPixels(int x, int y, int w, int h, int[] iArray,
299
                         DataBuffer data)
Tom Tromey committed
300
  {
301 302 303
    if (x < 0 || y < 0)
      throw new ArrayIndexOutOfBoundsException(
          "x and y must not be less than 0.");
304
    if (iArray == null)
305
      iArray = new int[w * h * numBands];
Tom Tromey committed
306 307 308 309 310
    int outOffset = 0;
    int maxX = x + w;
    int maxY = y + h;
    for (int yy = x; yy < maxY; yy++)
      {
311 312 313 314 315 316 317 318 319
        for (int xx = x; xx < maxX; xx++)
          {
            for (int b = 0; b < numBands; b++)
              {
                int offset = bandOffsets[b] + yy * scanlineStride + xx;
                iArray[outOffset++] =
                  data.getElem(bankIndices[b], offset);
              }
          }
Tom Tromey committed
320
      }
321
    return iArray;
Tom Tromey committed
322 323
  }

324
  /**
325
   * Returns a sample value for the pixel at (x, y) in the specified data
326
   * buffer.
327
   *
328 329
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
330
   * @param b  the band (in the range <code>0</code> to
331 332
   *     <code>getNumBands() - 1</code>).
   * @param data  the data buffer (<code>null</code> not permitted).
333
   *
334
   * @return The sample value.
335
   *
336 337
   * @throws NullPointerException if <code>data</code> is <code>null</code>.
   */
Tom Tromey committed
338 339 340 341 342
  public int getSample(int x, int y, int b, DataBuffer data)
  {
    int offset = bandOffsets[b] + y * scanlineStride + x;
    return data.getElem(bankIndices[b], offset);
  }
343

344
  /**
345
   * Returns a sample value for the pixel at (x, y) in the specified data
346
   * buffer.
347
   *
348 349
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
350
   * @param b  the band (in the range <code>0</code> to
351 352
   *     <code>getNumBands() - 1</code>).
   * @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 359
   * @see #getSample(int, int, int, DataBuffer)
   */
Tom Tromey committed
360 361 362 363 364
  public float getSampleFloat(int x, int y, int b, DataBuffer data)
  {
    int offset = bandOffsets[b] + y * scanlineStride + x;
    return data.getElemFloat(bankIndices[b], offset);
  }
365

366
  /**
367
   * Returns the sample value for the pixel at (x, y) in the specified data
368
   * buffer.
369
   *
370 371
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
372
   * @param b  the band (in the range <code>0</code> to
373 374
   *     <code>getNumBands() - 1</code>).
   * @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 381
   * @see #getSample(int, int, int, DataBuffer)
   */
Tom Tromey committed
382 383 384 385 386
  public double getSampleDouble(int x, int y, int b, DataBuffer data)
  {
    int offset = bandOffsets[b] + y * scanlineStride + x;
    return data.getElemDouble(bankIndices[b], offset);
  }
387

Tom Tromey committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
  /**
   * Copy one band's samples from a region into an array.
   *
   * Copies from one band the samples of the pixels in the rectangle starting
   * at x, y that is w pixels wide and h scanlines high.
   *
   * If iArray is null, a new array is allocated, filled, and returned.
   *
   * @param x The x-coordinate of the pixel rectangle to store in
   * <code>iArray</code>.
   * @param y The y-coordinate of the pixel rectangle to store in
   * <code>iArray</code>.
   * @param w The width in pixels of the rectangle.
   * @param h The height in pixels of the rectangle.
   * @param b The band to retrieve.
   * @param iArray The int array to store the pixels into or null to force
   * creation.
   * @param data The DataBuffer that is the source of the pixel data.
   * @return The primitive array containing the pixel data.
   */
  public int[] getSamples(int x, int y, int w, int h, int b, int[] iArray,
409
                          DataBuffer data)
Tom Tromey committed
410
  {
411 412 413
    if (x < 0 || y < 0)
      throw new ArrayIndexOutOfBoundsException(
          "x and y must not be less than 0.");
414
    if (iArray == null)
415
      iArray = new int[w * h];
Tom Tromey committed
416 417 418 419 420
    int outOffset = 0;
    int maxX = x + w;
    int maxY = y + h;
    for (int yy = y; yy < maxY; yy++)
      {
421 422 423 424 425 426
        for (int xx = x; xx < maxX; xx++)
          {
            int offset = bandOffsets[b] + yy * scanlineStride + xx;
            iArray[outOffset++] =
              data.getElem(bankIndices[b], offset);
          }
Tom Tromey committed
427
      }
428
    return iArray;
Tom Tromey committed
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
  }

  /**
   * Set the pixel at x, y to the value in the first element of the primitive
   * array obj.
   *
   * @param x The x-coordinate of the data elements in <code>obj</code>.
   * @param y The y-coordinate of the data elements in <code>obj</code>.
   * @param obj The primitive array containing the data elements to set.
   * @param data The DataBuffer to store the data elements into.
   * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
   */
  public void setDataElements(int x, int y, Object obj, DataBuffer data)
  {
    int transferType = getTransferType();
    if (getTransferType() != data.getDataType())
      {
446 447 448 449 450 451
        throw new IllegalArgumentException("transfer type ("+
                                           getTransferType()+"), "+
                                           "does not match data "+
                                           "buffer type (" +
                                           data.getDataType() +
                                           ").");
Tom Tromey committed
452 453 454
      }

    int offset = y * scanlineStride + x;
455

Tom Tromey committed
456 457
    try
      {
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
        switch (transferType)
          {
          case DataBuffer.TYPE_BYTE:
            {
              DataBufferByte out = (DataBufferByte) data;
              byte[] in = (byte[]) obj;
              for (int i = 0; i < numBands; i++)
                out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
              return;
            }
          case DataBuffer.TYPE_SHORT:
            {
              DataBufferShort out = (DataBufferShort) data;
              short[] in = (short[]) obj;
              for (int i = 0; i < numBands; i++)
                out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
              return;
            }
          case DataBuffer.TYPE_USHORT:
            {
              DataBufferUShort out = (DataBufferUShort) data;
              short[] in = (short[]) obj;
              for (int i = 0; i < numBands; i++)
                out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
              return;
            }
          case DataBuffer.TYPE_INT:
            {
              DataBufferInt out = (DataBufferInt) data;
              int[] in = (int[]) obj;
              for (int i = 0; i < numBands; i++)
                out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
              return;
            }
          case DataBuffer.TYPE_FLOAT:
            {
              DataBufferFloat out = (DataBufferFloat) data;
              float[] in = (float[]) obj;
              for (int i = 0; i < numBands; i++)
                out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
              return;
            }
          case DataBuffer.TYPE_DOUBLE:
            {
              DataBufferDouble out = (DataBufferDouble) data;
              double[] in = (double[]) obj;
              for (int i = 0; i < numBands; i++)
                out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
              return;
            }
          default:
            throw new ClassCastException("Unsupported data type");
          }
Tom Tromey committed
511 512 513
      }
    catch (ArrayIndexOutOfBoundsException aioobe)
      {
514 515 516 517 518 519 520
        String msg = "While writing data elements"
      + ", x=" + x + ", y=" + y
      + ", width=" + width + ", height=" + height
      + ", scanlineStride=" + scanlineStride
      + ", offset=" + offset
      + ", data.getSize()=" + data.getSize()
      + ", data.getOffset()=" + data.getOffset()
521
      + ": " + aioobe;
522
        throw new ArrayIndexOutOfBoundsException(msg);
Tom Tromey committed
523 524 525
      }
    }

526 527
  /**
   * Sets the samples for the pixel at (x, y) in the specified data buffer to
528 529
   * the specified values.
   *
530 531 532 533
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
   * @param iArray  the sample values (<code>null</code> not permitted).
   * @param data  the data buffer (<code>null</code> not permitted).
534 535
   *
   * @throws NullPointerException if either <code>iArray</code> or
536 537
   *     <code>data</code> is <code>null</code>.
   */
Tom Tromey committed
538 539
  public void setPixel(int x, int y, int[] iArray, DataBuffer data)
  {
540
    for (int b = 0; b < numBands; b++)
Tom Tromey committed
541
      data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
542
                   iArray[b]);
Tom Tromey committed
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 551
   * on).
   *
552 553 554 555 556 557
   * @param x  the x-coordinate of the top-left pixel.
   * @param y  the y-coordinate of the top-left pixel.
   * @param w  the width of the region of pixels.
   * @param h  the height of the region of pixels.
   * @param iArray  the pixel sample values (<code>null</code> not permitted).
   * @param data  the data buffer (<code>null</code> not permitted).
558 559
   *
   * @throws NullPointerException if either <code>iArray</code> or
560 561
   *     <code>data</code> is <code>null</code>.
   */
Tom Tromey committed
562
  public void setPixels(int x, int y, int w, int h, int[] iArray,
563
                        DataBuffer data)
Tom Tromey committed
564 565 566 567
  {
    int inOffset = 0;
    for (int hh = 0; hh < h; hh++)
      {
568 569 570 571 572 573 574 575
        for (int ww = 0; ww < w; ww++)
          {
            int offset = y * scanlineStride + (x + ww);
            for (int b = 0; b < numBands; b++)
              data.setElem(bankIndices[b], bandOffsets[b] + offset,
                           iArray[inOffset++]);
          }
        y++;
Tom Tromey committed
576 577 578
      }
  }

579 580 581
  /**
   * Sets the sample value for band <code>b</code> of the pixel at location
   * <code>(x, y)</code> in the specified data buffer.
582
   *
583 584 585 586 587
   * @param x  the x-coordinate.
   * @param y  the y-coordinate.
   * @param b  the band index.
   * @param s  the sample value.
   * @param data  the data buffer (<code>null</code> not permitted).
588
   *
589 590
   * @see #getSample(int, int, int, DataBuffer)
   */
Tom Tromey committed
591 592 593 594
  public void setSample(int x, int y, int b, int s, DataBuffer data)
  {
    data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
  }
595

596
  /**
597 598 599
   * Sets the sample value for a band for the pixel at (x, y) in the
   * specified data buffer.
   *
600 601
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
602
   * @param b  the band (in the range <code>0</code> to
603 604 605
   *     <code>getNumBands() - 1</code>).
   * @param s  the sample value.
   * @param data  the data buffer (<code>null</code> not permitted).
606
   *
607 608
   * @throws NullPointerException if <code>data</code> is <code>null</code>.
   */
Tom Tromey committed
609 610
  public void setSample(int x, int y, int b, float s, DataBuffer data)
  {
611
    data.setElemFloat(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
612
                      s);
Tom Tromey committed
613
  }
614

615
  /**
616 617 618
   * Sets the sample value for a band for the pixel at (x, y) in the
   * specified data buffer.
   *
619 620
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
621
   * @param b  the band (in the range <code>0</code> to
622 623 624
   *     <code>getNumBands() - 1</code>).
   * @param s  the sample value.
   * @param data  the data buffer (<code>null</code> not permitted).
625
   *
626 627
   * @throws NullPointerException if <code>data</code> is <code>null</code>.
   */
Tom Tromey committed
628 629
  public void setSample(int x, int y, int b, double s, DataBuffer data)
  {
630 631
    data.setElemDouble(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
                       s);
Tom Tromey committed
632
  }
633

634
  /**
635 636 637
   * Sets the sample values for one band for the pixels in the region
   * specified by (x, y, w, h) in the specified data buffer.
   *
638 639 640 641
   * @param x  the x-coordinate of the top-left pixel.
   * @param y  the y-coordinate of the top-left pixel.
   * @param w  the width of the region of pixels.
   * @param h  the height of the region of pixels.
642
   * @param b  the band (in the range <code>0</code> to
643 644 645
   *     </code>getNumBands() - 1</code>).
   * @param iArray  the sample values (<code>null</code> not permitted).
   * @param data  the data buffer (<code>null</code> not permitted).
646 647
   *
   * @throws NullPointerException if either <code>iArray</code> or
648 649
   *     <code>data</code> is <code>null</code>.
   */
Tom Tromey committed
650
  public void setSamples(int x, int y, int w, int h, int b, int[] iArray,
651
                         DataBuffer data)
Tom Tromey committed
652
  {
653 654 655
    if (x < 0 || y < 0)
      throw new ArrayIndexOutOfBoundsException(
          "x and y must not be less than 0.");
Tom Tromey committed
656 657 658 659 660
    int inOffset = 0;

    switch (getTransferType())
      {
      case DataBuffer.TYPE_BYTE:
661 662 663 664 665 666 667 668 669 670 671 672 673 674
        {
          DataBufferByte out = (DataBufferByte) data;
          byte[] bank = out.getData(bankIndices[b]);
          for (int hh = 0; hh < h; hh++)
            {
              for (int ww = 0; ww < w; ww++)
                {
                  int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
                  bank[offset] = (byte)iArray[inOffset++];
                }
              y++;
            }
          return;
        }
Tom Tromey committed
675
      case DataBuffer.TYPE_SHORT:
676 677 678 679 680 681 682 683 684 685 686 687 688 689
        {
          DataBufferShort out = (DataBufferShort) data;
          short[] bank = out.getData(bankIndices[b]);
          for (int hh = 0; hh < h; hh++)
            {
              for (int ww = 0; ww < w; ww++)
                {
                  int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
                  bank[offset] = (short)iArray[inOffset++];
                }
              y++;
            }
          return;
        }
Tom Tromey committed
690
      case DataBuffer.TYPE_USHORT:
691 692 693 694 695 696 697 698 699 700 701 702 703 704
        {
          DataBufferShort out = (DataBufferShort) data;
          short[] bank = out.getData(bankIndices[b]);
          for (int hh = 0; hh < h; hh++)
            {
              for (int ww = 0; ww < w; ww++)
                {
                  int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
                  bank[offset] = (short)iArray[inOffset++];
                }
              y++;
            }
          return;
        }
Tom Tromey committed
705
      case DataBuffer.TYPE_INT:
706 707 708 709 710 711 712 713 714 715 716 717 718 719
        {
          DataBufferInt out = (DataBufferInt) data;
          int[] bank = out.getData(bankIndices[b]);
          for (int hh = 0; hh < h; hh++)
            {
              for (int ww = 0; ww < w; ww++)
                {
                  int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
                  bank[offset] = iArray[inOffset++];
                }
              y++;
            }
          return;
        }
Tom Tromey committed
720 721
      case DataBuffer.TYPE_FLOAT:
      case DataBuffer.TYPE_DOUBLE:
722
        break;
Tom Tromey committed
723
      default:
724
        throw new ClassCastException("Unsupported data type");
Tom Tromey committed
725 726 727 728 729
      }

    // Default implementation probably slower for float and double
    for (int hh = 0; hh < h; hh++)
      {
730 731 732 733 734 735
        for (int ww = 0; ww < w; ww++)
          {
            int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
            data.setElem(bankIndices[b], offset, iArray[inOffset++]);
          }
        y++;
Tom Tromey committed
736 737 738 739 740 741 742 743 744 745
      }
  }

  /**
   * Creates a String with some information about this SampleModel.
   * @return A String describing this SampleModel.
   * @see java.lang.Object#toString()
   */
  public String toString()
  {
746
    CPStringBuilder result = new CPStringBuilder();
Tom Tromey committed
747 748 749
    result.append(getClass().getName());
    result.append("[");
    result.append("scanlineStride=").append(scanlineStride);
750
    for(int i = 0; i < bitMasks.length; i+=1)
Tom Tromey committed
751
    {
752 753
      result.append(", mask[").append(i).append("]=0x").append(
          Integer.toHexString(bitMasks[i]));
Tom Tromey committed
754
    }
755

Tom Tromey committed
756 757 758 759
    result.append("]");
    return result.toString();
  }
}