Записать компонент свинга в большое изображение TIFF с помощью JAI
У меня есть большой компонент свинга для записи в TIFF. Компонент слишком велик, чтобы загрузить TIFF в память, поэтому мне нужно либо создать большой BufferedImage, который поддерживается на основе WritableRaster на основе диска (как упомянуто здесь), либо использовать JAI.
JAI кажется лучшим ответом, кроме полной путаницы в проекте.
Учитывая это, кто-то может наметить шаги для записи моего компонента Swing в мозаичный TIFF без исчерпания памяти?
Размер изображения может быть 10000x700
В идеале я хотел бы создать какой-нибудь образ на основе диска и записать на него части компонента, каждая запись будет записана на диск.
РЕДАКТИРОВАТЬ
Я думаю, что я мог бы сделать это с ImageWriter, однако я получаю NoSuchElementException, когда я вызываю:
ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("tif").next();
У меня есть jai_code.jar и jai_core.jar jar на моем classpath, есть ли что-то еще, что я должен сделать?
РЕДАКТИРОВАТЬ Я могу создать очень большой TIFF с использованием JAI, но JAI не поддерживает сжатие TIFF, поэтому размер файла составляет 92 МБ.
Если я установлю JAI-ImageIO, я могу создать сжатый TIFF с помощью ImageWriter, но только из растра или BufferedImage, для которого у меня недостаточно памяти.
Есть ли какой-нибудь способ сделать двухэтапный подход, использовать JAI для создания большого TIFF, а затем сжать большой TIFF, не загружая все это в память?
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, у вас может не быть больше 1280-метрового размера HeapSpace, это все еще ограничение 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);
У меня была такая же ситуация, и я использовал эти шаги:
Загрузить как BufferedImage с JAI
Измените размер BufferedImage до предпочтительного размера (600x600px), поддерживая соотношение сторон, используя Image#getScaledInstance(int w, int h, Image.SCALE_SMOOTH)
Рисование изображения с использованием метода Graphics2d.drawImage(..) в методе JComponent#paintComponent(java.awt.Graphics)
Это помогло мне показать и манипулировать изображениями в формате TIFF ~50 МБ (5000x5000 пикселей).