Source for java.awt.image.BandedSampleModel

   1: /* Copyright (C) 2004, 2005, 2006, Free Software Foundation
   2: 
   3: This file is part of GNU Classpath.
   4: 
   5: GNU Classpath is free software; you can redistribute it and/or modify
   6: it under the terms of the GNU General Public License as published by
   7: the Free Software Foundation; either version 2, or (at your option)
   8: any later version.
   9: 
  10: GNU Classpath is distributed in the hope that it will be useful, but
  11: WITHOUT ANY WARRANTY; without even the implied warranty of
  12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13: General Public License for more details.
  14: 
  15: You should have received a copy of the GNU General Public License
  16: along with GNU Classpath; see the file COPYING.  If not, write to the
  17: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  18: 02110-1301 USA.
  19: 
  20: Linking this library statically or dynamically with other modules is
  21: making a combined work based on this library.  Thus, the terms and
  22: conditions of the GNU General Public License cover the whole
  23: combination.
  24: 
  25: As a special exception, the copyright holders of this library give you
  26: permission to link this library with independent modules to produce an
  27: executable, regardless of the license terms of these independent
  28: modules, and to copy and distribute the resulting executable under
  29: terms of your choice, provided that you also meet, for each linked
  30: independent module, the terms and conditions of the license of that
  31: module.  An independent module is a module which is not derived from
  32: or based on this library.  If you modify this library, you may extend
  33: this exception to your version of the library, but you are not
  34: obligated to do so.  If you do not wish to do so, delete this
  35: exception statement from your version. */
  36: 
  37: package java.awt.image;
  38: 
  39: import gnu.java.awt.Buffers;
  40: import gnu.java.lang.CPStringBuilder;
  41: 
  42: /**
  43:  * A sample model that reads each sample value from a separate band in the
  44:  * {@link DataBuffer}.
  45:  *
  46:  * @author Jerry Quinn (jlquinn@optonline.net)
  47:  */
  48: public final class BandedSampleModel extends ComponentSampleModel
  49: {
  50:   private int[] bitMasks;
  51:   private int[] bitOffsets;
  52:   private int[] sampleSize;
  53:   private int dataBitOffset;
  54:   private int elemBits;
  55:   private int numberOfBits;
  56:   private int numElems;
  57: 
  58:   private static int[] createBankArray(int size)
  59:   {
  60:     int[] result = new int[size];
  61:     for (int i = 0; i < size; i++)
  62:       result[i] = i;
  63:     return result;
  64:   }
  65: 
  66:   /**
  67:    * Creates a new <code>BandedSampleModel</code>.
  68:    *
  69:    * @param dataType  the data buffer type.
  70:    * @param w  the width (in pixels).
  71:    * @param h  the height (in pixels).
  72:    * @param numBands  the number of bands.
  73:    */
  74:   public BandedSampleModel(int dataType, int w, int h, int numBands)
  75:   {
  76:     this(dataType, w, h, w, createBankArray(numBands), new int[numBands]);
  77:   }
  78: 
  79:   /**
  80:    * Creates a new <code>BandedSampleModel</code>.
  81:    *
  82:    * @param dataType  the data buffer type.
  83:    * @param w  the width (in pixels).
  84:    * @param h  the height (in pixels).
  85:    * @param scanlineStride  the number of data elements from a pixel in one
  86:    *     row to the corresponding pixel in the next row.
  87:    * @param bankIndices  the bank indices.
  88:    * @param bandOffsets  the band offsets.
  89:    */
  90:   public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
  91:                            int[] bankIndices, int[] bandOffsets)
  92:   {
  93:     super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
  94:   }
  95: 
  96:   /**
  97:    * Creates a new data buffer that is compatible with this sample model.
  98:    *
  99:    * @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: }