Запишите компонент свинга в большое изображение TIFF, используя JAI

У меня есть большой компонент Swing для записи в TIFF. Компонент слишком велик для загрузки TIFF в память, поэтому мне либо нужно создать большой BufferedImage, который поддерживается дисковым WritableRaster (как упоминалось здесь) или использовать JAI.

JAI кажется лучшим ответом, если не считать полной путаницы проекта.

Учитывая это, может ли кто-нибудь наметить шаги для записи моего компонента Swing в мозаичный TIFF без нехватки памяти?

Размер изображения будет возможно 10000x700

В идеале я бы создал какой-то образ на диске и записал бы в него части компонента, при этом каждая запись сбрасывалась бы на диск.

ИЗМЕНИТЬ

Я думаю, что мог бы сделать это с помощью ImageWriter, однако я получаю исключение NoSuchElementException, когда я звоню:

ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("tif").next();

У меня есть jar-файлы jai_code.jar и jai_core.jar в моем пути к классам, есть ли что-то еще, что мне нужно сделать?

РЕДАКТИРОВАНИЕ Я могу создать очень большой файл TIFF с помощью JAI, но JAI не поддерживает сжатие TIFF, поэтому размер файла составляет 92 МБ.

Если я установлю JAI-ImageIO, я смогу создать сжатый TIFF с помощью ImageWriter, но только из растра или BufferedImage, для которого у меня недостаточно памяти.

Есть ли способ сделать двухэтапный подход, использовать JAI для создания большого TIFF, а затем сжать большой TIFF, не загружая все это в память?


person Sam Barnum    schedule 12.05.2011    source источник


Ответы (2)


Мне пришлось загрузить и сохранить большой TIFF (59392x40192px) с помощью JAI. Мое решение: TiledImages.

Я использовал TiledImage, потому что мне нужны плитки и части изображения. Чтобы использовать TiledImage эффективно, вы должны построить его с предпочитаемым размером плитки. JAI использует TileCache, поэтому не все изображение будет находиться в памяти, когда оно не нужно.

Чтобы записать TiledImage в файл, используйте параметр «writeTiled» (избегайте OutOfMemory, поскольку он записывает плитку за плиткой):

public void storeImage(TiledImage img, String filepath) {
    TIFFEncodeParam tep = new TIFFEncodeParam();
    //important to avoid OutOfMemory
    tep.setTileSize(256, 256);
    tep.setWriteTiled(true);
    //fast compression
    tep.setCompression(TIFFEncodeParam.COMPRESSION_PACKBITS);
    //write file
    JAI.create("filestore", img, filepath, "TIFF", tep);
}

Он отлично работает с изображениями размером до 690 МБ (сжатыми), для больших изображений я еще не тестировал.

Но если вы работаете с 32-разрядной версией WinXP, вы не сможете иметь размер HeapSpace больше 1280 м, это все еще ограничение Java VM.

Мой TiledImage построен с помощью IndexedColorModel из моих исходных данных изображения:

//here you create a ColorModel for your Image
ColorModel cm = source.createColorModel();
//then create a compatible SampleModel, with the tilesize
SampleModel sm = cm.createCompatibleSampleModel(tileWidth,tileHeight);

TiledImage image = new TiledImage(0, 0, imageWidth, imageHeight, 0, 0, sm, cm);
person Indimental    schedule 16.06.2011
comment
как вы создаете TiledImage? - person Sam Barnum; 16.06.2011
comment
Я добавил создание TiledImage выше. Я устанавливаю образцы прямо на изображении, потому что мне нужно загружать пиксели за пикселями из моего источника. Так что у меня всегда одна плитка в памяти при загрузке. - person Indimental; 16.06.2011

У меня была такая же ситуация, и я использовал следующие шаги:

Это помогло мне отображать и обрабатывать изображения TIFF ~ 50 МБ (5000x5000 пикселей).

person JMelnik    schedule 12.05.2011
comment
Спасибо, D1i, пытаюсь записать очень большой образ на диск. Я не могу создать BufferedImage достаточно большого размера, потому что мне не хватает памяти. Конечное изображение, я действительно хочу иметь ширину 10000 пикселей. - person Sam Barnum; 12.05.2011
comment
Понятно, тогда я неправильно понял вопрос ;О. Я тоже с нетерпением жду ответа, выглядит полезным. - person JMelnik; 12.05.2011