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