想要将 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();
}