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