我发布这个帖子是因为我在处理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>
有人可以帮助我吗?
答案 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)
我尝试过这里提到的方法,但由于某种原因,它们都没有奏效。使用ByteArrayInputStream
和ImageIO.read(...)
会返回null,而byte[] array = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
会返回图像数据的副本,而不是对它们的直接引用(另请参阅here)。
但是,以下内容对我有用。让我们假设图像数据的尺寸和类型是已知的。还允许byte[] srcbuf
成为要转换为BufferedImage
的数据的缓冲区。然后,
创建空白图片,例如
img=new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
将数据数组转换为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>
添加对以下内容的支持:
您可以使用以下方法查看支持的格式列表:
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可能更好。 。)