将多页TIFF图像拆分为单个图像(Java)
我一直在扯我的头发 如何将多页/多层TIFF图像分割为多个单独的图像 演示图像可用将多页TIFF图像拆分为单个图像(Java),java,tiff,Java,Tiff,我一直在扯我的头发 如何将多页/多层TIFF图像分割为多个单独的图像 演示图像可用 (更喜欢纯Java(即非本机)解决方案。该解决方案是否依赖于商业库无关紧要。)您可以使用Java Advanced Imaging库,通过使用ImageReader拆分多页TIFF: ImageInputStream is = ImageIO.createImageInputStream(new File(pathToImage)); if (is == null || is.length() == 0){
(更喜欢纯Java(即非本机)解决方案。该解决方案是否依赖于商业库无关紧要。)您可以使用Java Advanced Imaging库,通过使用ImageReader拆分多页TIFF:
ImageInputStream is = ImageIO.createImageInputStream(new File(pathToImage));
if (is == null || is.length() == 0){
// handle error
}
Iterator<ImageReader> iterator = ImageIO.getImageReaders(is);
if (iterator == null || !iterator.hasNext()) {
throw new IOException("Image file format not supported by ImageIO: " + pathToImage);
}
// We are just looking for the first reader compatible:
ImageReader reader = (ImageReader) iterator.next();
iterator = null;
reader.setInput(is);
并分别阅读以下页面:
reader.read(numPage)
我在上面的示例中使用了一个名为imageio tiff的tiff插件 Maven依赖项:
<dependency>
<groupId>com.tomgibara.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-imaging</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
com.tomgibara.imageio
图像tiff
1
我能够从tiff资源中获取缓冲图像:
Resource img3 = new ClassPathResource(TIFF4);
ImageInputStream is = ImageIO.createImageInputStream(img3.getInputStream());
Iterator<ImageReader> iterator = ImageIO.getImageReaders(is);
if (iterator == null || !iterator.hasNext()) {
throw new IOException("Image file format not supported by ImageIO: ");
}
// We are just looking for the first reader compatible:
ImageReader reader = (ImageReader) iterator.next();
iterator = null;
reader.setInput(is);
int nbPages = reader.getNumImages(true);
LOGGER.info("No. of pages for tiff file is {}", nbPages);
BufferedImage image1 = reader.read(0);
BufferedImage image2 = reader.read(1);
BufferedImage image3 = reader.read(2);
Resource img3=新类路径资源(TIFF4);
ImageInputStream=ImageIO.CreateMageInputStream(img3.getInputStream());
迭代器迭代器=ImageIO.getImageReaders(is);
if(iterator==null | |!iterator.hasNext()){
抛出新IOException(“ImageIO不支持图像文件格式:”);
}
//我们正在寻找第一个兼容的读卡器:
ImageReader=(ImageReader)迭代器。下一步();
迭代器=null;
reader.setInput(is);
int nbPages=reader.getNumImages(true);
info(“tiff文件的页数为{}”,nbPages);
BuffereImage image1=reader.read(0);
BuffereImage image2=读取器.read(1);
BuffereImage image3=读取器.read(2);
但后来我发现了另一个叫做ApacheCommonsImaging的项目
Maven依赖项:
<dependency>
<groupId>com.tomgibara.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-imaging</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
org.apache.commons
公共图像
1.0-快照
在一行中,您可以获得缓冲图像:
List<BufferedImage> bufferedImages = Imaging.getAllBufferedImages(img3.getInputStream(), TIFF4);
LOGGER.info("No. of pages for tiff file is {} using apache commons imaging", bufferedImages.size());
List bufferedImages=Imaging.getAllBufferedImages(img3.getInputStream(),TIFF4);
info(“使用apache commons imaging时tiff文件的页数为{}”,buffereImage.size());
然后写入文件示例:
final Map<String, Object> params = new HashMap<String, Object>();
// set optional parameters if you like
params.put(ImagingConstants.PARAM_KEY_COMPRESSION, new Integer(TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_4));
int i = 0;
for (Iterator<BufferedImage> iterator1 = bufferedImages.iterator(); iterator1.hasNext(); i++) {
BufferedImage bufferedImage = iterator1.next();
LOGGER.info("Image type {}", bufferedImage.getType());
File outFile = new File("C:\\tmp" + File.separator + "shane" + i + ".tiff");
Imaging.writeImage(bufferedImage, outFile, ImageFormats.TIFF, params);
}
final Map params=new HashMap();
//如果愿意,可以设置可选参数
参数put(ImagingConstants.PARAM_KEY_COMPRESSION,新整数(TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_4));
int i=0;
for(迭代器迭代器1=BuffereImage.Iterator();迭代器1.hasNext();i++){
BuffereImage BuffereImage=iterator1.next();
info(“图像类型{}”,buffereImage.getType());
File outFile=新文件(“C:\\tmp”+File.separator+“shane”+i+“.tiff”);
Imaging.writeImage(BuffereImage、outFile、ImageFormats.TIFF、params);
}
实际上,在测试性能时,apache的速度要慢得多
或者使用旧版本的iText,速度要快得多:
private ByteArrayOutputStream convertTiffToPdf(InputStream imageStream) throws IOException, DocumentException {
Image image;
ByteArrayOutputStream out = new ByteArrayOutputStream();
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, out);
writer.setStrictImageSequence(true);
document.open();
RandomAccessFileOrArray ra = new RandomAccessFileOrArray(imageStream);
int pages = TiffImage.getNumberOfPages(ra);
for (int i = 1; i <= pages; i++) {
image = TiffImage.getTiffImage(ra, i);
image.setAbsolutePosition(0, 0);
image.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());
document.setPageSize(PageSize.A4);
document.newPage();
document.add(image);
}
document.close();
out.flush();
return out;
}
private ByteArrayOutputStream converttifptodf(InputStream imageStream)引发IOException、DocumentException{
图像;
ByteArrayOutputStream out=新建ByteArrayOutputStream();
文档=新文档();
PdfWriter writer=PdfWriter.getInstance(文档,输出);
writer.setStritimagesequence(true);
document.open();
RandomAccessFileOrArray ra=新的RandomAccessFileOrArray(imageStream);
int pages=TiffImage.getNumberOfPages(ra);
对于(inti=1;i一个快速但非JAVA的解决方案是tiffsplit
。它是libtiff库的一部分
在tiff文件的所有层中拆分tiff文件的示例命令如下:
tiffsplit image.tif
主页说明了这一切:
NAME
tiffsplit - split a multi-image TIFF into single-image TIFF files
SYNOPSIS
tiffsplit src.tif [ prefix ]
DESCRIPTION
tiffsplit takes a multi-directory (page) TIFF file and creates one or more single-directory (page) TIFF files
from it. The output files are given names created by concatenating a prefix, a lexically ordered suffix in the
range [aaa-zzz], the suffix .tif (e.g. xaaa.tif, xaab.tif, xzzz.tif). If a prefix is not specified on the
command line, the default prefix of x is used.
OPTIONS
None.
BUGS
Only a select set of ‘‘known tags’’ is copied when splitting.
SEE ALSO
tiffcp(1), tiffinfo(1), libtiff(3TIFF)
Libtiff library home page: http://www.remotesensing.org/libtiff/
所有建议的解决方案都需要逐页读取多页图像,并将页面写回新的TIFF图像。除非您希望将各个页面保存为不同的图像格式,否则解码图像没有意义。鉴于TIFF图像的特殊结构,您可以将多页TIFF图像拆分为单个TIFF图像,而无需进行de编码
TIFF调整工具(我正在使用的一个更大的图像相关库的一部分)是用纯Java从头开始编写的。它可以删除页面、插入页面、保留某些页面、从多页TIFF中拆分页面,以及将多页TIFF图像合并到一个TIFF图像中而无需解压缩
尝试使用TIFF调整工具后,我可以将图像分割为3页:,和
注1:由于某些原因,原始演示图像包含“不正确”StripByteCounts值1不是图像条所需的实际字节。事实证明,图像数据没有压缩,因此每个图像条的实际字节可以通过其他TIFF字段值计算出来,如RowsPerStrip、SamplesPerPixel、ImageWidth等
注2:因为在拆分TIFF时,上述库不需要对图像进行解码和重新编码。因此,它速度很快,而且还保留了每个页面的原始编码和附加元数据!这就是我使用ImageIO的方法:
public List<BufferedImage> extractImages(InputStream fileInput) throws Exception {
List<BufferedImage> extractedImages = new ArrayList<BufferedImage>();
try (ImageInputStream iis = ImageIO.createImageInputStream(fileInput)) {
ImageReader reader = getTiffImageReader();
reader.setInput(iis);
int pages = reader.getNumImages(true);
for (int imageIndex = 0; imageIndex < pages; imageIndex++) {
BufferedImage bufferedImage = reader.read(imageIndex);
extractedImages.add(bufferedImage);
}
}
return extractedImages;
}
private ImageReader getTiffImageReader() {
Iterator<ImageReader> imageReaders = ImageIO.getImageReadersByFormatName("TIFF");
if (!imageReaders.hasNext()) {
throw new UnsupportedOperationException("No TIFF Reader found!");
}
return imageReaders.next();
}
public List extractImages(InputStream fileInput)引发异常{
List extractedimage=new ArrayList();
try(ImageInputStream iis=ImageIO.createImageInputStream(fileInput)){
ImageReader=getTiffImageReader();
reader.setInput(iis);
int pages=reader.getNumImages(true);
对于(int-imageIndex=0;imageIndex
我从中获取了部分代码。下面的代码将多个tiff转换为单个tiff,并生成包含tiff图像列表的Excel表格
你需要