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: }