将二维像素数组转换为 BufferedImage
Convert 2D pixel array into BufferedImage
我使用了 this SO 问题中接受的答案代码。现在,我想转换回 BufferedImage(最好不要使用 setRGB())。我试过这个:
private BufferedImage createImage(int[][] pixelData, BufferedImage outputImage){
final int[] outputImagePixelData = ((DataBufferInt) outputImage.getRaster().getDataBuffer()).getData();
System.arraycopy(pixelData, 0, outputImagePixelData, 0, pixelData.length);
return outputImage;
}
但它不起作用,因为它采用一维数组作为参数,而不是二维数组。
不使用 System.arraycopy
,您可以简单地使用双 for
循环并迭代 x
/y
,像这样:
private BufferedImage createImage(int[][] pixelData, BufferedImage outputImage) {
int[] outputImagePixelData = ((DataBufferInt) outputImage.getRaster().getDataBuffer()).getData();
int width = outputImage.getWidth();
int height = outputImage.getHeight();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
outputImagePixelData[y * width + x] = pixelData[x][y];
}
}
return outputImage;
}
上面的代码假定一个数组元素对应一个像素元素(所有 BufferedImage.TYPE_INT_*
类型都是这种情况)。
如果你的 outputImage 已经有了好的类型和格式,那么你可以简单地使用循环进行二维到一维的转换(假设你的数组编码是 [nbRows][RowLength]):
private BufferedImage createImage(int[][] pixelData, BufferedImage outputImage)
{
int[] outputImagePixelData = ((DataBufferInt) outputImage.getRaster().getDataBuffer()).getData() ;
final int width = outputImage.getWidth() ;
final int height = outputImage.getHeight() ;
for (int y=0, pos=0 ; y < height ; y++)
for (int x=0 ; x < width ; x++, pos++)
outputImagePixelData[pos] = pixelData[y][x] ;
return outputImage;
}
但是,INT 类型在 BufferedImage 中并没有很好地定义。默认情况下,您有 TYPE_INT_RGB 和 TYPE_INT_ARGB,它们将像素编码的 R、G、B、A 值与单个 INT 连接起来。如果你想创建一个灰度类型的单通道INT类型的BufferedImage,那么你应该这样做:
private BufferedImage createImage(int[][] pixelData)
{
final int width = pixelData[0].length ;
final int height = pixelData.length ;
// First I create a BufferedImage with a DataBufferInt, with the appropriate dimensions and number of channels/bands/colors
ColorSpace myColorSpace = new FloatCS(ColorSpace.TYPE_GRAY, channel) ;
int[] bits = new int[]{32} ;
ColorModel myColorModel = new ComponentColorModel(myColorSpace,bits,false,false,ColorModel.OPAQUE,DataBuffer.TYPE_INT) ;
BufferedImage outputImage = new BufferedImage(myColorModel, myColorModel.createCompatibleWritableRaster(width, height), false, null) ;
int[] outputImagePixelData = ((DataBufferInt) outputImage.getRaster().getDataBuffer()).getData() ;
for (int y=0, pos=0 ; y < height ; y++)
for (int x=0 ; x < width ; x++, pos++)
outputImagePixelData[pos] = pixelData[y][x] ;
return outputImage ;
}
将 FloatCS 作为 ColorSpace class。当您需要特定的 ColorSpace(如 Lab、HLS 等)时,您必须创建自己的 ColorSpace class
public class FloatCS extends ColorSpace
{
private static final long serialVersionUID = -7713114653902159981L;
private ColorSpace rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB) ;
public FloatCS(int type, int channel)
{
super(type, channel) ;
}
@Override
public float[] fromCIEXYZ(float[] pixel)
{
return fromRGB(rgb.fromCIEXYZ(pixel)) ;
}
@Override
public float[] fromRGB(float[] RGB)
{
return RGB ;
}
@Override
public float[] toCIEXYZ(float[] pixel)
{
return rgb.toCIEXYZ(toRGB(pixel)) ;
}
@Override
public float[] toRGB(float[] nRGB)
{
return nRGB ;
}
}
我使用了 this SO 问题中接受的答案代码。现在,我想转换回 BufferedImage(最好不要使用 setRGB())。我试过这个:
private BufferedImage createImage(int[][] pixelData, BufferedImage outputImage){
final int[] outputImagePixelData = ((DataBufferInt) outputImage.getRaster().getDataBuffer()).getData();
System.arraycopy(pixelData, 0, outputImagePixelData, 0, pixelData.length);
return outputImage;
}
但它不起作用,因为它采用一维数组作为参数,而不是二维数组。
不使用 System.arraycopy
,您可以简单地使用双 for
循环并迭代 x
/y
,像这样:
private BufferedImage createImage(int[][] pixelData, BufferedImage outputImage) {
int[] outputImagePixelData = ((DataBufferInt) outputImage.getRaster().getDataBuffer()).getData();
int width = outputImage.getWidth();
int height = outputImage.getHeight();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
outputImagePixelData[y * width + x] = pixelData[x][y];
}
}
return outputImage;
}
上面的代码假定一个数组元素对应一个像素元素(所有 BufferedImage.TYPE_INT_*
类型都是这种情况)。
如果你的 outputImage 已经有了好的类型和格式,那么你可以简单地使用循环进行二维到一维的转换(假设你的数组编码是 [nbRows][RowLength]):
private BufferedImage createImage(int[][] pixelData, BufferedImage outputImage)
{
int[] outputImagePixelData = ((DataBufferInt) outputImage.getRaster().getDataBuffer()).getData() ;
final int width = outputImage.getWidth() ;
final int height = outputImage.getHeight() ;
for (int y=0, pos=0 ; y < height ; y++)
for (int x=0 ; x < width ; x++, pos++)
outputImagePixelData[pos] = pixelData[y][x] ;
return outputImage;
}
但是,INT 类型在 BufferedImage 中并没有很好地定义。默认情况下,您有 TYPE_INT_RGB 和 TYPE_INT_ARGB,它们将像素编码的 R、G、B、A 值与单个 INT 连接起来。如果你想创建一个灰度类型的单通道INT类型的BufferedImage,那么你应该这样做:
private BufferedImage createImage(int[][] pixelData)
{
final int width = pixelData[0].length ;
final int height = pixelData.length ;
// First I create a BufferedImage with a DataBufferInt, with the appropriate dimensions and number of channels/bands/colors
ColorSpace myColorSpace = new FloatCS(ColorSpace.TYPE_GRAY, channel) ;
int[] bits = new int[]{32} ;
ColorModel myColorModel = new ComponentColorModel(myColorSpace,bits,false,false,ColorModel.OPAQUE,DataBuffer.TYPE_INT) ;
BufferedImage outputImage = new BufferedImage(myColorModel, myColorModel.createCompatibleWritableRaster(width, height), false, null) ;
int[] outputImagePixelData = ((DataBufferInt) outputImage.getRaster().getDataBuffer()).getData() ;
for (int y=0, pos=0 ; y < height ; y++)
for (int x=0 ; x < width ; x++, pos++)
outputImagePixelData[pos] = pixelData[y][x] ;
return outputImage ;
}
将 FloatCS 作为 ColorSpace class。当您需要特定的 ColorSpace(如 Lab、HLS 等)时,您必须创建自己的 ColorSpace class
public class FloatCS extends ColorSpace
{
private static final long serialVersionUID = -7713114653902159981L;
private ColorSpace rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB) ;
public FloatCS(int type, int channel)
{
super(type, channel) ;
}
@Override
public float[] fromCIEXYZ(float[] pixel)
{
return fromRGB(rgb.fromCIEXYZ(pixel)) ;
}
@Override
public float[] fromRGB(float[] RGB)
{
return RGB ;
}
@Override
public float[] toCIEXYZ(float[] pixel)
{
return rgb.toCIEXYZ(toRGB(pixel)) ;
}
@Override
public float[] toRGB(float[] nRGB)
{
return nRGB ;
}
}