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.
1060 lines
38 KiB
1060 lines
38 KiB
5 years ago
|
/*
|
||
|
* 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;
|
||
|
}
|
||
|
}
|
||
|
|