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.DataBufferByte; 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 40 * 8-bit data elements stored in close proximity to each other in a 41 * single byte array. 42 * <p> 43 * The bit precision per data element is that of the data type (that 44 * is, the bit precision for this Raster is 8). There is only one 45 * pixel stride and one scanline stride for all bands. This type of 46 * Raster can be used with a ComponentColorModel if there are multiple 47 * bands, or an IndexColorModel if there is only one band. 48 * 49 */ 50 public class ByteInterleavedRaster extends ByteComponentRaster { 51 52 /** True if the data offsets range from 0 to (pixelStride - 1) in order. */ 53 boolean inOrder; 54 55 /** 56 * The DataBuffer offset, minus sampleModelTranslateX*pixelStride, 57 * minus sampleModelTranslateY*scanlineStride, used to calculate 58 * pixel offsets. 59 */ 60 int dbOffset; 61 int dbOffsetPacked; 62 63 /** True if a SinglePixelPackedSampleModel is being used. */ 64 boolean packed = false; 65 66 /** If packed == true, the SampleModel's bit masks. */ 67 int[] bitMasks; 68 69 /** If packed == true, the SampleModel's bit offsets. */ 70 int[] bitOffsets; 71 72 /** A cached copy of minX + width for use in bounds checks. */ 73 private int maxX; 74 75 /** A cached copy of minY + height for use in bounds checks. */ 76 private int maxY; 77 78 /** 79 * Constructs a ByteInterleavedRaster with the given SampleModel. 80 * The Raster's upper left corner is origin and it is the same 81 * size as the SampleModel. A DataBuffer large enough to describe the 82 * Raster is automatically created. SampleModel must be of type 83 * SinglePixelPackedSampleModel or InterleavedSampleModel. 84 * @param sampleModel The SampleModel that specifies the layout. 85 * @param origin The Point that specified the origin. 86 */ 87 public ByteInterleavedRaster(SampleModel sampleModel, Point origin) { 88 this(sampleModel, 89 (DataBufferByte) sampleModel.createDataBuffer(), 90 new Rectangle(origin.x, 91 origin.y, 92 sampleModel.getWidth(), 93 sampleModel.getHeight()), 94 origin, 95 null); 96 } 97 98 /** 99 * Constructs a ByteInterleavedRaster with the given SampleModel 100 * and DataBuffer. The Raster's upper left corner is origin and 101 * it is the same size as the SampleModel. The DataBuffer is not 102 * initialized and must be a DataBufferByte compatible with SampleModel. 103 * SampleModel must be of type SinglePixelPackedSampleModel 104 * or InterleavedSampleModel. 105 * @param sampleModel The SampleModel that specifies the layout. 106 * @param dataBuffer The DataBufferByte that contains the image data. 107 * @param origin The Point that specifies the origin. 108 */ 109 public ByteInterleavedRaster(SampleModel sampleModel, 110 DataBufferByte dataBuffer, 111 Point origin) 112 { 113 this(sampleModel, 114 dataBuffer, 115 new Rectangle(origin.x, 116 origin.y, 117 sampleModel.getWidth(), 118 sampleModel.getHeight()), 119 origin, 120 null); 121 } 122 123 /*** Analyzes a ComponentSampleModel to determine if it can function 124 * as a PixelInterleavedSampleModel. In order to do so, it must use 125 * only bank 0 of its DataBuffer, and the data offsets must span a range 126 * of less than pixelStride. 127 * 128 * <p> These properties are trivially true for a 1-banded SampleModel. 129 */ 130 private boolean isInterleaved(ComponentSampleModel sm) { 131 // Analyze ComponentSampleModel to determine if it has the 132 // properties of a PixelInterleavedSampleModel 133 134 int numBands = sampleModel.getNumBands(); 135 if (numBands == 1) { 136 return true; 137 } 138 139 // Determine banks used 140 int[] bankIndices = sm.getBankIndices(); 141 for (int i = 0; i < numBands; i++) { 142 if (bankIndices[i] != 0) { 143 return false; 144 } 145 } 146 147 // Determine range of band offsets 148 int[] bandOffsets = sm.getBandOffsets(); 149 int minOffset = bandOffsets[0]; 150 int maxOffset = minOffset; 151 for (int i = 1; i < numBands; i++) { 152 int offset = bandOffsets[i]; 153 if (offset < minOffset) { 154 minOffset = offset; 155 } 156 if (offset > maxOffset) { 157 maxOffset = offset; 158 } 159 } 160 if (maxOffset - minOffset >= sm.getPixelStride()) { 161 return false; 162 } 163 164 return true; 165 } 166 167 /** 168 * Constructs a ByteInterleavedRaster with the given SampleModel, 169 * DataBuffer, and parent. DataBuffer must be a DataBufferByte and 170 * SampleModel must be of type SinglePixelPackedSampleModel 171 * or InterleavedSampleModel. 172 * When translated into the base Raster's 173 * coordinate system, aRegion must be contained by the base Raster. 174 * Origin is the coordinate in the new Raster's coordinate system of 175 * the origin of the base Raster. (The base Raster is the Raster's 176 * ancestor which has no parent.) 177 * 178 * Note that this constructor should generally be called by other 179 * constructors or create methods, it should not be used directly. 180 * @param sampleModel The SampleModel that specifies the layout. 181 * @param dataBuffer The DataBufferByte that contains the image data. 182 * @param aRegion The Rectangle that specifies the image area. 183 * @param origin The Point that specifies the origin. 184 * @param parent The parent (if any) of this raster. 185 */ 186 public ByteInterleavedRaster(SampleModel sampleModel, 187 DataBufferByte dataBuffer, 188 Rectangle aRegion, 189 Point origin, 190 ByteInterleavedRaster parent) 191 { 192 super(sampleModel, dataBuffer, aRegion, origin, parent); 193 this.maxX = minX + width; 194 this.maxY = minY + height; 195 196 this.data = stealData(dataBuffer, 0); 197 198 int xOffset = aRegion.x - origin.x; 199 int yOffset = aRegion.y - origin.y; 200 if (sampleModel instanceof PixelInterleavedSampleModel || 201 (sampleModel instanceof ComponentSampleModel && 202 isInterleaved((ComponentSampleModel)sampleModel))) { 203 ComponentSampleModel csm = (ComponentSampleModel)sampleModel; 204 this.scanlineStride = csm.getScanlineStride(); 205 this.pixelStride = csm.getPixelStride(); 206 this.dataOffsets = csm.getBandOffsets(); 207 for (int i = 0; i < getNumDataElements(); i++) { 208 dataOffsets[i] += xOffset*pixelStride+yOffset*scanlineStride; 209 } 210 } else if (sampleModel instanceof SinglePixelPackedSampleModel) { 211 SinglePixelPackedSampleModel sppsm = 212 (SinglePixelPackedSampleModel)sampleModel; 213 this.packed = true; 214 this.bitMasks = sppsm.getBitMasks(); 215 this.bitOffsets = sppsm.getBitOffsets(); 216 this.scanlineStride = sppsm.getScanlineStride(); 217 this.pixelStride = 1; 218 this.dataOffsets = new int[1]; 219 this.dataOffsets[0] = dataBuffer.getOffset(); 220 dataOffsets[0] += xOffset*pixelStride+yOffset*scanlineStride; 221 } else { 222 throw new RasterFormatException("ByteInterleavedRasters must " + 223 "have PixelInterleavedSampleModel, SinglePixelPackedSampleModel"+ 224 " or interleaved ComponentSampleModel. Sample model is " + 225 sampleModel); 226 } 227 this.bandOffset = this.dataOffsets[0]; 228 229 this.dbOffsetPacked = dataBuffer.getOffset() - 230 sampleModelTranslateY*scanlineStride - 231 sampleModelTranslateX*pixelStride; 232 this.dbOffset = dbOffsetPacked - 233 (xOffset*pixelStride+yOffset*scanlineStride); 234 235 // Set inOrder to true if the data elements are in order and 236 // have no gaps between them 237 this.inOrder = false; 238 if (numDataElements == pixelStride) { 239 inOrder = true; 240 for (int i = 1; i < numDataElements; i++) { 241 if (dataOffsets[i] - dataOffsets[0] != i) { 242 inOrder = false; 243 break; 244 } 245 } 246 } 247 248 verify(); 249 } 250 251 /** 252 * Returns a copy of the data offsets array. For each band the data offset 253 * is the index into the band's data array, of the first sample of the 254 * band. 255 */ 256 public int[] getDataOffsets() { 257 return dataOffsets.clone(); 258 } 259 260 /** 261 * Returns the data offset for the specified band. The data offset 262 * is the index into the data array 263 * in which the first sample of the first scanline is stored. 264 * @param band The band whose offset is returned. 265 */ 266 public int getDataOffset(int band) { 267 return dataOffsets[band]; 268 } 269 270 /** 271 * Returns the scanline stride -- the number of data array elements between 272 * a given sample and the sample in the same column of the next row in the 273 * same band. 274 */ 275 public int getScanlineStride() { 276 return scanlineStride; 277 } 278 279 /** 280 * Returns pixel stride -- the number of data array elements between two 281 * samples for the same band on the same scanline. 282 */ 283 public int getPixelStride() { 284 return pixelStride; 285 } 286 287 /** 288 * Returns a reference to the data array. 289 */ 290 public byte[] getDataStorage() { 291 return data; 292 } 293 294 /** 295 * Returns the data elements for all bands at the specified 296 * location. 297 * An ArrayIndexOutOfBounds exception will be thrown at runtime 298 * if the pixel coordinate is out of bounds. 299 * A ClassCastException will be thrown if the input object is non null 300 * and references anything other than an array of transferType. 301 * @param x The X coordinate of the pixel location. 302 * @param y The Y coordinate of the pixel location. 303 * @param obj An object reference to an array of type defined by 304 * getTransferType() and length getNumDataElements(). 305 * If null an array of appropriate type and size will be 306 * allocated. 307 * @return An object reference to an array of type defined by 308 * getTransferType() with the request pixel data. 309 */ 310 public Object getDataElements(int x, int y, Object obj) { 311 if ((x < this.minX) || (y < this.minY) || 312 (x >= this.maxX) || (y >= this.maxY)) { 313 throw new ArrayIndexOutOfBoundsException 314 ("Coordinate out of bounds!"); 315 } 316 byte[] outData; 317 if (obj == null) { 318 outData = new byte[numDataElements]; 319 } else { 320 outData = (byte[])obj; 321 } 322 int off = (y-minY)*scanlineStride + 323 (x-minX)*pixelStride; 324 325 for (int band = 0; band < numDataElements; band++) { 326 outData[band] = data[dataOffsets[band] + off]; 327 } 328 329 return outData; 330 } 331 332 /** 333 * Returns an array of data elements from the specified rectangular 334 * region. 335 * An ArrayIndexOutOfBounds exception will be thrown at runtime 336 * if the pixel coordinates are out of bounds. 337 * A ClassCastException will be thrown if the input object is non null 338 * and references anything other than an array of transferType. 339 * <pre> 340 * byte[] bandData = (byte[])raster.getDataElements(x, y, w, h, null); 341 * int numDataElements = raster.getNumDataElements(); 342 * byte[] pixel = new byte[numDataElements]; 343 * // To find a data element at location (x2, y2) 344 * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements, 345 * pixel, 0, numDataElements); 346 * </pre> 347 * @param x The X coordinate of the upper left pixel location. 348 * @param y The Y coordinate of the upper left pixel location. 349 * @param w Width of the pixel rectangle. 350 * @param h Height of the pixel rectangle. 351 * @param obj An object reference to an array of type defined by 352 * getTransferType() and length w*h*getNumDataElements(). 353 * If null an array of appropriate type and size will be 354 * allocated. 355 * @return An object reference to an array of type defined by 356 * getTransferType() with the request pixel data. 357 */ 358 public Object getDataElements(int x, int y, int w, int h, Object obj) { 359 return getByteData(x, y, w, h, (byte[])obj); 360 } 361 362 /** 363 * Returns a byte array of data elements from the specified rectangular 364 * region for the specified band. 365 * An ArrayIndexOutOfBounds exception will be thrown at runtime 366 * if the pixel coordinates are out of bounds. 367 * <pre> 368 * byte[] bandData = raster.getByteData(x, y, w, h, null); 369 * // To find the data element at location (x2, y2) 370 * byte bandElement = bandData[((y2-y)*w + (x2-x))]; 371 * </pre> 372 * @param x The X coordinate of the upper left pixel location. 373 * @param y The Y coordinate of the upper left pixel location. 374 * @param w Width of the pixel rectangle. 375 * @param h Height of the pixel rectangle. 376 * @param band The band to return. 377 * @param outData If non-null, data elements for all bands 378 * at the specified location are returned in this array. 379 * @return Data array with data elements for all bands. 380 */ 381 public byte[] getByteData(int x, int y, int w, int h, 382 int band, byte[] outData) { 383 // Bounds check for 'band' will be performed automatically 384 if ((x < this.minX) || (y < this.minY) || 385 (x + w > this.maxX) || (y + h > this.maxY)) { 386 throw new ArrayIndexOutOfBoundsException 387 ("Coordinate out of bounds!"); 388 } 389 if (outData == null) { 390 outData = new byte[w*h]; 391 } 392 int yoff = (y-minY)*scanlineStride + 393 (x-minX)*pixelStride + dataOffsets[band]; 394 int xoff; 395 int off = 0; 396 int xstart; 397 int ystart; 398 399 if (pixelStride == 1) { 400 if (scanlineStride == w) { 401 System.arraycopy(data, yoff, outData, 0, w*h); 402 } else { 403 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 404 System.arraycopy(data, yoff, outData, off, w); 405 off += w; 406 } 407 } 408 } else { 409 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 410 xoff = yoff; 411 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 412 outData[off++] = data[xoff]; 413 } 414 } 415 } 416 417 return outData; 418 } 419 420 /** 421 * Returns a byte array of data elements from the specified rectangular 422 * region. 423 * An ArrayIndexOutOfBounds exception will be thrown at runtime 424 * if the pixel coordinates are out of bounds. 425 * <pre> 426 * byte[] bandData = raster.getByteData(x, y, w, h, null); 427 * int numDataElements = raster.getnumDataElements(); 428 * byte[] pixel = new byte[numDataElements]; 429 * // To find a data element at location (x2, y2) 430 * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements, 431 * pixel, 0, numDataElements); 432 * </pre> 433 * @param x The X coordinate of the upper left pixel location. 434 * @param y The Y coordinate of the upper left pixel location. 435 * @param w Width of the pixel rectangle. 436 * @param h Height of the pixel rectangle. 437 * @param outData If non-null, data elements for all bands 438 * at the specified location are returned in this array. 439 * @return Data array with data elements for all bands. 440 */ 441 public byte[] getByteData(int x, int y, int w, int h, byte[] outData) { 442 if ((x < this.minX) || (y < this.minY) || 443 (x + w > this.maxX) || (y + h > this.maxY)) { 444 throw new ArrayIndexOutOfBoundsException 445 ("Coordinate out of bounds!"); 446 } 447 if (outData == null) { 448 outData = new byte[numDataElements*w*h]; 449 } 450 int yoff = (y-minY)*scanlineStride + 451 (x-minX)*pixelStride; 452 int xoff; 453 int off = 0; 454 int xstart; 455 int ystart; 456 457 if (inOrder) { 458 yoff += dataOffsets[0]; 459 int rowBytes = w*pixelStride; 460 if (scanlineStride == rowBytes) { 461 System.arraycopy(data, yoff, outData, off, rowBytes*h); 462 } else { 463 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 464 System.arraycopy(data, yoff, outData, off, rowBytes); 465 off += rowBytes; 466 } 467 } 468 } else if (numDataElements == 1) { 469 yoff += dataOffsets[0]; 470 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 471 xoff = yoff; 472 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 473 outData[off++] = data[xoff]; 474 } 475 } 476 } else if (numDataElements == 2) { 477 yoff += dataOffsets[0]; 478 int d1 = dataOffsets[1] - dataOffsets[0]; 479 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 480 xoff = yoff; 481 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 482 outData[off++] = data[xoff]; 483 outData[off++] = data[xoff + d1]; 484 } 485 } 486 } else if (numDataElements == 3) { 487 yoff += dataOffsets[0]; 488 int d1 = dataOffsets[1] - dataOffsets[0]; 489 int d2 = dataOffsets[2] - dataOffsets[0]; 490 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 491 xoff = yoff; 492 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 493 outData[off++] = data[xoff]; 494 outData[off++] = data[xoff + d1]; 495 outData[off++] = data[xoff + d2]; 496 } 497 } 498 } else if (numDataElements == 4) { 499 yoff += dataOffsets[0]; 500 int d1 = dataOffsets[1] - dataOffsets[0]; 501 int d2 = dataOffsets[2] - dataOffsets[0]; 502 int d3 = dataOffsets[3] - dataOffsets[0]; 503 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 504 xoff = yoff; 505 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 506 outData[off++] = data[xoff]; 507 outData[off++] = data[xoff + d1]; 508 outData[off++] = data[xoff + d2]; 509 outData[off++] = data[xoff + d3]; 510 } 511 } 512 } else { 513 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 514 xoff = yoff; 515 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 516 for (int c = 0; c < numDataElements; c++) { 517 outData[off++] = data[dataOffsets[c] + xoff]; 518 } 519 } 520 } 521 } 522 523 return outData; 524 } 525 526 /** 527 * Stores the data elements for all bands at the specified location. 528 * An ArrayIndexOutOfBounds exception will be thrown at runtime 529 * if the pixel coordinate is out of bounds. 530 * A ClassCastException will be thrown if the input object is non null 531 * and references anything other than an array of transferType. 532 * @param x The X coordinate of the pixel location. 533 * @param y The Y coordinate of the pixel location. 534 * @param obj An object reference to an array of type defined by 535 * getTransferType() and length getNumDataElements() 536 * containing the pixel data to place at x,y. 537 */ 538 public void setDataElements(int x, int y, Object obj) { 539 if ((x < this.minX) || (y < this.minY) || 540 (x >= this.maxX) || (y >= this.maxY)) { 541 throw new ArrayIndexOutOfBoundsException 542 ("Coordinate out of bounds!"); 543 } 544 byte[] inData = (byte[])obj; 545 int off = (y-minY)*scanlineStride + 546 (x-minX)*pixelStride; 547 548 for (int i = 0; i < numDataElements; i++) { 549 data[dataOffsets[i] + off] = inData[i]; 550 } 551 552 markDirty(); 553 } 554 555 /** 556 * Stores the Raster data at the specified location. 557 * An ArrayIndexOutOfBounds exception will be thrown at runtime 558 * if the pixel coordinates are out of bounds. 559 * @param x The X coordinate of the pixel location. 560 * @param y The Y coordinate of the pixel location. 561 * @param inRaster Raster of data to place at x,y location. 562 */ 563 public void setDataElements(int x, int y, Raster inRaster) { 564 int srcOffX = inRaster.getMinX(); 565 int srcOffY = inRaster.getMinY(); 566 int dstOffX = x + srcOffX; 567 int dstOffY = y + srcOffY; 568 int width = inRaster.getWidth(); 569 int height = inRaster.getHeight(); 570 if ((dstOffX < this.minX) || (dstOffY < this.minY) || 571 (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) { 572 throw new ArrayIndexOutOfBoundsException 573 ("Coordinate out of bounds!"); 574 } 575 576 setDataElements(dstOffX, dstOffY, srcOffX, srcOffY, 577 width, height, inRaster); 578 } 579 580 /** 581 * Stores the Raster data at the specified location. 582 * @param dstX The absolute X coordinate of the destination pixel 583 * that will receive a copy of the upper-left pixel of the 584 * inRaster 585 * @param dstY The absolute Y coordinate of the destination pixel 586 * that will receive a copy of the upper-left pixel of the 587 * inRaster 588 * @param srcX The absolute X coordinate of the upper-left source 589 * pixel that will be copied into this Raster 590 * @param srcY The absolute Y coordinate of the upper-left source 591 * pixel that will be copied into this Raster 592 * @param width The number of pixels to store horizontally 593 * @param height The number of pixels to store vertically 594 * @param inRaster Raster of data to place at x,y location. 595 */ 596 private void setDataElements(int dstX, int dstY, 597 int srcX, int srcY, 598 int width, int height, 599 Raster inRaster) { 600 // Assume bounds checking has been performed previously 601 if (width <= 0 || height <= 0) { 602 return; 603 } 604 605 // Write inRaster (minX, minY) to (dstX, dstY) 606 607 int srcOffX = inRaster.getMinX(); 608 int srcOffY = inRaster.getMinY(); 609 Object tdata = null; 610 611 if (inRaster instanceof ByteInterleavedRaster) { 612 ByteInterleavedRaster bct = (ByteInterleavedRaster) inRaster; 613 byte[] bdata = bct.getDataStorage(); 614 // copy whole scanlines 615 if (inOrder && bct.inOrder && pixelStride == bct.pixelStride) { 616 int toff = bct.getDataOffset(0); 617 int tss = bct.getScanlineStride(); 618 int tps = bct.getPixelStride(); 619 620 int srcOffset = toff + 621 (srcY - srcOffY) * tss + 622 (srcX - srcOffX) * tps; 623 int dstOffset = dataOffsets[0] + 624 (dstY - minY) * scanlineStride + 625 (dstX - minX) * pixelStride; 626 627 int nbytes = width*pixelStride; 628 for (int tmpY=0; tmpY < height; tmpY++) { 629 System.arraycopy(bdata, srcOffset, 630 data, dstOffset, nbytes); 631 srcOffset += tss; 632 dstOffset += scanlineStride; 633 } 634 markDirty(); 635 return; 636 } 637 } 638 639 for (int startY=0; startY < height; startY++) { 640 // Grab one scanline at a time 641 tdata = inRaster.getDataElements(srcOffX, srcOffY+startY, 642 width, 1, tdata); 643 setDataElements(dstX, dstY + startY, width, 1, tdata); 644 } 645 } 646 647 /** 648 * Stores an array of data elements into the specified rectangular 649 * region. 650 * An ArrayIndexOutOfBounds exception will be thrown at runtime 651 * if the pixel coordinates are out of bounds. 652 * A ClassCastException will be thrown if the input object is non null 653 * and references anything other than an array of transferType. 654 * The data elements in the 655 * data array are assumed to be packed. That is, a data element 656 * for the nth band at location (x2, y2) would be found at: 657 * <pre> 658 * inData[((y2-y)*w + (x2-x))*numDataElements + n] 659 * </pre> 660 * @param x The X coordinate of the upper left pixel location. 661 * @param y The Y coordinate of the upper left pixel location. 662 * @param w Width of the pixel rectangle. 663 * @param h Height of the pixel rectangle. 664 * @param obj An object reference to an array of type defined by 665 * getTransferType() and length w*h*getNumDataElements() 666 * containing the pixel data to place between x,y and 667 * x+h, y+h. 668 */ 669 public void setDataElements(int x, int y, int w, int h, Object obj) { 670 putByteData(x, y, w, h, (byte[])obj); 671 } 672 673 /** 674 * Stores a byte array of data elements into the specified rectangular 675 * region for the specified band. 676 * An ArrayIndexOutOfBounds exception will be thrown at runtime 677 * if the pixel coordinates are out of bounds. 678 * The data elements in the 679 * data array are assumed to be packed. That is, a data element 680 * at location (x2, y2) would be found at: 681 * <pre> 682 * inData[((y2-y)*w + (x2-x)) + n] 683 * </pre> 684 * @param x The X coordinate of the upper left pixel location. 685 * @param y The Y coordinate of the upper left pixel location. 686 * @param w Width of the pixel rectangle. 687 * @param h Height of the pixel rectangle. 688 * @param band The band to set. 689 * @param inData The data elements to be stored. 690 */ 691 public void putByteData(int x, int y, int w, int h, 692 int band, byte[] inData) { 693 // Bounds check for 'band' will be performed automatically 694 if ((x < this.minX) || (y < this.minY) || 695 (x + w > this.maxX) || (y + h > this.maxY)) { 696 throw new ArrayIndexOutOfBoundsException 697 ("Coordinate out of bounds!"); 698 } 699 int yoff = (y-minY)*scanlineStride + 700 (x-minX)*pixelStride + dataOffsets[band]; 701 int xoff; 702 int off = 0; 703 int xstart; 704 int ystart; 705 706 if (pixelStride == 1) { 707 if (scanlineStride == w) { 708 System.arraycopy(inData, 0, data, yoff, w*h); 709 } 710 else { 711 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 712 System.arraycopy(inData, off, data, yoff, w); 713 off += w; 714 } 715 } 716 } 717 else { 718 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 719 xoff = yoff; 720 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 721 data[xoff] = inData[off++]; 722 } 723 } 724 } 725 726 markDirty(); 727 } 728 729 /** 730 * Stores a byte array of data elements into the specified rectangular 731 * region. 732 * An ArrayIndexOutOfBounds exception will be thrown at runtime 733 * if the pixel coordinates are out of bounds. 734 * The data elements in the 735 * data array are assumed to be packed. That is, a data element 736 * for the nth band at location (x2, y2) would be found at: 737 * <pre> 738 * inData[((y2-y)*w + (x2-x))*numDataElements + n] 739 * </pre> 740 * @param x The X coordinate of the upper left pixel location. 741 * @param y The Y coordinate of the upper left pixel location. 742 * @param w Width of the pixel rectangle. 743 * @param h Height of the pixel rectangle. 744 * @param inData The data elements to be stored. 745 */ 746 public void putByteData(int x, int y, int w, int h, byte[] inData) { 747 if ((x < this.minX) || (y < this.minY) || 748 (x + w > this.maxX) || (y + h > this.maxY)) { 749 throw new ArrayIndexOutOfBoundsException 750 ("Coordinate out of bounds!"); 751 } 752 int yoff = (y-minY)*scanlineStride + 753 (x-minX)*pixelStride; 754 755 int xoff; 756 int off = 0; 757 int xstart; 758 int ystart; 759 760 if (inOrder) { 761 yoff += dataOffsets[0]; 762 int rowBytes = w*pixelStride; 763 if (rowBytes == scanlineStride) { 764 System.arraycopy(inData, 0, data, yoff, rowBytes*h); 765 } else { 766 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 767 System.arraycopy(inData, off, data, yoff, rowBytes); 768 off += rowBytes; 769 } 770 } 771 } else if (numDataElements == 1) { 772 yoff += dataOffsets[0]; 773 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 774 xoff = yoff; 775 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 776 data[xoff] = inData[off++]; 777 } 778 } 779 } else if (numDataElements == 2) { 780 yoff += dataOffsets[0]; 781 int d1 = dataOffsets[1] - dataOffsets[0]; 782 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 783 xoff = yoff; 784 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 785 data[xoff] = inData[off++]; 786 data[xoff + d1] = inData[off++]; 787 } 788 } 789 } else if (numDataElements == 3) { 790 yoff += dataOffsets[0]; 791 int d1 = dataOffsets[1] - dataOffsets[0]; 792 int d2 = dataOffsets[2] - dataOffsets[0]; 793 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 794 xoff = yoff; 795 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 796 data[xoff] = inData[off++]; 797 data[xoff + d1] = inData[off++]; 798 data[xoff + d2] = inData[off++]; 799 } 800 } 801 } else if (numDataElements == 4) { 802 yoff += dataOffsets[0]; 803 int d1 = dataOffsets[1] - dataOffsets[0]; 804 int d2 = dataOffsets[2] - dataOffsets[0]; 805 int d3 = dataOffsets[3] - dataOffsets[0]; 806 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 807 xoff = yoff; 808 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 809 data[xoff] = inData[off++]; 810 data[xoff + d1] = inData[off++]; 811 data[xoff + d2] = inData[off++]; 812 data[xoff + d3] = inData[off++]; 813 } 814 } 815 } else { 816 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 817 xoff = yoff; 818 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) { 819 for (int c = 0; c < numDataElements; c++) { 820 data[dataOffsets[c] + xoff] = inData[off++]; 821 } 822 } 823 } 824 } 825 826 markDirty(); 827 } 828 829 public int getSample(int x, int y, int b) { 830 if ((x < this.minX) || (y < this.minY) || 831 (x >= this.maxX) || (y >= this.maxY)) { 832 throw new ArrayIndexOutOfBoundsException 833 ("Coordinate out of bounds!"); 834 } 835 if (packed) { 836 int offset = y*scanlineStride + x + dbOffsetPacked; 837 byte sample = data[offset]; 838 return (sample & bitMasks[b]) >>> bitOffsets[b]; 839 } else { 840 int offset = y*scanlineStride + x*pixelStride + dbOffset; 841 return data[offset + dataOffsets[b]] & 0xff; 842 } 843 } 844 845 public void setSample(int x, int y, int b, int s) { 846 if ((x < this.minX) || (y < this.minY) || 847 (x >= this.maxX) || (y >= this.maxY)) { 848 throw new ArrayIndexOutOfBoundsException 849 ("Coordinate out of bounds!"); 850 } 851 if (packed) { 852 int offset = y*scanlineStride + x + dbOffsetPacked; 853 int bitMask = bitMasks[b]; 854 855 byte value = data[offset]; 856 value &= ~bitMask; 857 value |= (s << bitOffsets[b]) & bitMask; 858 data[offset] = value; 859 } else { 860 int offset = y*scanlineStride + x*pixelStride + dbOffset; 861 data[offset + dataOffsets[b]] = (byte)s; 862 } 863 864 markDirty(); 865 } 866 867 public int[] getSamples(int x, int y, int w, int h, int b, 868 int[] iArray) { 869 if ((x < this.minX) || (y < this.minY) || 870 (x + w > this.maxX) || (y + h > this.maxY)) { 871 throw new ArrayIndexOutOfBoundsException 872 ("Coordinate out of bounds!"); 873 } 874 int[] samples; 875 if (iArray != null) { 876 samples = iArray; 877 } else { 878 samples = new int [w*h]; 879 } 880 881 int lineOffset = y*scanlineStride + x*pixelStride; 882 int dstOffset = 0; 883 884 if (packed) { 885 lineOffset += dbOffsetPacked; 886 int bitMask = bitMasks[b]; 887 int bitOffset = bitOffsets[b]; 888 889 for (int j = 0; j < h; j++) { 890 int sampleOffset = lineOffset; 891 for (int i = 0; i < w; i++) { 892 int value = data[sampleOffset++]; 893 samples[dstOffset++] = ((value & bitMask) >>> bitOffset); 894 } 895 lineOffset += scanlineStride; 896 } 897 } else { 898 lineOffset += dbOffset + dataOffsets[b]; 899 for (int j = 0; j < h; j++) { 900 int sampleOffset = lineOffset; 901 for (int i = 0; i < w; i++) { 902 samples[dstOffset++] = data[sampleOffset] & 0xff; 903 sampleOffset += pixelStride; 904 } 905 lineOffset += scanlineStride; 906 } 907 } 908 909 return samples; 910 } 911 912 public void setSamples(int x, int y, int w, int h, int b, int[] iArray) { 913 if ((x < this.minX) || (y < this.minY) || 914 (x + w > this.maxX) || (y + h > this.maxY)) { 915 throw new ArrayIndexOutOfBoundsException 916 ("Coordinate out of bounds!"); 917 } 918 int lineOffset = y*scanlineStride + x*pixelStride; 919 int srcOffset = 0; 920 921 if (packed) { 922 lineOffset += dbOffsetPacked; 923 int bitMask = bitMasks[b]; 924 925 for (int j = 0; j < h; j++) { 926 int sampleOffset = lineOffset; 927 for (int i = 0; i < w; i++) { 928 byte value = data[sampleOffset]; 929 value &= ~bitMask; 930 int sample = iArray[srcOffset++]; 931 value |= (sample << bitOffsets[b]) & bitMask; 932 data[sampleOffset++] = value; 933 } 934 lineOffset += scanlineStride; 935 } 936 } else { 937 lineOffset += dbOffset + dataOffsets[b]; 938 for (int i = 0; i < h; i++) { 939 int sampleOffset = lineOffset; 940 for (int j = 0; j < w; j++) { 941 data[sampleOffset] = (byte)iArray[srcOffset++]; 942 sampleOffset += pixelStride; 943 } 944 lineOffset += scanlineStride; 945 } 946 } 947 948 markDirty(); 949 } 950 951 public int[] getPixels(int x, int y, int w, int h, int[] iArray) { 952 if ((x < this.minX) || (y < this.minY) || 953 (x + w > this.maxX) || (y + h > this.maxY)) { 954 throw new ArrayIndexOutOfBoundsException 955 ("Coordinate out of bounds!"); 956 } 957 int[] pixels; 958 if (iArray != null) { 959 pixels = iArray; 960 } else { 961 pixels = new int[w*h*numBands]; 962 } 963 964 int lineOffset = y*scanlineStride + x*pixelStride; 965 int dstOffset = 0; 966 967 if (packed) { 968 lineOffset += dbOffsetPacked; 969 for (int j = 0; j < h; j++) { 970 for (int i = 0; i < w; i++) { 971 int value = data[lineOffset + i]; 972 for (int k = 0; k < numBands; k++) { 973 pixels[dstOffset++] = 974 (value & bitMasks[k]) >>> bitOffsets[k]; 975 } 976 } 977 lineOffset += scanlineStride; 978 } 979 } else { 980 lineOffset += dbOffset; 981 int d0 = dataOffsets[0]; 982 983 if (numBands == 1) { 984 for (int j = 0; j < h; j++) { 985 int pixelOffset = lineOffset + d0; 986 for (int i = 0; i < w; i++) { 987 pixels[dstOffset++] = data[pixelOffset] & 0xff; 988 pixelOffset += pixelStride; 989 } 990 lineOffset += scanlineStride; 991 } 992 } else if (numBands == 2) { 993 int d1 = dataOffsets[1] - d0; 994 for (int j = 0; j < h; j++) { 995 int pixelOffset = lineOffset + d0; 996 for (int i = 0; i < w; i++) { 997 pixels[dstOffset++] = data[pixelOffset] & 0xff; 998 pixels[dstOffset++] = data[pixelOffset + d1] & 0xff; 999 pixelOffset += pixelStride; 1000 } 1001 lineOffset += scanlineStride; 1002 } 1003 } else if (numBands == 3) { 1004 int d1 = dataOffsets[1] - d0; 1005 int d2 = dataOffsets[2] - d0; 1006 for (int j = 0; j < h; j++) { 1007 int pixelOffset = lineOffset + d0; 1008 for (int i = 0; i < w; i++) { 1009 pixels[dstOffset++] = data[pixelOffset] & 0xff; 1010 pixels[dstOffset++] = data[pixelOffset + d1] & 0xff; 1011 pixels[dstOffset++] = data[pixelOffset + d2] & 0xff; 1012 pixelOffset += pixelStride; 1013 } 1014 lineOffset += scanlineStride; 1015 } 1016 } else if (numBands == 4) { 1017 int d1 = dataOffsets[1] - d0; 1018 int d2 = dataOffsets[2] - d0; 1019 int d3 = dataOffsets[3] - d0; 1020 for (int j = 0; j < h; j++) { 1021 int pixelOffset = lineOffset + d0; 1022 for (int i = 0; i < w; i++) { 1023 pixels[dstOffset++] = data[pixelOffset] & 0xff; 1024 pixels[dstOffset++] = data[pixelOffset + d1] & 0xff; 1025 pixels[dstOffset++] = data[pixelOffset + d2] & 0xff; 1026 pixels[dstOffset++] = data[pixelOffset + d3] & 0xff; 1027 pixelOffset += pixelStride; 1028 } 1029 lineOffset += scanlineStride; 1030 } 1031 } else { 1032 for (int j = 0; j < h; j++) { 1033 int pixelOffset = lineOffset; 1034 for (int i = 0; i < w; i++) { 1035 for (int k = 0; k < numBands; k++) { 1036 pixels[dstOffset++] = 1037 data[pixelOffset + dataOffsets[k]] & 0xff; 1038 } 1039 pixelOffset += pixelStride; 1040 } 1041 lineOffset += scanlineStride; 1042 } 1043 } 1044 } 1045 1046 return pixels; 1047 } 1048 1049 public void setPixels(int x, int y, int w, int h, int[] iArray) { 1050 if ((x < this.minX) || (y < this.minY) || 1051 (x + w > this.maxX) || (y + h > this.maxY)) { 1052 throw new ArrayIndexOutOfBoundsException 1053 ("Coordinate out of bounds!"); 1054 } 1055 int lineOffset = y*scanlineStride + x*pixelStride; 1056 int srcOffset = 0; 1057 1058 if (packed) { 1059 lineOffset += dbOffsetPacked; 1060 for (int j = 0; j < h; j++) { 1061 for (int i = 0; i < w; i++) { 1062 int value = 0; 1063 for (int k = 0; k < numBands; k++) { 1064 int srcValue = iArray[srcOffset++]; 1065 value |= ((srcValue << bitOffsets[k]) 1066 & bitMasks[k]); 1067 } 1068 data[lineOffset + i] = (byte)value; 1069 } 1070 lineOffset += scanlineStride; 1071 } 1072 } else { 1073 lineOffset += dbOffset; 1074 int d0 = dataOffsets[0]; 1075 1076 if (numBands == 1) { 1077 for (int j = 0; j < h; j++) { 1078 int pixelOffset = lineOffset + d0; 1079 for (int i = 0; i < w; i++) { 1080 data[pixelOffset] = (byte)iArray[srcOffset++]; 1081 pixelOffset += pixelStride; 1082 } 1083 lineOffset += scanlineStride; 1084 } 1085 } else if (numBands == 2) { 1086 int d1 = dataOffsets[1] - d0; 1087 for (int j = 0; j < h; j++) { 1088 int pixelOffset = lineOffset + d0; 1089 for (int i = 0; i < w; i++) { 1090 data[pixelOffset] = (byte)iArray[srcOffset++]; 1091 data[pixelOffset + d1] = (byte)iArray[srcOffset++]; 1092 pixelOffset += pixelStride; 1093 } 1094 lineOffset += scanlineStride; 1095 } 1096 } else if (numBands == 3) { 1097 int d1 = dataOffsets[1] - d0; 1098 int d2 = dataOffsets[2] - d0; 1099 for (int j = 0; j < h; j++) { 1100 int pixelOffset = lineOffset + d0; 1101 for (int i = 0; i < w; i++) { 1102 data[pixelOffset] = (byte)iArray[srcOffset++]; 1103 data[pixelOffset + d1] = (byte)iArray[srcOffset++]; 1104 data[pixelOffset + d2] = (byte)iArray[srcOffset++]; 1105 pixelOffset += pixelStride; 1106 } 1107 lineOffset += scanlineStride; 1108 } 1109 } else if (numBands == 4) { 1110 int d1 = dataOffsets[1] - d0; 1111 int d2 = dataOffsets[2] - d0; 1112 int d3 = dataOffsets[3] - d0; 1113 for (int j = 0; j < h; j++) { 1114 int pixelOffset = lineOffset + d0; 1115 for (int i = 0; i < w; i++) { 1116 data[pixelOffset] = (byte)iArray[srcOffset++]; 1117 data[pixelOffset + d1] = (byte)iArray[srcOffset++]; 1118 data[pixelOffset + d2] = (byte)iArray[srcOffset++]; 1119 data[pixelOffset + d3] = (byte)iArray[srcOffset++]; 1120 pixelOffset += pixelStride; 1121 } 1122 lineOffset += scanlineStride; 1123 } 1124 } else { 1125 for (int j = 0; j < h; j++) { 1126 int pixelOffset = lineOffset; 1127 for (int i = 0; i < w; i++) { 1128 for (int k = 0; k < numBands; k++) { 1129 data[pixelOffset + dataOffsets[k]] = 1130 (byte)iArray[srcOffset++]; 1131 } 1132 pixelOffset += pixelStride; 1133 } 1134 lineOffset += scanlineStride; 1135 } 1136 } 1137 } 1138 1139 markDirty(); 1140 } 1141 1142 public void setRect(int dx, int dy, Raster srcRaster) { 1143 if (!(srcRaster instanceof ByteInterleavedRaster)) { 1144 super.setRect(dx, dy, srcRaster); 1145 return; 1146 } 1147 1148 int width = srcRaster.getWidth(); 1149 int height = srcRaster.getHeight(); 1150 int srcOffX = srcRaster.getMinX(); 1151 int srcOffY = srcRaster.getMinY(); 1152 int dstOffX = dx+srcOffX; 1153 int dstOffY = dy+srcOffY; 1154 1155 // Clip to this raster 1156 if (dstOffX < this.minX) { 1157 int skipX = minX - dstOffX; 1158 width -= skipX; 1159 srcOffX += skipX; 1160 dstOffX = this.minX; 1161 } 1162 if (dstOffY < this.minY) { 1163 int skipY = this.minY - dstOffY; 1164 height -= skipY; 1165 srcOffY += skipY; 1166 dstOffY = this.minY; 1167 } 1168 if (dstOffX+width > this.maxX) { 1169 width = this.maxX - dstOffX; 1170 } 1171 if (dstOffY+height > this.maxY) { 1172 height = this.maxY - dstOffY; 1173 } 1174 1175 setDataElements(dstOffX, dstOffY, 1176 srcOffX, srcOffY, 1177 width, height, srcRaster); 1178 } 1179 1180 1181 /** 1182 * Creates a subraster given a region of the raster. The x and y 1183 * coordinates specify the horizontal and vertical offsets 1184 * from the upper-left corner of this raster to the upper-left corner 1185 * of the subraster. A subset of the bands of the parent Raster may 1186 * be specified. If this is null, then all the bands are present in the 1187 * subRaster. A translation to the subRaster may also be specified. 1188 * Note that the subraster will reference the same 1189 * DataBuffer as the parent raster, but using different offsets. 1190 * @param x X offset. 1191 * @param y Y offset. 1192 * @param width Width (in pixels) of the subraster. 1193 * @param height Height (in pixels) of the subraster. 1194 * @param x0 Translated X origin of the subraster. 1195 * @param y0 Translated Y origin of the subraster. 1196 * @param bandList Array of band indices. 1197 * @exception RasterFormatException 1198 * if the specified bounding box is outside of the parent raster. 1199 */ 1200 public Raster createChild(int x, int y, 1201 int width, int height, 1202 int x0, int y0, int[] bandList) { 1203 WritableRaster newRaster = createWritableChild(x, y, 1204 width, height, 1205 x0, y0, 1206 bandList); 1207 return (Raster) newRaster; 1208 } 1209 1210 /** 1211 * Creates a Writable subRaster given a region of the Raster. The x and y 1212 * coordinates specify the horizontal and vertical offsets 1213 * from the upper-left corner of this Raster to the upper-left corner 1214 * of the subRaster. A subset of the bands of the parent Raster may 1215 * be specified. If this is null, then all the bands are present in the 1216 * subRaster. A translation to the subRaster may also be specified. 1217 * Note that the subRaster will reference the same 1218 * DataBuffer as the parent Raster, but using different offsets. 1219 * @param x X offset. 1220 * @param y Y offset. 1221 * @param width Width (in pixels) of the subraster. 1222 * @param height Height (in pixels) of the subraster. 1223 * @param x0 Translated X origin of the subraster. 1224 * @param y0 Translated Y origin of the subraster. 1225 * @param bandList Array of band indices. 1226 * @exception RasterFormatException 1227 * if the specified bounding box is outside of the parent Raster. 1228 */ 1229 public WritableRaster createWritableChild(int x, int y, 1230 int width, int height, 1231 int x0, int y0, 1232 int[] bandList) { 1233 if (x < this.minX) { 1234 throw new RasterFormatException("x lies outside the raster"); 1235 } 1236 if (y < this.minY) { 1237 throw new RasterFormatException("y lies outside the raster"); 1238 } 1239 if ((x+width < x) || (x+width > this.minX + this.width)) { 1240 throw new RasterFormatException("(x + width) is outside of Raster"); 1241 } 1242 if ((y+height < y) || (y+height > this.minY + this.height)) { 1243 throw new RasterFormatException("(y + height) is outside of Raster"); 1244 } 1245 1246 SampleModel sm; 1247 1248 if (bandList != null) 1249 sm = sampleModel.createSubsetSampleModel(bandList); 1250 else 1251 sm = sampleModel; 1252 1253 int deltaX = x0 - x; 1254 int deltaY = y0 - y; 1255 1256 return new ByteInterleavedRaster(sm, 1257 (DataBufferByte) dataBuffer, 1258 new Rectangle(x0, y0, width, height), 1259 new Point(sampleModelTranslateX+deltaX, 1260 sampleModelTranslateY+deltaY), 1261 this); 1262 } 1263 1264 /** 1265 * Creates a Raster with the same layout but using a different 1266 * width and height, and with new zeroed data arrays. 1267 */ 1268 public WritableRaster createCompatibleWritableRaster(int w, int h) { 1269 if (w <= 0 || h <=0) { 1270 throw new RasterFormatException("negative "+ 1271 ((w <= 0) ? "width" : "height")); 1272 } 1273 1274 SampleModel sm = sampleModel.createCompatibleSampleModel(w, h); 1275 1276 return new ByteInterleavedRaster(sm, new Point(0,0)); 1277 1278 } 1279 1280 /** 1281 * Creates a Raster with the same layout and the same 1282 * width and height, and with new zeroed data arrays. If 1283 * the Raster is a subRaster, this will call 1284 * createCompatibleRaster(width, height). 1285 */ 1286 public WritableRaster createCompatibleWritableRaster() { 1287 return createCompatibleWritableRaster(width,height); 1288 } 1289 1290 public String toString() { 1291 return new String ("ByteInterleavedRaster: width = "+width+" height = " 1292 + height 1293 +" #numDataElements "+numDataElements 1294 // +" xOff = "+xOffset+" yOff = "+yOffset 1295 +" dataOff[0] = "+dataOffsets[0]); 1296 } 1297 1298 // /** 1299 // * For debugging... prints a region of a one-band ByteInterleavedRaster 1300 // */ 1301 // public void print(int x, int y, int w, int h) { 1302 // // REMIND: Only works for 1 band! 1303 // System.out.println(this); 1304 // int offset = dataOffsets[0] + y*scanlineStride + x*pixelStride; 1305 // int off; 1306 // for (int yoff=0; yoff < h; yoff++, offset += scanlineStride) { 1307 // off = offset; 1308 // System.out.print("Line "+(y+yoff)+": "); 1309 // for (int xoff = 0; xoff < w; xoff++, off+= pixelStride) { 1310 // String s = Integer.toHexString(data[off]); 1311 // if (s.length() == 8) { 1312 // s = s.substring(6,8); 1313 // } 1314 // System.out.print(s+" "); 1315 // } 1316 // System.out.println(""); 1317 // } 1318 // } 1319 }