DataBuffer
. 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 DataBuffer
.
* 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 DataBuffer
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 ComponentSampleModel
are stored with the same precision)
* . This class adds support for Double
and Float
data types in addition
* to those supported by the ComponentSampleModel
class in Java 2D.
* All strides and offsets must be non-negative.
* @see java.awt.image.ComponentSampleModel
*/
public class ComponentSampleModelJAI extends ComponentSampleModel {
/**
* Constructs a ComponentSampleModel
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 DataBuffer
.
*
* @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 ComponentSampleModel
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 DataBuffer
.
*
* @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 ComponentSampleModel
.
*/
private long getBufferSize() {
int maxBandOff=bandOffsets[0];
for (int i=1; iComponentSampleModel
with the specified
* width and height. The new SampleModel
will have the same
* number of bands, storage data type, interleaving scheme, and
* pixel stride as this SampleModel
.
*
* @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; iComponentSampleModel
. The new ComponentSampleModel
can be
* used with any DataBuffer
that the existing ComponentSampleModel
* can be used with. The new ComponentSampleModel
/DataBuffer
* combination will represent an image with a subset of the bands
* of the original ComponentSampleModel
/DataBuffer
combination.
*
* @param bands subset of bands of this ComponentSampleModel
*/
public SampleModel createSubsetSampleModel(int bands[]) {
int newBankIndices[] = new int[bands.length];
int newBandOffsets[] = new int[bands.length];
for (int i=0; iComponentSampleModel
.
* The DataBuffer
's data type, number of banks, and size
* will be consistent with this ComponentSampleModel
.
*/
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 ComponentSampleModel
, 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 Object
will be created
* automatically and will be of the right primitive data type.
*
* The following code illustrates transferring data for one pixel from
* DataBuffer
db1
, whose storage layout is described by
* ComponentSampleModel
csm1
, to DataBuffer
db2
,
* whose storage layout is described by
* ComponentSampleModel
csm2
.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
*
* ComponentSampleModel csm1, csm2; * DataBufferInt db1, db2; * csm2.setDataElements(x, y, * csm1.getDataElements(x, y, null, db1), db2); ** Using getDataElements/setDataElements to transfer between two *
DataBuffer
/SampleModel pairs is legitimate if the SampleModel
s have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
*
* @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
* The following code illustrates transferring data for a rectangular
* region of pixels from
*
* @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
* The following code illustrates transferring data for one pixel from
*
* @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
* The following code illustrates transferring data for a rectangular
* region of pixels from
*
* @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 DataBuffer
containing the image data.
* @throws ClassCastException
if obj is non-null and is not
* a primitive array of type TransferType.
* @throws ArrayIndexOutOfBoundsException
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; iDataBuffer
db1
, whose storage layout is described by
* SampleModel
sm1
, to DataBuffer
db2
, whose
* storage layout is described by SampleModel
sm2
.
* The transfer will generally be more efficient than using
* getPixels/setPixels.
*
* SampleModel sm1, sm2;
* DataBuffer db1, db2;
* sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w,
* h, null, db1), db2);
*
* Using getDataElements/setDataElements to transfer between two
* DataBuffer
/SampleModel pairs is legitimate if the SampleModel
s have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* DataBuffer
containing the image data.
* @see #getNumDataElements
* @see #getTransferType
* @see java.awt.image.DataBuffer
* @throws ClassCastException
if obj is non-null and is not
* a primitive array of type TransferType.
* @throws ArrayIndexOutOfBoundsException
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; iComponentSampleModel
,
* this will be the same as the data type, and samples are transferred
* one per array element.
* DataBuffer
db1
, whose storage layout is described by
* ComponentSampleModel
csm1
, to DataBuffer
db2
,
* whose storage layout is described by
* ComponentSampleModel
csm2
.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
*
* ComponentSampleModel csm1, csm2;
* DataBufferInt db1, db2;
* csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
* db2);
*
* Using getDataElements/setDataElements to transfer between two
* DataBuffer
/SampleModel pairs is legitimate if the SampleModel
s have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* DataBuffer
containing the image data.
* @throws ClassCastException
if obj is non-null and is not
* a primitive array of type TransferType.
* @throws ArrayIndexOutOfBoundsException
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; iDataBuffer
db1
, whose storage layout is described by
* SampleModel
sm1
, to DataBuffer
db2
, whose
* storage layout is described by SampleModel
sm2
.
* The transfer will generally be more efficient than using
* getPixels/setPixels.
*
* SampleModel sm1, sm2;
* DataBuffer db1, db2;
* sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w, h,
* null, db1), db2);
*
* Using getDataElements/setDataElements to transfer between two
* DataBuffer
/SampleModel pairs is legitimate if the SampleModel
s have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* DataBuffer
containing the image data.
* @throws ClassCastException
if obj is non-null and is not
* a primitive array of type TransferType.
* @throws ArrayIndexOutOfBoundsException
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; ifloat
for input.
* ArrayIndexOutOfBoundsException
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 float
.
* @param data The DataBuffer
containing the image data.
*
* @throws ArrayIndexOutOfBoundsException
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 float
.
* ArrayIndexOutOfBoundsException
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 DataBuffer
containing the image data.
* @return sample The floating point sample value
* @throws ArrayIndexOutOfBoundsException
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 DataBuffer
using a double
for input.
* ArrayIndexOutOfBoundsException
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 double
.
* @param data The DataBuffer
containing the image data.
*
* @throws ArrayIndexOutOfBoundsException
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 double
.
* ArrayIndexOutOfBoundsException
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 DataBuffer
containing the image data.
* @return sample The double
sample value
* @throws ArrayIndexOutOfBoundsException
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 double
* array, one sample per array element.
* ArrayIndexOutOfBoundsException
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 DataBuffer
containing the image data.
* @throws ArrayIndexOutOfBoundsException
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