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
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; |
|
} |
|
} |
|
|
|
|