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 /* **************************************************************** 27 ****************************************************************** 28 ****************************************************************** 29 *** COPYRIGHT (c) Eastman Kodak Company, 1997 30 *** As an unpublished work pursuant to Title 17 of the United 31 *** States Code. All rights reserved. 32 ****************************************************************** 33 ****************************************************************** 34 ******************************************************************/ 35 36 37 package java.awt.image; 38 import java.awt.Rectangle; 39 import java.awt.Point; 40 41 import sun.awt.image.ByteInterleavedRaster; 42 import sun.awt.image.ShortInterleavedRaster; 43 import sun.awt.image.IntegerInterleavedRaster; 44 import sun.awt.image.ByteBandedRaster; 45 import sun.awt.image.ShortBandedRaster; 46 import sun.awt.image.BytePackedRaster; 47 import sun.awt.image.SunWritableRaster; 48 49 /** 50 * A class representing a rectangular array of pixels. A Raster 51 * encapsulates a DataBuffer that stores the sample values and a 52 * SampleModel that describes how to locate a given sample value in a 53 * DataBuffer. 54 * <p> 55 * A Raster defines values for pixels occupying a particular 56 * rectangular area of the plane, not necessarily including (0, 0). 57 * The rectangle, known as the Raster's bounding rectangle and 58 * available by means of the getBounds method, is defined by minX, 59 * minY, width, and height values. The minX and minY values define 60 * the coordinate of the upper left corner of the Raster. References 61 * to pixels outside of the bounding rectangle may result in an 62 * exception being thrown, or may result in references to unintended 63 * elements of the Raster's associated DataBuffer. It is the user's 64 * responsibility to avoid accessing such pixels. 65 * <p> 66 * A SampleModel describes how samples of a Raster 67 * are stored in the primitive array elements of a DataBuffer. 68 * Samples may be stored one per data element, as in a 69 * PixelInterleavedSampleModel or BandedSampleModel, or packed several to 70 * an element, as in a SinglePixelPackedSampleModel or 71 * MultiPixelPackedSampleModel. The SampleModel is also 72 * controls whether samples are sign extended, allowing unsigned 73 * data to be stored in signed Java data types such as byte, short, and 74 * int. 75 * <p> 76 * Although a Raster may live anywhere in the plane, a SampleModel 77 * makes use of a simple coordinate system that starts at (0, 0). A 78 * Raster therefore contains a translation factor that allows pixel 79 * locations to be mapped between the Raster's coordinate system and 80 * that of the SampleModel. The translation from the SampleModel 81 * coordinate system to that of the Raster may be obtained by the 82 * getSampleModelTranslateX and getSampleModelTranslateY methods. 83 * <p> 84 * A Raster may share a DataBuffer with another Raster either by 85 * explicit construction or by the use of the createChild and 86 * createTranslatedChild methods. Rasters created by these methods 87 * can return a reference to the Raster they were created from by 88 * means of the getParent method. For a Raster that was not 89 * constructed by means of a call to createTranslatedChild or 90 * createChild, getParent will return null. 91 * <p> 92 * The createTranslatedChild method returns a new Raster that 93 * shares all of the data of the current Raster, but occupies a 94 * bounding rectangle of the same width and height but with a 95 * different starting point. For example, if the parent Raster 96 * occupied the region (10, 10) to (100, 100), and the translated 97 * Raster was defined to start at (50, 50), then pixel (20, 20) of the 98 * parent and pixel (60, 60) of the child occupy the same location in 99 * the DataBuffer shared by the two Rasters. In the first case, (-10, 100 * -10) should be added to a pixel coordinate to obtain the 101 * corresponding SampleModel coordinate, and in the second case (-50, 102 * -50) should be added. 103 * <p> 104 * The translation between a parent and child Raster may be 105 * determined by subtracting the child's sampleModelTranslateX and 106 * sampleModelTranslateY values from those of the parent. 107 * <p> 108 * The createChild method may be used to create a new Raster 109 * occupying only a subset of its parent's bounding rectangle 110 * (with the same or a translated coordinate system) or 111 * with a subset of the bands of its parent. 112 * <p> 113 * All constructors are protected. The correct way to create a 114 * Raster is to use one of the static create methods defined in this 115 * class. These methods create instances of Raster that use the 116 * standard Interleaved, Banded, and Packed SampleModels and that may 117 * be processed more efficiently than a Raster created by combining 118 * an externally generated SampleModel and DataBuffer. 119 * @see java.awt.image.DataBuffer 120 * @see java.awt.image.SampleModel 121 * @see java.awt.image.PixelInterleavedSampleModel 122 * @see java.awt.image.BandedSampleModel 123 * @see java.awt.image.SinglePixelPackedSampleModel 124 * @see java.awt.image.MultiPixelPackedSampleModel 125 */ 126 public class Raster { 127 128 /** 129 * The SampleModel that describes how pixels from this Raster 130 * are stored in the DataBuffer. 131 */ 132 protected SampleModel sampleModel; 133 134 /** The DataBuffer that stores the image data. */ 135 protected DataBuffer dataBuffer; 136 137 /** The X coordinate of the upper-left pixel of this Raster. */ 138 protected int minX; 139 140 /** The Y coordinate of the upper-left pixel of this Raster. */ 141 protected int minY; 142 143 /** The width of this Raster. */ 144 protected int width; 145 146 /** The height of this Raster. */ 147 protected int height; 148 149 /** 150 * The X translation from the coordinate space of the 151 * Raster's SampleModel to that of the Raster. 152 */ 153 protected int sampleModelTranslateX; 154 155 /** 156 * The Y translation from the coordinate space of the 157 * Raster's SampleModel to that of the Raster. 158 */ 159 protected int sampleModelTranslateY; 160 161 /** The number of bands in the Raster. */ 162 protected int numBands; 163 164 /** The number of DataBuffer data elements per pixel. */ 165 protected int numDataElements; 166 167 /** The parent of this Raster, or null. */ 168 protected Raster parent; 169 170 private static native void initIDs(); 171 static { 172 ColorModel.loadLibraries(); 173 initIDs(); 174 } 175 176 /** 177 * Creates a Raster based on a PixelInterleavedSampleModel with the 178 * specified data type, width, height, and number of bands. 179 * 180 * <p> The upper left corner of the Raster is given by the 181 * location argument. If location is null, (0, 0) will be used. 182 * The dataType parameter should be one of the enumerated values 183 * defined in the DataBuffer class. 184 * 185 * <p> Note that interleaved {@code DataBuffer.TYPE_INT} 186 * Rasters are not supported. To create a 1-band Raster of type 187 * {@code DataBuffer.TYPE_INT}, use 188 * Raster.createPackedRaster(). 189 * <p> The only dataTypes supported currently are TYPE_BYTE 190 * and TYPE_USHORT. 191 * @param dataType the data type for storing samples 192 * @param w the width in pixels of the image data 193 * @param h the height in pixels of the image data 194 * @param bands the number of bands 195 * @param location the upper-left corner of the {@code Raster} 196 * @return a WritableRaster object with the specified data type, 197 * width, height and number of bands. 198 * @throws RasterFormatException if {@code w} or {@code h} 199 * is less than or equal to zero, or computing either 200 * {@code location.x + w} or 201 * {@code location.y + h} results in integer 202 * overflow 203 */ 204 public static WritableRaster createInterleavedRaster(int dataType, 205 int w, int h, 206 int bands, 207 Point location) { 208 int[] bandOffsets = new int[bands]; 209 for (int i = 0; i < bands; i++) { 210 bandOffsets[i] = i; 211 } 212 return createInterleavedRaster(dataType, w, h, w*bands, bands, 213 bandOffsets, location); 214 } 215 216 /** 217 * Creates a Raster based on a PixelInterleavedSampleModel with the 218 * specified data type, width, height, scanline stride, pixel 219 * stride, and band offsets. The number of bands is inferred from 220 * bandOffsets.length. 221 * 222 * <p> The upper left corner of the Raster is given by the 223 * location argument. If location is null, (0, 0) will be used. 224 * The dataType parameter should be one of the enumerated values 225 * defined in the DataBuffer class. 226 * 227 * <p> Note that interleaved {@code DataBuffer.TYPE_INT} 228 * Rasters are not supported. To create a 1-band Raster of type 229 * {@code DataBuffer.TYPE_INT}, use 230 * Raster.createPackedRaster(). 231 * <p> The only dataTypes supported currently are TYPE_BYTE 232 * and TYPE_USHORT. 233 * @param dataType the data type for storing samples 234 * @param w the width in pixels of the image data 235 * @param h the height in pixels of the image data 236 * @param scanlineStride the line stride of the image data 237 * @param pixelStride the pixel stride of the image data 238 * @param bandOffsets the offsets of all bands 239 * @param location the upper-left corner of the {@code Raster} 240 * @return a WritableRaster object with the specified data type, 241 * width, height, scanline stride, pixel stride and band 242 * offsets. 243 * @throws RasterFormatException if {@code w} or {@code h} 244 * is less than or equal to zero, or computing either 245 * {@code location.x + w} or 246 * {@code location.y + h} results in integer 247 * overflow 248 * @throws IllegalArgumentException if {@code dataType} is not 249 * one of the supported data types, which are 250 * {@code DataBuffer.TYPE_BYTE}, or 251 * {@code DataBuffer.TYPE_USHORT}. 252 */ 253 public static WritableRaster createInterleavedRaster(int dataType, 254 int w, int h, 255 int scanlineStride, 256 int pixelStride, 257 int bandOffsets[], 258 Point location) { 259 DataBuffer d; 260 261 int size = scanlineStride * (h - 1) + // fisrt (h - 1) scans 262 pixelStride * w; // last scan 263 264 switch(dataType) { 265 case DataBuffer.TYPE_BYTE: 266 d = new DataBufferByte(size); 267 break; 268 269 case DataBuffer.TYPE_USHORT: 270 d = new DataBufferUShort(size); 271 break; 272 273 default: 274 throw new IllegalArgumentException("Unsupported data type " + 275 dataType); 276 } 277 278 return createInterleavedRaster(d, w, h, scanlineStride, 279 pixelStride, bandOffsets, location); 280 } 281 282 /** 283 * Creates a Raster based on a BandedSampleModel with the 284 * specified data type, width, height, and number of bands. 285 * 286 * <p> The upper left corner of the Raster is given by the 287 * location argument. If location is null, (0, 0) will be used. 288 * The dataType parameter should be one of the enumerated values 289 * defined in the DataBuffer class. 290 * 291 * <p> The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT, 292 * and TYPE_INT. 293 * @param dataType the data type for storing samples 294 * @param w the width in pixels of the image data 295 * @param h the height in pixels of the image data 296 * @param bands the number of bands 297 * @param location the upper-left corner of the {@code Raster} 298 * @return a WritableRaster object with the specified data type, 299 * width, height and number of bands. 300 * @throws RasterFormatException if {@code w} or {@code h} 301 * is less than or equal to zero, or computing either 302 * {@code location.x + w} or 303 * {@code location.y + h} results in integer 304 * overflow 305 * @throws ArrayIndexOutOfBoundsException if {@code bands} 306 * is less than 1 307 */ 308 public static WritableRaster createBandedRaster(int dataType, 309 int w, int h, 310 int bands, 311 Point location) { 312 if (bands < 1) { 313 throw new ArrayIndexOutOfBoundsException("Number of bands ("+ 314 bands+") must"+ 315 " be greater than 0"); 316 } 317 int[] bankIndices = new int[bands]; 318 int[] bandOffsets = new int[bands]; 319 for (int i = 0; i < bands; i++) { 320 bankIndices[i] = i; 321 bandOffsets[i] = 0; 322 } 323 324 return createBandedRaster(dataType, w, h, w, 325 bankIndices, bandOffsets, 326 location); 327 } 328 329 /** 330 * Creates a Raster based on a BandedSampleModel with the 331 * specified data type, width, height, scanline stride, bank 332 * indices and band offsets. The number of bands is inferred from 333 * bankIndices.length and bandOffsets.length, which must be the 334 * same. 335 * 336 * <p> The upper left corner of the Raster is given by the 337 * location argument. The dataType parameter should be one of the 338 * enumerated values defined in the DataBuffer class. 339 * 340 * <p> The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT, 341 * and TYPE_INT. 342 * @param dataType the data type for storing samples 343 * @param w the width in pixels of the image data 344 * @param h the height in pixels of the image data 345 * @param scanlineStride the line stride of the image data 346 * @param bankIndices the bank indices for each band 347 * @param bandOffsets the offsets of all bands 348 * @param location the upper-left corner of the {@code Raster} 349 * @return a WritableRaster object with the specified data type, 350 * width, height, scanline stride, bank indices and band 351 * offsets. 352 * @throws RasterFormatException if {@code w} or {@code h} 353 * is less than or equal to zero, or computing either 354 * {@code location.x + w} or 355 * {@code location.y + h} results in integer 356 * overflow 357 * @throws IllegalArgumentException if {@code dataType} is not 358 * one of the supported data types, which are 359 * {@code DataBuffer.TYPE_BYTE}, 360 * {@code DataBuffer.TYPE_USHORT} 361 * or {@code DataBuffer.TYPE_INT} 362 * @throws ArrayIndexOutOfBoundsException if {@code bankIndices} 363 * or {@code bandOffsets} is {@code null} 364 */ 365 public static WritableRaster createBandedRaster(int dataType, 366 int w, int h, 367 int scanlineStride, 368 int bankIndices[], 369 int bandOffsets[], 370 Point location) { 371 DataBuffer d; 372 int bands = bandOffsets.length; 373 374 if (bankIndices == null) { 375 throw new 376 ArrayIndexOutOfBoundsException("Bank indices array is null"); 377 } 378 if (bandOffsets == null) { 379 throw new 380 ArrayIndexOutOfBoundsException("Band offsets array is null"); 381 } 382 383 // Figure out the #banks and the largest band offset 384 int maxBank = bankIndices[0]; 385 int maxBandOff = bandOffsets[0]; 386 for (int i = 1; i < bands; i++) { 387 if (bankIndices[i] > maxBank) { 388 maxBank = bankIndices[i]; 389 } 390 if (bandOffsets[i] > maxBandOff) { 391 maxBandOff = bandOffsets[i]; 392 } 393 } 394 int banks = maxBank + 1; 395 int size = maxBandOff + 396 scanlineStride * (h - 1) + // first (h - 1) scans 397 w; // last scan 398 399 switch(dataType) { 400 case DataBuffer.TYPE_BYTE: 401 d = new DataBufferByte(size, banks); 402 break; 403 404 case DataBuffer.TYPE_USHORT: 405 d = new DataBufferUShort(size, banks); 406 break; 407 408 case DataBuffer.TYPE_INT: 409 d = new DataBufferInt(size, banks); 410 break; 411 412 default: 413 throw new IllegalArgumentException("Unsupported data type " + 414 dataType); 415 } 416 417 return createBandedRaster(d, w, h, scanlineStride, 418 bankIndices, bandOffsets, location); 419 } 420 421 /** 422 * Creates a Raster based on a SinglePixelPackedSampleModel with 423 * the specified data type, width, height, and band masks. 424 * The number of bands is inferred from bandMasks.length. 425 * 426 * <p> The upper left corner of the Raster is given by the 427 * location argument. If location is null, (0, 0) will be used. 428 * The dataType parameter should be one of the enumerated values 429 * defined in the DataBuffer class. 430 * 431 * <p> The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT, 432 * and TYPE_INT. 433 * @param dataType the data type for storing samples 434 * @param w the width in pixels of the image data 435 * @param h the height in pixels of the image data 436 * @param bandMasks an array containing an entry for each band 437 * @param location the upper-left corner of the {@code Raster} 438 * @return a WritableRaster object with the specified data type, 439 * width, height, and band masks. 440 * @throws RasterFormatException if {@code w} or {@code h} 441 * is less than or equal to zero, or computing either 442 * {@code location.x + w} or 443 * {@code location.y + h} results in integer 444 * overflow 445 * @throws IllegalArgumentException if {@code dataType} is not 446 * one of the supported data types, which are 447 * {@code DataBuffer.TYPE_BYTE}, 448 * {@code DataBuffer.TYPE_USHORT} 449 * or {@code DataBuffer.TYPE_INT} 450 */ 451 public static WritableRaster createPackedRaster(int dataType, 452 int w, int h, 453 int bandMasks[], 454 Point location) { 455 DataBuffer d; 456 457 switch(dataType) { 458 case DataBuffer.TYPE_BYTE: 459 d = new DataBufferByte(w*h); 460 break; 461 462 case DataBuffer.TYPE_USHORT: 463 d = new DataBufferUShort(w*h); 464 break; 465 466 case DataBuffer.TYPE_INT: 467 d = new DataBufferInt(w*h); 468 break; 469 470 default: 471 throw new IllegalArgumentException("Unsupported data type " + 472 dataType); 473 } 474 475 return createPackedRaster(d, w, h, w, bandMasks, location); 476 } 477 478 /** 479 * Creates a Raster based on a packed SampleModel with the 480 * specified data type, width, height, number of bands, and bits 481 * per band. If the number of bands is one, the SampleModel will 482 * be a MultiPixelPackedSampleModel. 483 * 484 * <p> If the number of bands is more than one, the SampleModel 485 * will be a SinglePixelPackedSampleModel, with each band having 486 * bitsPerBand bits. In either case, the requirements on dataType 487 * and bitsPerBand imposed by the corresponding SampleModel must 488 * be met. 489 * 490 * <p> The upper left corner of the Raster is given by the 491 * location argument. If location is null, (0, 0) will be used. 492 * The dataType parameter should be one of the enumerated values 493 * defined in the DataBuffer class. 494 * 495 * <p> The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT, 496 * and TYPE_INT. 497 * @param dataType the data type for storing samples 498 * @param w the width in pixels of the image data 499 * @param h the height in pixels of the image data 500 * @param bands the number of bands 501 * @param bitsPerBand the number of bits per band 502 * @param location the upper-left corner of the {@code Raster} 503 * @return a WritableRaster object with the specified data type, 504 * width, height, number of bands, and bits per band. 505 * @throws RasterFormatException if {@code w} or {@code h} 506 * is less than or equal to zero, or computing either 507 * {@code location.x + w} or 508 * {@code location.y + h} results in integer 509 * overflow 510 * @throws IllegalArgumentException if the product of 511 * {@code bitsPerBand} and {@code bands} is 512 * greater than the number of bits held by 513 * {@code dataType} 514 * @throws IllegalArgumentException if {@code bitsPerBand} or 515 * {@code bands} is not greater than zero 516 * @throws IllegalArgumentException if {@code dataType} is not 517 * one of the supported data types, which are 518 * {@code DataBuffer.TYPE_BYTE}, 519 * {@code DataBuffer.TYPE_USHORT} 520 * or {@code DataBuffer.TYPE_INT} 521 */ 522 public static WritableRaster createPackedRaster(int dataType, 523 int w, int h, 524 int bands, 525 int bitsPerBand, 526 Point location) { 527 DataBuffer d; 528 529 if (bands <= 0) { 530 throw new IllegalArgumentException("Number of bands ("+bands+ 531 ") must be greater than 0"); 532 } 533 534 if (bitsPerBand <= 0) { 535 throw new IllegalArgumentException("Bits per band ("+bitsPerBand+ 536 ") must be greater than 0"); 537 } 538 539 if (bands != 1) { 540 int[] masks = new int[bands]; 541 int mask = (1 << bitsPerBand) - 1; 542 int shift = (bands-1)*bitsPerBand; 543 544 /* Make sure the total mask size will fit in the data type */ 545 if (shift+bitsPerBand > DataBuffer.getDataTypeSize(dataType)) { 546 throw new IllegalArgumentException("bitsPerBand("+ 547 bitsPerBand+") * bands is "+ 548 " greater than data type "+ 549 "size."); 550 } 551 switch(dataType) { 552 case DataBuffer.TYPE_BYTE: 553 case DataBuffer.TYPE_USHORT: 554 case DataBuffer.TYPE_INT: 555 break; 556 default: 557 throw new IllegalArgumentException("Unsupported data type " + 558 dataType); 559 } 560 561 for (int i = 0; i < bands; i++) { 562 masks[i] = mask << shift; 563 shift = shift - bitsPerBand; 564 } 565 566 return createPackedRaster(dataType, w, h, masks, location); 567 } 568 else { 569 double fw = w; 570 switch(dataType) { 571 case DataBuffer.TYPE_BYTE: 572 d = new DataBufferByte((int)(Math.ceil(fw/(8/bitsPerBand)))*h); 573 break; 574 575 case DataBuffer.TYPE_USHORT: 576 d = new DataBufferUShort((int)(Math.ceil(fw/(16/bitsPerBand)))*h); 577 break; 578 579 case DataBuffer.TYPE_INT: 580 d = new DataBufferInt((int)(Math.ceil(fw/(32/bitsPerBand)))*h); 581 break; 582 583 default: 584 throw new IllegalArgumentException("Unsupported data type " + 585 dataType); 586 } 587 588 return createPackedRaster(d, w, h, bitsPerBand, location); 589 } 590 } 591 592 /** 593 * Creates a Raster based on a PixelInterleavedSampleModel with the 594 * specified DataBuffer, width, height, scanline stride, pixel 595 * stride, and band offsets. The number of bands is inferred from 596 * bandOffsets.length. The upper left corner of the Raster 597 * is given by the location argument. If location is null, (0, 0) 598 * will be used. 599 * <p> Note that interleaved {@code DataBuffer.TYPE_INT} 600 * Rasters are not supported. To create a 1-band Raster of type 601 * {@code DataBuffer.TYPE_INT}, use 602 * Raster.createPackedRaster(). 603 * @param dataBuffer the {@code DataBuffer} that contains the 604 * image data 605 * @param w the width in pixels of the image data 606 * @param h the height in pixels of the image data 607 * @param scanlineStride the line stride of the image data 608 * @param pixelStride the pixel stride of the image data 609 * @param bandOffsets the offsets of all bands 610 * @param location the upper-left corner of the {@code Raster} 611 * @return a WritableRaster object with the specified 612 * {@code DataBuffer}, width, height, scanline stride, 613 * pixel stride and band offsets. 614 * @throws RasterFormatException if {@code w} or {@code h} 615 * is less than or equal to zero, or computing either 616 * {@code location.x + w} or 617 * {@code location.y + h} results in integer 618 * overflow 619 * @throws IllegalArgumentException if {@code dataType} is not 620 * one of the supported data types, which are 621 * {@code DataBuffer.TYPE_BYTE}, 622 * {@code DataBuffer.TYPE_USHORT} 623 * @throws RasterFormatException if {@code dataBuffer} has more 624 * than one bank. 625 * @throws NullPointerException if {@code dataBuffer} is null 626 */ 627 public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer, 628 int w, int h, 629 int scanlineStride, 630 int pixelStride, 631 int bandOffsets[], 632 Point location) { 633 if (dataBuffer == null) { 634 throw new NullPointerException("DataBuffer cannot be null"); 635 } 636 if (location == null) { 637 location = new Point(0, 0); 638 } 639 int dataType = dataBuffer.getDataType(); 640 641 PixelInterleavedSampleModel csm = 642 new PixelInterleavedSampleModel(dataType, w, h, 643 pixelStride, 644 scanlineStride, 645 bandOffsets); 646 switch(dataType) { 647 case DataBuffer.TYPE_BYTE: 648 if (dataBuffer instanceof DataBufferByte) { 649 return new ByteInterleavedRaster(csm, 650 (DataBufferByte)dataBuffer, location); 651 } 652 break; 653 654 case DataBuffer.TYPE_USHORT: 655 if (dataBuffer instanceof DataBufferUShort) { 656 return new ShortInterleavedRaster(csm, 657 (DataBufferUShort)dataBuffer, location); 658 } 659 break; 660 661 default: 662 throw new IllegalArgumentException("Unsupported data type " + 663 dataType); 664 } 665 666 // Create the generic raster 667 return new SunWritableRaster(csm, dataBuffer, location); 668 } 669 670 /** 671 * Creates a Raster based on a BandedSampleModel with the 672 * specified DataBuffer, width, height, scanline stride, bank 673 * indices, and band offsets. The number of bands is inferred 674 * from bankIndices.length and bandOffsets.length, which must be 675 * the same. The upper left corner of the Raster is given by the 676 * location argument. If location is null, (0, 0) will be used. 677 * @param dataBuffer the {@code DataBuffer} that contains the 678 * image data 679 * @param w the width in pixels of the image data 680 * @param h the height in pixels of the image data 681 * @param scanlineStride the line stride of the image data 682 * @param bankIndices the bank indices for each band 683 * @param bandOffsets the offsets of all bands 684 * @param location the upper-left corner of the {@code Raster} 685 * @return a WritableRaster object with the specified 686 * {@code DataBuffer}, width, height, scanline stride, 687 * bank indices and band offsets. 688 * @throws RasterFormatException if {@code w} or {@code h} 689 * is less than or equal to zero, or computing either 690 * {@code location.x + w} or 691 * {@code location.y + h} results in integer 692 * overflow 693 * @throws IllegalArgumentException if {@code dataType} is not 694 * one of the supported data types, which are 695 * {@code DataBuffer.TYPE_BYTE}, 696 * {@code DataBuffer.TYPE_USHORT} 697 * or {@code DataBuffer.TYPE_INT} 698 * @throws NullPointerException if {@code dataBuffer} is null 699 */ 700 public static WritableRaster createBandedRaster(DataBuffer dataBuffer, 701 int w, int h, 702 int scanlineStride, 703 int bankIndices[], 704 int bandOffsets[], 705 Point location) { 706 if (dataBuffer == null) { 707 throw new NullPointerException("DataBuffer cannot be null"); 708 } 709 if (location == null) { 710 location = new Point(0,0); 711 } 712 int dataType = dataBuffer.getDataType(); 713 714 int bands = bankIndices.length; 715 if (bandOffsets.length != bands) { 716 throw new IllegalArgumentException( 717 "bankIndices.length != bandOffsets.length"); 718 } 719 720 BandedSampleModel bsm = 721 new BandedSampleModel(dataType, w, h, 722 scanlineStride, 723 bankIndices, bandOffsets); 724 725 switch(dataType) { 726 case DataBuffer.TYPE_BYTE: 727 if (dataBuffer instanceof DataBufferByte) { 728 return new ByteBandedRaster(bsm, 729 (DataBufferByte)dataBuffer, location); 730 } 731 break; 732 733 case DataBuffer.TYPE_USHORT: 734 if (dataBuffer instanceof DataBufferUShort) { 735 return new ShortBandedRaster(bsm, 736 (DataBufferUShort)dataBuffer, location); 737 } 738 break; 739 740 case DataBuffer.TYPE_INT: 741 if (dataBuffer instanceof DataBufferInt) { 742 return new SunWritableRaster(bsm, 743 (DataBufferInt)dataBuffer, location); 744 } 745 break; 746 747 default: 748 throw new IllegalArgumentException("Unsupported data type " + 749 dataType); 750 } 751 752 // Create the generic raster 753 return new SunWritableRaster(bsm, dataBuffer, location); 754 } 755 756 /** 757 * Creates a Raster based on a SinglePixelPackedSampleModel with 758 * the specified DataBuffer, width, height, scanline stride, and 759 * band masks. The number of bands is inferred from bandMasks.length. 760 * The upper left corner of the Raster is given by 761 * the location argument. If location is null, (0, 0) will be used. 762 * @param dataBuffer the {@code DataBuffer} that contains the 763 * image data 764 * @param w the width in pixels of the image data 765 * @param h the height in pixels of the image data 766 * @param scanlineStride the line stride of the image data 767 * @param bandMasks an array containing an entry for each band 768 * @param location the upper-left corner of the {@code Raster} 769 * @return a WritableRaster object with the specified 770 * {@code DataBuffer}, width, height, scanline stride, 771 * and band masks. 772 * @throws RasterFormatException if {@code w} or {@code h} 773 * is less than or equal to zero, or computing either 774 * {@code location.x + w} or 775 * {@code location.y + h} results in integer 776 * overflow 777 * @throws IllegalArgumentException if {@code dataType} is not 778 * one of the supported data types, which are 779 * {@code DataBuffer.TYPE_BYTE}, 780 * {@code DataBuffer.TYPE_USHORT} 781 * or {@code DataBuffer.TYPE_INT} 782 * @throws RasterFormatException if {@code dataBuffer} has more 783 * than one bank. 784 * @throws NullPointerException if {@code dataBuffer} is null 785 */ 786 public static WritableRaster createPackedRaster(DataBuffer dataBuffer, 787 int w, int h, 788 int scanlineStride, 789 int bandMasks[], 790 Point location) { 791 if (dataBuffer == null) { 792 throw new NullPointerException("DataBuffer cannot be null"); 793 } 794 if (location == null) { 795 location = new Point(0,0); 796 } 797 int dataType = dataBuffer.getDataType(); 798 799 SinglePixelPackedSampleModel sppsm = 800 new SinglePixelPackedSampleModel(dataType, w, h, scanlineStride, 801 bandMasks); 802 803 switch(dataType) { 804 case DataBuffer.TYPE_BYTE: 805 if (dataBuffer instanceof DataBufferByte) { 806 return new ByteInterleavedRaster(sppsm, 807 (DataBufferByte)dataBuffer, location); 808 } 809 break; 810 811 case DataBuffer.TYPE_USHORT: 812 if (dataBuffer instanceof DataBufferUShort) { 813 return new ShortInterleavedRaster(sppsm, 814 (DataBufferUShort)dataBuffer, location); 815 } 816 break; 817 818 case DataBuffer.TYPE_INT: 819 if (dataBuffer instanceof DataBufferInt) { 820 return new IntegerInterleavedRaster(sppsm, 821 (DataBufferInt)dataBuffer, location); 822 } 823 break; 824 825 default: 826 throw new IllegalArgumentException("Unsupported data type " + 827 dataType); 828 } 829 830 // Create the generic raster 831 return new SunWritableRaster(sppsm, dataBuffer, location); 832 } 833 834 /** 835 * Creates a Raster based on a MultiPixelPackedSampleModel with the 836 * specified DataBuffer, width, height, and bits per pixel. The upper 837 * left corner of the Raster is given by the location argument. If 838 * location is null, (0, 0) will be used. 839 * @param dataBuffer the {@code DataBuffer} that contains the 840 * image data 841 * @param w the width in pixels of the image data 842 * @param h the height in pixels of the image data 843 * @param bitsPerPixel the number of bits for each pixel 844 * @param location the upper-left corner of the {@code Raster} 845 * @return a WritableRaster object with the specified 846 * {@code DataBuffer}, width, height, and 847 * bits per pixel. 848 * @throws RasterFormatException if {@code w} or {@code h} 849 * is less than or equal to zero, or computing either 850 * {@code location.x + w} or 851 * {@code location.y + h} results in integer 852 * overflow 853 * @throws IllegalArgumentException if {@code dataType} is not 854 * one of the supported data types, which are 855 * {@code DataBuffer.TYPE_BYTE}, 856 * {@code DataBuffer.TYPE_USHORT} 857 * or {@code DataBuffer.TYPE_INT} 858 * @throws RasterFormatException if {@code dataBuffer} has more 859 * than one bank. 860 * @throws NullPointerException if {@code dataBuffer} is null 861 */ 862 public static WritableRaster createPackedRaster(DataBuffer dataBuffer, 863 int w, int h, 864 int bitsPerPixel, 865 Point location) { 866 if (dataBuffer == null) { 867 throw new NullPointerException("DataBuffer cannot be null"); 868 } 869 if (location == null) { 870 location = new Point(0,0); 871 } 872 int dataType = dataBuffer.getDataType(); 873 874 if (dataType != DataBuffer.TYPE_BYTE && 875 dataType != DataBuffer.TYPE_USHORT && 876 dataType != DataBuffer.TYPE_INT) { 877 throw new IllegalArgumentException("Unsupported data type " + 878 dataType); 879 } 880 881 if (dataBuffer.getNumBanks() != 1) { 882 throw new 883 RasterFormatException("DataBuffer for packed Rasters"+ 884 " must only have 1 bank."); 885 } 886 887 MultiPixelPackedSampleModel mppsm = 888 new MultiPixelPackedSampleModel(dataType, w, h, bitsPerPixel); 889 890 if (dataBuffer instanceof DataBufferByte && 891 (bitsPerPixel == 1 || bitsPerPixel == 2 || bitsPerPixel == 4)) { 892 return new BytePackedRaster(mppsm, (DataBufferByte)dataBuffer, location); 893 } else { 894 return new SunWritableRaster(mppsm, dataBuffer, location); 895 } 896 } 897 898 899 /** 900 * Creates a Raster with the specified SampleModel and DataBuffer. 901 * The upper left corner of the Raster is given by the location argument. 902 * If location is null, (0, 0) will be used. 903 * @param sm the specified {@code SampleModel} 904 * @param db the specified {@code DataBuffer} 905 * @param location the upper-left corner of the {@code Raster} 906 * @return a {@code Raster} with the specified 907 * {@code SampleModel}, {@code DataBuffer}, and 908 * location. 909 * @throws RasterFormatException if computing either 910 * {@code location.x + sm.getWidth()} or 911 * {@code location.y + sm.getHeight()} results in integer 912 * overflow 913 * @throws RasterFormatException if {@code db} has more 914 * than one bank and {@code sm} is a 915 * PixelInterleavedSampleModel, SinglePixelPackedSampleModel, 916 * or MultiPixelPackedSampleModel. 917 * @throws NullPointerException if either SampleModel or DataBuffer is 918 * null 919 */ 920 public static Raster createRaster(SampleModel sm, 921 DataBuffer db, 922 Point location) { 923 if ((sm == null) || (db == null)) { 924 throw new NullPointerException("SampleModel and DataBuffer cannot be null"); 925 } 926 927 if (location == null) { 928 location = new Point(0,0); 929 } 930 int dataType = sm.getDataType(); 931 932 if (sm instanceof PixelInterleavedSampleModel) { 933 switch(dataType) { 934 case DataBuffer.TYPE_BYTE: 935 if (db instanceof DataBufferByte) { 936 return new ByteInterleavedRaster(sm, 937 (DataBufferByte)db, location); 938 } 939 break; 940 941 case DataBuffer.TYPE_USHORT: 942 if (db instanceof DataBufferUShort) { 943 return new ShortInterleavedRaster(sm, 944 (DataBufferUShort)db, location); 945 } 946 break; 947 } 948 } else if (sm instanceof SinglePixelPackedSampleModel) { 949 switch(dataType) { 950 case DataBuffer.TYPE_BYTE: 951 if (db instanceof DataBufferByte) { 952 return new ByteInterleavedRaster(sm, 953 (DataBufferByte)db, location); 954 } 955 break; 956 957 case DataBuffer.TYPE_USHORT: 958 if (db instanceof DataBufferUShort) { 959 return new ShortInterleavedRaster(sm, 960 (DataBufferUShort)db, location); 961 } 962 break; 963 964 case DataBuffer.TYPE_INT: 965 if (db instanceof DataBufferInt) { 966 return new IntegerInterleavedRaster(sm, 967 (DataBufferInt)db, location); 968 } 969 break; 970 } 971 } else if (sm instanceof MultiPixelPackedSampleModel && 972 dataType == DataBuffer.TYPE_BYTE && 973 db instanceof DataBufferByte && 974 sm.getSampleSize(0) < 8) { 975 return new BytePackedRaster(sm, (DataBufferByte)db, location); 976 } 977 978 // we couldn't do anything special - do the generic thing 979 return new Raster(sm, db, location); 980 } 981 982 /** 983 * Creates a WritableRaster with the specified SampleModel. 984 * The upper left corner of the Raster is given by the location argument. 985 * If location is null, (0, 0) will be used. 986 * @param sm the specified {@code SampleModel} 987 * @param location the upper-left corner of the 988 * {@code WritableRaster} 989 * @return a {@code WritableRaster} with the specified 990 * {@code SampleModel} and location. 991 * @throws RasterFormatException if computing either 992 * {@code location.x + sm.getWidth()} or 993 * {@code location.y + sm.getHeight()} results in integer 994 * overflow 995 */ 996 public static WritableRaster createWritableRaster(SampleModel sm, 997 Point location) { 998 if (location == null) { 999 location = new Point(0,0); 1000 } 1001 1002 return createWritableRaster(sm, sm.createDataBuffer(), location); 1003 } 1004 1005 /** 1006 * Creates a WritableRaster with the specified SampleModel and DataBuffer. 1007 * The upper left corner of the Raster is given by the location argument. 1008 * If location is null, (0, 0) will be used. 1009 * @param sm the specified {@code SampleModel} 1010 * @param db the specified {@code DataBuffer} 1011 * @param location the upper-left corner of the 1012 * {@code WritableRaster} 1013 * @return a {@code WritableRaster} with the specified 1014 * {@code SampleModel}, {@code DataBuffer}, and 1015 * location. 1016 * @throws RasterFormatException if computing either 1017 * {@code location.x + sm.getWidth()} or 1018 * {@code location.y + sm.getHeight()} results in integer 1019 * overflow 1020 * @throws RasterFormatException if {@code db} has more 1021 * than one bank and {@code sm} is a 1022 * PixelInterleavedSampleModel, SinglePixelPackedSampleModel, 1023 * or MultiPixelPackedSampleModel. 1024 * @throws NullPointerException if either SampleModel or DataBuffer is null 1025 */ 1026 public static WritableRaster createWritableRaster(SampleModel sm, 1027 DataBuffer db, 1028 Point location) { 1029 if ((sm == null) || (db == null)) { 1030 throw new NullPointerException("SampleModel and DataBuffer cannot be null"); 1031 } 1032 if (location == null) { 1033 location = new Point(0,0); 1034 } 1035 1036 int dataType = sm.getDataType(); 1037 1038 if (sm instanceof PixelInterleavedSampleModel) { 1039 switch(dataType) { 1040 case DataBuffer.TYPE_BYTE: 1041 if (db instanceof DataBufferByte) { 1042 return new ByteInterleavedRaster(sm, 1043 (DataBufferByte)db, location); 1044 } 1045 break; 1046 1047 case DataBuffer.TYPE_USHORT: 1048 if (db instanceof DataBufferUShort) { 1049 return new ShortInterleavedRaster(sm, 1050 (DataBufferUShort)db, location); 1051 } 1052 break; 1053 } 1054 } else if (sm instanceof SinglePixelPackedSampleModel) { 1055 switch(dataType) { 1056 case DataBuffer.TYPE_BYTE: 1057 if (db instanceof DataBufferByte) { 1058 return new ByteInterleavedRaster(sm, 1059 (DataBufferByte)db, location); 1060 } 1061 break; 1062 1063 case DataBuffer.TYPE_USHORT: 1064 if (db instanceof DataBufferUShort) { 1065 return new ShortInterleavedRaster(sm, 1066 (DataBufferUShort)db, location); 1067 } 1068 break; 1069 1070 case DataBuffer.TYPE_INT: 1071 if (db instanceof DataBufferInt) { 1072 return new IntegerInterleavedRaster(sm, 1073 (DataBufferInt)db, location); 1074 } 1075 break; 1076 } 1077 } else if (sm instanceof MultiPixelPackedSampleModel && 1078 dataType == DataBuffer.TYPE_BYTE && 1079 db instanceof DataBufferByte && 1080 sm.getSampleSize(0) < 8) { 1081 return new BytePackedRaster(sm, (DataBufferByte)db, location); 1082 } 1083 1084 // we couldn't do anything special - do the generic thing 1085 return new SunWritableRaster(sm,db,location); 1086 } 1087 1088 /** 1089 * Constructs a Raster with the given SampleModel. The Raster's 1090 * upper left corner is origin and it is the same size as the 1091 * SampleModel. A DataBuffer large enough to describe the 1092 * Raster is automatically created. 1093 * @param sampleModel The SampleModel that specifies the layout 1094 * @param origin The Point that specified the origin 1095 * @throws RasterFormatException if computing either 1096 * {@code origin.x + sampleModel.getWidth()} or 1097 * {@code origin.y + sampleModel.getHeight()} results in 1098 * integer overflow 1099 * @throws NullPointerException either {@code sampleModel} or 1100 * {@code origin} is null 1101 */ 1102 protected Raster(SampleModel sampleModel, 1103 Point origin) { 1104 this(sampleModel, 1105 sampleModel.createDataBuffer(), 1106 new Rectangle(origin.x, 1107 origin.y, 1108 sampleModel.getWidth(), 1109 sampleModel.getHeight()), 1110 origin, 1111 null); 1112 } 1113 1114 /** 1115 * Constructs a Raster with the given SampleModel and DataBuffer. 1116 * The Raster's upper left corner is origin and it is the same size 1117 * as the SampleModel. The DataBuffer is not initialized and must 1118 * be compatible with SampleModel. 1119 * @param sampleModel The SampleModel that specifies the layout 1120 * @param dataBuffer The DataBuffer that contains the image data 1121 * @param origin The Point that specifies the origin 1122 * @throws RasterFormatException if computing either 1123 * {@code origin.x + sampleModel.getWidth()} or 1124 * {@code origin.y + sampleModel.getHeight()} results in 1125 * integer overflow 1126 * @throws NullPointerException either {@code sampleModel} or 1127 * {@code origin} is null 1128 */ 1129 protected Raster(SampleModel sampleModel, 1130 DataBuffer dataBuffer, 1131 Point origin) { 1132 this(sampleModel, 1133 dataBuffer, 1134 new Rectangle(origin.x, 1135 origin.y, 1136 sampleModel.getWidth(), 1137 sampleModel.getHeight()), 1138 origin, 1139 null); 1140 } 1141 1142 /** 1143 * Constructs a Raster with the given SampleModel, DataBuffer, and 1144 * parent. aRegion specifies the bounding rectangle of the new 1145 * Raster. When translated into the base Raster's coordinate 1146 * system, aRegion must be contained by the base Raster. 1147 * (The base Raster is the Raster's ancestor which has no parent.) 1148 * sampleModelTranslate specifies the sampleModelTranslateX and 1149 * sampleModelTranslateY values of the new Raster. 1150 * 1151 * Note that this constructor should generally be called by other 1152 * constructors or create methods, it should not be used directly. 1153 * @param sampleModel The SampleModel that specifies the layout 1154 * @param dataBuffer The DataBuffer that contains the image data 1155 * @param aRegion The Rectangle that specifies the image area 1156 * @param sampleModelTranslate The Point that specifies the translation 1157 * from SampleModel to Raster coordinates 1158 * @param parent The parent (if any) of this raster 1159 * @throws NullPointerException if any of {@code sampleModel}, 1160 * {@code dataBuffer}, {@code aRegion} or 1161 * {@code sampleModelTranslate} is null 1162 * @throws RasterFormatException if {@code aRegion} has width 1163 * or height less than or equal to zero, or computing either 1164 * {@code aRegion.x + aRegion.width} or 1165 * {@code aRegion.y + aRegion.height} results in integer 1166 * overflow 1167 */ 1168 protected Raster(SampleModel sampleModel, 1169 DataBuffer dataBuffer, 1170 Rectangle aRegion, 1171 Point sampleModelTranslate, 1172 Raster parent) { 1173 1174 if ((sampleModel == null) || (dataBuffer == null) || 1175 (aRegion == null) || (sampleModelTranslate == null)) { 1176 throw new NullPointerException("SampleModel, dataBuffer, aRegion and " + 1177 "sampleModelTranslate cannot be null"); 1178 } 1179 this.sampleModel = sampleModel; 1180 this.dataBuffer = dataBuffer; 1181 minX = aRegion.x; 1182 minY = aRegion.y; 1183 width = aRegion.width; 1184 height = aRegion.height; 1185 if (width <= 0 || height <= 0) { 1186 throw new RasterFormatException("negative or zero " + 1187 ((width <= 0) ? "width" : "height")); 1188 } 1189 if ((minX + width) < minX) { 1190 throw new RasterFormatException( 1191 "overflow condition for X coordinates of Raster"); 1192 } 1193 if ((minY + height) < minY) { 1194 throw new RasterFormatException( 1195 "overflow condition for Y coordinates of Raster"); 1196 } 1197 1198 sampleModelTranslateX = sampleModelTranslate.x; 1199 sampleModelTranslateY = sampleModelTranslate.y; 1200 1201 numBands = sampleModel.getNumBands(); 1202 numDataElements = sampleModel.getNumDataElements(); 1203 this.parent = parent; 1204 } 1205 1206 1207 /** 1208 * Returns the parent Raster (if any) of this Raster or null. 1209 * @return the parent Raster or {@code null}. 1210 */ 1211 public Raster getParent() { 1212 return parent; 1213 } 1214 1215 /** 1216 * Returns the X translation from the coordinate system of the 1217 * SampleModel to that of the Raster. To convert a pixel's X 1218 * coordinate from the Raster coordinate system to the SampleModel 1219 * coordinate system, this value must be subtracted. 1220 * @return the X translation from the coordinate space of the 1221 * Raster's SampleModel to that of the Raster. 1222 */ 1223 public final int getSampleModelTranslateX() { 1224 return sampleModelTranslateX; 1225 } 1226 1227 /** 1228 * Returns the Y translation from the coordinate system of the 1229 * SampleModel to that of the Raster. To convert a pixel's Y 1230 * coordinate from the Raster coordinate system to the SampleModel 1231 * coordinate system, this value must be subtracted. 1232 * @return the Y translation from the coordinate space of the 1233 * Raster's SampleModel to that of the Raster. 1234 */ 1235 public final int getSampleModelTranslateY() { 1236 return sampleModelTranslateY; 1237 } 1238 1239 /** 1240 * Create a compatible WritableRaster the same size as this Raster with 1241 * the same SampleModel and a new initialized DataBuffer. 1242 * @return a compatible {@code WritableRaster} with the same sample 1243 * model and a new data buffer. 1244 */ 1245 public WritableRaster createCompatibleWritableRaster() { 1246 return new SunWritableRaster(sampleModel, new Point(0,0)); 1247 } 1248 1249 /** 1250 * Create a compatible WritableRaster with the specified size, a new 1251 * SampleModel, and a new initialized DataBuffer. 1252 * @param w the specified width of the new {@code WritableRaster} 1253 * @param h the specified height of the new {@code WritableRaster} 1254 * @return a compatible {@code WritableRaster} with the specified 1255 * size and a new sample model and data buffer. 1256 * @exception RasterFormatException if the width or height is less than 1257 * or equal to zero. 1258 */ 1259 public WritableRaster createCompatibleWritableRaster(int w, int h) { 1260 if (w <= 0 || h <=0) { 1261 throw new RasterFormatException("negative " + 1262 ((w <= 0) ? "width" : "height")); 1263 } 1264 1265 SampleModel sm = sampleModel.createCompatibleSampleModel(w,h); 1266 1267 return new SunWritableRaster(sm, new Point(0,0)); 1268 } 1269 1270 /** 1271 * Create a compatible WritableRaster with location (minX, minY) 1272 * and size (width, height) specified by rect, a 1273 * new SampleModel, and a new initialized DataBuffer. 1274 * @param rect a {@code Rectangle} that specifies the size and 1275 * location of the {@code WritableRaster} 1276 * @return a compatible {@code WritableRaster} with the specified 1277 * size and location and a new sample model and data buffer. 1278 * @throws RasterFormatException if {@code rect} has width 1279 * or height less than or equal to zero, or computing either 1280 * {@code rect.x + rect.width} or 1281 * {@code rect.y + rect.height} results in integer 1282 * overflow 1283 * @throws NullPointerException if {@code rect} is null 1284 */ 1285 public WritableRaster createCompatibleWritableRaster(Rectangle rect) { 1286 if (rect == null) { 1287 throw new NullPointerException("Rect cannot be null"); 1288 } 1289 return createCompatibleWritableRaster(rect.x, rect.y, 1290 rect.width, rect.height); 1291 } 1292 1293 /** 1294 * Create a compatible WritableRaster with the specified 1295 * location (minX, minY) and size (width, height), a 1296 * new SampleModel, and a new initialized DataBuffer. 1297 * @param x the X coordinate of the upper-left corner of 1298 * the {@code WritableRaster} 1299 * @param y the Y coordinate of the upper-left corner of 1300 * the {@code WritableRaster} 1301 * @param w the specified width of the {@code WritableRaster} 1302 * @param h the specified height of the {@code WritableRaster} 1303 * @return a compatible {@code WritableRaster} with the specified 1304 * size and location and a new sample model and data buffer. 1305 * @throws RasterFormatException if {@code w} or {@code h} 1306 * is less than or equal to zero, or computing either 1307 * {@code x + w} or 1308 * {@code y + h} results in integer 1309 * overflow 1310 */ 1311 public WritableRaster createCompatibleWritableRaster(int x, int y, 1312 int w, int h) { 1313 WritableRaster ret = createCompatibleWritableRaster(w, h); 1314 return ret.createWritableChild(0,0,w,h,x,y,null); 1315 } 1316 1317 /** 1318 * Create a Raster with the same size, SampleModel and DataBuffer 1319 * as this one, but with a different location. The new Raster 1320 * will possess a reference to the current Raster, accessible 1321 * through its getParent() method. 1322 * 1323 * @param childMinX the X coordinate of the upper-left 1324 * corner of the new {@code Raster} 1325 * @param childMinY the Y coordinate of the upper-left 1326 * corner of the new {@code Raster} 1327 * @return a new {@code Raster} with the same size, SampleModel, 1328 * and DataBuffer as this {@code Raster}, but with the 1329 * specified location. 1330 * @throws RasterFormatException if computing either 1331 * {@code childMinX + this.getWidth()} or 1332 * {@code childMinY + this.getHeight()} results in integer 1333 * overflow 1334 */ 1335 public Raster createTranslatedChild(int childMinX, int childMinY) { 1336 return createChild(minX,minY,width,height, 1337 childMinX,childMinY,null); 1338 } 1339 1340 /** 1341 * Returns a new Raster which shares all or part of this Raster's 1342 * DataBuffer. The new Raster will possess a reference to the 1343 * current Raster, accessible through its getParent() method. 1344 * 1345 * <p> The parentX, parentY, width and height parameters 1346 * form a Rectangle in this Raster's coordinate space, 1347 * indicating the area of pixels to be shared. An error will 1348 * be thrown if this Rectangle is not contained with the bounds 1349 * of the current Raster. 1350 * 1351 * <p> The new Raster may additionally be translated to a 1352 * different coordinate system for the plane than that used by the current 1353 * Raster. The childMinX and childMinY parameters give the new 1354 * (x, y) coordinate of the upper-left pixel of the returned 1355 * Raster; the coordinate (childMinX, childMinY) in the new Raster 1356 * will map to the same pixel as the coordinate (parentX, parentY) 1357 * in the current Raster. 1358 * 1359 * <p> The new Raster may be defined to contain only a subset of 1360 * the bands of the current Raster, possibly reordered, by means 1361 * of the bandList parameter. If bandList is null, it is taken to 1362 * include all of the bands of the current Raster in their current 1363 * order. 1364 * 1365 * <p> To create a new Raster that contains a subregion of the current 1366 * Raster, but shares its coordinate system and bands, 1367 * this method should be called with childMinX equal to parentX, 1368 * childMinY equal to parentY, and bandList equal to null. 1369 * 1370 * @param parentX The X coordinate of the upper-left corner 1371 * in this Raster's coordinates 1372 * @param parentY The Y coordinate of the upper-left corner 1373 * in this Raster's coordinates 1374 * @param width Width of the region starting at (parentX, parentY) 1375 * @param height Height of the region starting at (parentX, parentY). 1376 * @param childMinX The X coordinate of the upper-left corner 1377 * of the returned Raster 1378 * @param childMinY The Y coordinate of the upper-left corner 1379 * of the returned Raster 1380 * @param bandList Array of band indices, or null to use all bands 1381 * @return a new {@code Raster}. 1382 * @exception RasterFormatException if the specified subregion is outside 1383 * of the raster bounds. 1384 * @throws RasterFormatException if {@code width} or 1385 * {@code height} 1386 * is less than or equal to zero, or computing any of 1387 * {@code parentX + width}, {@code parentY + height}, 1388 * {@code childMinX + width}, or 1389 * {@code childMinY + height} results in integer 1390 * overflow 1391 */ 1392 public Raster createChild(int parentX, int parentY, 1393 int width, int height, 1394 int childMinX, int childMinY, 1395 int bandList[]) { 1396 if (parentX < this.minX) { 1397 throw new RasterFormatException("parentX lies outside raster"); 1398 } 1399 if (parentY < this.minY) { 1400 throw new RasterFormatException("parentY lies outside raster"); 1401 } 1402 if ((parentX + width < parentX) || 1403 (parentX + width > this.width + this.minX)) { 1404 throw new RasterFormatException("(parentX + width) is outside raster"); 1405 } 1406 if ((parentY + height < parentY) || 1407 (parentY + height > this.height + this.minY)) { 1408 throw new RasterFormatException("(parentY + height) is outside raster"); 1409 } 1410 1411 SampleModel subSampleModel; 1412 // Note: the SampleModel for the child Raster should have the same 1413 // width and height as that for the parent, since it represents 1414 // the physical layout of the pixel data. The child Raster's width 1415 // and height represent a "virtual" view of the pixel data, so 1416 // they may be different than those of the SampleModel. 1417 if (bandList == null) { 1418 subSampleModel = sampleModel; 1419 } else { 1420 subSampleModel = sampleModel.createSubsetSampleModel(bandList); 1421 } 1422 1423 int deltaX = childMinX - parentX; 1424 int deltaY = childMinY - parentY; 1425 1426 return new Raster(subSampleModel, getDataBuffer(), 1427 new Rectangle(childMinX, childMinY, width, height), 1428 new Point(sampleModelTranslateX + deltaX, 1429 sampleModelTranslateY + deltaY), this); 1430 } 1431 1432 /** 1433 * Returns the bounding Rectangle of this Raster. This function returns 1434 * the same information as getMinX/MinY/Width/Height. 1435 * @return the bounding box of this {@code Raster}. 1436 */ 1437 public Rectangle getBounds() { 1438 return new Rectangle(minX, minY, width, height); 1439 } 1440 1441 /** Returns the minimum valid X coordinate of the Raster. 1442 * @return the minimum x coordinate of this {@code Raster}. 1443 */ 1444 public final int getMinX() { 1445 return minX; 1446 } 1447 1448 /** Returns the minimum valid Y coordinate of the Raster. 1449 * @return the minimum y coordinate of this {@code Raster}. 1450 */ 1451 public final int getMinY() { 1452 return minY; 1453 } 1454 1455 /** Returns the width in pixels of the Raster. 1456 * @return the width of this {@code Raster}. 1457 */ 1458 public final int getWidth() { 1459 return width; 1460 } 1461 1462 /** Returns the height in pixels of the Raster. 1463 * @return the height of this {@code Raster}. 1464 */ 1465 public final int getHeight() { 1466 return height; 1467 } 1468 1469 /** Returns the number of bands (samples per pixel) in this Raster. 1470 * @return the number of bands of this {@code Raster}. 1471 */ 1472 public final int getNumBands() { 1473 return numBands; 1474 } 1475 1476 /** 1477 * Returns the number of data elements needed to transfer one pixel 1478 * via the getDataElements and setDataElements methods. When pixels 1479 * are transferred via these methods, they may be transferred in a 1480 * packed or unpacked format, depending on the implementation of the 1481 * underlying SampleModel. Using these methods, pixels are transferred 1482 * as an array of getNumDataElements() elements of a primitive type given 1483 * by getTransferType(). The TransferType may or may not be the same 1484 * as the storage data type of the DataBuffer. 1485 * @return the number of data elements. 1486 */ 1487 public final int getNumDataElements() { 1488 return sampleModel.getNumDataElements(); 1489 } 1490 1491 /** 1492 * Returns the TransferType used to transfer pixels via the 1493 * getDataElements and setDataElements methods. When pixels 1494 * are transferred via these methods, they may be transferred in a 1495 * packed or unpacked format, depending on the implementation of the 1496 * underlying SampleModel. Using these methods, pixels are transferred 1497 * as an array of getNumDataElements() elements of a primitive type given 1498 * by getTransferType(). The TransferType may or may not be the same 1499 * as the storage data type of the DataBuffer. The TransferType will 1500 * be one of the types defined in DataBuffer. 1501 * @return this transfer type. 1502 */ 1503 public final int getTransferType() { 1504 return sampleModel.getTransferType(); 1505 } 1506 1507 /** Returns the DataBuffer associated with this Raster. 1508 * @return the {@code DataBuffer} of this {@code Raster}. 1509 */ 1510 public DataBuffer getDataBuffer() { 1511 return dataBuffer; 1512 } 1513 1514 /** Returns the SampleModel that describes the layout of the image data. 1515 * @return the {@code SampleModel} of this {@code Raster}. 1516 */ 1517 public SampleModel getSampleModel() { 1518 return sampleModel; 1519 } 1520 1521 /** 1522 * Returns data for a single pixel in a primitive array of type 1523 * TransferType. For image data supported by the Java 2D(tm) API, 1524 * this will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 1525 * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, 1526 * or DataBuffer.TYPE_DOUBLE. Data may be returned in a packed format, 1527 * thus increasing efficiency for data transfers. 1528 * An ArrayIndexOutOfBoundsException may be thrown 1529 * if the coordinates are not in bounds. However, explicit bounds 1530 * checking is not guaranteed. 1531 * A ClassCastException will be thrown if the input object is non null 1532 * and references anything other than an array of TransferType. 1533 * @see java.awt.image.SampleModel#getDataElements(int, int, Object, DataBuffer) 1534 * @param x The X coordinate of the pixel location 1535 * @param y The Y coordinate of the pixel location 1536 * @param outData An object reference to an array of type defined by 1537 * getTransferType() and length getNumDataElements(). 1538 * If null, an array of appropriate type and size will be 1539 * allocated 1540 * @return An object reference to an array of type defined by 1541 * getTransferType() with the requested pixel data. 1542 * 1543 * @throws ArrayIndexOutOfBoundsException if the coordinates are not 1544 * in bounds, or if outData is too small to hold the output. 1545 */ 1546 public Object getDataElements(int x, int y, Object outData) { 1547 return sampleModel.getDataElements(x - sampleModelTranslateX, 1548 y - sampleModelTranslateY, 1549 outData, dataBuffer); 1550 } 1551 1552 /** 1553 * Returns the pixel data for the specified rectangle of pixels in a 1554 * primitive array of type TransferType. 1555 * For image data supported by the Java 2D API, this 1556 * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 1557 * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, 1558 * or DataBuffer.TYPE_DOUBLE. Data may be returned in a packed format, 1559 * thus increasing efficiency for data transfers. 1560 * An ArrayIndexOutOfBoundsException may be thrown 1561 * if the coordinates are not in bounds. However, explicit bounds 1562 * checking is not guaranteed. 1563 * A ClassCastException will be thrown if the input object is non null 1564 * and references anything other than an array of TransferType. 1565 * @see java.awt.image.SampleModel#getDataElements(int, int, int, int, Object, DataBuffer) 1566 * @param x The X coordinate of the upper-left pixel location 1567 * @param y The Y coordinate of the upper-left pixel location 1568 * @param w Width of the pixel rectangle 1569 * @param h Height of the pixel rectangle 1570 * @param outData An object reference to an array of type defined by 1571 * getTransferType() and length w*h*getNumDataElements(). 1572 * If null, an array of appropriate type and size will be 1573 * allocated. 1574 * @return An object reference to an array of type defined by 1575 * getTransferType() with the requested pixel data. 1576 * 1577 * @throws ArrayIndexOutOfBoundsException if the coordinates are not 1578 * in bounds, or if outData is too small to hold the output. 1579 */ 1580 public Object getDataElements(int x, int y, int w, int h, Object outData) { 1581 return sampleModel.getDataElements(x - sampleModelTranslateX, 1582 y - sampleModelTranslateY, 1583 w, h, outData, dataBuffer); 1584 } 1585 1586 /** 1587 * Returns the samples in an array of int for the specified pixel. 1588 * An ArrayIndexOutOfBoundsException may be thrown 1589 * if the coordinates are not in bounds. However, explicit bounds 1590 * checking is not guaranteed. 1591 * @param x The X coordinate of the pixel location 1592 * @param y The Y coordinate of the pixel location 1593 * @param iArray An optionally preallocated int array 1594 * @return the samples for the specified pixel. 1595 * 1596 * @throws ArrayIndexOutOfBoundsException if the coordinates are not 1597 * in bounds, or if iArray is too small to hold the output. 1598 */ 1599 public int[] getPixel(int x, int y, int iArray[]) { 1600 return sampleModel.getPixel(x - sampleModelTranslateX, 1601 y - sampleModelTranslateY, 1602 iArray, dataBuffer); 1603 } 1604 1605 /** 1606 * Returns the samples in an array of float for the 1607 * specified pixel. 1608 * An ArrayIndexOutOfBoundsException may be thrown 1609 * if the coordinates are not in bounds. However, explicit bounds 1610 * checking is not guaranteed. 1611 * @param x The X coordinate of the pixel location 1612 * @param y The Y coordinate of the pixel location 1613 * @param fArray An optionally preallocated float array 1614 * @return the samples for the specified pixel. 1615 * 1616 * @throws ArrayIndexOutOfBoundsException if the coordinates are not 1617 * in bounds, or if fArray is too small to hold the output. 1618 */ 1619 public float[] getPixel(int x, int y, float fArray[]) { 1620 return sampleModel.getPixel(x - sampleModelTranslateX, 1621 y - sampleModelTranslateY, 1622 fArray, dataBuffer); 1623 } 1624 1625 /** 1626 * Returns the samples in an array of double for the specified pixel. 1627 * An ArrayIndexOutOfBoundsException may be thrown 1628 * if the coordinates are not in bounds. However, explicit bounds 1629 * checking is not guaranteed. 1630 * @param x The X coordinate of the pixel location 1631 * @param y The Y coordinate of the pixel location 1632 * @param dArray An optionally preallocated double array 1633 * @return the samples for the specified pixel. 1634 * 1635 * @throws ArrayIndexOutOfBoundsException if the coordinates are not 1636 * in bounds, or if dArray is too small to hold the output. 1637 */ 1638 public double[] getPixel(int x, int y, double dArray[]) { 1639 return sampleModel.getPixel(x - sampleModelTranslateX, 1640 y - sampleModelTranslateY, 1641 dArray, dataBuffer); 1642 } 1643 1644 /** 1645 * Returns an int array containing all samples for a rectangle of pixels, 1646 * one sample per array element. 1647 * An ArrayIndexOutOfBoundsException may be thrown 1648 * if the coordinates are not in bounds. However, explicit bounds 1649 * checking is not guaranteed. 1650 * @param x The X coordinate of the upper-left pixel location 1651 * @param y The Y coordinate of the upper-left pixel location 1652 * @param w Width of the pixel rectangle 1653 * @param h Height of the pixel rectangle 1654 * @param iArray An optionally pre-allocated int array 1655 * @return the samples for the specified rectangle of pixels. 1656 * 1657 * @throws ArrayIndexOutOfBoundsException if the coordinates are not 1658 * in bounds, or if iArray is too small to hold the output. 1659 */ 1660 public int[] getPixels(int x, int y, int w, int h, int iArray[]) { 1661 return sampleModel.getPixels(x - sampleModelTranslateX, 1662 y - sampleModelTranslateY, w, h, 1663 iArray, dataBuffer); 1664 } 1665 1666 /** 1667 * Returns a float array containing all samples for a rectangle of pixels, 1668 * one sample per array element. 1669 * An ArrayIndexOutOfBoundsException may be thrown 1670 * if the coordinates are not in bounds. However, explicit bounds 1671 * checking is not guaranteed. 1672 * @param x The X coordinate of the pixel location 1673 * @param y The Y coordinate of the pixel location 1674 * @param w Width of the pixel rectangle 1675 * @param h Height of the pixel rectangle 1676 * @param fArray An optionally pre-allocated float array 1677 * @return the samples for the specified rectangle of pixels. 1678 * 1679 * @throws ArrayIndexOutOfBoundsException if the coordinates are not 1680 * in bounds, or if fArray is too small to hold the output. 1681 */ 1682 public float[] getPixels(int x, int y, int w, int h, 1683 float fArray[]) { 1684 return sampleModel.getPixels(x - sampleModelTranslateX, 1685 y - sampleModelTranslateY, w, h, 1686 fArray, dataBuffer); 1687 } 1688 1689 /** 1690 * Returns a double array containing all samples for a rectangle of pixels, 1691 * one sample per array element. 1692 * An ArrayIndexOutOfBoundsException may be thrown 1693 * if the coordinates are not in bounds. However, explicit bounds 1694 * checking is not guaranteed. 1695 * @param x The X coordinate of the upper-left pixel location 1696 * @param y The Y coordinate of the upper-left pixel location 1697 * @param w Width of the pixel rectangle 1698 * @param h Height of the pixel rectangle 1699 * @param dArray An optionally pre-allocated double array 1700 * @return the samples for the specified rectangle of pixels. 1701 * 1702 * @throws ArrayIndexOutOfBoundsException if the coordinates are not 1703 * in bounds, or if dArray is too small to hold the output. 1704 */ 1705 public double[] getPixels(int x, int y, int w, int h, 1706 double dArray[]) { 1707 return sampleModel.getPixels(x - sampleModelTranslateX, 1708 y - sampleModelTranslateY, 1709 w, h, dArray, dataBuffer); 1710 } 1711 1712 1713 /** 1714 * Returns the sample in a specified band for the pixel located 1715 * at (x,y) as an int. 1716 * An ArrayIndexOutOfBoundsException may be thrown 1717 * if the coordinates are not in bounds. However, explicit bounds 1718 * checking is not guaranteed. 1719 * @param x The X coordinate of the pixel location 1720 * @param y The Y coordinate of the pixel location 1721 * @param b The band to return 1722 * @return the sample in the specified band for the pixel at the 1723 * specified coordinate. 1724 * 1725 * @throws ArrayIndexOutOfBoundsException if the coordinates or 1726 * the band index are not in bounds. 1727 */ 1728 public int getSample(int x, int y, int b) { 1729 return sampleModel.getSample(x - sampleModelTranslateX, 1730 y - sampleModelTranslateY, b, 1731 dataBuffer); 1732 } 1733 1734 /** 1735 * Returns the sample in a specified band 1736 * for the pixel located at (x,y) as a float. 1737 * An ArrayIndexOutOfBoundsException may be thrown 1738 * if the coordinates are not in bounds. However, explicit bounds 1739 * checking is not guaranteed. 1740 * @param x The X coordinate of the pixel location 1741 * @param y The Y coordinate of the pixel location 1742 * @param b The band to return 1743 * @return the sample in the specified band for the pixel at the 1744 * specified coordinate. 1745 * 1746 * @throws ArrayIndexOutOfBoundsException if the coordinates or 1747 * the band index are not in bounds. 1748 */ 1749 public float getSampleFloat(int x, int y, int b) { 1750 return sampleModel.getSampleFloat(x - sampleModelTranslateX, 1751 y - sampleModelTranslateY, b, 1752 dataBuffer); 1753 } 1754 1755 /** 1756 * Returns the sample in a specified band 1757 * for a pixel located at (x,y) as a double. 1758 * An ArrayIndexOutOfBoundsException may be thrown 1759 * if the coordinates are not in bounds. However, explicit bounds 1760 * checking is not guaranteed. 1761 * @param x The X coordinate of the pixel location 1762 * @param y The Y coordinate of the pixel location 1763 * @param b The band to return 1764 * @return the sample in the specified band for the pixel at the 1765 * specified coordinate. 1766 * 1767 * @throws ArrayIndexOutOfBoundsException if the coordinates or 1768 * the band index are not in bounds. 1769 */ 1770 public double getSampleDouble(int x, int y, int b) { 1771 return sampleModel.getSampleDouble(x - sampleModelTranslateX, 1772 y - sampleModelTranslateY, 1773 b, dataBuffer); 1774 } 1775 1776 /** 1777 * Returns the samples for a specified band for the specified rectangle 1778 * of pixels in an int array, one sample per array element. 1779 * An ArrayIndexOutOfBoundsException may be thrown 1780 * if the coordinates are not in bounds. However, explicit bounds 1781 * checking is not guaranteed. 1782 * @param x The X coordinate of the upper-left pixel location 1783 * @param y The Y coordinate of the upper-left pixel location 1784 * @param w Width of the pixel rectangle 1785 * @param h Height of the pixel rectangle 1786 * @param b The band to return 1787 * @param iArray An optionally pre-allocated int array 1788 * @return the samples for the specified band for the specified 1789 * rectangle of pixels. 1790 * 1791 * @throws ArrayIndexOutOfBoundsException if the coordinates or 1792 * the band index are not in bounds, or if iArray is too small to 1793 * hold the output. 1794 */ 1795 public int[] getSamples(int x, int y, int w, int h, int b, 1796 int iArray[]) { 1797 return sampleModel.getSamples(x - sampleModelTranslateX, 1798 y - sampleModelTranslateY, 1799 w, h, b, iArray, 1800 dataBuffer); 1801 } 1802 1803 /** 1804 * Returns the samples for a specified band for the specified rectangle 1805 * of pixels in a float array, one sample per array element. 1806 * An ArrayIndexOutOfBoundsException may be thrown 1807 * if the coordinates are not in bounds. However, explicit bounds 1808 * checking is not guaranteed. 1809 * @param x The X coordinate of the upper-left pixel location 1810 * @param y The Y coordinate of the upper-left pixel location 1811 * @param w Width of the pixel rectangle 1812 * @param h Height of the pixel rectangle 1813 * @param b The band to return 1814 * @param fArray An optionally pre-allocated float array 1815 * @return the samples for the specified band for the specified 1816 * rectangle of pixels. 1817 * 1818 * @throws ArrayIndexOutOfBoundsException if the coordinates or 1819 * the band index are not in bounds, or if fArray is too small to 1820 * hold the output. 1821 */ 1822 public float[] getSamples(int x, int y, int w, int h, int b, 1823 float fArray[]) { 1824 return sampleModel.getSamples(x - sampleModelTranslateX, 1825 y - sampleModelTranslateY, 1826 w, h, b, fArray, dataBuffer); 1827 } 1828 1829 /** 1830 * Returns the samples for a specified band for a specified rectangle 1831 * of pixels in a double array, one sample per array element. 1832 * An ArrayIndexOutOfBoundsException may be thrown 1833 * if the coordinates are not in bounds. However, explicit bounds 1834 * checking is not guaranteed. 1835 * @param x The X coordinate of the upper-left pixel location 1836 * @param y The Y coordinate of the upper-left pixel location 1837 * @param w Width of the pixel rectangle 1838 * @param h Height of the pixel rectangle 1839 * @param b The band to return 1840 * @param dArray An optionally pre-allocated double array 1841 * @return the samples for the specified band for the specified 1842 * rectangle of pixels. 1843 * 1844 * @throws ArrayIndexOutOfBoundsException if the coordinates or 1845 * the band index are not in bounds, or if dArray is too small to 1846 * hold the output. 1847 */ 1848 public double[] getSamples(int x, int y, int w, int h, int b, 1849 double dArray[]) { 1850 return sampleModel.getSamples(x - sampleModelTranslateX, 1851 y - sampleModelTranslateY, 1852 w, h, b, dArray, dataBuffer); 1853 } 1854 1855 }