History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/awt/image/ByteComponentRaster.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/awt/image/ByteComponentRaster.java+926−0
@@ -0,0 +1,926 @@
1/*
2 * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
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.SinglePixelPackedSampleModel;
33import java.awt.image.DataBuffer;
34import java.awt.image.DataBufferByte;
35import java.awt.Rectangle;
36import java.awt.Point;
37
38/**
39 * This class defines a Raster with pixels consisting of one or more 8-bit
40 * data elements stored in close proximity to each other in a single byte
41 * array.
42 * The bit precision per data element is that
43 * of the data type (that is, the bit precision for this Raster is 8).
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 an
47 * IndexColorModel if there is only one band.
48 * <p>
49 * For example, 3-3-2 RGB image data can be represented by a
50 * ByteComponentRaster using a SinglePixelPackedSampleModel and
51 * a ComponentColorModel.
52 *
53 */
54public class ByteComponentRaster extends SunWritableRaster {
55
56 /** private band offset for use by native code */
57 protected int bandOffset;
58
59 /** Data offsets for each band of image data. */
60 protected int[] dataOffsets;
61
62 /** Scanline stride of the image data contained in this Raster. */
63 protected int scanlineStride;
64
65 /** Pixel stride of the image data contained in this Raster. */
66 protected int pixelStride;
67
68 /** The image data array. */
69 protected byte[] data;
70
71 int type;
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 static private native void initIDs();
80 static {
81 /* ensure that the necessary native libraries are loaded */
82 NativeLibLoader.loadLibraries();
83 initIDs();
84 }
85
86 /**
87 * Constructs a ByteComponentRaster with the given SampleModel.
88 * The Raster's upper left corner is origin and it is the same
89 * size as the SampleModel. A DataBuffer large enough to describe the
90 * Raster is automatically created. SampleModel must be of type
91 * SinglePixelPackedSampleModel or ComponentSampleModel.
92 * @param sampleModel The SampleModel that specifies the layout.
93 * @param origin The Point that specified the origin.
94 */
95 public ByteComponentRaster(SampleModel sampleModel, Point origin) {
96 this(sampleModel,
97 sampleModel.createDataBuffer(),
98 new Rectangle(origin.x,
99 origin.y,
100 sampleModel.getWidth(),
101 sampleModel.getHeight()),
102 origin,
103 null);
104 }
105
106 /**
107 * Constructs a ByteComponentRaster with the given SampleModel
108 * and DataBuffer. The Raster's upper left corner is origin and
109 * it is the same size as the SampleModel. The DataBuffer is not
110 * initialized and must be a DataBufferByte compatible with SampleModel.
111 * SampleModel must be of type SinglePixelPackedSampleModel
112 * or ComponentSampleModel.
113 * @param sampleModel The SampleModel that specifies the layout.
114 * @param dataBuffer The DataBufferShort that contains the image data.
115 * @param origin The Point that specifies the origin.
116 */
117 public ByteComponentRaster(SampleModel sampleModel,
118 DataBuffer dataBuffer,
119 Point origin) {
120 this(sampleModel,
121 dataBuffer,
122 new Rectangle(origin.x,
123 origin.y,
124 sampleModel.getWidth(),
125 sampleModel.getHeight()),
126 origin,
127 null);
128 }
129
130 /**
131 * Constructs a ByteComponentRaster with the given SampleModel,
132 * DataBuffer, and parent. DataBuffer must be a DataBufferByte and
133 * SampleModel must be of type SinglePixelPackedSampleModel
134 * or ComponentSampleModel.
135 * When translated into the base Raster's
136 * coordinate system, aRegion must be contained by the base Raster.
137 * Origin is the coordinate in the new Raster's coordinate system of
138 * the origin of the base Raster. (The base Raster is the Raster's
139 * ancestor which has no parent.)
140 *
141 * Note that this constructor should generally be called by other
142 * constructors or create methods, it should not be used directly.
143 * @param sampleModel The SampleModel that specifies the layout.
144 * @param dataBuffer The DataBufferShort that contains the image data.
145 * @param aRegion The Rectangle that specifies the image area.
146 * @param origin The Point that specifies the origin.
147 * @param parent The parent (if any) of this raster.
148 */
149 public ByteComponentRaster(SampleModel sampleModel,
150 DataBuffer dataBuffer,
151 Rectangle aRegion,
152 Point origin,
153 ByteComponentRaster parent) {
154 super(sampleModel, dataBuffer, aRegion, origin, parent);
155 this.maxX = minX + width;
156 this.maxY = minY + height;
157
158 if (!(dataBuffer instanceof DataBufferByte)) {
159 throw new RasterFormatException("ByteComponentRasters must have " +
160 "byte DataBuffers");
161 }
162
163 DataBufferByte dbb = (DataBufferByte)dataBuffer;
164 this.data = stealData(dbb, 0);
165 if (dbb.getNumBanks() != 1) {
166 throw new
167 RasterFormatException("DataBuffer for ByteComponentRasters"+
168 " must only have 1 bank.");
169 }
170 int dbOffset = dbb.getOffset();
171
172 if (sampleModel instanceof ComponentSampleModel) {
173 ComponentSampleModel ism = (ComponentSampleModel)sampleModel;
174 this.type = IntegerComponentRaster.TYPE_BYTE_SAMPLES;
175 this.scanlineStride = ism.getScanlineStride();
176 this.pixelStride = ism.getPixelStride();
177 this.dataOffsets = ism.getBandOffsets();
178 int xOffset = aRegion.x - origin.x;
179 int yOffset = aRegion.y - origin.y;
180 for (int i = 0; i < getNumDataElements(); i++) {
181 dataOffsets[i] += dbOffset +
182 xOffset*pixelStride+yOffset*scanlineStride;
183 }
184 } else if (sampleModel instanceof SinglePixelPackedSampleModel) {
185 SinglePixelPackedSampleModel sppsm =
186 (SinglePixelPackedSampleModel)sampleModel;
187 this.type = IntegerComponentRaster.TYPE_BYTE_PACKED_SAMPLES;
188 this.scanlineStride = sppsm.getScanlineStride();
189 this.pixelStride = 1;
190 this.dataOffsets = new int[1];
191 this.dataOffsets[0] = dbOffset;
192 int xOffset = aRegion.x - origin.x;
193 int yOffset = aRegion.y - origin.y;
194 dataOffsets[0] += xOffset*pixelStride+yOffset*scanlineStride;
195 } else {
196 throw new RasterFormatException("IntegerComponentRasters must " +
197 "have ComponentSampleModel or SinglePixelPackedSampleModel");
198 }
199 this.bandOffset = this.dataOffsets[0];
200
201 verify(false);
202 }
203
204 /**
205 * Returns a copy of the data offsets array. For each band the data offset
206 * is the index into the band's data array, of the first sample of the
207 * band.
208 */
209 public int[] getDataOffsets() {
210 return (int[]) dataOffsets.clone();
211 }
212
213 /**
214 * Returns the data offset for the specified band. The data offset
215 * is the index into the data array
216 * in which the first sample of the first scanline is stored.
217 * @param band The band whose offset is returned.
218 */
219 public int getDataOffset(int band) {
220 return dataOffsets[band];
221 }
222
223 /**
224 * Returns the scanline stride -- the number of data array elements between
225 * a given sample and the sample in the same column of the next row in the
226 * same band.
227 */
228 public int getScanlineStride() {
229 return scanlineStride;
230 }
231
232 /**
233 * Returns pixel stride -- the number of data array elements between two
234 * samples for the same band on the same scanline.
235 */
236 public int getPixelStride() {
237 return pixelStride;
238 }
239
240 /**
241 * Returns a reference to the data array.
242 */
243 public byte[] getDataStorage() {
244 return data;
245 }
246
247 /**
248 * Returns the data elements for all bands at the specified
249 * location.
250 * An ArrayIndexOutOfBounds exception will be thrown at runtime
251 * if the pixel coordinate is out of bounds.
252 * A ClassCastException will be thrown if the input object is non null
253 * and references anything other than an array of transferType.
254 * @param x The X coordinate of the pixel location.
255 * @param y The Y coordinate of the pixel location.
256 * @param outData An object reference to an array of type defined by
257 * getTransferType() and length getNumDataElements().
258 * If null an array of appropriate type and size will be
259 * allocated.
260 * @return An object reference to an array of type defined by
261 * getTransferType() with the request pixel data.
262 */
263 public Object getDataElements(int x, int y, Object obj) {
264 if ((x < this.minX) || (y < this.minY) ||
265 (x >= this.maxX) || (y >= this.maxY)) {
266 throw new ArrayIndexOutOfBoundsException
267 ("Coordinate out of bounds!");
268 }
269 byte outData[];
270 if (obj == null) {
271 outData = new byte[numDataElements];
272 } else {
273 outData = (byte[])obj;
274 }
275 int off = (y-minY)*scanlineStride +
276 (x-minX)*pixelStride;
277
278 for (int band = 0; band < numDataElements; band++) {
279 outData[band] = data[dataOffsets[band] + off];
280 }
281
282 return outData;
283 }
284
285 /**
286 * Returns an array of data elements from the specified rectangular
287 * region.
288 * An ArrayIndexOutOfBounds exception will be thrown at runtime
289 * if the pixel coordinates are out of bounds.
290 * A ClassCastException will be thrown if the input object is non null
291 * and references anything other than an array of transferType.
292 * <pre>
293 * byte[] bandData = (byte[])raster.getDataElements(x, y, w, h, null);
294 * int numDataElements = raster.getNumDataElements();
295 * byte[] pixel = new byte[numDataElements];
296 * // To find a data element at location (x2, y2)
297 * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
298 * pixel, 0, numDataElements);
299 * </pre>
300 * @param x The X coordinate of the upper left pixel location.
301 * @param y The Y coordinate of the upper left pixel location.
302 * @param width Width of the pixel rectangle.
303 * @param height Height of the pixel rectangle.
304 * @param outData An object reference to an array of type defined by
305 * getTransferType() and length w*h*getNumDataElements().
306 * If null an array of appropriate type and size will be
307 * allocated.
308 * @return An object reference to an array of type defined by
309 * getTransferType() with the request pixel data.
310 */
311 public Object getDataElements(int x, int y, int w, int h, Object obj) {
312 if ((x < this.minX) || (y < this.minY) ||
313 (x + w > this.maxX) || (y + h > this.maxY)) {
314 throw new ArrayIndexOutOfBoundsException
315 ("Coordinate out of bounds!");
316 }
317 byte outData[];
318 if (obj == null) {
319 outData = new byte[w*h*numDataElements];
320 } else {
321 outData = (byte[])obj;
322 }
323
324 int yoff = (y-minY)*scanlineStride +
325 (x-minX)*pixelStride;
326 int xoff;
327 int off = 0;
328 int xstart;
329 int ystart;
330
331 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
332 xoff = yoff;
333 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
334 for (int c = 0; c < numDataElements; c++) {
335 outData[off++] = data[dataOffsets[c] + xoff];
336 }
337 }
338 }
339
340 return outData;
341 }
342
343 /**
344 * Returns a byte array of data elements from the specified rectangular
345 * region for the specified band.
346 * An ArrayIndexOutOfBounds exception will be thrown at runtime
347 * if the pixel coordinates are out of bounds.
348 * <pre>
349 * byte[] bandData = raster.getByteData(x, y, w, h, null);
350 * // To find the data element at location (x2, y2)
351 * byte bandElement = bandData[((y2-y)*w + (x2-x))];
352 * </pre>
353 * @param x The X coordinate of the upper left pixel location.
354 * @param y The Y coordinate of the upper left pixel location.
355 * @param width Width of the pixel rectangle.
356 * @param height Height of the pixel rectangle.
357 * @param band The band to return.
358 * @param outData If non-null, data elements for all bands
359 * at the specified location are returned in this array.
360 * @return Data array with data elements for all bands.
361 */
362 public byte[] getByteData(int x, int y, int w, int h,
363 int band, byte[] outData) {
364 // Bounds check for 'band' will be performed automatically
365 if ((x < this.minX) || (y < this.minY) ||
366 (x + w > this.maxX) || (y + h > this.maxY)) {
367 throw new ArrayIndexOutOfBoundsException
368 ("Coordinate out of bounds!");
369 }
370 if (outData == null) {
371 outData = new byte[scanlineStride*h];
372 }
373 int yoff = (y-minY)*scanlineStride +
374 (x-minX)*pixelStride + dataOffsets[band];
375 int xoff;
376 int off = 0;
377 int xstart;
378 int ystart;
379
380 if (pixelStride == 1) {
381 if (scanlineStride == w) {
382 System.arraycopy(data, yoff, outData, 0, w*h);
383 }
384 else {
385 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
386 System.arraycopy(data, yoff, outData, off, w);
387 off += w;
388 }
389 }
390 }
391 else {
392 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
393 xoff = yoff;
394 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
395 outData[off++] = data[xoff];
396 }
397 }
398 }
399
400 return outData;
401 }
402
403 /**
404 * Returns a byte array of data elements from the specified rectangular
405 * region.
406 * An ArrayIndexOutOfBounds exception will be thrown at runtime
407 * if the pixel coordinates are out of bounds.
408 * <pre>
409 * byte[] bandData = raster.getByteData(x, y, w, h, null);
410 * int numDataElements = raster.getnumDataElements();
411 * byte[] pixel = new byte[numDataElements];
412 * // To find a data element at location (x2, y2)
413 * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
414 * pixel, 0, numDataElements);
415 * </pre>
416 * @param x The X coordinate of the upper left pixel location.
417 * @param y The Y coordinate of the upper left pixel location.
418 * @param width Width of the pixel rectangle.
419 * @param height Height of the pixel rectangle.
420 * @param outData If non-null, data elements for all bands
421 * at the specified location are returned in this array.
422 * @return Data array with data elements for all bands.
423 */
424 public byte[] getByteData(int x, int y, int w, int h, byte[] outData) {
425 if ((x < this.minX) || (y < this.minY) ||
426 (x + w > this.maxX) || (y + h > this.maxY)) {
427 throw new ArrayIndexOutOfBoundsException
428 ("Coordinate out of bounds!");
429 }
430 if (outData == null) {
431 outData = new byte[numDataElements*scanlineStride*h];
432 }
433 int yoff = (y-minY)*scanlineStride +
434 (x-minX)*pixelStride;
435 int xoff;
436 int off = 0;
437 int xstart;
438 int ystart;
439
440 // REMIND: Should keep track if dataOffsets are in a nice order
441 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
442 xoff = yoff;
443 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
444 for (int c = 0; c < numDataElements; c++) {
445 outData[off++] = data[dataOffsets[c] + xoff];
446 }
447 }
448 }
449
450 return outData;
451 }
452
453 /**
454 * Stores the data elements for all bands at the specified location.
455 * An ArrayIndexOutOfBounds exception will be thrown at runtime
456 * if the pixel coordinate is out of bounds.
457 * A ClassCastException will be thrown if the input object is non null
458 * and references anything other than an array of transferType.
459 * @param x The X coordinate of the pixel location.
460 * @param y The Y coordinate of the pixel location.
461 * @param inData An object reference to an array of type defined by
462 * getTransferType() and length getNumDataElements()
463 * containing the pixel data to place at x,y.
464 */
465 public void setDataElements(int x, int y, Object obj) {
466 if ((x < this.minX) || (y < this.minY) ||
467 (x >= this.maxX) || (y >= this.maxY)) {
468 throw new ArrayIndexOutOfBoundsException
469 ("Coordinate out of bounds!");
470 }
471 byte inData[] = (byte[])obj;
472 int off = (y-minY)*scanlineStride +
473 (x-minX)*pixelStride;
474
475 for (int i = 0; i < numDataElements; i++) {
476 data[dataOffsets[i] + off] = inData[i];
477 }
478
479 markDirty();
480 }
481
482 /**
483 * Stores the Raster data at the specified location.
484 * An ArrayIndexOutOfBounds exception will be thrown at runtime
485 * if the pixel coordinates are out of bounds.
486 * @param x The X coordinate of the pixel location.
487 * @param y The Y coordinate of the pixel location.
488 * @param inRaster Raster of data to place at x,y location.
489 */
490 public void setDataElements(int x, int y, Raster inRaster) {
491 int dstOffX = inRaster.getMinX() + x;
492 int dstOffY = inRaster.getMinY() + y;
493 int width = inRaster.getWidth();
494 int height = inRaster.getHeight();
495 if ((dstOffX < this.minX) || (dstOffY < this.minY) ||
496 (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) {
497 throw new ArrayIndexOutOfBoundsException
498 ("Coordinate out of bounds!");
499 }
500
501 setDataElements(dstOffX, dstOffY, width, height, inRaster);
502 }
503
504 /**
505 * Stores the Raster data at the specified location.
506 * @param dstX The absolute X coordinate of the destination pixel
507 * that will receive a copy of the upper-left pixel of the
508 * inRaster
509 * @param dstY The absolute Y coordinate of the destination pixel
510 * that will receive a copy of the upper-left pixel of the
511 * inRaster
512 * @param width The number of pixels to store horizontally
513 * @param height The number of pixels to store vertically
514 * @param inRaster Raster of data to place at x,y location.
515 */
516 private void setDataElements(int dstX, int dstY,
517 int width, int height,
518 Raster inRaster) {
519 // Assume bounds checking has been performed previously
520 if (width <= 0 || height <= 0) {
521 return;
522 }
523
524 int srcOffX = inRaster.getMinX();
525 int srcOffY = inRaster.getMinY();
526 Object tdata = null;
527
528 if (inRaster instanceof ByteComponentRaster) {
529 ByteComponentRaster bct = (ByteComponentRaster) inRaster;
530 byte[] bdata = bct.getDataStorage();
531 // REMIND: Do something faster!
532 if (numDataElements == 1) {
533 int toff = bct.getDataOffset(0);
534 int tss = bct.getScanlineStride();
535
536 int srcOffset = toff;
537 int dstOffset = dataOffsets[0]+(dstY-minY)*scanlineStride+
538 (dstX-minX);
539
540
541 if (pixelStride == bct.getPixelStride()) {
542 width *= pixelStride;
543 for (int tmpY=0; tmpY < height; tmpY++) {
544 System.arraycopy(bdata, srcOffset,
545 data, dstOffset, width);
546 srcOffset += tss;
547 dstOffset += scanlineStride;
548 }
549 markDirty();
550 return;
551 }
552 }
553 }
554
555 for (int startY=0; startY < height; startY++) {
556 // Grab one scanline at a time
557 tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
558 width, 1, tdata);
559 setDataElements(dstX, dstY+startY, width, 1, tdata);
560 }
561 }
562
563 /**
564 * Stores an array of data elements into the specified rectangular
565 * region.
566 * An ArrayIndexOutOfBounds exception will be thrown at runtime
567 * if the pixel coordinates are out of bounds.
568 * A ClassCastException will be thrown if the input object is non null
569 * and references anything other than an array of transferType.
570 * The data elements in the
571 * data array are assumed to be packed. That is, a data element
572 * for the nth band at location (x2, y2) would be found at:
573 * <pre>
574 * inData[((y2-y)*w + (x2-x))*numDataElements + n]
575 * </pre>
576 * @param x The X coordinate of the upper left pixel location.
577 * @param y The Y coordinate of the upper left pixel location.
578 * @param w Width of the pixel rectangle.
579 * @param h Height of the pixel rectangle.
580 * @param inData An object reference to an array of type defined by
581 * getTransferType() and length w*h*getNumDataElements()
582 * containing the pixel data to place between x,y and
583 * x+h, y+h.
584 */
585 public void setDataElements(int x, int y, int w, int h, Object obj) {
586 if ((x < this.minX) || (y < this.minY) ||
587 (x + w > this.maxX) || (y + h > this.maxY)) {
588 throw new ArrayIndexOutOfBoundsException
589 ("Coordinate out of bounds!");
590 }
591 byte inData[] = (byte[])obj;
592 int yoff = (y-minY)*scanlineStride +
593 (x-minX)*pixelStride;
594 int xoff;
595 int off = 0;
596 int xstart;
597 int ystart;
598
599 if (numDataElements == 1) {
600 int srcOffset = 0;
601 int dstOffset = yoff + dataOffsets[0];
602 for (ystart=0; ystart < h; ystart++) {
603 xoff = yoff;
604 System.arraycopy(inData, srcOffset,
605 data, dstOffset, w);
606
607 srcOffset += w;
608 dstOffset += scanlineStride;
609 }
610 markDirty();
611 return;
612 }
613
614 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
615 xoff = yoff;
616 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
617 for (int c = 0; c < numDataElements; c++) {
618 data[dataOffsets[c] + xoff] = inData[off++];
619 }
620 }
621 }
622
623 markDirty();
624 }
625
626 /**
627 * Stores a byte array of data elements into the specified rectangular
628 * region for the specified band.
629 * An ArrayIndexOutOfBounds exception will be thrown at runtime
630 * if the pixel coordinates are out of bounds.
631 * The data elements in the
632 * data array are assumed to be packed. That is, a data element
633 * at location (x2, y2) would be found at:
634 * <pre>
635 * inData[((y2-y)*w + (x2-x)) + n]
636 * </pre>
637 * @param x The X coordinate of the upper left pixel location.
638 * @param y The Y coordinate of the upper left pixel location.
639 * @param w Width of the pixel rectangle.
640 * @param h Height of the pixel rectangle.
641 * @param band The band to set.
642 * @param inData The data elements to be stored.
643 */
644 public void putByteData(int x, int y, int w, int h,
645 int band, byte[] inData) {
646 // Bounds check for 'band' will be performed automatically
647 if ((x < this.minX) || (y < this.minY) ||
648 (x + w > this.maxX) || (y + h > this.maxY)) {
649 throw new ArrayIndexOutOfBoundsException
650 ("Coordinate out of bounds!");
651 }
652 int yoff = (y-minY)*scanlineStride +
653 (x-minX)*pixelStride + dataOffsets[band];
654 int xoff;
655 int off = 0;
656 int xstart;
657 int ystart;
658
659 if (pixelStride == 1) {
660 if (scanlineStride == w) {
661 System.arraycopy(inData, 0, data, yoff, w*h);
662 }
663 else {
664 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
665 System.arraycopy(inData, off, data, yoff, w);
666 off += w;
667 }
668 }
669 }
670 else {
671 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
672 xoff = yoff;
673 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
674 data[xoff] = inData[off++];
675 }
676 }
677 }
678
679 markDirty();
680 }
681
682 /**
683 * Stores a byte array of data elements into the specified rectangular
684 * region.
685 * An ArrayIndexOutOfBounds exception will be thrown at runtime
686 * if the pixel coordinates are out of bounds.
687 * The data elements in the
688 * data array are assumed to be packed. That is, a data element
689 * for the nth band at location (x2, y2) would be found at:
690 * <pre>
691 * inData[((y2-y)*w + (x2-x))*numDataElements + n]
692 * </pre>
693 * @param x The X coordinate of the upper left pixel location.
694 * @param y The Y coordinate of the upper left pixel location.
695 * @param w Width of the pixel rectangle.
696 * @param h Height of the pixel rectangle.
697 * @param inData The data elements to be stored.
698 */
699 public void putByteData(int x, int y, int w, int h, byte[] inData) {
700 if ((x < this.minX) || (y < this.minY) ||
701 (x + w > this.maxX) || (y + h > this.maxY)) {
702 throw new ArrayIndexOutOfBoundsException
703 ("Coordinate out of bounds!");
704 }
705 int yoff = (y-minY)*scanlineStride +
706 (x-minX)*pixelStride;
707
708 int xoff;
709 int off = 0;
710 int xstart;
711 int ystart;
712
713 if (numDataElements == 1) {
714 yoff += dataOffsets[0];
715 if (pixelStride == 1) {
716 if (scanlineStride == w) {
717 System.arraycopy(inData, 0, data, yoff, w*h);
718 }
719 else {
720 for (ystart=0; ystart < h; ystart++) {
721 System.arraycopy(inData, off, data, yoff, w);
722 off += w;
723 yoff += scanlineStride;
724 }
725 }
726 }
727 else {
728 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
729 xoff = yoff;
730 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
731 data[xoff] = inData[off++];
732 }
733 }
734 }
735 }
736 else {
737 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
738 xoff = yoff;
739 for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
740 for (int c = 0; c < numDataElements; c++) {
741 data[dataOffsets[c] + xoff] = inData[off++];
742 }
743 }
744 }
745 }
746
747 markDirty();
748 }
749
750 /**
751 * Creates a subraster given a region of the raster. The x and y
752 * coordinates specify the horizontal and vertical offsets
753 * from the upper-left corner of this raster to the upper-left corner
754 * of the subraster. A subset of the bands of the parent Raster may
755 * be specified. If this is null, then all the bands are present in the
756 * subRaster. A translation to the subRaster may also be specified.
757 * Note that the subraster will reference the same
758 * DataBuffer as the parent raster, but using different offsets.
759 * @param x X offset.
760 * @param y Y offset.
761 * @param width Width (in pixels) of the subraster.
762 * @param height Height (in pixels) of the subraster.
763 * @param x0 Translated X origin of the subraster.
764 * @param y0 Translated Y origin of the subraster.
765 * @param bandList Array of band indices.
766 * @exception RasterFormatException
767 * if the specified bounding box is outside of the parent raster.
768 */
769 public Raster createChild(int x, int y,
770 int width, int height,
771 int x0, int y0, int[] bandList) {
772 WritableRaster newRaster = createWritableChild(x, y,
773 width, height,
774 x0, y0,
775 bandList);
776 return (Raster) newRaster;
777 }
778
779 /**
780 * Creates a Writable subRaster given a region of the Raster. The x and y
781 * coordinates specify the horizontal and vertical offsets
782 * from the upper-left corner of this Raster to the upper-left corner
783 * of the subRaster. A subset of the bands of the parent Raster may
784 * be specified. If this is null, then all the bands are present in the
785 * subRaster. A translation to the subRaster may also be specified.
786 * Note that the subRaster will reference the same
787 * DataBuffer as the parent Raster, but using different offsets.
788 * @param x X offset.
789 * @param y Y offset.
790 * @param width Width (in pixels) of the subraster.
791 * @param height Height (in pixels) of the subraster.
792 * @param x0 Translated X origin of the subraster.
793 * @param y0 Translated Y origin of the subraster.
794 * @param bandList Array of band indices.
795 * @exception RasterFormatException
796 * if the specified bounding box is outside of the parent Raster.
797 */
798 public WritableRaster createWritableChild(int x, int y,
799 int width, int height,
800 int x0, int y0,
801 int[] bandList) {
802 if (x < this.minX) {
803 throw new RasterFormatException("x lies outside the raster");
804 }
805 if (y < this.minY) {
806 throw new RasterFormatException("y lies outside the raster");
807 }
808 if ((x+width < x) || (x+width > this.minX + this.width)) {
809 throw new RasterFormatException("(x + width) is outside of Raster");
810 }
811 if ((y+height < y) || (y+height > this.minY + this.height)) {
812 throw new RasterFormatException("(y + height) is outside of Raster");
813 }
814
815 SampleModel sm;
816
817 if (bandList != null)
818 sm = sampleModel.createSubsetSampleModel(bandList);
819 else
820 sm = sampleModel;
821
822 int deltaX = x0 - x;
823 int deltaY = y0 - y;
824
825 return new ByteComponentRaster(sm,
826 dataBuffer,
827 new Rectangle(x0, y0, width, height),
828 new Point(sampleModelTranslateX+deltaX,
829 sampleModelTranslateY+deltaY),
830 this);
831 }
832
833 /**
834 * Creates a Raster with the same layout but using a different
835 * width and height, and with new zeroed data arrays.
836 */
837 public WritableRaster createCompatibleWritableRaster(int w, int h) {
838 if (w <= 0 || h <=0) {
839 throw new RasterFormatException("negative "+
840 ((w <= 0) ? "width" : "height"));
841 }
842
843 SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
844
845 return new ByteComponentRaster(sm , new Point(0,0));
846
847 }
848
849 /**
850 * Creates a Raster with the same layout and the same
851 * width and height, and with new zeroed data arrays. If
852 * the Raster is a subRaster, this will call
853 * createCompatibleRaster(width, height).
854 */
855 public WritableRaster createCompatibleWritableRaster() {
856 return createCompatibleWritableRaster(width,height);
857 }
858
859 /**
860 * Verify that the layout parameters are consistent with
861 * the data. If strictCheck
862 * is false, this method will check for ArrayIndexOutOfBounds conditions. If
863 * strictCheck is true, this method will check for additional error
864 * conditions such as line wraparound (width of a line greater than
865 * the scanline stride).
866 * @return String Error string, if the layout is incompatible with
867 * the data. Otherwise returns null.
868 */
869 private void verify (boolean strictCheck) {
870 // Make sure data for Raster is in a legal range
871 for (int i=0; i < dataOffsets.length; i++) {
872 if (dataOffsets[i] < 0) {
873 throw new RasterFormatException("Data offsets for band "+i+
874 "("+dataOffsets[i]+
875 ") must be >= 0");
876 }
877 }
878
879 int maxSize = 0;
880 int size;
881
882 for (int i=0; i < numDataElements; i++) {
883 size = (height-1)*scanlineStride + (width-1)*pixelStride +
884 dataOffsets[i];
885 if (size > maxSize) {
886 maxSize = size;
887 }
888 }
889 if (data.length < maxSize) {
890 throw new RasterFormatException("Data array too small (should be "+
891 maxSize+" )");
892 }
893 }
894
895 public String toString() {
896 return new String ("ByteComponentRaster: width = "+width+" height = "
897 + height
898 +" #numDataElements "+numDataElements
899 // +" xOff = "+xOffset+" yOff = "+yOffset
900 +" dataOff[0] = "+dataOffsets[0]);
901 }
902
903// /**
904// * For debugging... prints a region of a one-band ByteComponentRaster
905// */
906// public void print(int x, int y, int w, int h) {
907// // REMIND: Only works for 1 band!
908// System.out.println(this);
909// int offset = dataOffsets[0] + y*scanlineStride + x*pixelStride;
910// int off;
911// for (int yoff=0; yoff < h; yoff++, offset += scanlineStride) {
912// off = offset;
913// System.out.print("Line "+(y+yoff)+": ");
914// for (int xoff = 0; xoff < w; xoff++, off+= pixelStride) {
915// String s = Integer.toHexString(data[off]);
916// if (s.length() == 8) {
917// s = s.substring(6,8);
918// }
919// System.out.print(s+" ");
920// }
921// System.out.println("");
922// }
923// }
924
925
926}