2012-04-25 126 views
4

我已经看到关于multipage tiffs和关于压缩的一些问题的几个问题,但没有一个(我见过)连接这两个问题。 This question就像我见过的一样近,让我感觉非常接近,所以我希望。我进入了上面提到的Oracle论坛主题(它正在讨论一个多页PDF到TIFF的压缩),我想我已经完成了代码的完成。任何人都可以协助我将删除try/catches来尝试缩短这段头发(基本上他们所做的只是在控制台中输出消息并返回false)。多页Tiff压缩

public static boolean CompressedTiff(List<BufferedImage> images, File path) 
{ 
    if (!path.getParentFile().exists()) 
     path.getParentFile().mkdirs(); 
    path.createNewFile(); 
    ImageOutputStream ios; 
     ios = ImageIO.createImageOutputStream(path); 

    Iterator<ImageWriter> imageWriters = ImageIO.getImageWritersByFormatName("TIFF"); 
    ImageWriter writer = (ImageWriter)imageWriters.next(); 
    writer.setOutput(ios); 
    TIFFImageWriteParam writeParam = (TIFFImageWriteParam)writer.getDefaultWriteParam(); 
    writeParam.setCompressionMode(2); 
    writeParam.setCompressionType("LZW"); 
    writer.prepareWriteSequence(null); 

    for(int i = 0; i < images.size(); i++) 
    { 
     ImageTypeSpecifier spec = ImageTypeSpecifier.createFromRenderedImage(images.get(i)); 
     javax.imageio.metadata.IIOMetadata metadata = writer.getDefaultImageMetadata(spec, writeParam); 
     IIOImage iioImage = new IIOImage(images.get(i), null, metadata); 
     writer.writeToSequence(iioImage, writeParam); 
     images.get(i).flush();//modified after release. 

     images.get(i).flush(); 
     writer.endWriteSequence(); 
     ios.flush(); 
     writer.dispose(); 
     ios.close(); 
    } 
    return true; 

} 

它在writer.writeToSequence的下一个传递失败,说我需要调用prepareWriteSequence。我将它改为

writer.prepareWriteSequence(metadata); 
writer.writeToSequence(iioImage, writeParam); 

也删除了更早的writer.prepareWriteSequence(null);

它似乎正在导航文件,但是,输出不是任何类型的可呈现的tif。多页或其他。

我已经安装了JAI,所以如果可以用某种方式来实现压缩的图像,那太棒了。我使用的代码生成一个TIFF正在使用这个,但我还没有看到任何工作,只要将压缩添加到页面。

编辑:我添加了一堆ios.flush(); ios.close();调用catch块,它可以防止不可呈现的TIFF问题。但是,它并没有在第一页之外添加任何页面。

回答

2

如果有帮助,这是我使用的修改TiffImageWriteParam设置压缩代码:

try { 
    jWriteParam.setCompressionMode(_compression != TiffCompression.NO_COMPRESSION 
        ? ImageWriteParam.MODE_EXPLICIT : ImageWriteParam.MODE_DISABLED); 

    if (_compression != TiffCompression.NO_COMPRESSION) { 
     // this code corrects the compression if, say, the client code asked for 
     // CCITT but the actual image pixel format was CMYK or some other non-1 bit 
     // image type. 
     TiffCompression mode = recastToValidCompression(_compression, pf); 
     jWriteParam.setCompressionType(getCompressionType(mode)); 
     TIFFCompressor compressor = getTiffCompressor(mode, jWriteParam, shouldUsePredictor(pf)); 
     jWriteParam.setTIFFCompressor(compressor); 
     if (_compression == TiffCompression.JPEG_COMPRESSION) { 
      // Java supports setting to 1.0 (ie 100), but it will not actually do lossless (maybe) 
      if (_jpegQuality == 100 && !jWriteParam.isCompressionLossless()) 
       continue; 
      jWriteParam.setCompressionQuality(toJavaJpegQuality()); 
     } 
    } 
} 
catch (UnsupportedOperationException e) 
{ 
    // this shouldn't get here, but you should consider what to do if it does. 
    // set a default? throw? 
} 

这里是getTiffCompressor():

private TIFFCompressor getTiffCompressor (TiffCompression compression, TIFFImageWriteParam writeParam, boolean usePredictor) 
{ 
    int predictor = usePredictor 
      ? BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING 
      : BaselineTIFFTagSet.PREDICTOR_NONE; 

    switch (compression) 
    { 
    case GROUP_3_FAX_ENCODING: 
     return new TIFFT4Compressor(); 
    case GROUP_4_FAX_ENCODING: 
     return new TIFFT6Compressor(); 
    case JPEG_COMPRESSION: 
     return new TIFFJPEGCompressor(writeParam); 
    case MACINTOSH_PACKBITS: 
     return new TIFFPackBitsCompressor(); 
    case DEFLATE: 
     return new TIFFDeflateCompressor(writeParam, predictor); 
    case LZW: 
     return new TIFFLZWCompressor(predictor); 
    case MODIFIED_HUFFMAN: 
     return new TIFFRLECompressor(); 
    case NO_COMPRESSION: 
    case DEFAULT: 
    default: 
     return null; 
    } 
} 

TiffCompression是我自己的枚举模型我为TIFF文件提供的压缩。最后,这里是getCompressionType():

private String getCompressionType (TiffCompression compression) 
{ 
    switch (compression) 
    { 
    case GROUP_3_FAX_ENCODING: 
     return "CCITT T.4"; 
    case GROUP_4_FAX_ENCODING: 
     return "CCITT T.6"; 
    case JPEG_COMPRESSION: 
     return "JPEG"; 
    case MACINTOSH_PACKBITS: 
     return "PackBits"; 
    case DEFLATE: 
     return "Deflate"; 
    case LZW: 
     return "LZW"; 
    case MODIFIED_HUFFMAN: 
     return "CCITT RLE"; 
    case NO_COMPRESSION: 
    case DEFAULT: 
    default: 
     return null; 
    } 
} 

现在,我不能告诉你一切,因为我的代码是建立在对图像进行编码的任意号码,你是不是,所以我们的代码结构不同似地。就我而言,我设置了编码器,以便使用具有更开放架构的序列编写器。我拉一个图像,触发一个事件,可以选择更改默认压缩,创建编写器和写入参数,设置元数据/图像标签,消除进度事件,然后编写序列。然后,我必须进入并修补最后写入的ifd,因为tiff编码器会将它们写入中断状态,因此需要修补它们。

+0

我想说的是压缩方面正在工作(在剩余的50%文件大小附近的某个地方),但我从来没有试过用这种方法做多页(我通常使用JAI,但每当我压缩单个页面上面提到的方法并试图使它们与JAI协调一致,文件大小压缩消失了)。在阅读之后,由于专利的发展,JAI不支持LZW。 – Robert 2012-04-25 17:04:18