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