แปลงข้อมูลพิกเซลดิบ (เป็นอาร์เรย์ไบต์) เป็น BufferedImage

ฉันมีข้อกำหนดในการใช้ไลบรารีดั้งเดิมซึ่งอ่านรูปแบบไฟล์รูปภาพที่เป็นกรรมสิทธิ์บางรูปแบบ (บางอย่างเกี่ยวกับการไม่สร้างวงล้อของเราเองขึ้นมาใหม่) ไลบรารีทำงานได้ดี แต่บางครั้งภาพอาจมีขนาดใหญ่มาก (บันทึกที่ฉันเคยเห็นคือ 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 กลืนกินหน่วยความจำมากเกินไป

มีวิธีที่ฉันสามารถข้ามขั้นตอนนั้นและเปลี่ยนจากไบต์ดิบไปเป็นภาพที่บัฟเฟอร์ได้โดยตรงหรือไม่


person captainroxors    schedule 27.01.2015    source แหล่งที่มา


คำตอบ (1)


ใช้ RawImageInputStreamจากใจ. สิ่งนี้จำเป็นต้องทราบข้อมูลเกี่ยวกับ SampleModel ซึ่งคุณได้รับจากโค้ดเนทีฟ

อีกทางเลือกหนึ่งคือการใส่ rawBytes ของคุณลงใน DataBuffer จากนั้น สร้าง WritableRaster และสุดท้ายสร้าง BufferedImage นี่คือสิ่งที่ RawImageInputStream จะทำเป็นหลัก

person Brett Okken    schedule 27.01.2015
comment
เนื่องจากการใช้หน่วยความจำน่าจะเป็นปัญหาที่นี่ ตัวเลือกหลังน่าจะดีที่สุด เนื่องจากคุณสามารถสร้าง DataBuffer ได้โดยตรงจากอาร์เรย์ไบต์ดิบ (เช่น new DataBufferByte(rawBytes, rawBytes.length)) - person Harald K; 27.01.2015
comment
เรื่องของความงามสุภาพบุรุษ ทำงานได้อย่างยอดเยี่ยม - person captainroxors; 27.01.2015