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