1 /* 2 * Copyright (c) 1998, 2016, 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 package sun.awt.image; 27 import java.awt.image.Raster; 28 import java.awt.image.WritableRaster; 29 import java.awt.image.RasterFormatException; 30 import java.awt.image.SampleModel; 31 import java.awt.image.ComponentSampleModel; 32 import java.awt.image.PixelInterleavedSampleModel; 33 import java.awt.image.SinglePixelPackedSampleModel; 34 import java.awt.image.DataBuffer; 35 import java.awt.image.DataBufferUShort; 36 import java.awt.Rectangle; 37 import java.awt.Point; 38 39 /** 40 * This class defines a Raster with pixels consisting of one or more 16-bit 41 * data elements stored in close proximity to each other in a short integer 42 * array. The bit precision per data element is that 43 * of the data type (that is, the bit precision for this Raster is 16). 44 * There is only one pixel stride and one scanline stride for all 45 * bands. This type of Raster can be used with a 46 * ComponentColorModel if there are multiple bands, or a 47 * IndexColorModel if there is only one band. 48 * <p> 49 * For example, 5-6-5 RGB image data can be represented by a 50 * ShortInterleavedRaster using a SinglePixelPackedSampleModel and 51 * a ComponentColorModel. 52 * 53 * 54 */ 55 public class ShortInterleavedRaster extends ShortComponentRaster { 56 57 /** A cached copy of minX + width for use in bounds checks. */ 58 private int maxX; 59 60 /** A cached copy of minY + height for use in bounds checks. */ 61 private int maxY; 62 63 /** 64 * Constructs a ShortInterleavedRaster with the given SampleModel. 65 * The Raster's upper left corner is origin and it is the same 66 * size as the SampleModel. A DataBuffer large enough to describe the 67 * Raster is automatically created. SampleModel must be of type 68 * PixelInterleavedSampleModel or SinglePixelPackedSampleModel. 69 * @param sampleModel The SampleModel that specifies the layout. 70 * @param origin The Point that specified the origin. 71 */ 72 public ShortInterleavedRaster(SampleModel sampleModel, Point origin) { 73 this(sampleModel, 74 (DataBufferUShort)sampleModel.createDataBuffer(), 75 new Rectangle(origin.x, 76 origin.y, 77 sampleModel.getWidth(), 78 sampleModel.getHeight()), 79 origin, 80 null); 81 } 82 83 /** 84 * Constructs a ShortInterleavedRaster with the given SampleModel 85 * and DataBuffer. The Raster's upper left corner is origin and 86 * it is the same sizes the SampleModel. The DataBuffer is not 87 * initialized and must be a DataBufferUShort compatible with SampleModel. 88 * SampleModel must be of type PixelInterleavedSampleModel or 89 * SinglePixelPackedSampleModel. 90 * @param sampleModel The SampleModel that specifies the layout. 91 * @param dataBuffer The DataBufferUShort that contains the image data. 92 * @param origin The Point that specifies the origin. 93 */ 94 public ShortInterleavedRaster(SampleModel sampleModel, 95 DataBufferUShort dataBuffer, 96 Point origin) { 97 this(sampleModel, 98 dataBuffer, 99 new Rectangle(origin.x, 100 origin.y, 101 sampleModel.getWidth(), 102 sampleModel.getHeight()), 103 origin, 104 null); 105 } 106 107 /** 108 * Constructs a ShortInterleavedRaster with the given SampleModel, 109 * DataBuffer, and parent. DataBuffer must be a DataBufferUShort and 110 * SampleModel must be of type PixelInterleavedSampleModel or 111 * SinglePixelPackedSampleModel. When translated into the base Raster's 112 * coordinate system, aRegion must be contained by the base Raster. 113 * Origin is the coodinate in the new Raster's coordinate system of 114 * the origin of the base Raster. (The base Raster is the Raster's 115 * ancestor which has no parent.) 116 * 117 * Note that this constructor should generally be called by other 118 * constructors or create methods, it should not be used directly. 119 * @param sampleModel The SampleModel that specifies the layout. 120 * @param dataBuffer The DataBufferUShort that contains the image data. 121 * @param aRegion The Rectangle that specifies the image area. 122 * @param origin The Point that specifies the origin. 123 * @param parent The parent (if any) of this raster. 124 */ 125 public ShortInterleavedRaster(SampleModel sampleModel, 126 DataBufferUShort dataBuffer, 127 Rectangle aRegion, 128 Point origin, 129 ShortInterleavedRaster parent) { 130 131 super(sampleModel, dataBuffer, aRegion, origin, parent); 132 this.maxX = minX + width; 133 this.maxY = minY + height; 134 135 this.data = stealData(dataBuffer, 0); 136 137 // REMIND: need case for interleaved ComponentSampleModel 138 if ((sampleModel instanceof PixelInterleavedSampleModel) || 139 (sampleModel instanceof ComponentSampleModel && 140 sampleModel.getNumBands() == 1)) { 141 ComponentSampleModel csm = (ComponentSampleModel)sampleModel; 142 143 this.scanlineStride = csm.getScanlineStride(); 144 this.pixelStride = csm.getPixelStride(); 145 this.dataOffsets = csm.getBandOffsets(); 146 int xOffset = aRegion.x - origin.x; 147 int yOffset = aRegion.y - origin.y; 148 for (int i = 0; i < getNumDataElements(); i++) { 149 dataOffsets[i] += xOffset*pixelStride+yOffset*scanlineStride; 150 } 151 } else if (sampleModel instanceof SinglePixelPackedSampleModel) { 152 SinglePixelPackedSampleModel sppsm = 153 (SinglePixelPackedSampleModel)sampleModel; 154 this.scanlineStride = sppsm.getScanlineStride(); 155 this.pixelStride = 1; 156 this.dataOffsets = new int[1]; 157 this.dataOffsets[0] = dataBuffer.getOffset(); 158 int xOffset = aRegion.x - origin.x; 159 int yOffset = aRegion.y - origin.y; 160 dataOffsets[0] += xOffset+yOffset*scanlineStride; 161 } else { 162 throw new RasterFormatException("ShortInterleavedRasters must "+ 163 "have PixelInterleavedSampleModel, SinglePixelPackedSampleModel"+ 164 " or 1 band ComponentSampleModel. Sample model is "+ 165 sampleModel); 166 } 167 this.bandOffset = this.dataOffsets[0]; 168 verify(); 169 } 170 171 /** 172 * Returns a copy of the data offsets array. For each band the data offset 173 * is the index into the band's data array, of the first sample of the 174 * band. 175 */ 176 public int[] getDataOffsets() { 177 return dataOffsets.clone(); 178 } 179 180 /** 181 * Returns the data offset for the specified band. The data offset 182 * is the index into the data array in which the first sample 183 * of the first scanline is stored. 184 * @param band The band whose offset is returned. 185 */ 186 public int getDataOffset(int band) { 187 return dataOffsets[band]; 188 } 189 190 /** 191 * Returns the scanline stride -- the number of data array elements between 192 * a given sample and the same sample in the same column of the next row. 193 */ 194 public int getScanlineStride() { 195 return scanlineStride; 196 } 197 198 /** 199 * Returns pixel stride -- the number of data array elements between two 200 * samples for the same band on the same scanline. 201 */ 202 public int getPixelStride() { 203 return pixelStride; 204 } 205 206 /** 207 * Returns a reference to the data array. 208 */ 209 public short[] getDataStorage() { 210 return data; 211 } 212 213 /** 214 * Returns the data elements for all bands at the specified 215 * location. 216 * An ArrayIndexOutOfBounds exception will be thrown at runtime 217 * if the pixel coordinate is out of bounds. 218 * A ClassCastException will be thrown if the input object is non null 219 * and references anything other than an array of transferType. 220 * @param x The X coordinate of the pixel location. 221 * @param y The Y coordinate of the pixel location. 222 * @param obj An object reference to an array of type defined by 223 * getTransferType() and length getNumDataElements(). 224 * If null an array of appropriate type and size will be 225 * allocated. 226 * @return An object reference to an array of type defined by 227 * getTransferType() with the request pixel data. 228 */ 229 public Object getDataElements(int x, int y, Object obj) { 230 if ((x < this.minX) || (y < this.minY) || 231 (x >= this.maxX) || (y >= this.maxY)) { 232 throw new ArrayIndexOutOfBoundsException 233 ("Coordinate out of bounds!"); 234 } 235 short outData[]; 236 if (obj == null) { 237 outData = new short[numDataElements]; 238 } else { 239 outData = (short[])obj; 240 } 241 int off = (y-minY)*scanlineStride + 242 (x-minX)*pixelStride; 243 244 for (int band = 0; band < numDataElements; band++) { 245 outData[band] = data[dataOffsets[band] + off]; 246 } 247 248 return outData; 249 } 250 251 /** 252 * Returns an array of data elements from the specified rectangular 253 * region. 254 * An ArrayIndexOutOfBounds exception will be thrown at runtime 255 * if the pixel coordinates are out of bounds. 256 * A ClassCastException will be thrown if the input object is non null 257 * and references anything other than an array of transferType. 258 * <pre> 259 * short[] bandData = (short[])Raster.getDataElements(x, y, w, h, null); 260 * int numDataElements = Raster.getBands(); 261 * short[] pixel = new short[numDataElements]; 262 * // To find the data element at location (x2, y2) 263 * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements, 264 * pixel, 0, numDataElements); 265 * </pre> 266 * @param x The X coordinate of the upper left pixel location. 267 * @param y The Y coordinate of the upper left pixel location. 268 * @param w Width of the pixel rectangle. 269 * @param h Height of the pixel rectangle. 270 * @param obj An object reference to an array of type defined by 271 * getTransferType() and length w*h*getNumDataElements(). 272 * If null an array of appropriate type and size will be 273 * allocated. 274 * @return An object reference to an array of type defined by 275 * getTransferType() with the request pixel data. 276 */ 277 public Object getDataElements(int x, int y, int w, int h, Object obj) { 278 if ((x < this.minX) || (y < this.minY) || 279 (x + w > this.maxX) || (y + h > this.maxY)) { 280 throw new ArrayIndexOutOfBoundsException 281 ("Coordinate out of bounds!"); 282 } 283 short outData[]; 284 if (obj == null) { 285 outData = new short[w*h*numDataElements]; 286 } else { 287 outData = (short[])obj; 288 } 289 int yoff = (y-minY)*scanlineStride + 290 (x-minX)*pixelStride; 291 292 int xoff; 293 int off = 0; 294 int xstart; 295 int ystart; 296 297 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 298 xoff = yoff; 299 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 300 for (int c = 0; c < numDataElements; c++) { 301 outData[off++] = data[dataOffsets[c] + xoff]; 302 } 303 } 304 } 305 306 return outData; 307 } 308 309 /** 310 * Returns a short integer array of data elements from the 311 * specified rectangular region. 312 * An ArrayIndexOutOfBounds exception will be thrown at runtime 313 * if the pixel coordinates are out of bounds. 314 * <pre> 315 * short[] bandData = Raster.getShortData(x, y, w, h, null); 316 * // To find the data element at location (x2, y2) 317 * short dataElenent = bandData[((y2-y)*w + (x2-x))]; 318 * </pre> 319 * @param x The X coordinate of the upper left pixel location. 320 * @param y The Y coordinate of the upper left pixel location. 321 * @param w Width of the sample rectangle. 322 * @param h Height of the sample rectangle. 323 * @param band The band to return. 324 * @param outData If non-null, data elements for all bands 325 * at the specified location are returned in this array. 326 * @return Data array with data elements for all bands. 327 */ 328 public short[] getShortData(int x, int y, int w, int h, 329 int band, short[] outData) { 330 // Bounds check for 'band' will be performed automatically 331 if ((x < this.minX) || (y < this.minY) || 332 (x + w > this.maxX) || (y + h > this.maxY)) { 333 throw new ArrayIndexOutOfBoundsException 334 ("Coordinate out of bounds!"); 335 } 336 if (outData == null) { 337 outData = new short[numDataElements*w*h]; 338 } 339 int yoff = (y-minY)*scanlineStride + 340 (x-minX)*pixelStride+ dataOffsets[band]; 341 int xoff; 342 int off = 0; 343 int xstart; 344 int ystart; 345 346 if (pixelStride == 1) { 347 if (scanlineStride == w) { 348 System.arraycopy(data, yoff, outData, 0, w*h); 349 } 350 else { 351 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 352 System.arraycopy(data, yoff, outData, off, w); 353 off += w; 354 } 355 } 356 } 357 else { 358 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 359 xoff = yoff; 360 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 361 outData[off++] = data[xoff]; 362 } 363 } 364 } 365 366 return outData; 367 } 368 369 /** 370 * Returns a short integer array of data elements from the 371 * specified rectangular region. 372 * An ArrayIndexOutOfBounds exception will be thrown at runtime 373 * if the pixel coordinates are out of bounds. 374 * <pre> 375 * short[] bandData = Raster.getShortData(x, y, w, h, null); 376 * int numDataElements = Raster.getNumBands(); 377 * short[] pixel = new short[numDataElements]; 378 * // To find the data element at location (x2, y2) 379 * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements, 380 * pixel, 0, numDataElements); 381 * </pre> 382 * @param x The X coordinate of the upper left pixel location. 383 * @param y The Y coordinate of the upper left pixel location. 384 * @param w Width of the pixel rectangle. 385 * @param h Height of the pixel rectangle. 386 * @param outData If non-null, data elements for all bands 387 * at the specified location are returned in this array. 388 * @return Data array with data elements for all bands. 389 */ 390 public short[] getShortData(int x, int y, int w, int h, short[] outData) { 391 if ((x < this.minX) || (y < this.minY) || 392 (x + w > this.maxX) || (y + h > this.maxY)) { 393 throw new ArrayIndexOutOfBoundsException 394 ("Coordinate out of bounds!"); 395 } 396 if (outData == null) { 397 outData = new short[numDataElements*w*h]; 398 } 399 int yoff = (y-minY)*scanlineStride + 400 (x-minX)*pixelStride; 401 int xoff; 402 int off = 0; 403 int xstart; 404 int ystart; 405 406 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 407 xoff = yoff; 408 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 409 for (int c = 0; c < numDataElements; c++) { 410 outData[off++] = data[dataOffsets[c] + xoff]; 411 } 412 } 413 } 414 415 return outData; 416 } 417 418 /** 419 * Stores the data elements for all bands at the specified location. 420 * An ArrayIndexOutOfBounds exception will be thrown at runtime 421 * if the pixel coordinate is out of bounds. 422 * A ClassCastException will be thrown if the input object is non null 423 * and references anything other than an array of transferType. 424 * @param x The X coordinate of the pixel location. 425 * @param y The Y coordinate of the pixel location. 426 * @param obj An object reference to an array of type defined by 427 * getTransferType() and length getNumDataElements() 428 * containing the pixel data to place at x,y. 429 */ 430 public void setDataElements(int x, int y, Object obj) { 431 if ((x < this.minX) || (y < this.minY) || 432 (x >= this.maxX) || (y >= this.maxY)) { 433 throw new ArrayIndexOutOfBoundsException 434 ("Coordinate out of bounds!"); 435 } 436 short inData[] = (short[])obj; 437 int off = (y-minY)*scanlineStride + 438 (x-minX)*pixelStride; 439 for (int i = 0; i < numDataElements; i++) { 440 data[dataOffsets[i] + off] = inData[i]; 441 } 442 markDirty(); 443 } 444 445 /** 446 * Stores the Raster data at the specified location. 447 * An ArrayIndexOutOfBounds exception will be thrown at runtime 448 * if the pixel coordinates are out of bounds. 449 * @param x The X coordinate of the pixel location. 450 * @param y The Y coordinate of the pixel location. 451 * @param inRaster Raster of data to place at x,y location. 452 */ 453 public void setDataElements(int x, int y, Raster inRaster) { 454 int dstOffX = x + inRaster.getMinX(); 455 int dstOffY = y + inRaster.getMinY(); 456 int width = inRaster.getWidth(); 457 int height = inRaster.getHeight(); 458 if ((dstOffX < this.minX) || (dstOffY < this.minY) || 459 (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) { 460 throw new ArrayIndexOutOfBoundsException 461 ("Coordinate out of bounds!"); 462 } 463 464 setDataElements(dstOffX, dstOffY, width, height, inRaster); 465 } 466 467 /** 468 * Stores the Raster data at the specified location. 469 * @param dstX The absolute X coordinate of the destination pixel 470 * that will receive a copy of the upper-left pixel of the 471 * inRaster 472 * @param dstY The absolute Y coordinate of the destination pixel 473 * that will receive a copy of the upper-left pixel of the 474 * inRaster 475 * @param width The number of pixels to store horizontally 476 * @param height The number of pixels to store vertically 477 * @param inRaster Raster of data to place at x,y location. 478 */ 479 private void setDataElements(int dstX, int dstY, 480 int width, int height, 481 Raster inRaster) { 482 // Assume bounds checking has been performed previously 483 if (width <= 0 || height <= 0) { 484 return; 485 } 486 487 // Write inRaster (minX, minY) to (dstX, dstY) 488 489 int srcOffX = inRaster.getMinX(); 490 int srcOffY = inRaster.getMinY(); 491 Object tdata = null; 492 493 // REMIND: Do something faster! 494 // if (inRaster instanceof ShortInterleavedRaster) { 495 // } 496 497 for (int startY=0; startY < height; startY++) { 498 // Grab one scanline at a time 499 tdata = inRaster.getDataElements(srcOffX, srcOffY+startY, 500 width, 1, tdata); 501 setDataElements(dstX, dstY + startY, width, 1, tdata); 502 } 503 } 504 505 /** 506 * Stores an array of data elements into the specified rectangular 507 * region. 508 * An ArrayIndexOutOfBounds exception will be thrown at runtime 509 * if the pixel coordinates are out of bounds. 510 * A ClassCastException will be thrown if the input object is non null 511 * and references anything other than an array of transferType. 512 * The data elements in the 513 * data array are assumed to be packed. That is, a data element 514 * for the nth band at location (x2, y2) would be found at: 515 * <pre> 516 * inData[((y2-y)*w + (x2-x))*numDataElements + n] 517 * </pre> 518 * @param x The X coordinate of the upper left pixel location. 519 * @param y The Y coordinate of the upper left pixel location. 520 * @param w Width of the pixel rectangle. 521 * @param h Height of the pixel rectangle. 522 * @param obj An object reference to an array of type defined by 523 * getTransferType() and length w*h*getNumDataElements() 524 * containing the pixel data to place between x,y and 525 * x+h, y+h. 526 */ 527 public void setDataElements(int x, int y, int w, int h, Object obj) { 528 if ((x < this.minX) || (y < this.minY) || 529 (x + w > this.maxX) || (y + h > this.maxY)) { 530 throw new ArrayIndexOutOfBoundsException 531 ("Coordinate out of bounds!"); 532 } 533 short inData[] = (short[])obj; 534 int yoff = (y-minY)*scanlineStride + 535 (x-minX)*pixelStride; 536 int xoff; 537 int off = 0; 538 int xstart; 539 int ystart; 540 541 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 542 xoff = yoff; 543 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 544 for (int c = 0; c < numDataElements; c++) { 545 data[dataOffsets[c] + xoff] = inData[off++]; 546 } 547 } 548 } 549 550 markDirty(); 551 } 552 553 /** 554 * Stores a short integer array of data elements into the 555 * specified rectangular region. 556 * An ArrayIndexOutOfBounds exception will be thrown at runtime 557 * if the pixel coordinates are out of bounds. 558 * The data elements in the 559 * data array are assumed to be packed. That is, a data element 560 * at location (x2, y2) would be found at: 561 * <pre> 562 * inData[((y2-y)*w + (x2-x))] 563 * </pre> 564 * @param x The X coordinate of the upper left pixel location. 565 * @param y The Y coordinate of the upper left pixel location. 566 * @param w Width of the pixel rectangle. 567 * @param h Height of the pixel rectangle. 568 * @param band The band to set. 569 * @param inData The data elements to be stored. 570 */ 571 public void putShortData(int x, int y, int w, int h, 572 int band, short[] inData) { 573 // Bounds check for 'band' will be performed automatically 574 if ((x < this.minX) || (y < this.minY) || 575 (x + w > this.maxX) || (y + h > this.maxY)) { 576 throw new ArrayIndexOutOfBoundsException 577 ("Coordinate out of bounds!"); 578 } 579 int yoff = (y-minY)*scanlineStride + 580 (x-minX)*pixelStride + dataOffsets[band]; 581 int xoff; 582 int off = 0; 583 int xstart; 584 int ystart; 585 586 if (pixelStride == 1) { 587 if (scanlineStride == w) { 588 System.arraycopy(inData, 0, data, yoff, w*h); 589 } 590 else { 591 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 592 System.arraycopy(inData, off, data, yoff, w); 593 off += w; 594 } 595 } 596 } 597 else { 598 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 599 xoff = yoff; 600 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 601 data[xoff] = inData[off++]; 602 } 603 } 604 } 605 606 markDirty(); 607 } 608 609 /** 610 * Stores a short integer array of data elements into the 611 * specified rectangular region. 612 * An ArrayIndexOutOfBounds exception will be thrown at runtime 613 * if the pixel coordinates are out of bounds. 614 * The data elements in the 615 * data array are assumed to be packed. That is, a data element 616 * for the nth band at location (x2, y2) would be found at: 617 * <pre> 618 * inData[((y2-y)*w + (x2-x))*numDataElements + n] 619 * </pre> 620 * @param x The X coordinate of the upper left pixel location. 621 * @param y The Y coordinate of the upper left pixel location. 622 * @param w Width of the pixel rectangle. 623 * @param h Height of the pixel rectangle. 624 * @param inData The data elements to be stored. 625 */ 626 public void putShortData(int x, int y, int w, int h, short[] inData) { 627 if ((x < this.minX) || (y < this.minY) || 628 (x + w > this.maxX) || (y + h > this.maxY)) { 629 throw new ArrayIndexOutOfBoundsException 630 ("Coordinate out of bounds!"); 631 } 632 int yoff = (y-minY)*scanlineStride + 633 (x-minX)*pixelStride; 634 int xoff; 635 int off = 0; 636 int xstart; 637 int ystart; 638 639 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 640 xoff = yoff; 641 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 642 for (int c = 0; c < numDataElements; c++) { 643 data[dataOffsets[c] + xoff] = inData[off++]; 644 } 645 } 646 } 647 648 markDirty(); 649 } 650 651 /** 652 * Creates a subraster given a region of the raster. The x and y 653 * coordinates specify the horizontal and vertical offsets 654 * from the upper-left corner of this raster to the upper-left corner 655 * of the subraster. A subset of the bands of the parent Raster may 656 * be specified. If this is null, then all the bands are present in the 657 * subRaster. A translation to the subRaster may also be specified. 658 * Note that the subraster will reference the same 659 * band objects as the parent raster, but using different offsets. 660 * @param x X offset. 661 * @param y Y offset. 662 * @param width Width (in pixels) of the subraster. 663 * @param height Height (in pixels) of the subraster. 664 * @param x0 Translated X origin of the subraster. 665 * @param y0 Translated Y origin of the subraster. 666 * @param bandList Array of band indices. 667 * @exception RasterFormatException 668 * if the specified bounding box is outside of the parent raster. 669 */ 670 public Raster createChild (int x, int y, 671 int width, int height, 672 int x0, int y0, int[] bandList) { 673 WritableRaster newRaster = createWritableChild(x, y, 674 width, height, 675 x0, y0, 676 bandList); 677 return (Raster) newRaster; 678 } 679 680 /** 681 * Creates a Writable subRaster given a region of the Raster. The x and y 682 * coordinates specify the horizontal and vertical offsets 683 * from the upper-left corner of this Raster to the upper-left corner 684 * of the subRaster. A subset of the bands of the parent Raster may 685 * be specified. If this is null, then all the bands are present in the 686 * subRaster. A translation to the subRaster may also be specified. 687 * Note that the subRaster will reference the same 688 * DataBuffers as the parent Raster, but using different offsets. 689 * @param x X offset. 690 * @param y Y offset. 691 * @param width Width (in pixels) of the subraster. 692 * @param height Height (in pixels) of the subraster. 693 * @param x0 Translated X origin of the subraster. 694 * @param y0 Translated Y origin of the subraster. 695 * @param bandList Array of band indices. 696 * @exception RasterFormatException 697 * if the specified bounding box is outside of the parent Raster. 698 */ 699 public WritableRaster createWritableChild(int x, int y, 700 int width, int height, 701 int x0, int y0, 702 int[] bandList) { 703 if (x < this.minX) { 704 throw new RasterFormatException("x lies outside the raster"); 705 } 706 if (y < this.minY) { 707 throw new RasterFormatException("y lies outside the raster"); 708 } 709 if ((x+width < x) || (x+width > this.minX + this.width)) { 710 throw new RasterFormatException("(x + width) is outside of Raster"); 711 } 712 if ((y+height < y) || (y+height > this.minY + this.height)) { 713 throw new RasterFormatException("(y + height) is outside of Raster"); 714 } 715 716 SampleModel sm; 717 718 if (bandList != null) 719 sm = sampleModel.createSubsetSampleModel(bandList); 720 else 721 sm = sampleModel; 722 723 int deltaX = x0 - x; 724 int deltaY = y0 - y; 725 726 return new ShortInterleavedRaster(sm, 727 (DataBufferUShort)dataBuffer, 728 new Rectangle(x0, y0, width, height), 729 new Point(sampleModelTranslateX+deltaX, 730 sampleModelTranslateY+deltaY), 731 this); 732 } 733 734 /** 735 * Creates a Raster with the same layout but using a different 736 * width and height, and with new zeroed data arrays. 737 */ 738 public WritableRaster createCompatibleWritableRaster(int w, int h) { 739 if (w <= 0 || h <=0) { 740 throw new RasterFormatException("negative "+ 741 ((w <= 0) ? "width" : "height")); 742 } 743 744 SampleModel sm = sampleModel.createCompatibleSampleModel(w, h); 745 746 return new ShortInterleavedRaster(sm, new Point(0, 0)); 747 } 748 749 /** 750 * Creates a Raster with the same layout and the same 751 * width and height, and with new zeroed data arrays. If 752 * the Raster is a subRaster, this will call 753 * createCompatibleRaster(width, height). 754 */ 755 public WritableRaster createCompatibleWritableRaster() { 756 return createCompatibleWritableRaster(width,height); 757 } 758 759 public String toString() { 760 return new String ("ShortInterleavedRaster: width = "+width 761 +" height = " + height 762 +" #numDataElements "+numDataElements); 763 // +" xOff = "+xOffset+" yOff = "+yOffset); 764 } 765 766 }