1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* **************************************************************** 27 ****************************************************************** 28 ****************************************************************** 29 *** COPYRIGHT (c) Eastman Kodak Company, 1997 30 *** As an unpublished work pursuant to Title 17 of the United 31 *** States Code. All rights reserved. 32 ****************************************************************** 33 ****************************************************************** 34 ******************************************************************/ 35 36 package java.awt.image; 37 38 /** 39 * This class represents image data which is stored in a band interleaved 40 * fashion and for 41 * which each sample of a pixel occupies one data element of the DataBuffer. 42 * It subclasses ComponentSampleModel but provides a more efficient 43 * implementation for accessing band interleaved image data than is provided 44 * by ComponentSampleModel. This class should typically be used when working 45 * with images which store sample data for each band in a different bank of the 46 * DataBuffer. Accessor methods are provided so that image data can be 47 * manipulated directly. Pixel stride is the number of 48 * data array elements between two samples for the same band on the same 49 * scanline. The pixel stride for a BandedSampleModel is one. 50 * Scanline stride is the number of data array elements between 51 * a given sample and the corresponding sample in the same column of the next 52 * scanline. Band offsets denote the number 53 * of data array elements from the first data array element of the bank 54 * of the DataBuffer holding each band to the first sample of the band. 55 * The bands are numbered from 0 to N-1. 56 * Bank indices denote the correspondence between a bank of the data buffer 57 * and a band of image data. This class supports 58 * {@link DataBuffer#TYPE_BYTE TYPE_BYTE}, 59 * {@link DataBuffer#TYPE_USHORT TYPE_USHORT}, 60 * {@link DataBuffer#TYPE_SHORT TYPE_SHORT}, 61 * {@link DataBuffer#TYPE_INT TYPE_INT}, 62 * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, and 63 * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes 64 */ 65 66 67 public final class BandedSampleModel extends ComponentSampleModel 68 { 69 70 /** 71 * Constructs a BandedSampleModel with the specified parameters. 72 * The pixel stride will be one data element. The scanline stride 73 * will be the same as the width. Each band will be stored in 74 * a separate bank and all band offsets will be zero. 75 * @param dataType The data type for storing samples. 76 * @param w The width (in pixels) of the region of 77 * image data described. 78 * @param h The height (in pixels) of the region of image 79 * data described. 80 * @param numBands The number of bands for the image data. 81 * @throws IllegalArgumentException if {@code dataType} is not 82 * one of the supported data types 83 */ 84 public BandedSampleModel(int dataType, int w, int h, int numBands) { 85 super(dataType, w, h, 1, w, 86 BandedSampleModel.createIndicesArray(numBands), 87 BandedSampleModel.createOffsetArray(numBands)); 88 } 89 90 /** 91 * Constructs a BandedSampleModel with the specified parameters. 92 * The number of bands will be inferred from the lengths of the 93 * bandOffsets bankIndices arrays, which must be equal. The pixel 94 * stride will be one data element. 95 * @param dataType The data type for storing samples. 96 * @param w The width (in pixels) of the region of 97 * image data described. 98 * @param h The height (in pixels) of the region of 99 * image data described. 100 * @param scanlineStride The line stride of the of the image data. 101 * @param bankIndices The bank index for each band. 102 * @param bandOffsets The band offset for each band. 103 * @throws IllegalArgumentException if {@code dataType} is not 104 * one of the supported data types 105 */ 106 public BandedSampleModel(int dataType, 107 int w, int h, 108 int scanlineStride, 109 int bankIndices[], 110 int bandOffsets[]) { 111 112 super(dataType, w, h, 1,scanlineStride, bankIndices, bandOffsets); 113 } 114 115 /** 116 * Creates a new BandedSampleModel with the specified 117 * width and height. The new BandedSampleModel will have the same 118 * number of bands, storage data type, and bank indices 119 * as this BandedSampleModel. The band offsets will be compressed 120 * such that the offset between bands will be w*pixelStride and 121 * the minimum of all of the band offsets is zero. 122 * @param w the width of the resulting {@code BandedSampleModel} 123 * @param h the height of the resulting {@code BandedSampleModel} 124 * @return a new {@code BandedSampleModel} with the specified 125 * width and height. 126 * @throws IllegalArgumentException if {@code w} or 127 * {@code h} equals either 128 * {@code Integer.MAX_VALUE} or 129 * {@code Integer.MIN_VALUE} 130 * @throws IllegalArgumentException if {@code dataType} is not 131 * one of the supported data types 132 */ 133 public SampleModel createCompatibleSampleModel(int w, int h) { 134 int[] bandOffs; 135 136 if (numBanks == 1) { 137 bandOffs = orderBands(bandOffsets, w*h); 138 } 139 else { 140 bandOffs = new int[bandOffsets.length]; 141 } 142 143 SampleModel sampleModel = 144 new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffs); 145 return sampleModel; 146 } 147 148 /** 149 * Creates a new BandedSampleModel with a subset of the bands of this 150 * BandedSampleModel. The new BandedSampleModel can be 151 * used with any DataBuffer that the existing BandedSampleModel 152 * can be used with. The new BandedSampleModel/DataBuffer 153 * combination will represent an image with a subset of the bands 154 * of the original BandedSampleModel/DataBuffer combination. 155 * @throws RasterFormatException if the number of bands is greater than 156 * the number of banks in this sample model. 157 * @throws IllegalArgumentException if {@code dataType} is not 158 * one of the supported data types 159 */ 160 public SampleModel createSubsetSampleModel(int bands[]) { 161 if (bands.length > bankIndices.length) 162 throw new RasterFormatException("There are only " + 163 bankIndices.length + 164 " bands"); 165 int newBankIndices[] = new int[bands.length]; 166 int newBandOffsets[] = new int[bands.length]; 167 168 for (int i=0; i<bands.length; i++) { 169 newBankIndices[i] = bankIndices[bands[i]]; 170 newBandOffsets[i] = bandOffsets[bands[i]]; 171 } 172 173 return new BandedSampleModel(this.dataType, width, height, 174 this.scanlineStride, 175 newBankIndices, newBandOffsets); 176 } 177 178 /** 179 * Creates a DataBuffer that corresponds to this BandedSampleModel, 180 * The DataBuffer's data type, number of banks, and size 181 * will be consistent with this BandedSampleModel. 182 * @throws IllegalArgumentException if {@code dataType} is not 183 * one of the supported types. 184 */ 185 public DataBuffer createDataBuffer() { 186 DataBuffer dataBuffer = null; 187 188 int size = scanlineStride * height; 189 switch (dataType) { 190 case DataBuffer.TYPE_BYTE: 191 dataBuffer = new DataBufferByte(size, numBanks); 192 break; 193 case DataBuffer.TYPE_USHORT: 194 dataBuffer = new DataBufferUShort(size, numBanks); 195 break; 196 case DataBuffer.TYPE_SHORT: 197 dataBuffer = new DataBufferShort(size, numBanks); 198 break; 199 case DataBuffer.TYPE_INT: 200 dataBuffer = new DataBufferInt(size, numBanks); 201 break; 202 case DataBuffer.TYPE_FLOAT: 203 dataBuffer = new DataBufferFloat(size, numBanks); 204 break; 205 case DataBuffer.TYPE_DOUBLE: 206 dataBuffer = new DataBufferDouble(size, numBanks); 207 break; 208 default: 209 throw new IllegalArgumentException("dataType is not one " + 210 "of the supported types."); 211 } 212 213 return dataBuffer; 214 } 215 216 217 /** 218 * Returns data for a single pixel in a primitive array of type 219 * TransferType. For a BandedSampleModel, this will be the same 220 * as the data type, and samples will be returned one per array 221 * element. Generally, obj 222 * should be passed in as null, so that the Object will be created 223 * automatically and will be of the right primitive data type. 224 * <p> 225 * The following code illustrates transferring data for one pixel from 226 * DataBuffer {@code db1}, whose storage layout is described by 227 * BandedSampleModel {@code bsm1}, to DataBuffer {@code db2}, 228 * whose storage layout is described by 229 * BandedSampleModel {@code bsm2}. 230 * The transfer will generally be more efficient than using 231 * getPixel/setPixel. 232 * <pre> 233 * BandedSampleModel bsm1, bsm2; 234 * DataBufferInt db1, db2; 235 * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1), 236 * db2); 237 * </pre> 238 * Using getDataElements/setDataElements to transfer between two 239 * DataBuffer/SampleModel pairs is legitimate if the SampleModels have 240 * the same number of bands, corresponding bands have the same number of 241 * bits per sample, and the TransferTypes are the same. 242 * <p> 243 * If obj is non-null, it should be a primitive array of type TransferType. 244 * Otherwise, a ClassCastException is thrown. An 245 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 246 * not in bounds, or if obj is non-null and is not large enough to hold 247 * the pixel data. 248 * @param x The X coordinate of the pixel location 249 * @param y The Y coordinate of the pixel location 250 * @param obj If non-null, a primitive array in which to return 251 * the pixel data. 252 * @param data The DataBuffer containing the image data. 253 * @return the data for the specified pixel. 254 * @see #setDataElements(int, int, Object, DataBuffer) 255 */ 256 public Object getDataElements(int x, int y, Object obj, DataBuffer data) { 257 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 258 throw new ArrayIndexOutOfBoundsException 259 ("Coordinate out of bounds!"); 260 } 261 int type = getTransferType(); 262 int numDataElems = getNumDataElements(); 263 int pixelOffset = y*scanlineStride + x; 264 265 switch(type) { 266 267 case DataBuffer.TYPE_BYTE: 268 269 byte[] bdata; 270 271 if (obj == null) { 272 bdata = new byte[numDataElems]; 273 } else { 274 bdata = (byte[])obj; 275 } 276 277 for (int i=0; i<numDataElems; i++) { 278 bdata[i] = (byte)data.getElem(bankIndices[i], 279 pixelOffset + bandOffsets[i]); 280 } 281 282 obj = (Object)bdata; 283 break; 284 285 case DataBuffer.TYPE_USHORT: 286 case DataBuffer.TYPE_SHORT: 287 288 short[] sdata; 289 290 if (obj == null) { 291 sdata = new short[numDataElems]; 292 } else { 293 sdata = (short[])obj; 294 } 295 296 for (int i=0; i<numDataElems; i++) { 297 sdata[i] = (short)data.getElem(bankIndices[i], 298 pixelOffset + bandOffsets[i]); 299 } 300 301 obj = (Object)sdata; 302 break; 303 304 case DataBuffer.TYPE_INT: 305 306 int[] idata; 307 308 if (obj == null) { 309 idata = new int[numDataElems]; 310 } else { 311 idata = (int[])obj; 312 } 313 314 for (int i=0; i<numDataElems; i++) { 315 idata[i] = data.getElem(bankIndices[i], 316 pixelOffset + bandOffsets[i]); 317 } 318 319 obj = (Object)idata; 320 break; 321 322 case DataBuffer.TYPE_FLOAT: 323 324 float[] fdata; 325 326 if (obj == null) { 327 fdata = new float[numDataElems]; 328 } else { 329 fdata = (float[])obj; 330 } 331 332 for (int i=0; i<numDataElems; i++) { 333 fdata[i] = data.getElemFloat(bankIndices[i], 334 pixelOffset + bandOffsets[i]); 335 } 336 337 obj = (Object)fdata; 338 break; 339 340 case DataBuffer.TYPE_DOUBLE: 341 342 double[] ddata; 343 344 if (obj == null) { 345 ddata = new double[numDataElems]; 346 } else { 347 ddata = (double[])obj; 348 } 349 350 for (int i=0; i<numDataElems; i++) { 351 ddata[i] = data.getElemDouble(bankIndices[i], 352 pixelOffset + bandOffsets[i]); 353 } 354 355 obj = (Object)ddata; 356 break; 357 } 358 359 return obj; 360 } 361 362 /** 363 * Returns all samples for the specified pixel in an int array. 364 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 365 * not in bounds. 366 * @param x The X coordinate of the pixel location 367 * @param y The Y coordinate of the pixel location 368 * @param iArray If non-null, returns the samples in this array 369 * @param data The DataBuffer containing the image data 370 * @return the samples for the specified pixel. 371 * @see #setPixel(int, int, int[], DataBuffer) 372 */ 373 public int[] getPixel(int x, int y, int iArray[], DataBuffer data) { 374 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 375 throw new ArrayIndexOutOfBoundsException 376 ("Coordinate out of bounds!"); 377 } 378 379 int[] pixels; 380 381 if (iArray != null) { 382 pixels = iArray; 383 } else { 384 pixels = new int [numBands]; 385 } 386 387 int pixelOffset = y*scanlineStride + x; 388 for (int i=0; i<numBands; i++) { 389 pixels[i] = data.getElem(bankIndices[i], 390 pixelOffset + bandOffsets[i]); 391 } 392 return pixels; 393 } 394 395 /** 396 * Returns all samples for the specified rectangle of pixels in 397 * an int array, one sample per data array element. 398 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 399 * not in bounds. 400 * @param x The X coordinate of the upper left pixel location 401 * @param y The Y coordinate of the upper left pixel location 402 * @param w The width of the pixel rectangle 403 * @param h The height of the pixel rectangle 404 * @param iArray If non-null, returns the samples in this array 405 * @param data The DataBuffer containing the image data 406 * @return the samples for the pixels within the specified region. 407 * @see #setPixels(int, int, int, int, int[], DataBuffer) 408 */ 409 public int[] getPixels(int x, int y, int w, int h, 410 int iArray[], DataBuffer data) { 411 int x1 = x + w; 412 int y1 = y + h; 413 414 if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width || 415 y < 0 || y >= height || h > height || y1 < 0 || y1 > height) 416 { 417 throw new ArrayIndexOutOfBoundsException 418 ("Coordinate out of bounds!"); 419 } 420 int[] pixels; 421 422 if (iArray != null) { 423 pixels = iArray; 424 } else { 425 pixels = new int[w*h*numBands]; 426 } 427 428 for (int k = 0; k < numBands; k++) { 429 int lineOffset = y*scanlineStride + x + bandOffsets[k]; 430 int srcOffset = k; 431 int bank = bankIndices[k]; 432 433 for (int i = 0; i < h; i++) { 434 int pixelOffset = lineOffset; 435 for (int j = 0; j < w; j++) { 436 pixels[srcOffset] = data.getElem(bank, pixelOffset++); 437 srcOffset += numBands; 438 } 439 lineOffset += scanlineStride; 440 } 441 } 442 return pixels; 443 } 444 445 /** 446 * Returns as int the sample in a specified band for the pixel 447 * located at (x,y). 448 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 449 * not in bounds. 450 * @param x The X coordinate of the pixel location 451 * @param y The Y coordinate of the pixel location 452 * @param b The band to return 453 * @param data The DataBuffer containing the image data 454 * @return the sample in the specified band for the specified pixel. 455 * @see #setSample(int, int, int, int, DataBuffer) 456 */ 457 public int getSample(int x, int y, int b, DataBuffer data) { 458 // Bounds check for 'b' will be performed automatically 459 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 460 throw new ArrayIndexOutOfBoundsException 461 ("Coordinate out of bounds!"); 462 } 463 int sample = 464 data.getElem(bankIndices[b], 465 y*scanlineStride + x + bandOffsets[b]); 466 return sample; 467 } 468 469 /** 470 * Returns the sample in a specified band 471 * for the pixel located at (x,y) as a float. 472 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 473 * not in bounds. 474 * @param x The X coordinate of the pixel location 475 * @param y The Y coordinate of the pixel location 476 * @param b The band to return 477 * @param data The DataBuffer containing the image data 478 * @return a float value that represents the sample in the specified 479 * band for the specified pixel. 480 */ 481 public float getSampleFloat(int x, int y, int b, DataBuffer data) { 482 // Bounds check for 'b' will be performed automatically 483 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 484 throw new ArrayIndexOutOfBoundsException 485 ("Coordinate out of bounds!"); 486 } 487 488 float sample = data.getElemFloat(bankIndices[b], 489 y*scanlineStride + x + bandOffsets[b]); 490 return sample; 491 } 492 493 /** 494 * Returns the sample in a specified band 495 * for a pixel located at (x,y) as a double. 496 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 497 * not in bounds. 498 * @param x The X coordinate of the pixel location 499 * @param y The Y coordinate of the pixel location 500 * @param b The band to return 501 * @param data The DataBuffer containing the image data 502 * @return a double value that represents the sample in the specified 503 * band for the specified pixel. 504 */ 505 public double getSampleDouble(int x, int y, int b, DataBuffer data) { 506 // Bounds check for 'b' will be performed automatically 507 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 508 throw new ArrayIndexOutOfBoundsException 509 ("Coordinate out of bounds!"); 510 } 511 512 double sample = data.getElemDouble(bankIndices[b], 513 y*scanlineStride + x + bandOffsets[b]); 514 return sample; 515 } 516 517 /** 518 * Returns the samples in a specified band for the specified rectangle 519 * of pixels in an int array, one sample per data array element. 520 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 521 * not in bounds. 522 * @param x The X coordinate of the upper left pixel location 523 * @param y The Y coordinate of the upper left pixel location 524 * @param w The width of the pixel rectangle 525 * @param h The height of the pixel rectangle 526 * @param b The band to return 527 * @param iArray If non-null, returns the samples in this array 528 * @param data The DataBuffer containing the image data 529 * @return the samples in the specified band for the pixels within 530 * the specified region. 531 * @see #setSamples(int, int, int, int, int, int[], DataBuffer) 532 */ 533 public int[] getSamples(int x, int y, int w, int h, int b, 534 int iArray[], DataBuffer data) { 535 // Bounds check for 'b' will be performed automatically 536 if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { 537 throw new ArrayIndexOutOfBoundsException 538 ("Coordinate out of bounds!"); 539 } 540 int samples[]; 541 if (iArray != null) { 542 samples = iArray; 543 } else { 544 samples = new int [w*h]; 545 } 546 547 int lineOffset = y*scanlineStride + x + bandOffsets[b]; 548 int srcOffset = 0; 549 int bank = bankIndices[b]; 550 551 for (int i = 0; i < h; i++) { 552 int sampleOffset = lineOffset; 553 for (int j = 0; j < w; j++) { 554 samples[srcOffset++] = data.getElem(bank, sampleOffset++); 555 } 556 lineOffset += scanlineStride; 557 } 558 return samples; 559 } 560 561 /** 562 * Sets the data for a single pixel in the specified DataBuffer from a 563 * primitive array of type TransferType. For a BandedSampleModel, 564 * this will be the same as the data type, and samples are transferred 565 * one per array element. 566 * <p> 567 * The following code illustrates transferring data for one pixel from 568 * DataBuffer {@code db1}, whose storage layout is described by 569 * BandedSampleModel {@code bsm1}, to DataBuffer {@code db2}, 570 * whose storage layout is described by 571 * BandedSampleModel {@code bsm2}. 572 * The transfer will generally be more efficient than using 573 * getPixel/setPixel. 574 * <pre> 575 * BandedSampleModel bsm1, bsm2; 576 * DataBufferInt db1, db2; 577 * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1), 578 * db2); 579 * </pre> 580 * Using getDataElements/setDataElements to transfer between two 581 * DataBuffer/SampleModel pairs is legitimate if the SampleModels have 582 * the same number of bands, corresponding bands have the same number of 583 * bits per sample, and the TransferTypes are the same. 584 * <p> 585 * obj must be a primitive array of type TransferType. Otherwise, 586 * a ClassCastException is thrown. An 587 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 588 * not in bounds, or if obj is not large enough to hold the pixel data. 589 * @param x The X coordinate of the pixel location 590 * @param y The Y coordinate of the pixel location 591 * @param obj If non-null, returns the primitive array in this 592 * object 593 * @param data The DataBuffer containing the image data 594 * @see #getDataElements(int, int, Object, DataBuffer) 595 */ 596 public void setDataElements(int x, int y, Object obj, DataBuffer data) { 597 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 598 throw new ArrayIndexOutOfBoundsException 599 ("Coordinate out of bounds!"); 600 } 601 int type = getTransferType(); 602 int numDataElems = getNumDataElements(); 603 int pixelOffset = y*scanlineStride + x; 604 605 switch(type) { 606 607 case DataBuffer.TYPE_BYTE: 608 609 byte[] barray = (byte[])obj; 610 611 for (int i=0; i<numDataElems; i++) { 612 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i], 613 barray[i] & 0xff); 614 } 615 break; 616 617 case DataBuffer.TYPE_USHORT: 618 case DataBuffer.TYPE_SHORT: 619 620 short[] sarray = (short[])obj; 621 622 for (int i=0; i<numDataElems; i++) { 623 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i], 624 sarray[i] & 0xffff); 625 } 626 break; 627 628 case DataBuffer.TYPE_INT: 629 630 int[] iarray = (int[])obj; 631 632 for (int i=0; i<numDataElems; i++) { 633 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i], 634 iarray[i]); 635 } 636 break; 637 638 case DataBuffer.TYPE_FLOAT: 639 640 float[] farray = (float[])obj; 641 642 for (int i=0; i<numDataElems; i++) { 643 data.setElemFloat(bankIndices[i], pixelOffset + bandOffsets[i], 644 farray[i]); 645 } 646 break; 647 648 case DataBuffer.TYPE_DOUBLE: 649 650 double[] darray = (double[])obj; 651 652 for (int i=0; i<numDataElems; i++) { 653 data.setElemDouble(bankIndices[i], pixelOffset + bandOffsets[i], 654 darray[i]); 655 } 656 break; 657 658 } 659 } 660 661 /** 662 * Sets a pixel in the DataBuffer using an int array of samples for input. 663 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 664 * not in bounds. 665 * @param x The X coordinate of the pixel location 666 * @param y The Y coordinate of the pixel location 667 * @param iArray The input samples in an int array 668 * @param data The DataBuffer containing the image data 669 * @see #getPixel(int, int, int[], DataBuffer) 670 */ 671 public void setPixel(int x, int y, int iArray[], DataBuffer data) { 672 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 673 throw new ArrayIndexOutOfBoundsException 674 ("Coordinate out of bounds!"); 675 } 676 int pixelOffset = y*scanlineStride + x; 677 for (int i=0; i<numBands; i++) { 678 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i], 679 iArray[i]); 680 } 681 } 682 683 /** 684 * Sets all samples for a rectangle of pixels from an int array containing 685 * one sample per array element. 686 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 687 * not in bounds. 688 * @param x The X coordinate of the upper left pixel location 689 * @param y The Y coordinate of the upper left pixel location 690 * @param w The width of the pixel rectangle 691 * @param h The height of the pixel rectangle 692 * @param iArray The input samples in an int array 693 * @param data The DataBuffer containing the image data 694 * @see #getPixels(int, int, int, int, int[], DataBuffer) 695 */ 696 public void setPixels(int x, int y, int w, int h, 697 int iArray[], DataBuffer data) { 698 int x1 = x + w; 699 int y1 = y + h; 700 701 if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width || 702 y < 0 || y >= height || h > height || y1 < 0 || y1 > height) 703 { 704 throw new ArrayIndexOutOfBoundsException 705 ("Coordinate out of bounds!"); 706 } 707 708 for (int k = 0; k < numBands; k++) { 709 int lineOffset = y*scanlineStride + x + bandOffsets[k]; 710 int srcOffset = k; 711 int bank = bankIndices[k]; 712 713 for (int i = 0; i < h; i++) { 714 int pixelOffset = lineOffset; 715 for (int j = 0; j < w; j++) { 716 data.setElem(bank, pixelOffset++, iArray[srcOffset]); 717 srcOffset += numBands; 718 } 719 lineOffset += scanlineStride; 720 } 721 } 722 } 723 724 /** 725 * Sets a sample in the specified band for the pixel located at (x,y) 726 * in the DataBuffer using an int for input. 727 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 728 * not in bounds. 729 * @param x The X coordinate of the pixel location 730 * @param y The Y coordinate of the pixel location 731 * @param b The band to set 732 * @param s The input sample as an int 733 * @param data The DataBuffer containing the image data 734 * @see #getSample(int, int, int, DataBuffer) 735 */ 736 public void setSample(int x, int y, int b, int s, 737 DataBuffer data) { 738 // Bounds check for 'b' will be performed automatically 739 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 740 throw new ArrayIndexOutOfBoundsException 741 ("Coordinate out of bounds!"); 742 } 743 data.setElem(bankIndices[b], 744 y*scanlineStride + x + bandOffsets[b], s); 745 } 746 747 /** 748 * Sets a sample in the specified band for the pixel located at (x,y) 749 * in the DataBuffer using a float for input. 750 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 751 * not in bounds. 752 * @param x The X coordinate of the pixel location 753 * @param y The Y coordinate of the pixel location 754 * @param b The band to set 755 * @param s The input sample as a float 756 * @param data The DataBuffer containing the image data 757 * @see #getSample(int, int, int, DataBuffer) 758 */ 759 public void setSample(int x, int y, int b, 760 float s , 761 DataBuffer data) { 762 // Bounds check for 'b' will be performed automatically 763 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 764 throw new ArrayIndexOutOfBoundsException 765 ("Coordinate out of bounds!"); 766 } 767 data.setElemFloat(bankIndices[b], 768 y*scanlineStride + x + bandOffsets[b], s); 769 } 770 771 /** 772 * Sets a sample in the specified band for the pixel located at (x,y) 773 * in the DataBuffer using a double for input. 774 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 775 * not in bounds. 776 * @param x The X coordinate of the pixel location 777 * @param y The Y coordinate of the pixel location 778 * @param b The band to set 779 * @param s The input sample as a double 780 * @param data The DataBuffer containing the image data 781 * @see #getSample(int, int, int, DataBuffer) 782 */ 783 public void setSample(int x, int y, int b, 784 double s, 785 DataBuffer data) { 786 // Bounds check for 'b' will be performed automatically 787 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { 788 throw new ArrayIndexOutOfBoundsException 789 ("Coordinate out of bounds!"); 790 } 791 data.setElemDouble(bankIndices[b], 792 y*scanlineStride + x + bandOffsets[b], s); 793 } 794 795 /** 796 * Sets the samples in the specified band for the specified rectangle 797 * of pixels from an int array containing one sample per data array element. 798 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 799 * not in bounds. 800 * @param x The X coordinate of the upper left pixel location 801 * @param y The Y coordinate of the upper left pixel location 802 * @param w The width of the pixel rectangle 803 * @param h The height of the pixel rectangle 804 * @param b The band to set 805 * @param iArray The input sample array 806 * @param data The DataBuffer containing the image data 807 * @see #getSamples(int, int, int, int, int, int[], DataBuffer) 808 */ 809 public void setSamples(int x, int y, int w, int h, int b, 810 int iArray[], DataBuffer data) { 811 // Bounds check for 'b' will be performed automatically 812 if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { 813 throw new ArrayIndexOutOfBoundsException 814 ("Coordinate out of bounds!"); 815 } 816 int lineOffset = y*scanlineStride + x + bandOffsets[b]; 817 int srcOffset = 0; 818 int bank = bankIndices[b]; 819 820 for (int i = 0; i < h; i++) { 821 int sampleOffset = lineOffset; 822 for (int j = 0; j < w; j++) { 823 data.setElem(bank, sampleOffset++, iArray[srcOffset++]); 824 } 825 lineOffset += scanlineStride; 826 } 827 } 828 829 private static int[] createOffsetArray(int numBands) { 830 int[] bandOffsets = new int[numBands]; 831 for (int i=0; i < numBands; i++) { 832 bandOffsets[i] = 0; 833 } 834 return bandOffsets; 835 } 836 837 private static int[] createIndicesArray(int numBands) { 838 int[] bankIndices = new int[numBands]; 839 for (int i=0; i < numBands; i++) { 840 bankIndices[i] = i; 841 } 842 return bankIndices; 843 } 844 845 // Differentiate hash code from other ComponentSampleModel subclasses 846 public int hashCode() { 847 return super.hashCode() ^ 0x2; 848 } 849 }