2012-06-01 72 views
0

我正在接收大型CCITT Group 4壓縮的TIFF文件,這些文件需要作爲未壓縮的TIFF文件在其他位置寫入。我使用jai_imageio TIFF閱讀器和書寫器來做到這一點,只要圖像的產品_width * height_適合整數,它就可以很好地工作。解壓縮TIFF文件而不經過BufferedImage

這裏是我使用的代碼:

TIFFImageReaderSpi readerSpi= new TIFFImageReaderSpi(); 
ImageReader imageReader = readerSpi.createReaderInstance(); 
byte[] data = blobManager.getObjectForIdAndVersion(id, version); 
ImageInputStream imageInputStream = ImageIO.createImageInputStream(data); 
imageReader.setInput(imageInputStream); 

TIFFImageWriterSpi writerSpi = new TIFFImageWriterSpi(); 
ImageWriter imageWriter = writerSpi.createWriterInstance(); 
ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam(); 
imageWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED); 
//bufferFile is created in the constructor 
ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(bufferFile); 
imageWriter.setOutput(imageOutputStream); 

//Now read the bitmap 
BufferedImage bufferedImage = imageReader.read(0); 
IIOImage iIOImage = new IIOImage(bufferedImage, null, null); 
//and write it 
imageWriter.write(null, iIOImage, imageWriteParam); 

不幸的是,我收到的文件通常非常大,數據的BufferedImage無法創建。 我一直在試圖找到一種方法從ImageReader直接流到ImageWriter,但我無法找到如何做到這一點。 任何人有建議嗎?

回答

1

我已經有一些問題,而最終的結果可能會讓你大吃一驚:

我結束了通話IrfanView中有使用的Runtime.exec()方法中的一些命令行選項。這樣,我不擔心壓縮或大小,它只是工作,併爲我輸出正確的文件在正確的文件夾。

如果你在Linux上,你可以使用ImageMagik或類似的東西。

+0

謝謝,但這不是我的選擇。首先,因爲它不是開源的,只能在Windows下運行。如果我決定使用本機代碼,我可以很容易地使用libtiff編寫自己的解壓縮程序。 – Gert

+0

你可以在Linux上使用ImageMagik做同樣的事情:) – Ewald

+0

我的問題是關於JAI類。我知道在Java環境之外還有其他的解決方案,但這不是我正在尋找的。 – Gert

0

爲Java VM提供更多內存。

如果不行,請看source code of the TIFF plugin in the JAI source code。你可能可以編寫自己的處理器,它只是使用流式方法解壓縮數據結構(所以你不需要隨時將整個映像保存在內存中)。

如果這樣也行不通,請看JNA,它允許您從Java的DLL中調用代碼(不需要C代碼;一切都是從純Java完成的,與Sun的JNI API不同)。

+0

謝謝,但它與VM內存無關。問題是圖像數據數組的數量增長得比整數的最大值大。我確實可以分解JAI代碼,但這是我想避免的。 JNA聽起來像一個有趣的項目,但JNI在其他地方很適合我。我只是想避免在外部解決這個問題,但是看起來似乎不可能。 – Gert

1

您可以使用TIFF圖塊將TIFF分割成更小的部分(「圖塊」)。如果您控制創建大圖片的代碼,JAI允許您逐一檢索圖片內容。

下面是關於如何使用JAI創建平鋪圖像的例子:

ColorModel cm = source.createColorModel(); 
// SampleModel with the tilesize 
SampleModel sm = cm.createCompatibleSampleModel(tileWidth, tileHeight); 
TiledImage image = new TiledImage(0, 0, imageWidth, imageHeight, 0, 0, sm, cm); 

TIFFEncodeParam tep = new TIFFEncodeParam(); 
tep.setTileSize(tileWidth, tileHeight); // Set tile size to avoid OOM 
tep.setWriteTiled(true); 
JAI.create("filestore", image, filepath, "TIFF", tep); 

如果你無法控制TIFF生產,我JAI的知識太有限有很大幫助。