0001: /*
0002: * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package sun.awt.image;
0027:
0028: import java.awt.image.Raster;
0029: import java.awt.image.WritableRaster;
0030: import java.awt.image.RasterFormatException;
0031: import java.awt.image.SampleModel;
0032: import java.awt.image.ComponentSampleModel;
0033: import java.awt.image.PixelInterleavedSampleModel;
0034: import java.awt.image.SinglePixelPackedSampleModel;
0035: import java.awt.image.DataBuffer;
0036: import java.awt.image.DataBufferByte;
0037: import java.awt.Rectangle;
0038: import java.awt.Point;
0039:
0040: /**
0041: * This class defines a Raster with pixels consisting of one or more
0042: * 8-bit data elements stored in close proximity to each other in a
0043: * single byte array.
0044: * <p>
0045: * The bit precision per data element is that of the data type (that
0046: * is, the bit precision for this Raster is 8). There is only one
0047: * pixel stride and one scanline stride for all bands. This type of
0048: * Raster can be used with a ComponentColorModel if there are multiple
0049: * bands, or an IndexColorModel if there is only one band.
0050: *
0051: * @version 7 Jul 1999
0052: */
0053: public class ByteInterleavedRaster extends ByteComponentRaster {
0054:
0055: /** True if the data offsets range from 0 to (pixelStride - 1) in order. */
0056: boolean inOrder;
0057:
0058: /**
0059: * The DataBuffer offset, minus sampleModelTranslateX*pixelStride,
0060: * minus sampleModelTranslateY*scanlineStride, used to calculate
0061: * pixel offsets.
0062: */
0063: int dbOffset;
0064: int dbOffsetPacked;
0065:
0066: /** True if a SinglePixelPackedSampleModel is being used. */
0067: boolean packed = false;
0068:
0069: /** If packed == true, the SampleModel's bit masks. */
0070: int[] bitMasks;
0071:
0072: /** If packed == true, the SampleModel's bit offsets. */
0073: int[] bitOffsets;
0074:
0075: /** A cached copy of minX + width for use in bounds checks. */
0076: private int maxX;
0077:
0078: /** A cached copy of minY + height for use in bounds checks. */
0079: private int maxY;
0080:
0081: /**
0082: * Constructs a ByteInterleavedRaster with the given SampleModel.
0083: * The Raster's upper left corner is origin and it is the same
0084: * size as the SampleModel. A DataBuffer large enough to describe the
0085: * Raster is automatically created. SampleModel must be of type
0086: * SinglePixelPackedSampleModel or InterleavedSampleModel.
0087: * @param sampleModel The SampleModel that specifies the layout.
0088: * @param origin The Point that specified the origin.
0089: */
0090: public ByteInterleavedRaster(SampleModel sampleModel, Point origin) {
0091: this (sampleModel, sampleModel.createDataBuffer(),
0092: new Rectangle(origin.x, origin.y, sampleModel
0093: .getWidth(), sampleModel.getHeight()), origin,
0094: null);
0095: }
0096:
0097: /**
0098: * Constructs a ByteInterleavedRaster with the given SampleModel
0099: * and DataBuffer. The Raster's upper left corner is origin and
0100: * it is the same size as the SampleModel. The DataBuffer is not
0101: * initialized and must be a DataBufferByte compatible with SampleModel.
0102: * SampleModel must be of type SinglePixelPackedSampleModel
0103: * or InterleavedSampleModel.
0104: * @param sampleModel The SampleModel that specifies the layout.
0105: * @param dataBuffer The DataBufferShort that contains the image data.
0106: * @param origin The Point that specifies the origin.
0107: */
0108: public ByteInterleavedRaster(SampleModel sampleModel,
0109: DataBuffer dataBuffer, Point origin) {
0110: this (sampleModel, dataBuffer, new Rectangle(origin.x, origin.y,
0111: sampleModel.getWidth(), sampleModel.getHeight()),
0112: origin, null);
0113: }
0114:
0115: /*** Analyzes a ComponentSampleModel to determine if it can function
0116: * as a PixelInterleavedSampleModel. In order to do so, it must use
0117: * only bank 0 of its DataBuffer, and the data offsets must span a range
0118: * of less than pixelStride.
0119: *
0120: * <p> These properties are trivially true for a 1-banded SampleModel.
0121: */
0122: private boolean isInterleaved(ComponentSampleModel sm) {
0123: // Analyze ComponentSampleModel to determine if it has the
0124: // properties of a PixelInterleavedSampleModel
0125:
0126: int numBands = sampleModel.getNumBands();
0127: if (numBands == 1) {
0128: return true;
0129: }
0130:
0131: // Determine banks used
0132: int[] bankIndices = sm.getBankIndices();
0133: for (int i = 0; i < numBands; i++) {
0134: if (bankIndices[i] != 0) {
0135: return false;
0136: }
0137: }
0138:
0139: // Determine range of band offsets
0140: int[] bandOffsets = sm.getBandOffsets();
0141: int minOffset = bandOffsets[0];
0142: int maxOffset = minOffset;
0143: for (int i = 1; i < numBands; i++) {
0144: int offset = bandOffsets[i];
0145: if (offset < minOffset) {
0146: minOffset = offset;
0147: }
0148: if (offset > maxOffset) {
0149: maxOffset = offset;
0150: }
0151: }
0152: if (maxOffset - minOffset >= sm.getPixelStride()) {
0153: return false;
0154: }
0155:
0156: return true;
0157: }
0158:
0159: /**
0160: * Constructs a ByteInterleavedRaster with the given SampleModel,
0161: * DataBuffer, and parent. DataBuffer must be a DataBufferByte and
0162: * SampleModel must be of type SinglePixelPackedSampleModel
0163: * or InterleavedSampleModel.
0164: * When translated into the base Raster's
0165: * coordinate system, aRegion must be contained by the base Raster.
0166: * Origin is the coordinate in the new Raster's coordinate system of
0167: * the origin of the base Raster. (The base Raster is the Raster's
0168: * ancestor which has no parent.)
0169: *
0170: * Note that this constructor should generally be called by other
0171: * constructors or create methods, it should not be used directly.
0172: * @param sampleModel The SampleModel that specifies the layout.
0173: * @param dataBuffer The DataBufferShort that contains the image data.
0174: * @param aRegion The Rectangle that specifies the image area.
0175: * @param origin The Point that specifies the origin.
0176: * @param parent The parent (if any) of this raster.
0177: */
0178: public ByteInterleavedRaster(SampleModel sampleModel,
0179: DataBuffer dataBuffer, Rectangle aRegion, Point origin,
0180: ByteInterleavedRaster parent) {
0181: super (sampleModel, dataBuffer, aRegion, origin, parent);
0182: this .maxX = minX + width;
0183: this .maxY = minY + height;
0184:
0185: if (!(dataBuffer instanceof DataBufferByte)) {
0186: throw new RasterFormatException(
0187: "ByteInterleavedRasters must have "
0188: + "byte DataBuffers");
0189: }
0190:
0191: DataBufferByte dbb = (DataBufferByte) dataBuffer;
0192: this .data = stealData(dbb, 0);
0193:
0194: int xOffset = aRegion.x - origin.x;
0195: int yOffset = aRegion.y - origin.y;
0196: if (sampleModel instanceof PixelInterleavedSampleModel
0197: || (sampleModel instanceof ComponentSampleModel && isInterleaved((ComponentSampleModel) sampleModel))) {
0198: ComponentSampleModel csm = (ComponentSampleModel) sampleModel;
0199: this .scanlineStride = csm.getScanlineStride();
0200: this .pixelStride = csm.getPixelStride();
0201: this .dataOffsets = csm.getBandOffsets();
0202: for (int i = 0; i < getNumDataElements(); i++) {
0203: dataOffsets[i] += xOffset * pixelStride + yOffset
0204: * scanlineStride;
0205: }
0206: } else if (sampleModel instanceof SinglePixelPackedSampleModel) {
0207: SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sampleModel;
0208: this .packed = true;
0209: this .bitMasks = sppsm.getBitMasks();
0210: this .bitOffsets = sppsm.getBitOffsets();
0211: this .scanlineStride = sppsm.getScanlineStride();
0212: this .pixelStride = 1;
0213: this .dataOffsets = new int[1];
0214: this .dataOffsets[0] = dbb.getOffset();
0215: dataOffsets[0] += xOffset * pixelStride + yOffset
0216: * scanlineStride;
0217: } else {
0218: throw new RasterFormatException(
0219: "ByteInterleavedRasters must "
0220: + "have PixelInterleavedSampleModel, SinglePixelPackedSampleModel"
0221: + " or interleaved ComponentSampleModel. Sample model is "
0222: + sampleModel);
0223: }
0224: this .bandOffset = this .dataOffsets[0];
0225:
0226: this .dbOffsetPacked = dataBuffer.getOffset()
0227: - sampleModelTranslateY * scanlineStride
0228: - sampleModelTranslateX * pixelStride;
0229: this .dbOffset = dbOffsetPacked
0230: - (xOffset * pixelStride + yOffset * scanlineStride);
0231:
0232: // Set inOrder to true if the data elements are in order and
0233: // have no gaps between them
0234: this .inOrder = false;
0235: if (numDataElements == pixelStride) {
0236: inOrder = true;
0237: for (int i = 1; i < numDataElements; i++) {
0238: if (dataOffsets[i] - dataOffsets[0] != i) {
0239: inOrder = false;
0240: break;
0241: }
0242: }
0243: }
0244:
0245: verify(false);
0246: }
0247:
0248: /**
0249: * Returns a copy of the data offsets array. For each band the data offset
0250: * is the index into the band's data array, of the first sample of the
0251: * band.
0252: */
0253: public int[] getDataOffsets() {
0254: return (int[]) dataOffsets.clone();
0255: }
0256:
0257: /**
0258: * Returns the data offset for the specified band. The data offset
0259: * is the index into the data array
0260: * in which the first sample of the first scanline is stored.
0261: * @param band The band whose offset is returned.
0262: */
0263: public int getDataOffset(int band) {
0264: return dataOffsets[band];
0265: }
0266:
0267: /**
0268: * Returns the scanline stride -- the number of data array elements between
0269: * a given sample and the sample in the same column of the next row in the
0270: * same band.
0271: */
0272: public int getScanlineStride() {
0273: return scanlineStride;
0274: }
0275:
0276: /**
0277: * Returns pixel stride -- the number of data array elements between two
0278: * samples for the same band on the same scanline.
0279: */
0280: public int getPixelStride() {
0281: return pixelStride;
0282: }
0283:
0284: /**
0285: * Returns a reference to the data array.
0286: */
0287: public byte[] getDataStorage() {
0288: return data;
0289: }
0290:
0291: /**
0292: * Returns the data elements for all bands at the specified
0293: * location.
0294: * An ArrayIndexOutOfBounds exception will be thrown at runtime
0295: * if the pixel coordinate is out of bounds.
0296: * A ClassCastException will be thrown if the input object is non null
0297: * and references anything other than an array of transferType.
0298: * @param x The X coordinate of the pixel location.
0299: * @param y The Y coordinate of the pixel location.
0300: * @param outData An object reference to an array of type defined by
0301: * getTransferType() and length getNumDataElements().
0302: * If null an array of appropriate type and size will be
0303: * allocated.
0304: * @return An object reference to an array of type defined by
0305: * getTransferType() with the request pixel data.
0306: */
0307: public Object getDataElements(int x, int y, Object obj) {
0308: if ((x < this .minX) || (y < this .minY) || (x >= this .maxX)
0309: || (y >= this .maxY)) {
0310: throw new ArrayIndexOutOfBoundsException(
0311: "Coordinate out of bounds!");
0312: }
0313: byte outData[];
0314: if (obj == null) {
0315: outData = new byte[numDataElements];
0316: } else {
0317: outData = (byte[]) obj;
0318: }
0319: int off = (y - minY) * scanlineStride + (x - minX)
0320: * pixelStride;
0321:
0322: for (int band = 0; band < numDataElements; band++) {
0323: outData[band] = data[dataOffsets[band] + off];
0324: }
0325:
0326: return outData;
0327: }
0328:
0329: /**
0330: * Returns an array of data elements from the specified rectangular
0331: * region.
0332: * An ArrayIndexOutOfBounds exception will be thrown at runtime
0333: * if the pixel coordinates are out of bounds.
0334: * A ClassCastException will be thrown if the input object is non null
0335: * and references anything other than an array of transferType.
0336: * <pre>
0337: * byte[] bandData = (byte[])raster.getDataElements(x, y, w, h, null);
0338: * int numDataElements = raster.getNumDataElements();
0339: * byte[] pixel = new byte[numDataElements];
0340: * // To find a data element at location (x2, y2)
0341: * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
0342: * pixel, 0, numDataElements);
0343: * </pre>
0344: * @param x The X coordinate of the upper left pixel location.
0345: * @param y The Y coordinate of the upper left pixel location.
0346: * @param width Width of the pixel rectangle.
0347: * @param height Height of the pixel rectangle.
0348: * @param outData An object reference to an array of type defined by
0349: * getTransferType() and length w*h*getNumDataElements().
0350: * If null an array of appropriate type and size will be
0351: * allocated.
0352: * @return An object reference to an array of type defined by
0353: * getTransferType() with the request pixel data.
0354: */
0355: public Object getDataElements(int x, int y, int w, int h, Object obj) {
0356: return getByteData(x, y, w, h, (byte[]) obj);
0357: }
0358:
0359: /**
0360: * Returns a byte array of data elements from the specified rectangular
0361: * region for the specified band.
0362: * An ArrayIndexOutOfBounds exception will be thrown at runtime
0363: * if the pixel coordinates are out of bounds.
0364: * <pre>
0365: * byte[] bandData = raster.getByteData(x, y, w, h, null);
0366: * // To find the data element at location (x2, y2)
0367: * byte bandElement = bandData[((y2-y)*w + (x2-x))];
0368: * </pre>
0369: * @param x The X coordinate of the upper left pixel location.
0370: * @param y The Y coordinate of the upper left pixel location.
0371: * @param width Width of the pixel rectangle.
0372: * @param height Height of the pixel rectangle.
0373: * @param band The band to return.
0374: * @param outData If non-null, data elements for all bands
0375: * at the specified location are returned in this array.
0376: * @return Data array with data elements for all bands.
0377: */
0378: public byte[] getByteData(int x, int y, int w, int h, int band,
0379: byte[] outData) {
0380: // Bounds check for 'band' will be performed automatically
0381: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
0382: || (y + h > this .maxY)) {
0383: throw new ArrayIndexOutOfBoundsException(
0384: "Coordinate out of bounds!");
0385: }
0386: if (outData == null) {
0387: outData = new byte[w * h];
0388: }
0389: int yoff = (y - minY) * scanlineStride + (x - minX)
0390: * pixelStride + dataOffsets[band];
0391: int xoff;
0392: int off = 0;
0393: int xstart;
0394: int ystart;
0395:
0396: if (pixelStride == 1) {
0397: if (scanlineStride == w) {
0398: System.arraycopy(data, yoff, outData, 0, w * h);
0399: } else {
0400: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0401: System.arraycopy(data, yoff, outData, off, w);
0402: off += w;
0403: }
0404: }
0405: } else {
0406: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0407: xoff = yoff;
0408: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0409: outData[off++] = data[xoff];
0410: }
0411: }
0412: }
0413:
0414: return outData;
0415: }
0416:
0417: /**
0418: * Returns a byte array of data elements from the specified rectangular
0419: * region.
0420: * An ArrayIndexOutOfBounds exception will be thrown at runtime
0421: * if the pixel coordinates are out of bounds.
0422: * <pre>
0423: * byte[] bandData = raster.getByteData(x, y, w, h, null);
0424: * int numDataElements = raster.getnumDataElements();
0425: * byte[] pixel = new byte[numDataElements];
0426: * // To find a data element at location (x2, y2)
0427: * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
0428: * pixel, 0, numDataElements);
0429: * </pre>
0430: * @param x The X coordinate of the upper left pixel location.
0431: * @param y The Y coordinate of the upper left pixel location.
0432: * @param width Width of the pixel rectangle.
0433: * @param height Height of the pixel rectangle.
0434: * @param outData If non-null, data elements for all bands
0435: * at the specified location are returned in this array.
0436: * @return Data array with data elements for all bands.
0437: */
0438: public byte[] getByteData(int x, int y, int w, int h, byte[] outData) {
0439: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
0440: || (y + h > this .maxY)) {
0441: throw new ArrayIndexOutOfBoundsException(
0442: "Coordinate out of bounds!");
0443: }
0444: if (outData == null) {
0445: outData = new byte[numDataElements * w * h];
0446: }
0447: int yoff = (y - minY) * scanlineStride + (x - minX)
0448: * pixelStride;
0449: int xoff;
0450: int off = 0;
0451: int xstart;
0452: int ystart;
0453:
0454: if (inOrder) {
0455: yoff += dataOffsets[0];
0456: int rowBytes = w * pixelStride;
0457: if (scanlineStride == rowBytes) {
0458: System
0459: .arraycopy(data, yoff, outData, off, rowBytes
0460: * h);
0461: } else {
0462: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0463: System
0464: .arraycopy(data, yoff, outData, off,
0465: rowBytes);
0466: off += rowBytes;
0467: }
0468: }
0469: } else if (numDataElements == 1) {
0470: yoff += dataOffsets[0];
0471: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0472: xoff = yoff;
0473: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0474: outData[off++] = data[xoff];
0475: }
0476: }
0477: } else if (numDataElements == 2) {
0478: yoff += dataOffsets[0];
0479: int d1 = dataOffsets[1] - dataOffsets[0];
0480: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0481: xoff = yoff;
0482: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0483: outData[off++] = data[xoff];
0484: outData[off++] = data[xoff + d1];
0485: }
0486: }
0487: } else if (numDataElements == 3) {
0488: yoff += dataOffsets[0];
0489: int d1 = dataOffsets[1] - dataOffsets[0];
0490: int d2 = dataOffsets[2] - dataOffsets[0];
0491: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0492: xoff = yoff;
0493: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0494: outData[off++] = data[xoff];
0495: outData[off++] = data[xoff + d1];
0496: outData[off++] = data[xoff + d2];
0497: }
0498: }
0499: } else if (numDataElements == 4) {
0500: yoff += dataOffsets[0];
0501: int d1 = dataOffsets[1] - dataOffsets[0];
0502: int d2 = dataOffsets[2] - dataOffsets[0];
0503: int d3 = dataOffsets[3] - dataOffsets[0];
0504: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0505: xoff = yoff;
0506: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0507: outData[off++] = data[xoff];
0508: outData[off++] = data[xoff + d1];
0509: outData[off++] = data[xoff + d2];
0510: outData[off++] = data[xoff + d3];
0511: }
0512: }
0513: } else {
0514: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0515: xoff = yoff;
0516: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0517: for (int c = 0; c < numDataElements; c++) {
0518: outData[off++] = data[dataOffsets[c] + xoff];
0519: }
0520: }
0521: }
0522: }
0523:
0524: return outData;
0525: }
0526:
0527: /**
0528: * Stores the data elements for all bands at the specified location.
0529: * An ArrayIndexOutOfBounds exception will be thrown at runtime
0530: * if the pixel coordinate is out of bounds.
0531: * A ClassCastException will be thrown if the input object is non null
0532: * and references anything other than an array of transferType.
0533: * @param x The X coordinate of the pixel location.
0534: * @param y The Y coordinate of the pixel location.
0535: * @param inData An object reference to an array of type defined by
0536: * getTransferType() and length getNumDataElements()
0537: * containing the pixel data to place at x,y.
0538: */
0539: public void setDataElements(int x, int y, Object obj) {
0540: if ((x < this .minX) || (y < this .minY) || (x >= this .maxX)
0541: || (y >= this .maxY)) {
0542: throw new ArrayIndexOutOfBoundsException(
0543: "Coordinate out of bounds!");
0544: }
0545: byte inData[] = (byte[]) obj;
0546: int off = (y - minY) * scanlineStride + (x - minX)
0547: * pixelStride;
0548:
0549: for (int i = 0; i < numDataElements; i++) {
0550: data[dataOffsets[i] + off] = inData[i];
0551: }
0552:
0553: markDirty();
0554: }
0555:
0556: /**
0557: * Stores the Raster data at the specified location.
0558: * An ArrayIndexOutOfBounds exception will be thrown at runtime
0559: * if the pixel coordinates are out of bounds.
0560: * @param x The X coordinate of the pixel location.
0561: * @param y The Y coordinate of the pixel location.
0562: * @param inRaster Raster of data to place at x,y location.
0563: */
0564: public void setDataElements(int x, int y, Raster inRaster) {
0565: int srcOffX = inRaster.getMinX();
0566: int srcOffY = inRaster.getMinY();
0567: int dstOffX = x + srcOffX;
0568: int dstOffY = y + srcOffY;
0569: int width = inRaster.getWidth();
0570: int height = inRaster.getHeight();
0571: if ((dstOffX < this .minX) || (dstOffY < this .minY)
0572: || (dstOffX + width > this .maxX)
0573: || (dstOffY + height > this .maxY)) {
0574: throw new ArrayIndexOutOfBoundsException(
0575: "Coordinate out of bounds!");
0576: }
0577:
0578: setDataElements(dstOffX, dstOffY, srcOffX, srcOffY, width,
0579: height, inRaster);
0580: }
0581:
0582: /**
0583: * Stores the Raster data at the specified location.
0584: * @param dstX The absolute X coordinate of the destination pixel
0585: * that will receive a copy of the upper-left pixel of the
0586: * inRaster
0587: * @param dstY The absolute Y coordinate of the destination pixel
0588: * that will receive a copy of the upper-left pixel of the
0589: * inRaster
0590: * @param srcX The absolute X coordinate of the upper-left source
0591: * pixel that will be copied into this Raster
0592: * @param srcY The absolute Y coordinate of the upper-left source
0593: * pixel that will be copied into this Raster
0594: * @param width The number of pixels to store horizontally
0595: * @param height The number of pixels to store vertically
0596: * @param inRaster Raster of data to place at x,y location.
0597: */
0598: private void setDataElements(int dstX, int dstY, int srcX,
0599: int srcY, int width, int height, Raster inRaster) {
0600: // Assume bounds checking has been performed previously
0601: if (width <= 0 || height <= 0) {
0602: return;
0603: }
0604:
0605: // Write inRaster (minX, minY) to (dstX, dstY)
0606:
0607: int srcOffX = inRaster.getMinX();
0608: int srcOffY = inRaster.getMinY();
0609: Object tdata = null;
0610:
0611: if (inRaster instanceof ByteInterleavedRaster) {
0612: ByteInterleavedRaster bct = (ByteInterleavedRaster) inRaster;
0613: byte[] bdata = bct.getDataStorage();
0614: // copy whole scanlines
0615: if (inOrder && bct.inOrder
0616: && pixelStride == bct.pixelStride) {
0617: int toff = bct.getDataOffset(0);
0618: int tss = bct.getScanlineStride();
0619: int tps = bct.getPixelStride();
0620:
0621: int srcOffset = toff + (srcY - srcOffY) * tss
0622: + (srcX - srcOffX) * tps;
0623: int dstOffset = dataOffsets[0] + (dstY - minY)
0624: * scanlineStride + (dstX - minX) * pixelStride;
0625:
0626: int nbytes = width * pixelStride;
0627: for (int tmpY = 0; tmpY < height; tmpY++) {
0628: System.arraycopy(bdata, srcOffset, data, dstOffset,
0629: nbytes);
0630: srcOffset += tss;
0631: dstOffset += scanlineStride;
0632: }
0633: markDirty();
0634: return;
0635: }
0636: }
0637:
0638: for (int startY = 0; startY < height; startY++) {
0639: // Grab one scanline at a time
0640: tdata = inRaster.getDataElements(srcOffX, srcOffY + startY,
0641: width, 1, tdata);
0642: setDataElements(dstX, dstY + startY, width, 1, tdata);
0643: }
0644: }
0645:
0646: /**
0647: * Stores an array of data elements into the specified rectangular
0648: * region.
0649: * An ArrayIndexOutOfBounds exception will be thrown at runtime
0650: * if the pixel coordinates are out of bounds.
0651: * A ClassCastException will be thrown if the input object is non null
0652: * and references anything other than an array of transferType.
0653: * The data elements in the
0654: * data array are assumed to be packed. That is, a data element
0655: * for the nth band at location (x2, y2) would be found at:
0656: * <pre>
0657: * inData[((y2-y)*w + (x2-x))*numDataElements + n]
0658: * </pre>
0659: * @param x The X coordinate of the upper left pixel location.
0660: * @param y The Y coordinate of the upper left pixel location.
0661: * @param w Width of the pixel rectangle.
0662: * @param h Height of the pixel rectangle.
0663: * @param inData An object reference to an array of type defined by
0664: * getTransferType() and length w*h*getNumDataElements()
0665: * containing the pixel data to place between x,y and
0666: * x+h, y+h.
0667: */
0668: public void setDataElements(int x, int y, int w, int h, Object obj) {
0669: putByteData(x, y, w, h, (byte[]) obj);
0670: }
0671:
0672: /**
0673: * Stores a byte array of data elements into the specified rectangular
0674: * region for the specified band.
0675: * An ArrayIndexOutOfBounds exception will be thrown at runtime
0676: * if the pixel coordinates are out of bounds.
0677: * The data elements in the
0678: * data array are assumed to be packed. That is, a data element
0679: * at location (x2, y2) would be found at:
0680: * <pre>
0681: * inData[((y2-y)*w + (x2-x)) + n]
0682: * </pre>
0683: * @param x The X coordinate of the upper left pixel location.
0684: * @param y The Y coordinate of the upper left pixel location.
0685: * @param w Width of the pixel rectangle.
0686: * @param h Height of the pixel rectangle.
0687: * @param band The band to set.
0688: * @param inData The data elements to be stored.
0689: */
0690: public void putByteData(int x, int y, int w, int h, int band,
0691: byte[] inData) {
0692: // Bounds check for 'band' will be performed automatically
0693: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
0694: || (y + h > this .maxY)) {
0695: throw new ArrayIndexOutOfBoundsException(
0696: "Coordinate out of bounds!");
0697: }
0698: int yoff = (y - minY) * scanlineStride + (x - minX)
0699: * pixelStride + dataOffsets[band];
0700: int xoff;
0701: int off = 0;
0702: int xstart;
0703: int ystart;
0704:
0705: if (pixelStride == 1) {
0706: if (scanlineStride == w) {
0707: System.arraycopy(inData, 0, data, yoff, w * h);
0708: } else {
0709: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0710: System.arraycopy(inData, off, data, yoff, w);
0711: off += w;
0712: }
0713: }
0714: } else {
0715: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0716: xoff = yoff;
0717: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0718: data[xoff] = inData[off++];
0719: }
0720: }
0721: }
0722:
0723: markDirty();
0724: }
0725:
0726: /**
0727: * Stores a byte array of data elements into the specified rectangular
0728: * region.
0729: * An ArrayIndexOutOfBounds exception will be thrown at runtime
0730: * if the pixel coordinates are out of bounds.
0731: * The data elements in the
0732: * data array are assumed to be packed. That is, a data element
0733: * for the nth band at location (x2, y2) would be found at:
0734: * <pre>
0735: * inData[((y2-y)*w + (x2-x))*numDataElements + n]
0736: * </pre>
0737: * @param x The X coordinate of the upper left pixel location.
0738: * @param y The Y coordinate of the upper left pixel location.
0739: * @param w Width of the pixel rectangle.
0740: * @param h Height of the pixel rectangle.
0741: * @param inData The data elements to be stored.
0742: */
0743: public void putByteData(int x, int y, int w, int h, byte[] inData) {
0744: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
0745: || (y + h > this .maxY)) {
0746: throw new ArrayIndexOutOfBoundsException(
0747: "Coordinate out of bounds!");
0748: }
0749: int yoff = (y - minY) * scanlineStride + (x - minX)
0750: * pixelStride;
0751:
0752: int xoff;
0753: int off = 0;
0754: int xstart;
0755: int ystart;
0756:
0757: if (inOrder) {
0758: yoff += dataOffsets[0];
0759: int rowBytes = w * pixelStride;
0760: if (rowBytes == scanlineStride) {
0761: System.arraycopy(inData, 0, data, yoff, rowBytes * h);
0762: } else {
0763: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0764: System.arraycopy(inData, off, data, yoff, rowBytes);
0765: off += rowBytes;
0766: }
0767: }
0768: } else if (numDataElements == 1) {
0769: yoff += dataOffsets[0];
0770: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0771: xoff = yoff;
0772: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0773: data[xoff] = inData[off++];
0774: }
0775: }
0776: } else if (numDataElements == 2) {
0777: yoff += dataOffsets[0];
0778: int d1 = dataOffsets[1] - dataOffsets[0];
0779: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0780: xoff = yoff;
0781: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0782: data[xoff] = inData[off++];
0783: data[xoff + d1] = inData[off++];
0784: }
0785: }
0786: } else if (numDataElements == 3) {
0787: yoff += dataOffsets[0];
0788: int d1 = dataOffsets[1] - dataOffsets[0];
0789: int d2 = dataOffsets[2] - dataOffsets[0];
0790: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0791: xoff = yoff;
0792: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0793: data[xoff] = inData[off++];
0794: data[xoff + d1] = inData[off++];
0795: data[xoff + d2] = inData[off++];
0796: }
0797: }
0798: } else if (numDataElements == 4) {
0799: yoff += dataOffsets[0];
0800: int d1 = dataOffsets[1] - dataOffsets[0];
0801: int d2 = dataOffsets[2] - dataOffsets[0];
0802: int d3 = dataOffsets[3] - dataOffsets[0];
0803: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0804: xoff = yoff;
0805: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0806: data[xoff] = inData[off++];
0807: data[xoff + d1] = inData[off++];
0808: data[xoff + d2] = inData[off++];
0809: data[xoff + d3] = inData[off++];
0810: }
0811: }
0812: } else {
0813: for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) {
0814: xoff = yoff;
0815: for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) {
0816: for (int c = 0; c < numDataElements; c++) {
0817: data[dataOffsets[c] + xoff] = inData[off++];
0818: }
0819: }
0820: }
0821: }
0822:
0823: markDirty();
0824: }
0825:
0826: public int getSample(int x, int y, int b) {
0827: if ((x < this .minX) || (y < this .minY) || (x >= this .maxX)
0828: || (y >= this .maxY)) {
0829: throw new ArrayIndexOutOfBoundsException(
0830: "Coordinate out of bounds!");
0831: }
0832: if (packed) {
0833: int offset = y * scanlineStride + x + dbOffsetPacked;
0834: byte sample = data[offset];
0835: return (sample & bitMasks[b]) >>> bitOffsets[b];
0836: } else {
0837: int offset = y * scanlineStride + x * pixelStride
0838: + dbOffset;
0839: return data[offset + dataOffsets[b]] & 0xff;
0840: }
0841: }
0842:
0843: public void setSample(int x, int y, int b, int s) {
0844: if ((x < this .minX) || (y < this .minY) || (x >= this .maxX)
0845: || (y >= this .maxY)) {
0846: throw new ArrayIndexOutOfBoundsException(
0847: "Coordinate out of bounds!");
0848: }
0849: if (packed) {
0850: int offset = y * scanlineStride + x + dbOffsetPacked;
0851: int bitMask = bitMasks[b];
0852:
0853: byte value = data[offset];
0854: value &= ~bitMask;
0855: value |= (s << bitOffsets[b]) & bitMask;
0856: data[offset] = value;
0857: } else {
0858: int offset = y * scanlineStride + x * pixelStride
0859: + dbOffset;
0860: data[offset + dataOffsets[b]] = (byte) s;
0861: }
0862:
0863: markDirty();
0864: }
0865:
0866: public int[] getSamples(int x, int y, int w, int h, int b,
0867: int[] iArray) {
0868: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
0869: || (y + h > this .maxY)) {
0870: throw new ArrayIndexOutOfBoundsException(
0871: "Coordinate out of bounds!");
0872: }
0873: int samples[];
0874: if (iArray != null) {
0875: samples = iArray;
0876: } else {
0877: samples = new int[w * h];
0878: }
0879:
0880: int lineOffset = y * scanlineStride + x * pixelStride;
0881: int dstOffset = 0;
0882:
0883: if (packed) {
0884: lineOffset += dbOffsetPacked;
0885: int bitMask = bitMasks[b];
0886: int bitOffset = bitOffsets[b];
0887:
0888: for (int j = 0; j < h; j++) {
0889: int sampleOffset = lineOffset;
0890: for (int i = 0; i < w; i++) {
0891: int value = data[sampleOffset++];
0892: samples[dstOffset++] = ((value & bitMask) >>> bitOffset);
0893: }
0894: lineOffset += scanlineStride;
0895: }
0896: } else {
0897: lineOffset += dbOffset + dataOffsets[b];
0898: for (int j = 0; j < h; j++) {
0899: int sampleOffset = lineOffset;
0900: for (int i = 0; i < w; i++) {
0901: samples[dstOffset++] = data[sampleOffset] & 0xff;
0902: sampleOffset += pixelStride;
0903: }
0904: lineOffset += scanlineStride;
0905: }
0906: }
0907:
0908: return samples;
0909: }
0910:
0911: public void setSamples(int x, int y, int w, int h, int b,
0912: int iArray[]) {
0913: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
0914: || (y + h > this .maxY)) {
0915: throw new ArrayIndexOutOfBoundsException(
0916: "Coordinate out of bounds!");
0917: }
0918: int lineOffset = y * scanlineStride + x * pixelStride;
0919: int srcOffset = 0;
0920:
0921: if (packed) {
0922: lineOffset += dbOffsetPacked;
0923: int bitMask = bitMasks[b];
0924:
0925: for (int j = 0; j < h; j++) {
0926: int sampleOffset = lineOffset;
0927: for (int i = 0; i < w; i++) {
0928: byte value = data[sampleOffset];
0929: value &= ~bitMask;
0930: int sample = iArray[srcOffset++];
0931: value |= (sample << bitOffsets[b]) & bitMask;
0932: data[sampleOffset++] = value;
0933: }
0934: lineOffset += scanlineStride;
0935: }
0936: } else {
0937: lineOffset += dbOffset + dataOffsets[b];
0938: for (int i = 0; i < h; i++) {
0939: int sampleOffset = lineOffset;
0940: for (int j = 0; j < w; j++) {
0941: data[sampleOffset] = (byte) iArray[srcOffset++];
0942: sampleOffset += pixelStride;
0943: }
0944: lineOffset += scanlineStride;
0945: }
0946: }
0947:
0948: markDirty();
0949: }
0950:
0951: public int[] getPixels(int x, int y, int w, int h, int[] iArray) {
0952: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
0953: || (y + h > this .maxY)) {
0954: throw new ArrayIndexOutOfBoundsException(
0955: "Coordinate out of bounds!");
0956: }
0957: int pixels[];
0958: if (iArray != null) {
0959: pixels = iArray;
0960: } else {
0961: pixels = new int[w * h * numBands];
0962: }
0963:
0964: int lineOffset = y * scanlineStride + x * pixelStride;
0965: int dstOffset = 0;
0966:
0967: if (packed) {
0968: lineOffset += dbOffsetPacked;
0969: for (int j = 0; j < h; j++) {
0970: for (int i = 0; i < w; i++) {
0971: int value = data[lineOffset + i];
0972: for (int k = 0; k < numBands; k++) {
0973: pixels[dstOffset++] = (value & bitMasks[k]) >>> bitOffsets[k];
0974: }
0975: }
0976: lineOffset += scanlineStride;
0977: }
0978: } else {
0979: lineOffset += dbOffset;
0980: int d0 = dataOffsets[0];
0981:
0982: if (numBands == 1) {
0983: for (int j = 0; j < h; j++) {
0984: int pixelOffset = lineOffset + d0;
0985: for (int i = 0; i < w; i++) {
0986: pixels[dstOffset++] = data[pixelOffset] & 0xff;
0987: pixelOffset += pixelStride;
0988: }
0989: lineOffset += scanlineStride;
0990: }
0991: } else if (numBands == 2) {
0992: int d1 = dataOffsets[1] - d0;
0993: for (int j = 0; j < h; j++) {
0994: int pixelOffset = lineOffset + d0;
0995: for (int i = 0; i < w; i++) {
0996: pixels[dstOffset++] = data[pixelOffset] & 0xff;
0997: pixels[dstOffset++] = data[pixelOffset + d1] & 0xff;
0998: pixelOffset += pixelStride;
0999: }
1000: lineOffset += scanlineStride;
1001: }
1002: } else if (numBands == 3) {
1003: int d1 = dataOffsets[1] - d0;
1004: int d2 = dataOffsets[2] - d0;
1005: for (int j = 0; j < h; j++) {
1006: int pixelOffset = lineOffset + d0;
1007: for (int i = 0; i < w; i++) {
1008: pixels[dstOffset++] = data[pixelOffset] & 0xff;
1009: pixels[dstOffset++] = data[pixelOffset + d1] & 0xff;
1010: pixels[dstOffset++] = data[pixelOffset + d2] & 0xff;
1011: pixelOffset += pixelStride;
1012: }
1013: lineOffset += scanlineStride;
1014: }
1015: } else if (numBands == 4) {
1016: int d1 = dataOffsets[1] - d0;
1017: int d2 = dataOffsets[2] - d0;
1018: int d3 = dataOffsets[3] - d0;
1019: for (int j = 0; j < h; j++) {
1020: int pixelOffset = lineOffset + d0;
1021: for (int i = 0; i < w; i++) {
1022: pixels[dstOffset++] = data[pixelOffset] & 0xff;
1023: pixels[dstOffset++] = data[pixelOffset + d1] & 0xff;
1024: pixels[dstOffset++] = data[pixelOffset + d2] & 0xff;
1025: pixels[dstOffset++] = data[pixelOffset + d3] & 0xff;
1026: pixelOffset += pixelStride;
1027: }
1028: lineOffset += scanlineStride;
1029: }
1030: } else {
1031: for (int j = 0; j < h; j++) {
1032: int pixelOffset = lineOffset;
1033: for (int i = 0; i < w; i++) {
1034: for (int k = 0; k < numBands; k++) {
1035: pixels[dstOffset++] = data[pixelOffset
1036: + dataOffsets[k]] & 0xff;
1037: }
1038: pixelOffset += pixelStride;
1039: }
1040: lineOffset += scanlineStride;
1041: }
1042: }
1043: }
1044:
1045: return pixels;
1046: }
1047:
1048: public void setPixels(int x, int y, int w, int h, int[] iArray) {
1049: if ((x < this .minX) || (y < this .minY) || (x + w > this .maxX)
1050: || (y + h > this .maxY)) {
1051: throw new ArrayIndexOutOfBoundsException(
1052: "Coordinate out of bounds!");
1053: }
1054: int lineOffset = y * scanlineStride + x * pixelStride;
1055: int srcOffset = 0;
1056:
1057: if (packed) {
1058: lineOffset += dbOffsetPacked;
1059: for (int j = 0; j < h; j++) {
1060: for (int i = 0; i < w; i++) {
1061: int value = 0;
1062: for (int k = 0; k < numBands; k++) {
1063: int srcValue = iArray[srcOffset++];
1064: value |= ((srcValue << bitOffsets[k]) & bitMasks[k]);
1065: }
1066: data[lineOffset + i] = (byte) value;
1067: }
1068: lineOffset += scanlineStride;
1069: }
1070: } else {
1071: lineOffset += dbOffset;
1072: int d0 = dataOffsets[0];
1073:
1074: if (numBands == 1) {
1075: for (int j = 0; j < h; j++) {
1076: int pixelOffset = lineOffset + d0;
1077: for (int i = 0; i < w; i++) {
1078: data[pixelOffset] = (byte) iArray[srcOffset++];
1079: pixelOffset += pixelStride;
1080: }
1081: lineOffset += scanlineStride;
1082: }
1083: } else if (numBands == 2) {
1084: int d1 = dataOffsets[1] - d0;
1085: for (int j = 0; j < h; j++) {
1086: int pixelOffset = lineOffset + d0;
1087: for (int i = 0; i < w; i++) {
1088: data[pixelOffset] = (byte) iArray[srcOffset++];
1089: data[pixelOffset + d1] = (byte) iArray[srcOffset++];
1090: pixelOffset += pixelStride;
1091: }
1092: lineOffset += scanlineStride;
1093: }
1094: } else if (numBands == 3) {
1095: int d1 = dataOffsets[1] - d0;
1096: int d2 = dataOffsets[2] - d0;
1097: for (int j = 0; j < h; j++) {
1098: int pixelOffset = lineOffset + d0;
1099: for (int i = 0; i < w; i++) {
1100: data[pixelOffset] = (byte) iArray[srcOffset++];
1101: data[pixelOffset + d1] = (byte) iArray[srcOffset++];
1102: data[pixelOffset + d2] = (byte) iArray[srcOffset++];
1103: pixelOffset += pixelStride;
1104: }
1105: lineOffset += scanlineStride;
1106: }
1107: } else if (numBands == 4) {
1108: int d1 = dataOffsets[1] - d0;
1109: int d2 = dataOffsets[2] - d0;
1110: int d3 = dataOffsets[3] - d0;
1111: for (int j = 0; j < h; j++) {
1112: int pixelOffset = lineOffset + d0;
1113: for (int i = 0; i < w; i++) {
1114: data[pixelOffset] = (byte) iArray[srcOffset++];
1115: data[pixelOffset + d1] = (byte) iArray[srcOffset++];
1116: data[pixelOffset + d2] = (byte) iArray[srcOffset++];
1117: data[pixelOffset + d3] = (byte) iArray[srcOffset++];
1118: pixelOffset += pixelStride;
1119: }
1120: lineOffset += scanlineStride;
1121: }
1122: } else {
1123: for (int j = 0; j < h; j++) {
1124: int pixelOffset = lineOffset;
1125: for (int i = 0; i < w; i++) {
1126: for (int k = 0; k < numBands; k++) {
1127: data[pixelOffset + dataOffsets[k]] = (byte) iArray[srcOffset++];
1128: }
1129: pixelOffset += pixelStride;
1130: }
1131: lineOffset += scanlineStride;
1132: }
1133: }
1134: }
1135:
1136: markDirty();
1137: }
1138:
1139: public void setRect(int dx, int dy, Raster srcRaster) {
1140: if (!(srcRaster instanceof ByteInterleavedRaster)) {
1141: super .setRect(dx, dy, srcRaster);
1142: return;
1143: }
1144:
1145: int width = srcRaster.getWidth();
1146: int height = srcRaster.getHeight();
1147: int srcOffX = srcRaster.getMinX();
1148: int srcOffY = srcRaster.getMinY();
1149: int dstOffX = dx + srcOffX;
1150: int dstOffY = dy + srcOffY;
1151:
1152: // Clip to this raster
1153: if (dstOffX < this .minX) {
1154: int skipX = minX - dstOffX;
1155: width -= skipX;
1156: srcOffX += skipX;
1157: dstOffX = this .minX;
1158: }
1159: if (dstOffY < this .minY) {
1160: int skipY = this .minY - dstOffY;
1161: height -= skipY;
1162: srcOffY += skipY;
1163: dstOffY = this .minY;
1164: }
1165: if (dstOffX + width > this .maxX) {
1166: width = this .maxX - dstOffX;
1167: }
1168: if (dstOffY + height > this .maxY) {
1169: height = this .maxY - dstOffY;
1170: }
1171:
1172: setDataElements(dstOffX, dstOffY, srcOffX, srcOffY, width,
1173: height, srcRaster);
1174: }
1175:
1176: /**
1177: * Creates a subraster given a region of the raster. The x and y
1178: * coordinates specify the horizontal and vertical offsets
1179: * from the upper-left corner of this raster to the upper-left corner
1180: * of the subraster. A subset of the bands of the parent Raster may
1181: * be specified. If this is null, then all the bands are present in the
1182: * subRaster. A translation to the subRaster may also be specified.
1183: * Note that the subraster will reference the same
1184: * DataBuffer as the parent raster, but using different offsets.
1185: * @param x X offset.
1186: * @param y Y offset.
1187: * @param width Width (in pixels) of the subraster.
1188: * @param height Height (in pixels) of the subraster.
1189: * @param x0 Translated X origin of the subraster.
1190: * @param y0 Translated Y origin of the subraster.
1191: * @param bandList Array of band indices.
1192: * @exception RasterFormatException
1193: * if the specified bounding box is outside of the parent raster.
1194: */
1195: public Raster createChild(int x, int y, int width, int height,
1196: int x0, int y0, int[] bandList) {
1197: WritableRaster newRaster = createWritableChild(x, y, width,
1198: height, x0, y0, bandList);
1199: return (Raster) newRaster;
1200: }
1201:
1202: /**
1203: * Creates a Writable subRaster given a region of the Raster. The x and y
1204: * coordinates specify the horizontal and vertical offsets
1205: * from the upper-left corner of this Raster to the upper-left corner
1206: * of the subRaster. A subset of the bands of the parent Raster may
1207: * be specified. If this is null, then all the bands are present in the
1208: * subRaster. A translation to the subRaster may also be specified.
1209: * Note that the subRaster will reference the same
1210: * DataBuffer as the parent Raster, but using different offsets.
1211: * @param x X offset.
1212: * @param y Y offset.
1213: * @param width Width (in pixels) of the subraster.
1214: * @param height Height (in pixels) of the subraster.
1215: * @param x0 Translated X origin of the subraster.
1216: * @param y0 Translated Y origin of the subraster.
1217: * @param bandList Array of band indices.
1218: * @exception RasterFormatException
1219: * if the specified bounding box is outside of the parent Raster.
1220: */
1221: public WritableRaster createWritableChild(int x, int y, int width,
1222: int height, int x0, int y0, int[] bandList) {
1223: if (x < this .minX) {
1224: throw new RasterFormatException("x lies outside the raster");
1225: }
1226: if (y < this .minY) {
1227: throw new RasterFormatException("y lies outside the raster");
1228: }
1229: if ((x + width < x) || (x + width > this .minX + this .width)) {
1230: throw new RasterFormatException(
1231: "(x + width) is outside of Raster");
1232: }
1233: if ((y + height < y) || (y + height > this .minY + this .height)) {
1234: throw new RasterFormatException(
1235: "(y + height) is outside of Raster");
1236: }
1237:
1238: SampleModel sm;
1239:
1240: if (bandList != null)
1241: sm = sampleModel.createSubsetSampleModel(bandList);
1242: else
1243: sm = sampleModel;
1244:
1245: int deltaX = x0 - x;
1246: int deltaY = y0 - y;
1247:
1248: return new ByteInterleavedRaster(sm, dataBuffer, new Rectangle(
1249: x0, y0, width, height), new Point(sampleModelTranslateX
1250: + deltaX, sampleModelTranslateY + deltaY), this );
1251: }
1252:
1253: /**
1254: * Creates a Raster with the same layout but using a different
1255: * width and height, and with new zeroed data arrays.
1256: */
1257: public WritableRaster createCompatibleWritableRaster(int w, int h) {
1258: if (w <= 0 || h <= 0) {
1259: throw new RasterFormatException("negative "
1260: + ((w <= 0) ? "width" : "height"));
1261: }
1262:
1263: SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
1264:
1265: return new ByteInterleavedRaster(sm, new Point(0, 0));
1266:
1267: }
1268:
1269: /**
1270: * Creates a Raster with the same layout and the same
1271: * width and height, and with new zeroed data arrays. If
1272: * the Raster is a subRaster, this will call
1273: * createCompatibleRaster(width, height).
1274: */
1275: public WritableRaster createCompatibleWritableRaster() {
1276: return createCompatibleWritableRaster(width, height);
1277: }
1278:
1279: /**
1280: * Verify that the layout parameters are consistent with
1281: * the data. If strictCheck
1282: * is false, this method will check for ArrayIndexOutOfBounds conditions. If
1283: * strictCheck is true, this method will check for additional error
1284: * conditions such as line wraparound (width of a line greater than
1285: * the scanline stride).
1286: * @return String Error string, if the layout is incompatible with
1287: * the data. Otherwise returns null.
1288: */
1289: private void verify(boolean strictCheck) {
1290: int maxSize = 0;
1291: int size;
1292:
1293: for (int i = 0; i < numDataElements; i++) {
1294: size = (height - 1) * scanlineStride + (width - 1)
1295: * pixelStride + dataOffsets[i];
1296: if (size > maxSize) {
1297: maxSize = size;
1298: }
1299: }
1300: if (data.length < maxSize) {
1301: throw new RasterFormatException(
1302: "Data array too small (should be " + maxSize + " )");
1303: }
1304: }
1305:
1306: public String toString() {
1307: return new String("ByteInterleavedRaster: width = " + width
1308: + " height = " + height + " #numDataElements "
1309: + numDataElements
1310: // +" xOff = "+xOffset+" yOff = "+yOffset
1311: + " dataOff[0] = " + dataOffsets[0]);
1312: }
1313:
1314: // /**
1315: // * For debugging... prints a region of a one-band ByteInterleavedRaster
1316: // */
1317: // public void print(int x, int y, int w, int h) {
1318: // // REMIND: Only works for 1 band!
1319: // System.out.println(this);
1320: // int offset = dataOffsets[0] + y*scanlineStride + x*pixelStride;
1321: // int off;
1322: // for (int yoff=0; yoff < h; yoff++, offset += scanlineStride) {
1323: // off = offset;
1324: // System.out.print("Line "+(y+yoff)+": ");
1325: // for (int xoff = 0; xoff < w; xoff++, off+= pixelStride) {
1326: // String s = Integer.toHexString(data[off]);
1327: // if (s.length() == 8) {
1328: // s = s.substring(6,8);
1329: // }
1330: // System.out.print(s+" ");
1331: // }
1332: // System.out.println("");
1333: // }
1334: // }
1335: }
|