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