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