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+
26+package sun.awt.image;
27+import java.awt.image.Raster;
28+import java.awt.image.WritableRaster;
29+import java.awt.image.RasterFormatException;
30+import java.awt.image.SampleModel;
31+import java.awt.image.ComponentSampleModel;
32+import java.awt.image.SinglePixelPackedSampleModel;
33+import java.awt.image.DataBuffer;
34+import java.awt.image.DataBufferByte;
35+import java.awt.Rectangle;
36+import 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+ */
54+public 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+}