Konversikan data piksel mentah (sebagai array byte) ke BufferedImage

Saya memiliki persyaratan untuk menggunakan perpustakaan asli yang membaca beberapa format file gambar berpemilik (sesuatu tentang tidak menciptakan kembali roda kita sendiri). Perpustakaannya berfungsi dengan baik, hanya saja terkadang gambarnya bisa menjadi cukup besar (rekor yang pernah saya lihat adalah 13k x 15k piksel). Masalahnya adalah JVM saya yang malang terus mengalami kematian yang menyakitkan dan/atau membuang OutOfMemoryError setiap kali gambar mulai menjadi besar.

Inilah yang saya jalankan

//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;
}

Cuplikan ini berfungsi dengan baik untuk sebagian besar gambar asalkan ukurannya tidak terlalu besar. Kecepatannya juga baik-baik saja. Masalahnya adalah Image menggambar ke langkah BufferedImage menghabiskan terlalu banyak memori.

Apakah ada cara agar saya dapat melewati langkah itu dan langsung beralih dari byte mentah ke gambar yang di-buffer?


person captainroxors    schedule 27.01.2015    source sumber


Jawaban (1)


Gunakan RawImageInputStream dari jai. Hal ini memerlukan mengetahui informasi tentang SampleModel, yang tampaknya Anda miliki dari kode asli.

Opsi lainnya adalah memasukkan rawBytes Anda ke dalam DataBuffer, lalu buat WritableRaster, dan terakhir buat BufferedImage. Ini pada dasarnya adalah apa yang akan dilakukan RawImageInputStream.

person Brett Okken    schedule 27.01.2015
comment
Karena penggunaan memori tampaknya menjadi masalah di sini, opsi terakhir mungkin yang terbaik, karena Anda dapat membuat DataBuffer langsung dari array byte mentah (yaitu new DataBufferByte(rawBytes, rawBytes.length)). - person Harald K; 27.01.2015
comment
Sesuatu yang indah, tuan-tuan. Bekerja dengan cemerlang. - person captainroxors; 27.01.2015