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