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