如何从原始数据创建 BufferedImage

9

我想从原始样本获取BufferedImage,但是我遇到了关于试图读取超出可用数据范围的异常,这让我很不理解。我想要做的是:

val datasize = image.width * image.height
val imgbytes = image.data.getIntArray(0, datasize)
val datamodel = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, image.width, image.height, Array(image.red_mask.intValue, image.green_mask.intValue, image.blue_mask.intValue))
val buffer = datamodel.createDataBuffer
val raster = Raster.createRaster(datamodel, buffer, new Point(0,0))
datamodel.setPixels(0, 0, image.width, image.height, imgbytes, buffer)
val newimage = new BufferedImage(image.width, image.height, BufferedImage.TYPE_INT_RGB)
newimage.setData(raster)

很不幸,我得到了以下错误:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 32784
    at java.awt.image.SinglePixelPackedSampleModel.setPixels(SinglePixelPackedSampleModel.java:689)
    at screenplayer.Main$.ximage_to_swt(Main.scala:40)
    at screenplayer.Main$.main(Main.scala:31)
    at screenplayer.Main.main(Main.scala)

数据使用标准RGB格式,每个像素点占用4个字节(即每个像素点占用1个字节的填充)。图片尺寸为1366x24 px。


根据下面的建议,我终于使代码运行成功了。最终的代码如下:

val datasize = image.width * image.height
val imgbytes = image.data.getIntArray(0, datasize)

val raster = Raster.createPackedRaster(DataBuffer.TYPE_INT, image.width, image.height, 3, 8, null)
raster.setDataElements(0, 0, image.width, image.height, imgbytes)

val newimage = new BufferedImage(image.width, image.height, BufferedImage.TYPE_INT_RGB)
newimage.setData(raster)

如果可以改进的话,当然我很乐意听取建议,但总的来说它的表现符合预期。

1个回答

10

setPixels 假设图像数据是 打包的。因此,它寻找长度为 image.width*image.height*3 的输入,并在数组末尾运行。

以下是三种解决方法。

(1) 将 imgbytes 解包为 3 倍长,并按照上述方式处理。

(2) 手动从 imgbytes 加载缓冲区,而不是使用 setPixels

var i=0
while (i < imgbytes.length) {
  buffer.setElem(i, imgbytes(i))
  i += 1
}

(3) 不要使用createDataBuffer;如果你已经知道你的数据格式正确,可以自己创建相应的缓冲区(在这种情况下,是一个DataBufferInt):

val buffer = new DataBufferInt(imgbytes, imgbytes.length)

(如果您的原始副本可能被其他因素改变,您可能需要执行imgbytes.clone)。


我尝试了那些解决方案,但要么得到无关的垃圾数据,要么是黑屏。如果我查看它的十六进制转储,数据是正确的。您能提供一小段实际从imgbytes到BufferedImage的代码片段吗?这将不胜感激 :) - viraptor
如果您可以提供在示例中创建“image”的代码,那当然可以。或者,如果您不关心数据如何进入,我将创建一个不是来自图像的示例。 - Rex Kerr
这是我直接从Xorg获取的自定义对象。如果您可以使用已知的heightwidth和每个像素的4字节组件数组(RGB顺序+ 1字节填充)或单个int(相同格式)来完成它,我可以解决其余部分。我可能失败的部分是缓冲区<->栅格交互(我甚至不确定两者是否都需要)。非常感谢。 - viraptor
好的 - 我已经让它工作了(代码包含在问题中)。除非有更简单的方法 - 随意进行更正 :) - viraptor
经过两周的努力寻找这样的信息,我非常非常高兴能够找到这个问题。感谢提问和回答! - OzBarry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接