想要将 DataBufferUShort 转换为 DataBufferInt
Want to convert DataBufferUShort to DataBufferInt
我有一个 BufferedImage.TYPE_USHORT_GRAY
类型的 BufferedImage
(DataBufferUShort
),我想将其转换为 BufferedImage.TYPE_INT_RGB (DataBufferInt)
类型的 BufferedImage
。有什么建议可以实现吗?
注意,一个BufferedImage.TYPE_USHORT_GRAY(DataBufferUShort)确实是每个像素在16位(2字节)上的编码。但是 BufferedImage.TYPE_INT_RGB (DataBufferInt) 如果在单个 int 上对具有 3 种颜色的像素进行编码!因此,如果你这样做,你将失去 16 位精度并下降到 8 位。如果你仍然想这样做,你可以使用 getRaster().getSample 和 getRaster().setSample.
为了做你想做的事,你必须创建一个 BufferedImage.TYPE_CUSTOM,只有一个通道和 DataBufferInt。这是执行此操作的代码。
ColorSpace myColorSpace = new FloatCS(channel == 1 ? ColorSpace.TYPE_GRAY : ColorSpace.TYPE_RGB, channel) ;
int[] bits = new int[channel] ;
Arrays.fill(bits, 32) ;
ColorModel myColorModel = new ComponentColorModel(myColorSpace,bits,false,false,ColorModel.OPAQUE,DataBuffer.TYPE_INT) ;
return new BufferedImage(myColorModel, myColorModel.createCompatibleWritableRaster(width, height), false, null) ;
[编辑]这里有更多的精度。
FloatCS 只是扩展了 ColorSpace:
public class FloatCS extends ColorSpace
{
private ColorSpace rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB) ;
public FloatCS(int type, int channel)
{
super(type, channel) ;
}
public float[] fromCIEXYZ(float[] pixel)
{
return fromRGB(rgb.fromCIEXYZ(pixel)) ;
}
public float[] fromRGB(float[] RGB)
{
return RGB ;
}
public float[] toCIEXYZ(float[] pixel)
{
return rgb.toCIEXYZ(toRGB(pixel)) ;
}
public float[] toRGB(float[] nRGB)
{
return nRGB ;
}
}
然后你执行一个简单的复制:
BufferedImage imshort = new BufferedImage(512, 512, BufferedImage.TYPE_USHORT_GRAY) ;
BufferedImage imint = ImageNew.Integer(imshort.getWidth(), imshort.getHeight(), 1) ; // It calls the first little code I gave you to create a BufferedImage.TYPE_CUSTOM with DataBufferInt
short[] bufshort = ((DataBufferUShort)imshort.getRaster().getDataBuffer()).getData() ;
int[] bufint = ((DataBufferInt)imint.getRaster().getDataBuffer()).getData() ;
for (int i=0 ; i < bufshort.length ; i++)
bugint[i] = bufshort[i] & 0xFFFF ;
如果您只想提取 min/max/mean,则无需转换 BufferedImage
:
// Assuming image is always TYPE_USHORT_GRAY
short[] values = ((DataBufferUShort) image.getRaster().getDataBuffer()).getData();
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
double mean;
for (int i = 0; i < values.length; i++) {
int unsignedValue = values[i] & 0xFFFF;
if (unsignedValue < min) {
min = unsignedValue;
}
if (unsignedValue > max) {
max = unsignedValue;
}
// ...etc. for mean and other values you like to extract. :-)
}
如果您想将图像转换为 TYPE_INT_RGB
以供显示(不关心精度),您可以简单地创建所需类型的新图像并在其上绘制原始图像:
BufferedImage display = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = display.createGraphics();
try {
g.drawImage(original, 0, 0, null);
}
finally {
g.dispose();
}
我有一个 BufferedImage.TYPE_USHORT_GRAY
类型的 BufferedImage
(DataBufferUShort
),我想将其转换为 BufferedImage.TYPE_INT_RGB (DataBufferInt)
类型的 BufferedImage
。有什么建议可以实现吗?
注意,一个BufferedImage.TYPE_USHORT_GRAY(DataBufferUShort)确实是每个像素在16位(2字节)上的编码。但是 BufferedImage.TYPE_INT_RGB (DataBufferInt) 如果在单个 int 上对具有 3 种颜色的像素进行编码!因此,如果你这样做,你将失去 16 位精度并下降到 8 位。如果你仍然想这样做,你可以使用 getRaster().getSample 和 getRaster().setSample.
为了做你想做的事,你必须创建一个 BufferedImage.TYPE_CUSTOM,只有一个通道和 DataBufferInt。这是执行此操作的代码。
ColorSpace myColorSpace = new FloatCS(channel == 1 ? ColorSpace.TYPE_GRAY : ColorSpace.TYPE_RGB, channel) ;
int[] bits = new int[channel] ;
Arrays.fill(bits, 32) ;
ColorModel myColorModel = new ComponentColorModel(myColorSpace,bits,false,false,ColorModel.OPAQUE,DataBuffer.TYPE_INT) ;
return new BufferedImage(myColorModel, myColorModel.createCompatibleWritableRaster(width, height), false, null) ;
[编辑]这里有更多的精度。
FloatCS 只是扩展了 ColorSpace:
public class FloatCS extends ColorSpace
{
private ColorSpace rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB) ;
public FloatCS(int type, int channel)
{
super(type, channel) ;
}
public float[] fromCIEXYZ(float[] pixel)
{
return fromRGB(rgb.fromCIEXYZ(pixel)) ;
}
public float[] fromRGB(float[] RGB)
{
return RGB ;
}
public float[] toCIEXYZ(float[] pixel)
{
return rgb.toCIEXYZ(toRGB(pixel)) ;
}
public float[] toRGB(float[] nRGB)
{
return nRGB ;
}
}
然后你执行一个简单的复制:
BufferedImage imshort = new BufferedImage(512, 512, BufferedImage.TYPE_USHORT_GRAY) ;
BufferedImage imint = ImageNew.Integer(imshort.getWidth(), imshort.getHeight(), 1) ; // It calls the first little code I gave you to create a BufferedImage.TYPE_CUSTOM with DataBufferInt
short[] bufshort = ((DataBufferUShort)imshort.getRaster().getDataBuffer()).getData() ;
int[] bufint = ((DataBufferInt)imint.getRaster().getDataBuffer()).getData() ;
for (int i=0 ; i < bufshort.length ; i++)
bugint[i] = bufshort[i] & 0xFFFF ;
如果您只想提取 min/max/mean,则无需转换 BufferedImage
:
// Assuming image is always TYPE_USHORT_GRAY
short[] values = ((DataBufferUShort) image.getRaster().getDataBuffer()).getData();
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
double mean;
for (int i = 0; i < values.length; i++) {
int unsignedValue = values[i] & 0xFFFF;
if (unsignedValue < min) {
min = unsignedValue;
}
if (unsignedValue > max) {
max = unsignedValue;
}
// ...etc. for mean and other values you like to extract. :-)
}
如果您想将图像转换为 TYPE_INT_RGB
以供显示(不关心精度),您可以简单地创建所需类型的新图像并在其上绘制原始图像:
BufferedImage display = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = display.createGraphics();
try {
g.drawImage(original, 0, 0, null);
}
finally {
g.dispose();
}