我看到了一些关于多页 tiff 的问题和一些关于压缩的问题,但没有(我看到的)将两者联系起来。 This question和我见过的一样近,让我非常接近,所以我希望如此。我进入了提到的 Oracle 论坛线程(它正在谈论通过压缩将多页 PDF 转换为 TIFF)并且我认为我已经接近完成代码来完成此操作。有人可以帮忙吗?我将删除 try/catches 以尝试将其缩短(基本上他们所做的只是在控制台中输出一条消息并返回 false)。
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 block 中调用它可以防止不可渲染的 TIFF 问题。但是,除了第一个页面之外,它没有添加任何页面。
最佳答案
如果有帮助,这是我用来修改 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 编码器将它们写入损坏,因此需要修补它们。
关于java - 多页 Tiff 压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10317353/