2010-11-20 7 views
9

Tôi đang cố gắng lấy BufferedImage từ mẫu thô, nhưng tôi có ngoại lệ về việc cố đọc qua phạm vi dữ liệu có sẵn mà tôi không hiểu. Những gì tôi đang cố gắng làm là:Cách tạo BufferedImage từ dữ liệu thô

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) 

Đáng tiếc là tôi nhận được:

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) 

Dữ liệu là tiêu chuẩn RGB với 1 byte đệm (để 1 pixel == 4 byte) và kích thước hình ảnh là 1366x24 px.


Cuối cùng tôi đã nhận được mã để chạy với đề xuất bên dưới. Mã cuối cùng là:

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) 

Nếu nó có thể được cải thiện, tôi mở để gợi ý tất nhiên, nhưng nói chung nó hoạt động như mong đợi.

Trả lời

10

setPixels giả định rằng dữ liệu hình ảnh là không phải được đóng gói. Vì vậy, nó tìm kiếm một đầu vào của chiều dài image.width * image.height * 3, và chạy ra khỏi phần cuối của mảng.

Dưới đây là ba tùy chọn để khắc phục sự cố.

(1) Giải nén imgbytes để dài gấp 3 lần và thực hiện theo cách tương tự như trên.

(2) thủ nạp đệm từ imgbytes thay vì sử dụng setPixels:

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

(3) Không sử dụng createDataBuffer; nếu bạn đã biết rằng dữ liệu của bạn có định dạng thích hợp, bạn có thể tạo bộ đệm phù hợp cho mình (trong trường hợp này, một DataBufferInt):

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

(bạn có thể cần phải làm imgbytes.clone nếu bản gốc của bạn có thể bị biến đổi bởi một cái gì đó khác).

+0

Tôi đã thử các giải pháp đó, nhưng tôi hoặc nhận được rác không liên quan hoặc màn hình đen. Dữ liệu là chính xác nếu tôi nhìn vào bãi chứa hex của nó. Bạn có thể cung cấp một đoạn ngắn thực sự chuyển từ imgbyte sang BufferedImage không? Nó sẽ thực sự được đánh giá cao :) – viraptor

+0

Nếu bạn có thể cung cấp mã tạo 'hình ảnh' trong ví dụ của bạn, chắc chắn. Hoặc nếu bạn không quan tâm đến dữ liệu đến, tôi sẽ tạo một ví dụ không phải từ hình ảnh. –

+0

Đó là một đối tượng tùy chỉnh tôi nhận được ngay từ Xorg. Nếu bạn có thể làm điều đó với 'chiều cao',' chiều rộng' và một mảng gồm 4 thành phần (thứ tự RGB + 1byte padding), hoặc int đơn (cùng định dạng) cho mỗi pixel, tôi có thể tìm ra phần còn lại. Phần mà tôi thất bại có lẽ là sự tương tác raster <-> đệm (tôi thậm chí không chắc chắn nếu cả hai đều cần thiết). Cảm ơn rất nhiều. – viraptor