Как создать BufferedImage из необработанных данных - PullRequest
9 голосов
/ 20 ноября 2010

Я пытаюсь получить 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 с отступом в 1 байт (так, чтобы 1 пиксель == 4 байта), а размер изображения - 1366x24 пикселей.


Я наконец-то получил код для запуска с предложением ниже. Окончательный код:

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 голосов
/ 21 ноября 2010

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, если ваша оригинальная копия может быть видоизменена чем-то другим).

...