如何在Java中将byte []转换为BufferedImage?

时间:2012-10-03 09:18:33

标签: arrays byte bufferedimage

我发布这个帖子是因为我在处理Java中的图片时遇到了一些困难。我希望能够将图片转换为byte []数组,然后才能进行反向操作,这样我就可以更改每个像素的RGB,然后创建一个新图片。我想使用这个解决方案,因为BufferedImage的setRGB()和getRGB()对于大型图片来说可能太慢了(如果我错了,请纠正我)。

我在这里阅读了一些帖子以获得byte []数组(such as here),以便每个像素由包含红色,绿色和蓝色值的数组的3或4个单元格表示(附加alpha值,当有4个单元格时),这对我来说非常有用且易于使用。这是我用来获取这个数组的代码(存储在我创建的PixelArray类中):

public PixelArray(BufferedImage image)
{
    width = image.getWidth();
    height = image.getHeight();
    DataBuffer toArray = image.getRaster().getDataBuffer();
    array = ((DataBufferByte) toArray).getData();
    hasAlphaChannel = image.getAlphaRaster() != null;
}

我最大的麻烦是我没有找到任何有效的方法将此byte []数组转换为新图像,如果我想转换图片(例如,删除蓝色/绿色值并仅保留红色一)。我尝试了这些解决方案:

1)创建一个DataBuffer对象,然后创建一个SampleModel,最后创建一个WritableRaster,然后创建BufferedImage(带有额外的ColorModel和Hashtable对象)。它没有用,因为我显然没有我需要的所有信息(我不知道什么是BufferedImage()构造函数的Hashtable)。

2)使用ByteArrayInputStream。这不起作用,因为ByteArrayInputStream预期的byte []数组与我的无关:它代表文件的每个字节,而不是每个像素的每个分量(每个像素有3-4个字节)...... / p>

有人可以帮助我吗?

5 个答案:

答案 0 :(得分:32)

试试这个:

private BufferedImage createImageFromBytes(byte[] imageData) {
    ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
    try {
        return ImageIO.read(bais);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

答案 1 :(得分:10)

我尝试过这里提到的方法,但由于某种原因,它们都没有奏效。使用ByteArrayInputStreamImageIO.read(...)会返回null,而byte[] array = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();会返回图像数据的副本,而不是对它们的直接引用(另请参阅here)。

但是,以下内容对我有用。让我们假设图像数据的尺寸和类型是已知的。还允许byte[] srcbuf成为要转换为BufferedImage的数据的缓冲区。然后,

  1. 创建空白图片,例如

    img=new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
    
  2. 将数据数组转换为Raster并使用setData填充图像,即

    img.setData(Raster.createRaster(img.getSampleModel(), new DataBufferByte(srcbuf, srcbuf.length), new Point() ) );
    

答案 2 :(得分:6)

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
byte[] array = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(pixelArray, 0, array, 0, array.length);

当您尝试使用生成的图像的Graphics对象时,此方法确实会失去同步。如果您需要在图像上绘制,请构建第二个图像(可以是持久的,不是每次都构建但重新使用)并且drawImage第一个图像在其上。

答案 3 :(得分:3)

有几个人对评论认为接受的答案是错误的。

如果接受的答案不起作用,可能是因为Image.IO不支持您尝试的图像类型(例如tiff)。

将它添加到你的pom(也就是你的类路径中的jai-imageio-core-1.3.1.jar):

    <!-- https://mvnrepository.com/artifact/com.github.jai-imageio/jai-imageio-core -->
    <dependency>
        <groupId>com.github.jai-imageio</groupId>
        <artifactId>jai-imageio-core</artifactId>
        <version>1.3.1</version>
    </dependency>

添加对以下内容的支持:

  • WBMP
  • BMP
  • PCX
  • PNM
  • 原始
  • TIFF
  • gif(写)

您可以使用以下方法查看支持的格式列表:

     for(String format : ImageIO.getReaderFormatNames())
        System.out.println(format);

请注意,您只需将jai-imageio-core-1.3.1.jar放入类路径即可使其正常工作。

其他增加额外支持的项目包括:

答案 4 :(得分:0)

在某些情况下,直接使用ImageIO.read的方法并不正确。在我的例子中,原始字节[]不包含有关图像的宽度和高度以及格式的任何信息。仅使用ImageIO.read,程序无法构建有效的图像。

必须将图像的基本信息传递给BufferedImage对象:

    BufferedImage outBufImg = new BufferedImage(width, height, bufferedImage.TYPE_3BYTE_BGR);

然后使用setRGB或setData设置BufferedImage对象的数据。 (当使用setRGB时,似乎我们必须首先将byte []转换为int []。因此,如果源图像数据很大,可能会导致性能问题。对于大字节[]类型的源数据,setData可能更好。 。)