Преобразование необработанных данных пикселей (в виде массива байтов) в 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