最直接的方法,可能是使用ByteBuffer
來交換字節順序,並創建一個新的short
數組來保存像素數據。
然後將(short
)像素數據包裝在DataBufferUShort
中。創建一個匹配的WritableRaster
和ColorModel
,最後從中創建一個BufferedImage
。該圖像應與上面代碼中的圖像(BufferedImage.TYPE_USHORT_GRAY
)相同,但創建速度稍快,因爲您只需複製一次像素(而不是代碼中的兩次)。
int w = 2;
int h = 2;
int stride = 1;
byte[] rawBytes = {0x21, 0x27, 0x33, (byte) 0xF6, 0x28, (byte) 0xF3, (byte) 0x27, (byte) 0xF2};
short[] rawShorts = new short[rawBytes.length/2];
ByteBuffer.wrap(rawBytes)
.order(ByteOrder.LITTLE_ENDIAN)
.asShortBuffer()
.get(rawShorts);
DataBuffer dataBuffer = new DataBufferUShort(rawShorts, rawShorts.length);
WritableRaster raster = Raster.createInterleavedRaster(dataBuffer, w, h, w * stride, stride, new int[]{0}, null);
ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
另外,稍微令人費解,但可能更快的方式(如你不要複製的支持像素陣列的話),是創建一個自定義SampleModel
與MSB(小端)字節數據的作品,但將它們公開爲TYPE_USHORT
。這將創建一個TYPE_CUSTOM
圖像。
int w = 2, h = 2, stride = 2;
byte[] rawBytes = {0x21, 0x27, 0x33, (byte) 0xF6, 0x28, (byte) 0xF3, (byte) 0x27, (byte) 0xF2};
DataBuffer dataBuffer = new DataBufferByte(rawBytes, rawBytes.length);
SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_USHORT, w, h, stride, w * stride, new int[] {0}) {
@Override
public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException("Coordinate out of bounds!");
}
// Simplified, as we only support TYPE_USHORT
int numDataElems = getNumDataElements();
int pixelOffset = y * scanlineStride + x * pixelStride;
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] + 1) << 8|
data.getElem(bankIndices[i], pixelOffset + bandOffsets[i]));
}
return sdata;
}
};
ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, null);
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
我真的沒有看到創建RenderedImage
子類的一個原因。
這真棒,非複製代碼減少了我的JVM內存消耗幾乎沒有,謝謝! – Black0ut