001: /*
002: * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.image;
027:
028: import java.awt.image.Raster;
029: import java.awt.image.WritableRaster;
030: import java.awt.image.RasterFormatException;
031: import java.awt.image.SampleModel;
032: import java.awt.image.BandedSampleModel;
033: import java.awt.image.DataBuffer;
034: import java.awt.image.DataBufferUShort;
035: import java.awt.Rectangle;
036: import java.awt.Point;
037:
038: /**
039: * This class defines a Raster with pixels consisting of multiple 16-bit
040: * samples stored in separate arrays for each band. Operations on
041: * sets of pixels are performed on a given band of each pixel
042: * in the set before moving on to the next band. The arrays used
043: * for storage may be distinct or shared between some or all of
044: * the bands.
045: * There is only one pixel stride and one scanline stride for all
046: * bands. This type of Raster can be used with a
047: * ComponentColorModel. This class requires a BandedSampleModel.
048: *
049: * @version 10 Feb 1997
050: */
051: public class ShortBandedRaster extends SunWritableRaster {
052:
053: /** Data offsets for each band of image data. */
054: int[] dataOffsets;
055:
056: /** Scanline stride of the image data contained in this Raster. */
057: int scanlineStride;
058:
059: /** The image data array. */
060: short[][] data;
061:
062: /** A cached copy of minX + width for use in bounds checks. */
063: private int maxX;
064:
065: /** A cached copy of minY + height for use in bounds checks. */
066: private int maxY;
067:
068: /**
069: * Constructs a ShortBandedRaster with the given SampleModel.
070: * The Raster's upper left corner is origin and it is the same
071: * size as the SampleModel. A DataBuffer large enough to describe the
072: * Raster is automatically created. SampleModel must be of type
073: * BandedSampleModel.
074: * @param sampleModel The SampleModel that specifies the layout.
075: * @param origin The Point that specified the origin.
076: */
077: public ShortBandedRaster(SampleModel sampleModel, Point origin) {
078: this (sampleModel, sampleModel.createDataBuffer(),
079: new Rectangle(origin.x, origin.y, sampleModel
080: .getWidth(), sampleModel.getHeight()), origin,
081: null);
082: }
083:
084: /**
085: * Constructs a ShortBandedRaster with the given SampleModel
086: * and DataBuffer. The Raster's upper left corner is origin and
087: * it is the same size as the SampleModel. The DataBuffer is not
088: * initialized and must be a DataBufferUShort compatible with SampleModel.
089: * SampleModel must be of type BandedSampleModel.
090: * @param sampleModel The SampleModel that specifies the layout.
091: * @param dataBuffer The DataBufferUShort that contains the image data.
092: * @param origin The Point that specifies the origin.
093: */
094: public ShortBandedRaster(SampleModel sampleModel,
095: DataBuffer dataBuffer, Point origin) {
096: this (sampleModel, dataBuffer, new Rectangle(origin.x, origin.y,
097: sampleModel.getWidth(), sampleModel.getHeight()),
098: origin, null);
099: }
100:
101: /**
102: * Constructs a ShortBandedRaster with the given SampleModel,
103: * DataBuffer, and parent. DataBuffer must be a DataBufferUShort and
104: * SampleModel must be of type BandedSampleModel.
105: * When translated into the base Raster's
106: * coordinate system, aRegion must be contained by the base Raster.
107: * Origin is the coordinate in the new Raster's coordinate system of
108: * the origin of the base Raster. (The base Raster is the Raster's
109: * ancestor which has no parent.)
110: *
111: * Note that this constructor should generally be called by other
112: * constructors or create methods, it should not be used directly.
113: * @param sampleModel The SampleModel that specifies the layout.
114: * @param dataBuffer The DataBufferUShort that contains the image data.
115: * @param aRegion The Rectangle that specifies the image area.
116: * @param origin The Point that specifies the origin.
117: * @param parent The parent (if any) of this raster.
118: */
119: public ShortBandedRaster(SampleModel sampleModel,
120: DataBuffer dataBuffer, Rectangle aRegion, Point origin,
121: ShortBandedRaster parent) {
122:
123: super (sampleModel, dataBuffer, aRegion, origin, parent);
124: this .maxX = minX + width;
125: this .maxY = minY + height;
126: if (!(dataBuffer instanceof DataBufferUShort)) {
127: throw new RasterFormatException(
128: "ShortBandedRaster must have "
129: + "ushort DataBuffers");
130: }
131: DataBufferUShort dbus = (DataBufferUShort) dataBuffer;
132:
133: if (sampleModel instanceof BandedSampleModel) {
134: BandedSampleModel bsm = (BandedSampleModel) sampleModel;
135: this .scanlineStride = bsm.getScanlineStride();
136: int bankIndices[] = bsm.getBankIndices();
137: int bandOffsets[] = bsm.getBandOffsets();
138: int dOffsets[] = dbus.getOffsets();
139: dataOffsets = new int[bankIndices.length];
140: data = new short[bankIndices.length][];
141: int xOffset = aRegion.x - origin.x;
142: int yOffset = aRegion.y - origin.y;
143: for (int i = 0; i < bankIndices.length; i++) {
144: data[i] = stealData(dbus, bankIndices[i]);
145: dataOffsets[i] = dOffsets[bankIndices[i]] + xOffset
146: + yOffset * scanlineStride + bandOffsets[i];
147: }
148: } else {
149: throw new RasterFormatException(
150: "ShortBandedRasters must have "
151: + "BandedSampleModels");
152: }
153: verify(false);
154: }
155:
156: /**
157: * Returns a copy of the data offsets array. For each band the data offset
158: * is the index into the band's data array, of the first sample of the
159: * band.
160: */
161: public int[] getDataOffsets() {
162: return (int[]) dataOffsets.clone();
163: }
164:
165: /**
166: * Returns the data offset for the specified band. The data offset
167: * is the index into the band's data array
168: * in which the first sample of the first scanline is stored.
169: * @param The band whose offset is returned.
170: */
171: public int getDataOffset(int band) {
172: return dataOffsets[band];
173: }
174:
175: /**
176: * Returns the scanline stride -- the number of data array elements between
177: * a given sample and the sample in the same column
178: * of the next row in the same band.
179: */
180: public int getScanlineStride() {
181: return scanlineStride;
182: }
183:
184: /**
185: * Returns the pixel stride, which is always equal to one for
186: * a Raster with a BandedSampleModel.
187: */
188: public int getPixelStride() {
189: return 1;
190: }
191:
192: /**
193: * Returns a reference to the entire data array.
194: */
195: public short[][] getDataStorage() {
196: return data;
197: }
198:
199: /**
200: * Returns a reference to the specific band data array.
201: */
202: public short[] getDataStorage(int band) {
203: return data[band];
204: }
205:
206: /**
207: * Returns the data elements for all bands at the specified
208: * location.
209: * An ArrayIndexOutOfBounds exception will be thrown at runtime
210: * if the pixel coordinate is out of bounds.
211: * A ClassCastException will be thrown if the input object is non null
212: * and references anything other than an array of transferType.
213: * @param x The X coordinate of the pixel location.
214: * @param y The Y coordinate of the pixel location.
215: * @param outData An object reference to an array of type defined by
216: * getTransferType() and length getNumDataElements().
217: * If null an array of appropriate type and size will be
218: * allocated.
219: * @return An object reference to an array of type defined by
220: * getTransferType() with the request pixel data.
221: */
222: public Object getDataElements(int x, int y, Object obj) {
223: if ((x < this .minX) || (y < this .minY) || (x >= this .maxX)
224: || (y >= this .maxY)) {
225: throw new ArrayIndexOutOfBoundsException(
226: "Coordinate out of bounds!");
227: }
228: short outData[];
229: if (obj == null) {
230: outData = new short[numDataElements];
231: } else {
232: outData = (short[]) obj;
233: }
234:
235: int off = (y - minY) * scanlineStride + (x - minX);
236:
237: for (int band = 0; band < numDataElements; band++) {
238: outData[band] = data[band][dataOffsets[band] + off];
239: }
240:
241: return outData;
242: }
243:
244: /**
245: * Returns an array of data elements from the specified rectangular
246: * region.
247: * An ArrayIndexOutOfBounds exception will be thrown at runtime
248: * if the pixel coordinates are out of bounds.
249: * <pre>
250: * short[] bandData = (short[])Raster.getDataElements(x, y, w, h, null);
251: * int numDataElements = Raster.getnumDataElements();
252: * short[] pixel = new short[numDataElements];
253: * // To find a data element at location (x2, y2)
254: * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
255: * pixel, 0, numDataElements);
256: * </pre>
257: * @param x The X coordinate of the upper left pixel location.
258: * @param y The Y coordinate of the upper left pixel location.
259: * @param width Width of the pixel rectangle.
260: * @param height Height of the pixel rectangle.
261: * @param outData An object reference to an array of type defined by
262: * getTransferType() and length w*h*getNumDataElements().
263: * If null an array of appropriate type and size will be
264: * allocated.
265: * @return An object reference to an array of type defined by
266: * getTransferType() with the request pixel data.
267: */
268: public Object getDataElements(int x, int y, int w, int h, Object obj) {
269: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
270: || (y + h > this .maxY)) {
271: throw new ArrayIndexOutOfBoundsException(
272: "Coordinate out of bounds!");
273: }
274: short outData[];
275: if (obj == null) {
276: outData = new short[numDataElements * w * h];
277: } else {
278: outData = (short[]) obj;
279: }
280: int yoff = (y - minY) * scanlineStride + (x - minX);
281:
282: for (int c = 0; c < numDataElements; c++) {
283: int off = c;
284: short[] bank = data[c];
285: int dataOffset = dataOffsets[c];
286:
287: int yoff2 = yoff;
288: for (int ystart = 0; ystart < h; ystart++, yoff2 += scanlineStride) {
289: int xoff = dataOffset + yoff2;
290: for (int xstart = 0; xstart < w; xstart++) {
291: outData[off] = bank[xoff++];
292: off += numDataElements;
293: }
294: }
295: }
296:
297: return outData;
298: }
299:
300: /**
301: * Returns a short array of data elements from the specified rectangular
302: * region for the specified band.
303: * An ArrayIndexOutOfBounds exception will be thrown at runtime
304: * if the pixel coordinates are out of bounds.
305: * <pre>
306: * short[] bandData = Raster.getShortData(x, y, w, h, null);
307: * // To find the data element at location (x2, y2)
308: * short bandElement = bandData[((y2-y)*w + (x2-x))];
309: * </pre>
310: * @param x The X coordinate of the upper left pixel location.
311: * @param y The Y coordinate of the upper left pixel location.
312: * @param width Width of the pixel rectangle.
313: * @param height Height of the pixel rectangle.
314: * @param band The band to return.
315: * @param outData If non-null, data elements for all bands
316: * at the specified location are returned in this array.
317: * @return Data array with data elements for all bands.
318: */
319: public short[] getShortData(int x, int y, int w, int h, int band,
320: short[] outData) {
321: // Bounds check for 'band' will be performed automatically
322: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
323: || (y + h > this .maxY)) {
324: throw new ArrayIndexOutOfBoundsException(
325: "Coordinate out of bounds!");
326: }
327: if (outData == null) {
328: outData = new short[scanlineStride * h];
329: }
330: int yoff = (y - minY) * scanlineStride + (x - minX)
331: + dataOffsets[band];
332:
333: if (scanlineStride == w) {
334: System.arraycopy(data[band], yoff, outData, 0, w * h);
335: } else {
336: int off = 0;
337: for (int ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
338: System.arraycopy(data[band], yoff, outData, off, w);
339: off += w;
340: }
341: }
342:
343: return outData;
344: }
345:
346: /**
347: * Returns a short array of data elements from the specified rectangular
348: * region.
349: * An ArrayIndexOutOfBounds exception will be thrown at runtime
350: * if the pixel coordinates are out of bounds.
351: * <pre>
352: * short[] bandData = Raster.getShortData(x, y, w, h, null);
353: * int numDataElements = Raster.getnumDataElements();
354: * short[] pixel = new short[numDataElements];
355: * // To find a data element at location (x2, y2)
356: * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
357: * pixel, 0, numDataElements);
358: * </pre>
359: * @param x The X coordinate of the upper left pixel location.
360: * @param y The Y coordinate of the upper left pixel location.
361: * @param width Width of the pixel rectangle.
362: * @param height Height of the pixel rectangle.
363: * @param outData If non-null, data elements for all bands
364: * at the specified location are returned in this array.
365: * @return Data array with data elements for all bands.
366: */
367: public short[] getShortData(int x, int y, int w, int h,
368: short[] outData) {
369: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
370: || (y + h > this .maxY)) {
371: throw new ArrayIndexOutOfBoundsException(
372: "Coordinate out of bounds!");
373: }
374: if (outData == null) {
375: outData = new short[numDataElements * scanlineStride * h];
376: }
377: int yoff = (y - minY) * scanlineStride + (x - minX);
378:
379: for (int c = 0; c < numDataElements; c++) {
380: int off = c;
381: short[] bank = data[c];
382: int dataOffset = dataOffsets[c];
383:
384: int yoff2 = yoff;
385: for (int ystart = 0; ystart < h; ystart++, yoff2 += scanlineStride) {
386: int xoff = dataOffset + yoff2;
387: for (int xstart = 0; xstart < w; xstart++) {
388: outData[off] = bank[xoff++];
389: off += numDataElements;
390: }
391: }
392: }
393:
394: return outData;
395: }
396:
397: /**
398: * Stores the data element for all bands at the specified location.
399: * An ArrayIndexOutOfBounds exception will be thrown at runtime
400: * if the pixel coordinate is out of bounds.
401: * A ClassCastException will be thrown if the input object is non null
402: * and references anything other than an array of transferType.
403: * @param x The X coordinate of the pixel location.
404: * @param y The Y coordinate of the pixel location.
405: * @param inData An object reference to an array of type defined by
406: * getTransferType() and length getNumDataElements()
407: * containing the pixel data to place at x,y.
408: */
409: public void setDataElements(int x, int y, Object obj) {
410: if ((x < this .minX) || (y < this .minY) || (x >= this .maxX)
411: || (y >= this .maxY)) {
412: throw new ArrayIndexOutOfBoundsException(
413: "Coordinate out of bounds!");
414: }
415: short inData[] = (short[]) obj;
416: int off = (y - minY) * scanlineStride + (x - minX);
417: for (int i = 0; i < numDataElements; i++) {
418: data[i][dataOffsets[i] + off] = inData[i];
419: }
420:
421: markDirty();
422: }
423:
424: /**
425: * Stores the Raster data at the specified location.
426: * An ArrayIndexOutOfBounds exception will be thrown at runtime
427: * if the pixel coordinates are out of bounds.
428: * @param x The X coordinate of the pixel location.
429: * @param y The Y coordinate of the pixel location.
430: * @param inRaster Raster of data to place at x,y location.
431: */
432: public void setDataElements(int x, int y, Raster inRaster) {
433: int dstOffX = x + inRaster.getMinX();
434: int dstOffY = y + inRaster.getMinY();
435: int width = inRaster.getWidth();
436: int height = inRaster.getHeight();
437: if ((dstOffX < this .minX) || (dstOffY < this .minY)
438: || (dstOffX + width > this .maxX)
439: || (dstOffY + height > this .maxY)) {
440: throw new ArrayIndexOutOfBoundsException(
441: "Coordinate out of bounds!");
442: }
443:
444: setDataElements(dstOffX, dstOffY, width, height, inRaster);
445: }
446:
447: /**
448: * Stores the Raster data at the specified location.
449: * @param dstX The absolute X coordinate of the destination pixel
450: * that will receive a copy of the upper-left pixel of the
451: * inRaster
452: * @param dstY The absolute Y coordinate of the destination pixel
453: * that will receive a copy of the upper-left pixel of the
454: * inRaster
455: * @param width The number of pixels to store horizontally
456: * @param height The number of pixels to store vertically
457: * @param inRaster Raster of data to place at x,y location.
458: */
459: private void setDataElements(int dstX, int dstY, int width,
460: int height, Raster inRaster) {
461: // Assume bounds checking has been performed previously
462: if (width <= 0 || height <= 0) {
463: return;
464: }
465:
466: // Write inRaster (minX, minY) to (dstX, dstY)
467:
468: int srcOffX = inRaster.getMinX();
469: int srcOffY = inRaster.getMinY();
470: Object tdata = null;
471:
472: // // REMIND: Do something faster!
473: // if (inRaster instanceof ShortBandedRaster) {
474: // }
475:
476: for (int startY = 0; startY < height; startY++) {
477: // Grab one scanline at a time
478: tdata = inRaster.getDataElements(srcOffX, srcOffY + startY,
479: width, 1, tdata);
480: setDataElements(dstX, dstY + startY, width, 1, tdata);
481: }
482: }
483:
484: /**
485: * Stores an array of data elements into the specified rectangular
486: * region.
487: * An ArrayIndexOutOfBounds exception will be thrown at runtime
488: * if the pixel coordinates are out of bounds.
489: * A ClassCastException will be thrown if the input object is non null
490: * and references anything other than an array of transferType.
491: * The data elements in the
492: * data array are assumed to be packed. That is, a data element
493: * for the nth band at location (x2, y2) would be found at:
494: * <pre>
495: * inData[((y2-y)*w + (x2-x))*numDataElements + n]
496: * </pre>
497: * @param x The X coordinate of the upper left pixel location.
498: * @param y The Y coordinate of the upper left pixel location.
499: * @param w Width of the pixel rectangle.
500: * @param h Height of the pixel rectangle.
501: * @param inData An object reference to an array of type defined by
502: * getTransferType() and length w*h*getNumDataElements()
503: * containing the pixel data to place between x,y and
504: * x+h, y+h.
505: */
506: public void setDataElements(int x, int y, int w, int h, Object obj) {
507: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
508: || (y + h > this .maxY)) {
509: throw new ArrayIndexOutOfBoundsException(
510: "Coordinate out of bounds!");
511: }
512: short inData[] = (short[]) obj;
513: int yoff = (y - minY) * scanlineStride + (x - minX);
514:
515: for (int c = 0; c < numDataElements; c++) {
516: int off = c;
517: short[] bank = data[c];
518: int dataOffset = dataOffsets[c];
519:
520: int yoff2 = yoff;
521: for (int ystart = 0; ystart < h; ystart++, yoff2 += scanlineStride) {
522: int xoff = dataOffset + yoff2;
523: for (int xstart = 0; xstart < w; xstart++) {
524: bank[xoff++] = inData[off];
525: off += numDataElements;
526: }
527: }
528: }
529:
530: markDirty();
531: }
532:
533: /**
534: * Stores a short array of data elements into the specified
535: * rectangular region for the specified band.
536: * An ArrayIndexOutOfBounds exception will be thrown at runtime
537: * if the pixel coordinates are out of bounds.
538: * The data elements in the
539: * data array are assumed to be packed. That is, a data element
540: * at location (x2, y2) would be found at:
541: * <pre>
542: * inData[((y2-y)*w + (x2-x))]
543: * </pre>
544: * @param x The X coordinate of the upper left pixel location.
545: * @param y The Y coordinate of the upper left pixel location.
546: * @param w Width of the pixel rectangle.
547: * @param h Height of the pixel rectangle.
548: * @param band The band to set.
549: * @param inData The data elements to be stored.
550: */
551: public void putShortData(int x, int y, int w, int h, int band,
552: short[] inData) {
553: // Bounds check for 'band' will be performed automatically
554: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
555: || (y + h > this .maxY)) {
556: throw new ArrayIndexOutOfBoundsException(
557: "Coordinate out of bounds!");
558: }
559: int yoff = (y - minY) * scanlineStride + (x - minX)
560: + dataOffsets[band];
561: int xoff;
562: int off = 0;
563: int xstart;
564: int ystart;
565:
566: if (scanlineStride == w) {
567: System.arraycopy(inData, 0, data[band], yoff, w * h);
568: } else {
569: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
570: System.arraycopy(inData, off, data[band], yoff, w);
571: off += w;
572: }
573: }
574:
575: markDirty();
576: }
577:
578: /**
579: * Stores a short integer array of data elements into the specified
580: * rectangular region.
581: * An ArrayIndexOutOfBounds exception will be thrown at runtime
582: * if the pixel coordinates are out of bounds.
583: * The data elements in the
584: * data array are assumed to be packed. That is, a data element
585: * for the nth band at location (x2, y2) would be found at:
586: * <pre>
587: * inData[((y2-y)*w + (x2-x))*numDataElements + n]
588: * </pre>
589: * @param x The X coordinate of the upper left pixel location.
590: * @param y The Y coordinate of the upper left pixel location.
591: * @param w Width of the pixel rectangle.
592: * @param h Height of the pixel rectangle.
593: * @param inData The data elements to be stored.
594: */
595: public void putShortData(int x, int y, int w, int h, short[] inData) {
596: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
597: || (y + h > this .maxY)) {
598: throw new ArrayIndexOutOfBoundsException(
599: "Coordinate out of bounds!");
600: }
601: int yoff = (y - minY) * scanlineStride + (x - minX);
602:
603: for (int c = 0; c < numDataElements; c++) {
604: int off = c;
605: short[] bank = data[c];
606: int dataOffset = dataOffsets[c];
607:
608: int yoff2 = yoff;
609: for (int ystart = 0; ystart < h; ystart++, yoff2 += scanlineStride) {
610: int xoff = dataOffset + yoff2;
611: for (int xstart = 0; xstart < w; xstart++) {
612: bank[xoff++] = inData[off];
613: off += numDataElements;
614: }
615: }
616: }
617:
618: markDirty();
619: }
620:
621: /**
622: * Creates a Writable subRaster given a region of the Raster. The x and y
623: * coordinates specify the horizontal and vertical offsets
624: * from the upper-left corner of this Raster to the upper-left corner
625: * of the subRaster. A subset of the bands of the parent Raster may
626: * be specified. If this is null, then all the bands are present in the
627: * subRaster. A translation to the subRaster may also be specified.
628: * Note that the subRaster will reference the same
629: * DataBuffers as the parent Raster, but using different offsets.
630: * @param x X offset.
631: * @param y Y offset.
632: * @param width Width (in pixels) of the subraster.
633: * @param height Height (in pixels) of the subraster.
634: * @param x0 Translated X origin of the subraster.
635: * @param y0 Translated Y origin of the subraster.
636: * @param bandList Array of band indices.
637: * @exception RasterFormatException
638: * if the specified bounding box is outside of the parent Raster.
639: */
640: public WritableRaster createWritableChild(int x, int y, int width,
641: int height, int x0, int y0, int bandList[]) {
642:
643: if (x < this .minX) {
644: throw new RasterFormatException("x lies outside raster");
645: }
646: if (y < this .minY) {
647: throw new RasterFormatException("y lies outside raster");
648: }
649: if ((x + width < x) || (x + width > this .minX + this .width)) {
650: throw new RasterFormatException(
651: "(x + width) is outside of Raster");
652: }
653: if ((y + height < y) || (y + height > this .minY + this .height)) {
654: throw new RasterFormatException(
655: "(y + height) is outside of Raster");
656: }
657:
658: SampleModel sm;
659:
660: if (bandList != null)
661: sm = sampleModel.createSubsetSampleModel(bandList);
662: else
663: sm = sampleModel;
664:
665: int deltaX = x0 - x;
666: int deltaY = y0 - y;
667:
668: return new ShortBandedRaster(sm, dataBuffer, new Rectangle(x0,
669: y0, width, height), new Point(sampleModelTranslateX
670: + deltaX, sampleModelTranslateY + deltaY), this );
671:
672: }
673:
674: /**
675: * Creates a subraster given a region of the raster. The x and y
676: * coordinates specify the horizontal and vertical offsets
677: * from the upper-left corner of this raster to the upper-left corner
678: * of the subraster. A subset of the bands of the parent Raster may
679: * be specified. If this is null, then all the bands are present in the
680: * subRaster. A translation to the subRaster may also be specified.
681: * Note that the subraster will reference the same
682: * DataBuffers as the parent raster, but using different offsets.
683: * @param x X offset.
684: * @param y Y offset.
685: * @param width Width (in pixels) of the subraster.
686: * @param height Height (in pixels) of the subraster.
687: * @param x0 Translated X origin of the subraster.
688: * @param y0 Translated Y origin of the subraster.
689: * @param bandList Array of band indices.
690: * @exception RasterFormatException
691: * if the specified bounding box is outside of the parent raster.
692: */
693: public Raster createChild(int x, int y, int width, int height,
694: int x0, int y0, int bandList[]) {
695: return createWritableChild(x, y, width, height, x0, y0,
696: bandList);
697: }
698:
699: /**
700: * Creates a Raster with the same layout but using a different
701: * width and height, and with new zeroed data arrays.
702: */
703: public WritableRaster createCompatibleWritableRaster(int w, int h) {
704: if (w <= 0 || h <= 0) {
705: throw new RasterFormatException("negative "
706: + ((w <= 0) ? "width" : "height"));
707: }
708:
709: SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
710:
711: return new ShortBandedRaster(sm, new Point(0, 0));
712: }
713:
714: /**
715: * Creates a Raster with the same layout and the same
716: * width and height, and with new zeroed data arrays. If
717: * the Raster is a subRaster, this will call
718: * createCompatibleRaster(width, height).
719: */
720: public WritableRaster createCompatibleWritableRaster() {
721: return createCompatibleWritableRaster(width, height);
722: }
723:
724: /**
725: * Verify that the layout parameters are consistent with
726: * the data. If strictCheck
727: * is false, this method will check for ArrayIndexOutOfBounds conditions. If
728: * strictCheck is true, this method will check for additional error
729: * conditions such as line wraparound (width of a line greater than
730: * the scanline stride).
731: * @return String Error string, if the layout is incompatible with
732: * the data. Otherwise returns null.
733: */
734: private void verify(boolean strictCheck) {
735: // Make sure data for Raster is in a legal range
736: for (int i = 0; i < dataOffsets.length; i++) {
737: if (dataOffsets[i] < 0) {
738: throw new RasterFormatException(
739: "Data offsets for band " + i + "("
740: + dataOffsets[i] + ") must be >= 0");
741: }
742: }
743:
744: int maxSize = 0;
745: int size;
746:
747: for (int i = 0; i < numDataElements; i++) {
748: size = (height - 1) * scanlineStride + (width - 1)
749: + dataOffsets[i];
750: if (size > maxSize) {
751: maxSize = size;
752: }
753: }
754: for (int i = 0; i < numDataElements; i++) {
755: if (data[i].length < maxSize) {
756: throw new RasterFormatException(
757: "Data array too small (should be " + maxSize
758: + " )");
759: }
760: }
761: }
762:
763: public String toString() {
764: return new String("ShortBandedRaster: width = " + width
765: + " height = " + height + " #numBands " + numBands
766: + " #dataElements " + numDataElements);
767:
768: }
769:
770: }
|