帆软使用的第三方框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1059 lines
38 KiB

/*
* Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
*
* 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.
*
* -Redistribution in binary form must reproduct 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 Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that Software is not designed,licensed or intended for use in
* the design, construction, operation or maintenance of any nuclear facility.
*/
package com.fr.third.JAI;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferShort;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferUShort;
import java.awt.image.SampleModel;
/**
* This class represents image data which is stored such that each sample
* of a pixel occupies one data element of the <code>DataBuffer</code>. It stores the
* N samples which make up a pixel in N separate data array elements.
* Different bands may be in different banks of the <code>DataBuffer</code>.
* Accessor methods are provided so that image data can be manipulated
* directly. This class can support different kinds of interleaving, e.g.
* band interleaving, scanline interleaving, and pixel interleaving.
* Pixel stride is the number of data array elements between two samples
* for the same band on the same scanline. Scanline stride is the number
* of data array elements between a given sample and the corresponding sample
* in the same column of the next scanline. Band offsets denote the number
* of data array elements from the first data array element of the bank
* of the <code>DataBuffer</code> holding each band to the first sample of the band.
* The bands are numbered from 0 to N-1. This class can represent image
* data for the dataTypes enumerated in java.awt.image.DataBuffer (all
* samples of a given <code>ComponentSampleModel</code> are stored with the same precision)
* . This class adds support for <code>Double</code> and <code>Float</code> data types in addition
* to those supported by the <code>ComponentSampleModel</code> class in Java 2D.
* All strides and offsets must be non-negative.
* @see java.awt.image.ComponentSampleModel
*/
public class ComponentSampleModelJAI extends ComponentSampleModel {
/**
* Constructs a <code>ComponentSampleModel</code> with the specified
* parameters. The number of bands will be given by the length of
* the bandOffsets array. All bands will be stored in the first
* bank of the <code>DataBuffer</code>.
*
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of
* image data described.
* @param h The height (in pixels) of the region of
* image data described.
* @param pixelStride The pixel stride of the region of image
* data described.
* @param scanlineStride The line stride of the region of image
* data described.
* @param bandOffsets The offsets of all bands.
*/
public ComponentSampleModelJAI(int dataType,
int w, int h,
int pixelStride,
int scanlineStride,
int bandOffsets[]) {
super(dataType, w, h, pixelStride, scanlineStride, bandOffsets);
}
/**
* Constructs a <code>ComponentSampleModel</code> with the specified
* parameters. The number of bands will be given by the length of
* the bandOffsets array. Different bands may be stored in
* different banks of the <code>DataBuffer</code>.
*
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of
* image data described.
* @param h The height (in pixels) of the region of
* image data described.
* @param pixelStride The pixel stride of the region of image
* data described.
* @param scanlineStride The line stride of the region of image
* data described.
* @param bankIndices The bank indices of all bands.
* @param bandOffsets The band offsets of all bands.
*/
public ComponentSampleModelJAI(int dataType,
int w, int h,
int pixelStride,
int scanlineStride,
int bankIndices[],
int bandOffsets[]) {
super(dataType, w, h, pixelStride, scanlineStride,
bankIndices, bandOffsets);
}
/**
* Returns the size of the data buffer (in data elements) needed
* for a data buffer that matches this <code>ComponentSampleModel</code>.
*/
private long getBufferSize() {
int maxBandOff=bandOffsets[0];
for (int i=1; i<bandOffsets.length; i++)
maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
long size = 0;
if (maxBandOff >= 0)
size += maxBandOff+1;
if (pixelStride > 0)
size += pixelStride * (width-1);
if (scanlineStride > 0)
size += scanlineStride*(height-1);
return size;
}
/**
* Preserves band ordering with new step factor...
*/
private int[] JAIorderBands(int orig[], int step) {
int map[] = new int[orig.length];
int ret[] = new int[orig.length];
for (int i=0; i<map.length; i++) map[i] = i;
for (int i = 0; i < ret.length; i++) {
int index = i;
for (int j = i+1; j < ret.length; j++) {
if (orig[map[index]] > orig[map[j]]) {
index = j;
}
}
ret[map[index]] = i*step;
map[index] = map[i];
}
return ret;
}
/**
* Creates a new <code>ComponentSampleModel</code> with the specified
* width and height. The new <code>SampleModel</code> will have the same
* number of bands, storage data type, interleaving scheme, and
* pixel stride as this <code>SampleModel</code>.
*
* @param w The width in pixels.
* @param h The height in pixels
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
SampleModel ret=null;
long size;
int minBandOff=bandOffsets[0];
int maxBandOff=bandOffsets[0];
for (int i=1; i<bandOffsets.length; i++) {
minBandOff = Math.min(minBandOff,bandOffsets[i]);
maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
}
maxBandOff -= minBandOff;
int bands = bandOffsets.length;
int bandOff[];
int pStride = Math.abs(pixelStride);
int lStride = Math.abs(scanlineStride);
int bStride = Math.abs(maxBandOff);
if (pStride > lStride) {
if (pStride > bStride) {
if (lStride > bStride) { // pix > line > band
bandOff = new int[bandOffsets.length];
for (int i=0; i<bands; i++)
bandOff[i] = bandOffsets[i]-minBandOff;
lStride = bStride+1;
pStride = lStride*h;
} else { // pix > band > line
bandOff = JAIorderBands(bandOffsets,lStride*h);
pStride = bands*lStride*h;
}
} else { // band > pix > line
pStride = lStride*h;
bandOff = JAIorderBands(bandOffsets,pStride*w);
}
} else {
if (pStride > bStride) { // line > pix > band
bandOff = new int[bandOffsets.length];
for (int i=0; i<bands; i++)
bandOff[i] = bandOffsets[i]-minBandOff;
pStride = bStride+1;
lStride = pStride*w;
} else {
if (lStride > bStride) { // line > band > pix
bandOff = JAIorderBands(bandOffsets,pStride*w);
lStride = bands*pStride*w;
} else { // band > line > pix
lStride = pStride*w;
bandOff = JAIorderBands(bandOffsets,lStride*h);
}
}
}
// make sure we make room for negative offsets...
int base = 0;
if (scanlineStride < 0) {
base += lStride*h;
lStride *= -1;
}
if (pixelStride < 0) {
base += pStride*w;
pStride *= -1;
}
for (int i=0; i<bands; i++)
bandOff[i] += base;
return new ComponentSampleModelJAI(dataType, w, h, pStride,
lStride, bankIndices, bandOff);
}
/**
* This creates a new <code>ComponentSampleModel</code> with a subset of the bands
* of this <code>ComponentSampleModel</code>. The new <code>ComponentSampleModel</code> can be
* used with any <code>DataBuffer</code> that the existing <code>ComponentSampleModel</code>
* can be used with. The new <code>ComponentSampleModel</code>/<code>DataBuffer</code>
* combination will represent an image with a subset of the bands
* of the original <code>ComponentSampleModel</code>/<code>DataBuffer</code> combination.
*
* @param bands subset of bands of this <code>ComponentSampleModel</code>
*/
public SampleModel createSubsetSampleModel(int bands[]) {
int newBankIndices[] = new int[bands.length];
int newBandOffsets[] = new int[bands.length];
for (int i=0; i<bands.length; i++) {
int b = bands[i];
newBankIndices[i] = bankIndices[b];
newBandOffsets[i] = bandOffsets[b];
}
return new ComponentSampleModelJAI(this.dataType, width, height,
this.pixelStride,
this.scanlineStride,
newBankIndices,
newBandOffsets);
}
/**
* Creates a <code>DataBuffer</code> that corresponds to this <code>ComponentSampleModel</code>.
* The <code>DataBuffer</code>'s data type, number of banks, and size
* will be consistent with this <code>ComponentSampleModel</code>.
*/
public DataBuffer createDataBuffer() {
DataBuffer dataBuffer = null;
int size = (int)getBufferSize();
switch (dataType) {
case DataBuffer.TYPE_BYTE:
dataBuffer = new DataBufferByte(size, numBanks);
break;
case DataBuffer.TYPE_USHORT:
dataBuffer = new DataBufferUShort(size, numBanks);
break;
case DataBuffer.TYPE_INT:
dataBuffer = new DataBufferInt(size, numBanks);
break;
case DataBuffer.TYPE_SHORT:
dataBuffer = new DataBufferShort(size, numBanks);
break;
case DataBuffer.TYPE_FLOAT:
dataBuffer = new DataBufferFloat(size, numBanks);
break;
case DataBuffer.TYPE_DOUBLE:
dataBuffer = new DataBufferDouble(size, numBanks);
break;
default:
throw new RuntimeException(JaiI18N.getString("RasterFactory3"));
}
return dataBuffer;
}
/**
* Returns data for a single pixel in a primitive array of type
* TransferType. For a <code>ComponentSampleModel</code>, this will be the same
* as the data type, and samples will be returned one per array
* element. Generally, obj
* should be passed in as null, so that the <code>Object</code> will be created
* automatically and will be of the right primitive data type.
* <p>
* The following code illustrates transferring data for one pixel from
* <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by
* <code>ComponentSampleModel</code> <code>csm1</code>, to <code>DataBuffer</code> <code>db2</code>,
* whose storage layout is described by
* <code>ComponentSampleModel</code> <code>csm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* ComponentSampleModel csm1, csm2;
* DataBufferInt db1, db2;
* csm2.setDataElements(x, y,
* csm1.getDataElements(x, y, null, db1), db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param obj If non-null, a primitive array in which to return
* the pixel data.
* @param data The <code>DataBuffer</code> containing the image data.
* @throws <code>ClassCastException</code> if obj is non-null and is not
* a primitive array of type TransferType.
* @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates
* are not in bounds, or if obj is non-null and is not large
* enough to hold the pixel data.
*/
public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
int type = getTransferType();
int numDataElems = getNumDataElements();
int pixelOffset = y*scanlineStride + x*pixelStride;
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] bdata;
if (obj == null)
bdata = new byte[numDataElems];
else
bdata = (byte[])obj;
for (int i=0; i<numDataElems; i++) {
bdata[i] = (byte)data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)bdata;
break;
case DataBuffer.TYPE_USHORT:
short[] usdata;
if (obj == null)
usdata = new short[numDataElems];
else
usdata = (short[])obj;
for (int i=0; i<numDataElems; i++) {
usdata[i] = (short)data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)usdata;
break;
case DataBuffer.TYPE_INT:
int[] idata;
if (obj == null)
idata = new int[numDataElems];
else
idata = (int[])obj;
for (int i=0; i<numDataElems; i++) {
idata[i] = data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)idata;
break;
case DataBuffer.TYPE_SHORT:
short[] sdata;
if (obj == null)
sdata = new short[numDataElems];
else
sdata = (short[])obj;
for (int i=0; i<numDataElems; i++) {
sdata[i] = (short)data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)sdata;
break;
case DataBuffer.TYPE_FLOAT:
float[] fdata;
if (obj == null)
fdata = new float[numDataElems];
else
fdata = (float[])obj;
for (int i=0; i<numDataElems; i++) {
fdata[i] = data.getElemFloat(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)fdata;
break;
case DataBuffer.TYPE_DOUBLE:
double[] ddata;
if (obj == null)
ddata = new double[numDataElems];
else
ddata = (double[])obj;
for (int i=0; i<numDataElems; i++) {
ddata[i] = data.getElemDouble(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)ddata;
break;
default:
throw new RuntimeException(JaiI18N.getString("RasterFactory3"));
}
return obj;
}
/**
* Returns the pixel data for the specified rectangle of pixels in a
* primitive array of type TransferType.
* For image data supported by the Java 2D API, this
* will be one of the dataTypes supported by java.awt.image.DataBuffer.
* Data may be returned in a packed format, thus increasing efficiency
* for data transfers. Generally, obj should be passed in as null, so
* that the <code>Object</code> will be created automatically and will be of the right
* primitive data type.
* <p>
* The following code illustrates transferring data for a rectangular
* region of pixels from
* <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by
* <code>SampleModel</code> <code>sm1</code>, to <code>DataBuffer</code> <code>db2</code>, whose
* storage layout is described by <code>SampleModel</code> <code>sm2</code>.
* The transfer will generally be more efficient than using
* getPixels/setPixels.
* <pre>
* SampleModel sm1, sm2;
* DataBuffer db1, db2;
* sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w,
* h, null, db1), db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* @param x The minimum X coordinate of the pixel rectangle.
* @param y The minimum Y coordinate of the pixel rectangle.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param obj If non-null, a primitive array in which to return
* the pixel data.
* @param data The <code>DataBuffer</code> containing the image data.
* @see #getNumDataElements
* @see #getTransferType
* @see java.awt.image.DataBuffer
* @throws <code>ClassCastException</code> if obj is non-null and is not
* a primitive array of type TransferType.
* @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates
* are not in bounds, or if obj is non-null and is not large
* enough to hold the pixel data.
*/
public Object getDataElements(int x, int y, int w, int h,
Object obj, DataBuffer data) {
int type = getTransferType();
int numDataElems = getNumDataElements();
int cnt = 0;
Object o = null;
switch(type) {
case DataBuffer.TYPE_BYTE: {
byte[] btemp;
byte[] bdata;
if (obj == null)
bdata = new byte[numDataElems*w*h];
else
bdata = (byte[])obj;
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
o = getDataElements(j, i, o, data);
btemp = (byte[])o;
for (int k=0; k<numDataElems; k++) {
bdata[cnt++] = btemp[k];
}
}
}
obj = (Object)bdata;
break;
}
case DataBuffer.TYPE_USHORT: {
short[] usdata;
short[] ustemp;
if (obj == null)
usdata = new short[numDataElems*w*h];
else
usdata = (short[])obj;
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
o = getDataElements(j, i, o, data);
ustemp = (short[])o;
for (int k=0; k<numDataElems; k++) {
usdata[cnt++] = ustemp[k];
}
}
}
obj = (Object)usdata;
break;
}
case DataBuffer.TYPE_INT: {
int[] idata;
int[] itemp;
if (obj == null)
idata = new int[numDataElems*w*h];
else
idata = (int[])obj;
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
o = getDataElements(j, i, o, data);
itemp = (int[])o;
for (int k=0; k<numDataElems; k++) {
idata[cnt++] = itemp[k];
}
}
}
obj = (Object)idata;
break;
}
case DataBuffer.TYPE_SHORT: {
short[] sdata;
short[] stemp;
if (obj == null)
sdata = new short[numDataElems*w*h];
else
sdata = (short[])obj;
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
o = getDataElements(j, i, o, data);
stemp = (short[])o;
for (int k=0; k<numDataElems; k++) {
sdata[cnt++] = stemp[k];
}
}
}
obj = (Object)sdata;
break;
}
case DataBuffer.TYPE_FLOAT: {
float[] fdata;
float[] ftemp;
if (obj == null)
fdata = new float[numDataElems*w*h];
else
fdata = (float[])obj;
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
o = getDataElements(j, i, o, data);
ftemp = (float[])o;
for (int k=0; k<numDataElems; k++) {
fdata[cnt++] = ftemp[k];
}
}
}
obj = (Object)fdata;
break;
}
case DataBuffer.TYPE_DOUBLE: {
double[] ddata;
double[] dtemp;
if (obj == null)
ddata = new double[numDataElems*w*h];
else
ddata = (double[])obj;
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
o = getDataElements(j, i, o, data);
dtemp = (double[])o;
for (int k=0; k<numDataElems; k++) {
ddata[cnt++] = dtemp[k];
}
}
}
obj = (Object)ddata;
break;
}
default:
throw new RuntimeException(JaiI18N.getString("RasterFactory3"));
}
return obj;
}
/**
* Sets the data for a single pixel in the specified <code>DataBuffer</code> from a
* primitive array of type TransferType. For a <code>ComponentSampleModel</code>,
* this will be the same as the data type, and samples are transferred
* one per array element.
* <p>
* The following code illustrates transferring data for one pixel from
* <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by
* <code>ComponentSampleModel</code> <code>csm1</code>, to <code>DataBuffer</code> <code>db2</code>,
* whose storage layout is described by
* <code>ComponentSampleModel</code> <code>csm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* ComponentSampleModel csm1, csm2;
* DataBufferInt db1, db2;
* csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
* db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param obj A primitive array containing pixel data.
* @param data The <code>DataBuffer</code> containing the image data.
* @throws <code>ClassCastException</code> if obj is non-null and is not
* a primitive array of type TransferType.
* @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates
* are not in bounds, or if obj is non-null and is not large
* enough to hold the pixel data.
*/
public void setDataElements(int x, int y, Object obj, DataBuffer data) {
int type = getTransferType();
int numDataElems = getNumDataElements();
int pixelOffset = y*scanlineStride + x*pixelStride;
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] barray = (byte[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
((int)barray[i])&0xff);
}
break;
case DataBuffer.TYPE_USHORT:
short[] usarray = (short[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
((int)usarray[i])&0xffff);
}
break;
case DataBuffer.TYPE_INT:
int[] iarray = (int[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i],
pixelOffset + bandOffsets[i], iarray[i]);
}
break;
case DataBuffer.TYPE_SHORT:
short[] sarray = (short[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i],
pixelOffset + bandOffsets[i], sarray[i]);
}
break;
case DataBuffer.TYPE_FLOAT:
float[] farray = (float[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElemFloat(bankIndices[i],
pixelOffset + bandOffsets[i], farray[i]);
}
break;
case DataBuffer.TYPE_DOUBLE:
double[] darray = (double[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElemDouble(bankIndices[i],
pixelOffset + bandOffsets[i], darray[i]);
}
break;
default:
throw new RuntimeException(JaiI18N.getString("RasterFactory3"));
}
}
/**
* Sets the data for a rectangle of pixels in the specified <code>DataBuffer</code>
* from a primitive array of type TransferType. For image data supported
* by the Java 2D API, this will be one of the dataTypes supported by
* java.awt.image.DataBuffer. Data in the array may be in a packed
* format, thus increasing efficiency for data transfers.
* <p>
* The following code illustrates transferring data for a rectangular
* region of pixels from
* <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by
* <code>SampleModel</code> <code>sm1</code>, to <code>DataBuffer</code> <code>db2</code>, whose
* storage layout is described by <code>SampleModel</code> <code>sm2</code>.
* The transfer will generally be more efficient than using
* getPixels/setPixels.
* <pre>
* SampleModel sm1, sm2;
* DataBuffer db1, db2;
* sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w, h,
* null, db1), db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* @param x The minimum X coordinate of the pixel rectangle.
* @param y The minimum Y coordinate of the pixel rectangle.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param obj A primitive array containing pixel data.
* @param data The <code>DataBuffer</code> containing the image data.
* @throws <code>ClassCastException</code> if obj is non-null and is not
* a primitive array of type TransferType.
* @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates
* are not in bounds, or if obj is non-null and is not large
* enough to hold the pixel data.
* @see #getNumDataElements
* @see #getTransferType
* @see java.awt.image.DataBuffer
*/
public void setDataElements(int x, int y, int w, int h,
Object obj, DataBuffer data) {
int cnt = 0;
Object o = null;
int type = getTransferType();
int numDataElems = getNumDataElements();
switch(type) {
case DataBuffer.TYPE_BYTE: {
byte[] barray = (byte[])obj;
byte[] btemp = new byte[numDataElems];
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
for (int k=0; k<numDataElems; k++) {
btemp[k] = barray[cnt++];
}
setDataElements(j, i, btemp, data);
}
}
break;
}
case DataBuffer.TYPE_USHORT: {
short[] usarray = (short[])obj;
short[] ustemp = new short[numDataElems];
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
for (int k=0; k<numDataElems; k++) {
ustemp[k] = usarray[cnt++];
}
setDataElements(j, i, ustemp, data);
}
}
break;
}
case DataBuffer.TYPE_INT: {
int[] iArray = (int[])obj;
int[] itemp = new int[numDataElems];
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
for (int k=0; k<numDataElems; k++) {
itemp[k] = iArray[cnt++];
}
setDataElements(j, i, itemp, data);
}
}
break;
}
case DataBuffer.TYPE_SHORT: {
short[] sArray = (short[])obj;
short[] stemp = new short[numDataElems];
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
for (int k=0; k<numDataElems; k++) {
stemp[k] = sArray[cnt++];
}
setDataElements(j, i, stemp, data);
}
}
break;
}
case DataBuffer.TYPE_FLOAT: {
float[] fArray = (float[])obj;
float[] ftemp = new float[numDataElems];
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
for (int k=0; k<numDataElems; k++) {
ftemp[k] = fArray[cnt++];
}
setDataElements(j, i, ftemp, data);
}
}
break;
}
case DataBuffer.TYPE_DOUBLE: {
double[] dArray = (double[])obj;
double[] dtemp = new double[numDataElems];
for (int i=y; i<y+h; i++) {
for (int j=x; j<x+w; j++) {
for (int k=0; k<numDataElems; k++) {
dtemp[k] = dArray[cnt++];
}
setDataElements(j, i, dtemp, data);
}
}
break;
}
default:
throw new RuntimeException(JaiI18N.getString("RasterFactory3"));
}
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the <code>DataBuffer</code> using a <code>float</code> for input.
* <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample as a <code>float</code>.
* @param data The <code>DataBuffer</code> containing the image data.
*
* @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
*/
public void setSample(int x, int y, int b,
float s,
DataBuffer data) {
data.setElemFloat(bankIndices[b],
y*scanlineStride + x*pixelStride + bandOffsets[b],
s);
}
/**
* Returns the sample in a specified band
* for the pixel located at (x,y) as a <code>float</code>.
* <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to return.
* @param data The <code>DataBuffer</code> containing the image data.
* @return sample The floating point sample value
* @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
*/
public float getSampleFloat(int x, int y, int b,
DataBuffer data) {
float sample =
data.getElemFloat(bankIndices[b],
y*scanlineStride + x*pixelStride +
bandOffsets[b]);
return sample;
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the <code>DataBuffer</code> using a <code>double</code> for input.
* <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample as a <code>double</code>.
* @param data The <code>DataBuffer</code> containing the image data.
*
* @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
*/
public void setSample(int x, int y, int b,
double s,
DataBuffer data) {
data.setElemDouble(bankIndices[b],
y*scanlineStride + x*pixelStride + bandOffsets[b],
s);
}
/**
* Returns the sample in a specified band
* for a pixel located at (x,y) as a <code>double</code>.
* <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to return.
* @param data The <code>DataBuffer</code> containing the image data.
* @return sample The <code>double</code> sample value
* @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
*/
public double getSampleDouble(int x, int y, int b,
DataBuffer data) {
double sample =
data.getElemDouble(bankIndices[b],
y*scanlineStride + x*pixelStride +
bandOffsets[b]);
return sample;
}
/**
* Returns all samples for a rectangle of pixels in a <code>double</code>
* array, one sample per array element.
* <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param dArray If non-null, returns the samples in this array.
* @param data The <code>DataBuffer</code> containing the image data.
* @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
*/
public double[] getPixels(int x, int y, int w, int h,
double dArray[], DataBuffer data) {
double pixels[];
int Offset = 0;
if (dArray != null)
pixels = dArray;
else
pixels = new double[numBands * w * h];
for (int i=y; i<(h+y); i++) {
for (int j=x; j<(w+x); j++) {
for (int k=0; k<numBands; k++) {
pixels[Offset++] = getSampleDouble(j, i, k, data);
}
}
}
return pixels;
}
/** Returns a <code>String</code> containing the values of all valid fields. */
public String toString() {
String ret = "ComponentSampleModelJAI: " +
" dataType=" + this.getDataType() +
" numBands=" + this.getNumBands() +
" width=" +this.getWidth() +
" height=" +this.getHeight() +
" bandOffsets=[ ";
for (int i = 0; i < numBands; i++) {
ret += this.getBandOffsets()[i] + " ";
}
ret += "]";
return ret;
}
}