All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.intarsys.cwt.swt.image.SwtCompatibleRaster Maven / Gradle / Ivy

There is a newer version: 5.6
Show newest version
/*
 * Copyright (c) 2008, intarsys consulting GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * - Neither the name of intarsys nor the names of its contributors may be used
 *   to endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package de.intarsys.cwt.swt.image;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.Raster;
import java.awt.image.RasterFormatException;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;

public class SwtCompatibleRaster extends WritableRaster {

	/** private band offset for use by native code */
	protected int bandOffset;

	/** If packed == true, the SampleModel's bit masks. */
	int[] bitMasks;

	/** If packed == true, the SampleModel's bit offsets. */
	int[] bitOffsets;

	/** The image data array. */
	protected byte[] data;

	/** Data offsets for each band of image data. */
	protected int[] dataOffsets;

	/**
	 * The DataBuffer offset, minus sampleModelTranslateX*pixelStride, minus
	 * sampleModelTranslateY*scanlineStride, used to calculate pixel offsets.
	 */
	int dbOffset;

	int dbOffsetPacked;

	/** True if the data offsets range from 0 to (pixelStride - 1) in order. */
	boolean inOrder;

	/** A cached copy of minX + width for use in bounds checks. */
	private int maxX;

	/** A cached copy of minY + height for use in bounds checks. */
	private int maxY;

	/** True if a SinglePixelPackedSampleModel is being used. */
	boolean packed = false;

	/** Pixel stride of the image data contained in this Raster. */
	protected int pixelStride;

	/** Scanline stride of the image data contained in this Raster. */
	protected int scanlineStride;

	int type;

	public SwtCompatibleRaster(SampleModel paramSampleModel,
			DataBuffer paramDataBuffer, Point origin) {
		this(paramSampleModel, paramDataBuffer, new Rectangle(origin.x,
				origin.y, paramSampleModel.getWidth(), paramSampleModel
						.getHeight()), origin, null);
	}

	public SwtCompatibleRaster(SampleModel paramSampleModel,
			DataBuffer paramDataBuffer, Rectangle aRegion, Point origin,
			WritableRaster paramParent) {
		super(paramSampleModel, paramDataBuffer, aRegion, origin, paramParent);
		this.maxX = minX + width;
		this.maxY = minY + height;

		if (!(dataBuffer instanceof DataBufferByte)) {
			throw new RasterFormatException("SwtCompatibleRasters must have "
					+ "byte DataBuffers");
		}

		DataBufferByte dbb = (DataBufferByte) dataBuffer;
		this.data = dbb.getData();

		int xOffset = aRegion.x - origin.x;
		int yOffset = aRegion.y - origin.y;
		if (sampleModel instanceof PixelInterleavedSampleModel
				|| (sampleModel instanceof ComponentSampleModel && isInterleaved((ComponentSampleModel) sampleModel))) {
			ComponentSampleModel csm = (ComponentSampleModel) sampleModel;
			this.scanlineStride = csm.getScanlineStride();
			this.pixelStride = csm.getPixelStride();
			this.dataOffsets = csm.getBandOffsets();
			for (int i = 0; i < getNumDataElements(); i++) {
				dataOffsets[i] += xOffset * pixelStride + yOffset
						* scanlineStride;
			}
		} else if (sampleModel instanceof SinglePixelPackedSampleModel) {
			SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sampleModel;
			this.packed = true;
			this.bitMasks = sppsm.getBitMasks();
			this.bitOffsets = sppsm.getBitOffsets();
			this.scanlineStride = sppsm.getScanlineStride();
			this.pixelStride = 1;
			this.dataOffsets = new int[1];
			this.dataOffsets[0] = dbb.getOffset();
			dataOffsets[0] += xOffset * pixelStride + yOffset * scanlineStride;
		} else {
			throw new RasterFormatException(
					"SwtCompatibleRasters must "
							+ "have PixelInterleavedSampleModel, SinglePixelPackedSampleModel"
							+ " or interleaved ComponentSampleModel.  Sample model is "
							+ sampleModel);
		}
		this.bandOffset = this.dataOffsets[0];

		this.dbOffsetPacked = dataBuffer.getOffset() - sampleModelTranslateY
				* scanlineStride - sampleModelTranslateX * pixelStride;
		this.dbOffset = dbOffsetPacked
				- (xOffset * pixelStride + yOffset * scanlineStride);

		// Set inOrder to true if the data elements are in order and
		// have no gaps between them
		this.inOrder = false;
		if (numDataElements == pixelStride) {
			inOrder = true;
			for (int i = 1; i < numDataElements; i++) {
				if (dataOffsets[i] - dataOffsets[0] != i) {
					inOrder = false;
					break;
				}
			}
		}

		verify(false);
	}

	public SwtCompatibleRaster(SampleModel paramSampleModel, Point origin) {
		super(paramSampleModel, origin);
	}

	/**
	 * Creates a subraster given a region of the raster. The x and y coordinates
	 * specify the horizontal and vertical offsets from the upper-left corner of
	 * this raster to the upper-left corner of the subraster. A subset of the
	 * bands of the parent Raster may be specified. If this is null, then all
	 * the bands are present in the subRaster. A translation to the subRaster
	 * may also be specified. Note that the subraster will reference the same
	 * DataBuffer as the parent raster, but using different offsets.
	 * 
	 * @param x
	 *            X offset.
	 * @param y
	 *            Y offset.
	 * @param width
	 *            Width (in pixels) of the subraster.
	 * @param height
	 *            Height (in pixels) of the subraster.
	 * @param x0
	 *            Translated X origin of the subraster.
	 * @param y0
	 *            Translated Y origin of the subraster.
	 * @param bandList
	 *            Array of band indices.
	 * @exception RasterFormatException
	 *                if the specified bounding box is outside of the parent
	 *                raster.
	 */
	@Override
	public Raster createChild(int x, int y, int width, int height, int x0,
			int y0, int[] bandList) {
		return createWritableChild(x, y, width, height, x0, y0, bandList);
	}

	/**
	 * Creates a Raster with the same layout and the same width and height, and
	 * with new zeroed data arrays. If the Raster is a subRaster, this will call
	 * createCompatibleRaster(width, height).
	 */
	@Override
	public WritableRaster createCompatibleWritableRaster() {
		return createCompatibleWritableRaster(width, height);
	}

	/**
	 * Creates a Raster with the same layout but using a different width and
	 * height, and with new zeroed data arrays.
	 */
	@Override
	public WritableRaster createCompatibleWritableRaster(int w, int h) {
		if (w <= 0 || h <= 0) {
			throw new RasterFormatException("negative "
					+ ((w <= 0) ? "width" : "height"));
		}

		SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);

		return new SwtCompatibleRaster(sm, new Point(0, 0));

	}

	/**
	 * Creates a Writable subRaster given a region of the Raster. The x and y
	 * coordinates specify the horizontal and vertical offsets from the
	 * upper-left corner of this Raster to the upper-left corner of the
	 * subRaster. A subset of the bands of the parent Raster may be specified.
	 * If this is null, then all the bands are present in the subRaster. A
	 * translation to the subRaster may also be specified. Note that the
	 * subRaster will reference the same DataBuffer as the parent Raster, but
	 * using different offsets.
	 * 
	 * @param x
	 *            X offset.
	 * @param y
	 *            Y offset.
	 * @param width
	 *            Width (in pixels) of the subraster.
	 * @param height
	 *            Height (in pixels) of the subraster.
	 * @param x0
	 *            Translated X origin of the subraster.
	 * @param y0
	 *            Translated Y origin of the subraster.
	 * @param bandList
	 *            Array of band indices.
	 * @exception RasterFormatException
	 *                if the specified bounding box is outside of the parent
	 *                Raster.
	 */
	@Override
	public WritableRaster createWritableChild(int x, int y, int width,
			int height, int x0, int y0, int[] bandList) {
		if (x < this.minX) {
			throw new RasterFormatException("x lies outside the raster");
		}
		if (y < this.minY) {
			throw new RasterFormatException("y lies outside the raster");
		}
		if ((x + width < x) || (x + width > this.minX + this.width)) {
			throw new RasterFormatException("(x + width) is outside of Raster");
		}
		if ((y + height < y) || (y + height > this.minY + this.height)) {
			throw new RasterFormatException("(y + height) is outside of Raster");
		}

		SampleModel sm;

		if (bandList != null)
			sm = sampleModel.createSubsetSampleModel(bandList);
		else
			sm = sampleModel;

		int deltaX = x0 - x;
		int deltaY = y0 - y;

		return new SwtCompatibleRaster(sm, dataBuffer, new Rectangle(x0, y0,
				width, height), new Point(sampleModelTranslateX + deltaX,
				sampleModelTranslateY + deltaY), this);
	}

	/**
	 * Returns a byte array of data elements from the specified rectangular
	 * region. An ArrayIndexOutOfBounds exception will be thrown at runtime if
	 * the pixel coordinates are out of bounds.
	 * 
	 * 
	 * byte[] bandData = raster.getByteData(x, y, w, h, null);
	 * int numDataElements = raster.getnumDataElements();
	 * byte[] pixel = new byte[numDataElements];
	 * // To find a data element at location (x2, y2)
	 * System.arraycopy(bandData, ((y2 - y) * w + (x2 - x)) * numDataElements, pixel,
	 * 		0, numDataElements);
	 * 
* * @param x * The X coordinate of the upper left pixel location. * @param y * The Y coordinate of the upper left pixel location. * @param width * Width of the pixel rectangle. * @param height * Height of the pixel rectangle. * @param outData * If non-null, data elements for all bands at the specified * location are returned in this array. * @return Data array with data elements for all bands. */ public byte[] getByteData(int x, int y, int w, int h, byte[] outData) { if ((x < this.minX) || (y < this.minY) || (x + w > this.maxX) || (y + h > this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } if (outData == null) { outData = new byte[numDataElements * w * h]; } int yoff = (y - minY) * scanlineStride + (x - minX) * pixelStride; int xoff; int off = 0; int xstart; int ystart; if (inOrder) { yoff += dataOffsets[0]; int rowBytes = w * pixelStride; if (scanlineStride == rowBytes) { System.arraycopy(data, yoff, outData, off, rowBytes * h); } else { for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { System.arraycopy(data, yoff, outData, off, rowBytes); off += rowBytes; } } } else if (numDataElements == 1) { yoff += dataOffsets[0]; for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { outData[off++] = data[xoff]; } } } else if (numDataElements == 2) { yoff += dataOffsets[0]; int d1 = dataOffsets[1] - dataOffsets[0]; for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { outData[off++] = data[xoff]; outData[off++] = data[xoff + d1]; } } } else if (numDataElements == 3) { yoff += dataOffsets[0]; int d1 = dataOffsets[1] - dataOffsets[0]; int d2 = dataOffsets[2] - dataOffsets[0]; for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { outData[off++] = data[xoff]; outData[off++] = data[xoff + d1]; outData[off++] = data[xoff + d2]; } } } else if (numDataElements == 4) { yoff += dataOffsets[0]; int d1 = dataOffsets[1] - dataOffsets[0]; int d2 = dataOffsets[2] - dataOffsets[0]; int d3 = dataOffsets[3] - dataOffsets[0]; for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { outData[off++] = data[xoff]; outData[off++] = data[xoff + d1]; outData[off++] = data[xoff + d2]; outData[off++] = data[xoff + d3]; } } } else { for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { for (int c = 0; c < numDataElements; c++) { outData[off++] = data[dataOffsets[c] + xoff]; } } } } return outData; } /** * Returns a byte array of data elements from the specified rectangular * region for the specified band. An ArrayIndexOutOfBounds exception will be * thrown at runtime if the pixel coordinates are out of bounds. * *
	 * byte[] bandData = raster.getByteData(x, y, w, h, null);
	 * 
	 * // To find the data element at location (x2, y2)
	 * byte bandElement = bandData[((y2 - y) * w + (x2 - x))];
	 * 
* * @param x * The X coordinate of the upper left pixel location. * @param y * The Y coordinate of the upper left pixel location. * @param width * Width of the pixel rectangle. * @param height * Height of the pixel rectangle. * @param band * The band to return. * @param outData * If non-null, data elements for all bands at the specified * location are returned in this array. * @return Data array with data elements for all bands. */ public byte[] getByteData(int x, int y, int w, int h, int band, byte[] outData) { // Bounds check for 'band' will be performed automatically if ((x < this.minX) || (y < this.minY) || (x + w > this.maxX) || (y + h > this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } if (outData == null) { outData = new byte[w * h]; } int yoff = (y - minY) * scanlineStride + (x - minX) * pixelStride + dataOffsets[band]; int xoff; int off = 0; int xstart; int ystart; if (pixelStride == 1) { if (scanlineStride == w) { System.arraycopy(data, yoff, outData, 0, w * h); } else { for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { System.arraycopy(data, yoff, outData, off, w); off += w; } } } else { for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { outData[off++] = data[xoff]; } } } return outData; } /** * Returns an array of data elements from the specified rectangular region. * An ArrayIndexOutOfBounds exception will be thrown at runtime if the pixel * coordinates are out of bounds. A ClassCastException will be thrown if the * input object is non null and references anything other than an array of * transferType. * *
	 * byte[] bandData = (byte[]) raster.getDataElements(x, y, w, h, null);
	 * int numDataElements = raster.getNumDataElements();
	 * byte[] pixel = new byte[numDataElements];
	 * // To find a data element at location (x2, y2)
	 * System.arraycopy(bandData, ((y2 - y) * w + (x2 - x)) * numDataElements, pixel,
	 * 		0, numDataElements);
	 * 
* * @param x * The X coordinate of the upper left pixel location. * @param y * The Y coordinate of the upper left pixel location. * @param width * Width of the pixel rectangle. * @param height * Height of the pixel rectangle. * @param outData * An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements(). If null * an array of appropriate type and size will be allocated. * @return An object reference to an array of type defined by * getTransferType() with the request pixel data. */ @Override public Object getDataElements(int x, int y, int w, int h, Object obj) { return getByteData(x, y, w, h, (byte[]) obj); } /** * Returns the data elements for all bands at the specified location. An * ArrayIndexOutOfBounds exception will be thrown at runtime if the pixel * coordinate is out of bounds. A ClassCastException will be thrown if the * input object is non null and references anything other than an array of * transferType. * * @param actualX * The X coordinate of the pixel location. * @param actualY * The Y coordinate of the pixel location. * @param outData * An object reference to an array of type defined by * getTransferType() and length getNumDataElements(). If null an * array of appropriate type and size will be allocated. * @return An object reference to an array of type defined by * getTransferType() with the request pixel data. */ @Override public Object getDataElements(int actualX, int actualY, Object obj) { byte outData[]; if (obj == null) { outData = new byte[numDataElements]; } else { outData = (byte[]) obj; } if ((actualX < this.minX) || (actualY < this.minY) || (actualX >= this.maxX) || (actualY >= this.maxY)) { for (int band = 0; band < numDataElements; band++) { outData[band] = 0; } return outData; } int off = (actualY - minY) * scanlineStride + (actualX - minX) * pixelStride; for (int band = 0; band < numDataElements; band++) { outData[band] = data[dataOffsets[band] + off]; } return outData; } /** * Returns the data offset for the specified band. The data offset is the * index into the data array in which the first sample of the first scanline * is stored. * * @param band * The band whose offset is returned. */ public int getDataOffset(int band) { return dataOffsets[band]; } /** * Returns a copy of the data offsets array. For each band the data offset * is the index into the band's data array, of the first sample of the band. */ public int[] getDataOffsets() { return dataOffsets.clone(); } /** * Returns a reference to the data array. */ public byte[] getDataStorage() { return data; } @Override public int[] getPixels(int x, int y, int w, int h, int[] iArray) { if ((x < this.minX) || (y < this.minY) || (x + w > this.maxX) || (y + h > this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } int pixels[]; if (iArray != null) { pixels = iArray; } else { pixels = new int[w * h * numBands]; } int lineOffset = y * scanlineStride + x * pixelStride; int dstOffset = 0; if (packed) { lineOffset += dbOffsetPacked; for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { int value = data[lineOffset + i]; for (int k = 0; k < numBands; k++) { pixels[dstOffset++] = (value & bitMasks[k]) >>> bitOffsets[k]; } } lineOffset += scanlineStride; } } else { lineOffset += dbOffset; int d0 = dataOffsets[0]; if (numBands == 1) { for (int j = 0; j < h; j++) { int pixelOffset = lineOffset + d0; for (int i = 0; i < w; i++) { pixels[dstOffset++] = data[pixelOffset] & 0xff; pixelOffset += pixelStride; } lineOffset += scanlineStride; } } else if (numBands == 2) { int d1 = dataOffsets[1] - d0; for (int j = 0; j < h; j++) { int pixelOffset = lineOffset + d0; for (int i = 0; i < w; i++) { pixels[dstOffset++] = data[pixelOffset] & 0xff; pixels[dstOffset++] = data[pixelOffset + d1] & 0xff; pixelOffset += pixelStride; } lineOffset += scanlineStride; } } else if (numBands == 3) { int d1 = dataOffsets[1] - d0; int d2 = dataOffsets[2] - d0; for (int j = 0; j < h; j++) { int pixelOffset = lineOffset + d0; for (int i = 0; i < w; i++) { pixels[dstOffset++] = data[pixelOffset] & 0xff; pixels[dstOffset++] = data[pixelOffset + d1] & 0xff; pixels[dstOffset++] = data[pixelOffset + d2] & 0xff; pixelOffset += pixelStride; } lineOffset += scanlineStride; } } else if (numBands == 4) { int d1 = dataOffsets[1] - d0; int d2 = dataOffsets[2] - d0; int d3 = dataOffsets[3] - d0; for (int j = 0; j < h; j++) { int pixelOffset = lineOffset + d0; for (int i = 0; i < w; i++) { pixels[dstOffset++] = data[pixelOffset] & 0xff; pixels[dstOffset++] = data[pixelOffset + d1] & 0xff; pixels[dstOffset++] = data[pixelOffset + d2] & 0xff; pixels[dstOffset++] = data[pixelOffset + d3] & 0xff; pixelOffset += pixelStride; } lineOffset += scanlineStride; } } else { for (int j = 0; j < h; j++) { int pixelOffset = lineOffset; for (int i = 0; i < w; i++) { for (int k = 0; k < numBands; k++) { pixels[dstOffset++] = data[pixelOffset + dataOffsets[k]] & 0xff; } pixelOffset += pixelStride; } lineOffset += scanlineStride; } } } return pixels; } /** * Returns pixel stride -- the number of data array elements between two * samples for the same band on the same scanline. */ public int getPixelStride() { return pixelStride; } @Override public int getSample(int x, int y, int b) { if ((x < this.minX) || (y < this.minY) || (x >= this.maxX) || (y >= this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } if (packed) { int offset = y * scanlineStride + x + dbOffsetPacked; byte sample = data[offset]; return (sample & bitMasks[b]) >>> bitOffsets[b]; } else { int offset = y * scanlineStride + x * pixelStride + dbOffset; return data[offset + dataOffsets[b]] & 0xff; } } @Override public int[] getSamples(int x, int y, int w, int h, int b, int[] iArray) { if ((x < this.minX) || (y < this.minY) || (x + w > this.maxX) || (y + h > this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } int samples[]; if (iArray != null) { samples = iArray; } else { samples = new int[w * h]; } int lineOffset = y * scanlineStride + x * pixelStride; int dstOffset = 0; if (packed) { lineOffset += dbOffsetPacked; int bitMask = bitMasks[b]; int bitOffset = bitOffsets[b]; for (int j = 0; j < h; j++) { int sampleOffset = lineOffset; for (int i = 0; i < w; i++) { int value = data[sampleOffset++]; samples[dstOffset++] = ((value & bitMask) >>> bitOffset); } lineOffset += scanlineStride; } } else { lineOffset += dbOffset + dataOffsets[b]; for (int j = 0; j < h; j++) { int sampleOffset = lineOffset; for (int i = 0; i < w; i++) { samples[dstOffset++] = data[sampleOffset] & 0xff; sampleOffset += pixelStride; } lineOffset += scanlineStride; } } return samples; } /** * Returns the scanline stride -- the number of data array elements between * a given sample and the sample in the same column of the next row in the * same band. */ public int getScanlineStride() { return scanlineStride; } /** * * Analyzes a ComponentSampleModel to determine if it can function as a * PixelInterleavedSampleModel. In order to do so, it must use only bank 0 * of its DataBuffer, and the data offsets must span a range of less than * pixelStride. * *

* These properties are trivially true for a 1-banded SampleModel. */ private boolean isInterleaved(ComponentSampleModel sm) { // Analyze ComponentSampleModel to determine if it has the // properties of a PixelInterleavedSampleModel int numBands = sampleModel.getNumBands(); if (numBands == 1) { return true; } // Determine banks used int[] bankIndices = sm.getBankIndices(); for (int i = 0; i < numBands; i++) { if (bankIndices[i] != 0) { return false; } } // Determine range of band offsets int[] bandOffsets = sm.getBandOffsets(); int minOffset = bandOffsets[0]; int maxOffset = minOffset; for (int i = 1; i < numBands; i++) { int offset = bandOffsets[i]; if (offset < minOffset) { minOffset = offset; } if (offset > maxOffset) { maxOffset = offset; } } if (maxOffset - minOffset >= sm.getPixelStride()) { return false; } return true; } /** * Stores a byte array of data elements into the specified rectangular * region. An ArrayIndexOutOfBounds exception will be thrown at runtime if * the pixel coordinates are out of bounds. The data elements in the data * array are assumed to be packed. That is, a data element for the nth band * at location (x2, y2) would be found at: * *

	 * inData[((y2 - y) * w + (x2 - x)) * numDataElements + n]
	 * 
* * @param x * The X coordinate of the upper left pixel location. * @param y * The Y coordinate of the upper left pixel location. * @param w * Width of the pixel rectangle. * @param h * Height of the pixel rectangle. * @param inData * The data elements to be stored. */ public void putByteData(int x, int y, int w, int h, byte[] inData) { if ((x < this.minX) || (y < this.minY) || (x + w > this.maxX) || (y + h > this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } int yoff = (y - minY) * scanlineStride + (x - minX) * pixelStride; int xoff; int off = 0; int xstart; int ystart; if (inOrder) { yoff += dataOffsets[0]; int rowBytes = w * pixelStride; if (rowBytes == scanlineStride) { System.arraycopy(inData, 0, data, yoff, rowBytes * h); } else { for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { System.arraycopy(inData, off, data, yoff, rowBytes); off += rowBytes; } } } else if (numDataElements == 1) { yoff += dataOffsets[0]; for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { data[xoff] = inData[off++]; } } } else if (numDataElements == 2) { yoff += dataOffsets[0]; int d1 = dataOffsets[1] - dataOffsets[0]; for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { data[xoff] = inData[off++]; data[xoff + d1] = inData[off++]; } } } else if (numDataElements == 3) { yoff += dataOffsets[0]; int d1 = dataOffsets[1] - dataOffsets[0]; int d2 = dataOffsets[2] - dataOffsets[0]; for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { data[xoff] = inData[off++]; data[xoff + d1] = inData[off++]; data[xoff + d2] = inData[off++]; } } } else if (numDataElements == 4) { yoff += dataOffsets[0]; int d1 = dataOffsets[1] - dataOffsets[0]; int d2 = dataOffsets[2] - dataOffsets[0]; int d3 = dataOffsets[3] - dataOffsets[0]; for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { data[xoff] = inData[off++]; data[xoff + d1] = inData[off++]; data[xoff + d2] = inData[off++]; data[xoff + d3] = inData[off++]; } } } else { for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { for (int c = 0; c < numDataElements; c++) { data[dataOffsets[c] + xoff] = inData[off++]; } } } } } /** * Stores a byte array of data elements into the specified rectangular * region for the specified band. An ArrayIndexOutOfBounds exception will be * thrown at runtime if the pixel coordinates are out of bounds. The data * elements in the data array are assumed to be packed. That is, a data * element at location (x2, y2) would be found at: * *
	 * inData[((y2 - y) * w + (x2 - x)) + n]
	 * 
* * @param x * The X coordinate of the upper left pixel location. * @param y * The Y coordinate of the upper left pixel location. * @param w * Width of the pixel rectangle. * @param h * Height of the pixel rectangle. * @param band * The band to set. * @param inData * The data elements to be stored. */ public void putByteData(int x, int y, int w, int h, int band, byte[] inData) { // Bounds check for 'band' will be performed automatically if ((x < this.minX) || (y < this.minY) || (x + w > this.maxX) || (y + h > this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } int yoff = (y - minY) * scanlineStride + (x - minX) * pixelStride + dataOffsets[band]; int xoff; int off = 0; int xstart; int ystart; if (pixelStride == 1) { if (scanlineStride == w) { System.arraycopy(inData, 0, data, yoff, w * h); } else { for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { System.arraycopy(inData, off, data, yoff, w); off += w; } } } else { for (ystart = 0; ystart < h; ystart++, yoff += scanlineStride) { xoff = yoff; for (xstart = 0; xstart < w; xstart++, xoff += pixelStride) { data[xoff] = inData[off++]; } } } } /** * Stores the Raster data at the specified location. * * @param dstX * The absolute X coordinate of the destination pixel that will * receive a copy of the upper-left pixel of the inRaster * @param dstY * The absolute Y coordinate of the destination pixel that will * receive a copy of the upper-left pixel of the inRaster * @param srcX * The absolute X coordinate of the upper-left source pixel that * will be copied into this Raster * @param srcY * The absolute Y coordinate of the upper-left source pixel that * will be copied into this Raster * @param width * The number of pixels to store horizontally * @param height * The number of pixels to store vertically * @param inRaster * Raster of data to place at x,y location. */ private void setDataElements(int dstX, int dstY, int srcX, int srcY, int width, int height, Raster inRaster) { // Assume bounds checking has been performed previously if (width <= 0 || height <= 0) { return; } // Write inRaster (minX, minY) to (dstX, dstY) int srcOffX = inRaster.getMinX(); int srcOffY = inRaster.getMinY(); Object tdata = null; if (inRaster instanceof SwtCompatibleRaster) { SwtCompatibleRaster bct = (SwtCompatibleRaster) inRaster; byte[] bdata = bct.getDataStorage(); // copy whole scanlines if (inOrder && bct.inOrder && pixelStride == bct.pixelStride) { int toff = bct.getDataOffset(0); int tss = bct.getScanlineStride(); int tps = bct.getPixelStride(); int srcOffset = toff + (srcY - srcOffY) * tss + (srcX - srcOffX) * tps; int dstOffset = dataOffsets[0] + (dstY - minY) * scanlineStride + (dstX - minX) * pixelStride; int nbytes = width * pixelStride; for (int tmpY = 0; tmpY < height; tmpY++) { System.arraycopy(bdata, srcOffset, data, dstOffset, nbytes); srcOffset += tss; dstOffset += scanlineStride; } return; } } for (int startY = 0; startY < height; startY++) { // Grab one scanline at a time tdata = inRaster.getDataElements(srcOffX, srcOffY + startY, width, 1, tdata); setDataElements(dstX, dstY + startY, width, 1, tdata); } } /** * Stores an array of data elements into the specified rectangular region. * An ArrayIndexOutOfBounds exception will be thrown at runtime if the pixel * coordinates are out of bounds. A ClassCastException will be thrown if the * input object is non null and references anything other than an array of * transferType. The data elements in the data array are assumed to be * packed. That is, a data element for the nth band at location (x2, y2) * would be found at: * *
	 * inData[((y2 - y) * w + (x2 - x)) * numDataElements + n]
	 * 
* * @param x * The X coordinate of the upper left pixel location. * @param y * The Y coordinate of the upper left pixel location. * @param w * Width of the pixel rectangle. * @param h * Height of the pixel rectangle. * @param inData * An object reference to an array of type defined by * getTransferType() and length w*h*getNumDataElements() * containing the pixel data to place between x,y and x+h, y+h. */ @Override public void setDataElements(int x, int y, int w, int h, Object obj) { putByteData(x, y, w, h, (byte[]) obj); } /** * Stores the data elements for all bands at the specified location. An * ArrayIndexOutOfBounds exception will be thrown at runtime if the pixel * coordinate is out of bounds. A ClassCastException will be thrown if the * input object is non null and references anything other than an array of * transferType. * * @param x * The X coordinate of the pixel location. * @param y * The Y coordinate of the pixel location. * @param inData * An object reference to an array of type defined by * getTransferType() and length getNumDataElements() containing * the pixel data to place at x,y. */ @Override public void setDataElements(int x, int y, Object obj) { if ((x < this.minX) || (y < this.minY) || (x >= this.maxX) || (y >= this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } byte inData[] = (byte[]) obj; int off = (y - minY) * scanlineStride + (x - minX) * pixelStride; for (int i = 0; i < numDataElements; i++) { data[dataOffsets[i] + off] = inData[i]; } } /** * Stores the Raster data at the specified location. An * ArrayIndexOutOfBounds exception will be thrown at runtime if the pixel * coordinates are out of bounds. * * @param x * The X coordinate of the pixel location. * @param y * The Y coordinate of the pixel location. * @param inRaster * Raster of data to place at x,y location. */ @Override public void setDataElements(int x, int y, Raster inRaster) { int srcOffX = inRaster.getMinX(); int srcOffY = inRaster.getMinY(); int dstOffX = x + srcOffX; int dstOffY = y + srcOffY; int width = inRaster.getWidth(); int height = inRaster.getHeight(); if ((dstOffX < this.minX) || (dstOffY < this.minY) || (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } setDataElements(dstOffX, dstOffY, srcOffX, srcOffY, width, height, inRaster); } @Override public void setPixels(int x, int y, int w, int h, int[] iArray) { if ((x < this.minX) || (y < this.minY) || (x + w > this.maxX) || (y + h > this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } int lineOffset = y * scanlineStride + x * pixelStride; int srcOffset = 0; if (packed) { lineOffset += dbOffsetPacked; for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { int value = 0; for (int k = 0; k < numBands; k++) { int srcValue = iArray[srcOffset++]; value |= ((srcValue << bitOffsets[k]) & bitMasks[k]); } data[lineOffset + i] = (byte) value; } lineOffset += scanlineStride; } } else { lineOffset += dbOffset; int d0 = dataOffsets[0]; if (numBands == 1) { for (int j = 0; j < h; j++) { int pixelOffset = lineOffset + d0; for (int i = 0; i < w; i++) { data[pixelOffset] = (byte) iArray[srcOffset++]; pixelOffset += pixelStride; } lineOffset += scanlineStride; } } else if (numBands == 2) { int d1 = dataOffsets[1] - d0; for (int j = 0; j < h; j++) { int pixelOffset = lineOffset + d0; for (int i = 0; i < w; i++) { data[pixelOffset] = (byte) iArray[srcOffset++]; data[pixelOffset + d1] = (byte) iArray[srcOffset++]; pixelOffset += pixelStride; } lineOffset += scanlineStride; } } else if (numBands == 3) { int d1 = dataOffsets[1] - d0; int d2 = dataOffsets[2] - d0; for (int j = 0; j < h; j++) { int pixelOffset = lineOffset + d0; for (int i = 0; i < w; i++) { data[pixelOffset] = (byte) iArray[srcOffset++]; data[pixelOffset + d1] = (byte) iArray[srcOffset++]; data[pixelOffset + d2] = (byte) iArray[srcOffset++]; pixelOffset += pixelStride; } lineOffset += scanlineStride; } } else if (numBands == 4) { int d1 = dataOffsets[1] - d0; int d2 = dataOffsets[2] - d0; int d3 = dataOffsets[3] - d0; for (int j = 0; j < h; j++) { int pixelOffset = lineOffset + d0; for (int i = 0; i < w; i++) { data[pixelOffset] = (byte) iArray[srcOffset++]; data[pixelOffset + d1] = (byte) iArray[srcOffset++]; data[pixelOffset + d2] = (byte) iArray[srcOffset++]; data[pixelOffset + d3] = (byte) iArray[srcOffset++]; pixelOffset += pixelStride; } lineOffset += scanlineStride; } } else { for (int j = 0; j < h; j++) { int pixelOffset = lineOffset; for (int i = 0; i < w; i++) { for (int k = 0; k < numBands; k++) { data[pixelOffset + dataOffsets[k]] = (byte) iArray[srcOffset++]; } pixelOffset += pixelStride; } lineOffset += scanlineStride; } } } } @Override public void setRect(int dx, int dy, Raster srcRaster) { if (!(srcRaster instanceof SwtCompatibleRaster)) { super.setRect(dx, dy, srcRaster); return; } int width = srcRaster.getWidth(); int height = srcRaster.getHeight(); int srcOffX = srcRaster.getMinX(); int srcOffY = srcRaster.getMinY(); int dstOffX = dx + srcOffX; int dstOffY = dy + srcOffY; // Clip to this raster if (dstOffX < this.minX) { int skipX = minX - dstOffX; width -= skipX; srcOffX += skipX; dstOffX = this.minX; } if (dstOffY < this.minY) { int skipY = this.minY - dstOffY; height -= skipY; srcOffY += skipY; dstOffY = this.minY; } if (dstOffX + width > this.maxX) { width = this.maxX - dstOffX; } if (dstOffY + height > this.maxY) { height = this.maxY - dstOffY; } setDataElements(dstOffX, dstOffY, srcOffX, srcOffY, width, height, srcRaster); } @Override public void setSample(int x, int y, int b, int s) { if ((x < this.minX) || (y < this.minY) || (x >= this.maxX) || (y >= this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } if (packed) { int offset = y * scanlineStride + x + dbOffsetPacked; int bitMask = bitMasks[b]; byte value = data[offset]; value &= ~bitMask; value |= (s << bitOffsets[b]) & bitMask; data[offset] = value; } else { int offset = y * scanlineStride + x * pixelStride + dbOffset; data[offset + dataOffsets[b]] = (byte) s; } } @Override public void setSamples(int x, int y, int w, int h, int b, int iArray[]) { if ((x < this.minX) || (y < this.minY) || (x + w > this.maxX) || (y + h > this.maxY)) { throw new ArrayIndexOutOfBoundsException( "Coordinate out of bounds!"); } int lineOffset = y * scanlineStride + x * pixelStride; int srcOffset = 0; if (packed) { lineOffset += dbOffsetPacked; int bitMask = bitMasks[b]; for (int j = 0; j < h; j++) { int sampleOffset = lineOffset; for (int i = 0; i < w; i++) { byte value = data[sampleOffset]; value &= ~bitMask; int sample = iArray[srcOffset++]; value |= (sample << bitOffsets[b]) & bitMask; data[sampleOffset++] = value; } lineOffset += scanlineStride; } } else { lineOffset += dbOffset + dataOffsets[b]; for (int i = 0; i < h; i++) { int sampleOffset = lineOffset; for (int j = 0; j < w; j++) { data[sampleOffset] = (byte) iArray[srcOffset++]; sampleOffset += pixelStride; } lineOffset += scanlineStride; } } } @Override public String toString() { return new String("SwtCompatibleRaster: width = " + width + " height = " + height + " #numDataElements " + numDataElements // +" xOff = "+xOffset+" yOff = "+yOffset + " dataOff[0] = " + dataOffsets[0]); } /** * Verify that the layout parameters are consistent with the data. If * strictCheck is false, this method will check for ArrayIndexOutOfBounds * conditions. If strictCheck is true, this method will check for additional * error conditions such as line wraparound (width of a line greater than * the scanline stride). * * @return String Error string, if the layout is incompatible with the data. * Otherwise returns null. */ private void verify(boolean strictCheck) { int maxSize = 0; int size; for (int i = 0; i < numDataElements; i++) { size = (height - 1) * scanlineStride + (width - 1) * pixelStride + dataOffsets[i]; if (size > maxSize) { maxSize = size; } } if (data.length < maxSize) { throw new RasterFormatException("Data array too small (should be " + maxSize + " )"); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy