MultiPixelPackedSampleModel.java [plain text]
package java.awt.image;
import gnu.java.awt.Buffers;
public class MultiPixelPackedSampleModel extends SampleModel
{
private int scanlineStride;
private int[] bitMasks;
private int[] bitOffsets;
private int[] sampleSize;
private int dataBitOffset;
private int elemBits;
private int numberOfBits;
private int numElems;
public MultiPixelPackedSampleModel(int dataType, int w, int h,
int numberOfBits)
{
this(dataType, w, h, numberOfBits, 0, 0);
}
public MultiPixelPackedSampleModel(int dataType, int w, int h,
int numberOfBits, int scanlineStride,
int dataBitOffset)
{
super(dataType, w, h, 1);
switch (dataType)
{
case DataBuffer.TYPE_BYTE:
elemBits = 8;
break;
case DataBuffer.TYPE_USHORT:
elemBits = 16;
break;
case DataBuffer.TYPE_INT:
elemBits = 32;
break;
default:
throw new IllegalArgumentException("MultiPixelPackedSampleModel"
+ " unsupported dataType");
}
this.dataBitOffset = dataBitOffset;
this.numberOfBits = numberOfBits;
if (numberOfBits > elemBits)
throw new RasterFormatException("MultiPixelPackedSampleModel pixel size"
+ " larger than dataType");
switch (numberOfBits)
{
case 1: case 2: case 4: case 8: case 16: case 32: break;
default:
throw new RasterFormatException("MultiPixelPackedSampleModel pixel"
+ " size not 2^n bits");
}
numElems = elemBits / numberOfBits;
if (scanlineStride == 0)
scanlineStride = ((dataBitOffset + w * numberOfBits) / elemBits);
this.scanlineStride = scanlineStride;
sampleSize = new int[1];
sampleSize[0] = numberOfBits;
bitMasks = new int[numElems];
bitOffsets = new int[numElems];
for (int i=0; i < numElems; i++)
{
bitOffsets[numElems - i- 1] = numberOfBits * i;
bitMasks[numElems - i - 1] = ((1 << numberOfBits) - 1) <<
bitOffsets[numElems - i - 1];
}
}
public SampleModel createCompatibleSampleModel(int w, int h)
{
return new MultiPixelPackedSampleModel(dataType, w, h, numberOfBits);
}
public DataBuffer createDataBuffer()
{
int size;
size = scanlineStride * height;
return Buffers.createBuffer(getDataType(), size);
}
public int getNumDataElements()
{
return 1;
}
public int[] getSampleSize()
{
return sampleSize;
}
public int getSampleSize(int band)
{
return sampleSize[0];
}
public int getOffset(int x, int y)
{
return scanlineStride * y + ((dataBitOffset + x*numberOfBits) / elemBits);
}
public int getBitOffset(int x)
{
return (dataBitOffset + x*numberOfBits) % elemBits;
}
public int getDataBitOffset()
{
return dataBitOffset;
}
public int getScanlineStride()
{
return scanlineStride;
}
public int getPixelBitStride()
{
return numberOfBits;
}
public SampleModel createSubsetSampleModel(int[] bands)
{
int numBands = bands.length;
if (numBands != 1)
throw new RasterFormatException("MultiPixelPackedSampleModel only"
+ " supports one band");
return new MultiPixelPackedSampleModel(dataType, width, height,
numberOfBits, scanlineStride,
dataBitOffset);
}
public Object getDataElements(int x, int y, Object obj,
DataBuffer data)
{
int pixel = getSample(x, y, 0, data);
switch (getTransferType())
{
case DataBuffer.TYPE_BYTE:
if (obj == null) obj = new byte[1];
((byte[])obj)[0] = (byte)pixel;
return obj;
case DataBuffer.TYPE_USHORT:
if (obj == null) obj = new short[1];
((short[])obj)[0] = (short)pixel;
return obj;
case DataBuffer.TYPE_INT:
if (obj == null) obj = new int[1];
((int[])obj)[0] = pixel;
return obj;
default:
throw new ClassCastException();
}
}
public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
{
if (iArray == null) iArray = new int[1];
iArray[0] = getSample(x, y, 0, data);
return iArray;
}
public int[] getPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
int offset = getOffset(x, y);
if (iArray == null) iArray = new int[w*h];
int outOffset = 0;
for (y=0; y<h; y++)
{
int lineOffset = offset;
for (x=0; x<w;)
{
int samples = data.getElem(lineOffset++);
for (int b=0; b<numElems && x<w; b++)
{
iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
x++;
}
}
offset += scanlineStride;
}
return iArray;
}
public int getSample(int x, int y, int b, DataBuffer data)
{
int pos =
((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits;
int offset = getOffset(x, y);
int samples = data.getElem(offset);
return (samples & bitMasks[pos]) >>> bitOffsets[pos];
}
public void setDataElements(int x, int y, Object obj, DataBuffer data)
{
int transferType = getTransferType();
if (getTransferType() != data.getDataType())
{
throw new IllegalArgumentException("transfer type ("+
getTransferType()+"), "+
"does not match data "+
"buffer type (" +
data.getDataType() +
").");
}
int offset = getOffset(x, y);
try
{
switch (transferType)
{
case DataBuffer.TYPE_BYTE:
{
DataBufferByte out = (DataBufferByte) data;
byte[] in = (byte[]) obj;
out.getData()[offset] = in[0];
return;
}
case DataBuffer.TYPE_USHORT:
{
DataBufferUShort out = (DataBufferUShort) data;
short[] in = (short[]) obj;
out.getData()[offset] = in[0];
return;
}
case DataBuffer.TYPE_INT:
{
DataBufferInt out = (DataBufferInt) data;
int[] in = (int[]) obj;
out.getData()[offset] = in[0];
return;
}
default:
throw new ClassCastException("Unsupported data type");
}
}
catch (ArrayIndexOutOfBoundsException aioobe)
{
String msg = "While writing data elements" +
", x="+x+", y="+y+
", width="+width+", height="+height+
", scanlineStride="+scanlineStride+
", offset="+offset+
", data.getSize()="+data.getSize()+
", data.getOffset()="+data.getOffset()+
": " +
aioobe;
throw new ArrayIndexOutOfBoundsException(msg);
}
}
public void setPixel(int x, int y, int[] iArray, DataBuffer data)
{
setSample(x, y, 0, iArray[0], data);
}
public void setSample(int x, int y, int b, int s, DataBuffer data)
{
int bitpos =
((dataBitOffset + x * numberOfBits) % elemBits) / numberOfBits;
int offset = getOffset(x, y);
s = s << bitOffsets[bitpos];
s = s & bitMasks[bitpos];
int sample = data.getElem(offset);
sample |= s;
data.setElem(offset, sample);
}
public String toString()
{
StringBuffer result = new StringBuffer();
result.append(getClass().getName());
result.append("[");
result.append("scanlineStride=").append(scanlineStride);
for(int i=0; i < bitMasks.length; i+=1)
{
result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
}
result.append("]");
return result.toString();
}
}