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