I'm trying to get a BufferedImage from raw samples, but I get exceptions about trying to read past the available data range which I just don't understand. What I'm trying to do is:
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)
Unfortunately I get:
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)
The data is standard RGB with 1 byte padding (so that 1 pixel == 4 bytes) and the image size is 1366x24 px.
I finally got the code to run with the suggestion below. The final code is:
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)
If it can be improved, I'm open to suggestions of course, but in general it works as expected.
This article shows how to convert a byte[] to a BufferedImage in Java. InputStream is = new ByteArrayInputStream(bytes); BufferedImage bi = ImageIO. read(is); The idea is puts the byte[] into an ByteArrayInputStream object, and we can use ImageIO.
List, the difference between Image and BufferedImage is the same as the difference between List and LinkedList. Image is a generic concept and BufferedImage is the concrete implementation of the generic concept; kind of like BMW is a make of a Car. Show activity on this post. Image is an abstract class.
setPixels
assumes that the image data is not packed. So it's looking for an input of length image.width*image.height*3, and running off the end of the array.
Here are three options for how to fix the problem.
(1) Unpack imgbytes
so it is 3x longer, and do it the same way as above.
(2) Manually load the buffer from imgbytes
instead of using setPixels
:
var i=0
while (i < imgbytes.length) {
buffer.setElem(i, imgbytes(i))
i += 1
}
(3) Don't use createDataBuffer
; if you already know that your data has the proper formatting you can create the appropriate buffer yourself (in this case, a DataBufferInt
):
val buffer = new DataBufferInt(imgbytes, imgbytes.length)
(you may need to do imgbytes.clone
if your original copy could get mutated by something else).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With