ฉันมีข้อกำหนดในการใช้ไลบรารีดั้งเดิมซึ่งอ่านรูปแบบไฟล์รูปภาพที่เป็นกรรมสิทธิ์บางรูปแบบ (บางอย่างเกี่ยวกับการไม่สร้างวงล้อของเราเองขึ้นมาใหม่) ไลบรารีทำงานได้ดี แต่บางครั้งภาพอาจมีขนาดใหญ่มาก (บันทึกที่ฉันเคยเห็นคือ 13k x 15k พิกเซล) ปัญหาคือ JVM ที่น่าสงสารของฉันยังคงตายอย่างเจ็บปวดและ / หรือโยน OutOfMemoryError ทุกครั้งที่รูปภาพเริ่มมีขนาดใหญ่
นี่คือสิ่งที่ฉันกำลังทำงานอยู่
//the bands, width, and height fields are set in the native code
//And the rawBytes array is also populated in the native code.
public BufferedImage getImage(){
int type = bands == 1 ? BufferedImage.TYPE_BYTE_GRAY : BufferedImage.TYPE_INT_BRG;
BufferedImage bi = new BufferedImage(width, height, type);
ImageFilter filter = new RGBImageFilter(){
@Override
public int filterRGB(int x, int y, int rgb){
int r, g, b;
if (bands == 3) {
r = (((int) rawBytes[y * (width / bands) * 3 + x * 3 + 2]) & 0xFF) << 16;
g = (((int) rawBytes[y * (width / bands) * 3 + x * 3 + 1]) & 0xFF) << 8;
b = (((int) rawBytes[y * (width / bands) * 3 + x * 3 + 0]) & 0xFF);
} else {
b = (((int) rawBytes[y * width + x]) & 0xFF);
g = b << 8;
r = b << 16;
}
return 0xFF000000 | r | g | b;
}
};
//this is the problematic block
ImageProducer ip = new FilteredImageSource(bi.getSource(), filter);
Image i = Toolkit.getDefaultToolkit().createImage(ip);
Graphics g = bi.createGraphics();
//with this next line being where the error tends to occur.
g.drawImage(i, 0, 0, null);
return bi;
}
ตัวอย่างนี้ใช้งานได้ดีกับภาพส่วนใหญ่ตราบใดที่ภาพไม่ใหญ่จนเกินไป ความเร็วของมันก็ถือว่าใช้ได้เช่นกัน ปัญหาคือว่า Image
วาดลงบนขั้นตอน BufferedImage
กลืนกินหน่วยความจำมากเกินไป
มีวิธีที่ฉันสามารถข้ามขั้นตอนนั้นและเปลี่ยนจากไบต์ดิบไปเป็นภาพที่บัฟเฟอร์ได้โดยตรงหรือไม่