答案 0 :(得分:20)
您可以使用 Java Advanced Imaging 库JAI,通过使用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);
然后你可以得到页数:
nbPages = reader.getNumImages(true);
分开阅读页面:
reader.read(numPage)
答案 1 :(得分:2)
我在上面的示例中使用了一个名为imageio-tiff的tiff插件。
Maven依赖:
<dependency>
<groupId>com.tomgibara.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>1.0</version>
</dependency>
我能够从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);
但后来我发现了另一个名为apache commons imaging的项目 Maven依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-imaging</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
在一行中,您可以获得缓冲的图像:
List<BufferedImage> bufferedImages = Imaging.getAllBufferedImages(img3.getInputStream(), TIFF4);
LOGGER.info("No. of pages for tiff file is {} using apache commons imaging", bufferedImages.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);
}
实际测试性能,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;
}
答案 2 :(得分:2)
快速但非JAVA解决方案是tiffsplit
。它是libtiff库的一部分。
在所有图层中拆分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/
答案 3 :(得分:1)
所有提议的解决方案都需要逐页读取多页图像并将页面写回新的TIFF图像。除非您想将各个页面保存为不同的图像格式,否则解码图像毫无意义。鉴于TIFF图像的特殊结构,您可以将多页TIFF分割为单个TIFF图像而无需解码。
TIFF调整工具(一个较大的图像相关库的一部分 - "icafe"我正在使用纯Java编写。它可以删除页面,插入页面,保留某些页面,从多个页面拆分页面TIFF以及将多页TIFF图像合并为一个TIFF图像而不对其进行解压缩。
尝试使用TIFF调整工具后,我可以将图像拆分为3页:page#0,page#1和page#2
NOTE1:原始演示图像由于某种原因包含“不正确”的StripByteCounts值1,这不是图像条带所需的实际字节数。事实证明,图像数据没有被压缩,因此每个图像条的实际字节可以通过其他TIFF字段值计算出来,例如RowsPerStrip,SamplesPerPixel,ImageWidth等。
注2:由于在拆分TIFF时,上述库不需要对图像进行解码和重新编码。所以它很快,它还保留了每个页面的原始编码和附加元数据!
答案 4 :(得分:1)
这就是我使用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();
}
我从this blog获取了部分代码。
答案 5 :(得分:0)
下面的代码会将多个tiff转换为单个tiff,并生成一张带有tiff图像列表的Excel表格。
您需要创建一个名为&#39; FAX&#39;的文件夹。在C盘中将TIFF图像放入其中,然后运行此代码。您可以在&#34; C:\ Final_FAX \&#34;
中找到转换后的图像需要从http://www.java2s.com/Code/JarDownload/sun/
导入以下广告罐1.sun-as-jsr88-dm-4.0-sources
2./sun-jai_codec
3.sun-jai_core
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.IOException;
import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.TIFFEncodeParam;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import javax.swing.JOptionPane;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
public class TIFF_Sepreator {
File folder = new File("C:/FAX/");
public static void infoBox(String infoMessage, String titleBar)
{
JOptionPane.showMessageDialog(null, infoMessage, "InfoBox: " + titleBar, JOptionPane.INFORMATION_MESSAGE);
}
public void splitting() throws IOException, AWTException
{
boolean FinalFAXFolder = (new File("C:/Final_FAX")).mkdirs();
// int ListOfFiles = new File("C:/Final_FAX/").listFiles().length;
// System.out.println(ListOfFiles);
File[] listOfFiles = folder.listFiles();
String dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime());
try{
if (listOfFiles.length > 0)
{
for(int file=0; file<listOfFiles.length; file++)
{
System.out.println(listOfFiles[file]);
FileSeekableStream ss = new FileSeekableStream(listOfFiles[file]);
ImageDecoder dec = ImageCodec.createImageDecoder("tiff", ss, null);
int count = dec.getNumPages();
TIFFEncodeParam param = new TIFFEncodeParam();
param.setCompression(TIFFEncodeParam.COMPRESSION_GROUP4);
param.setLittleEndian(false); // Intel
System.out.println("This TIF has " + count + " image(s)");
for (int i = 0; i < count; i++)
{
RenderedImage page = dec.decodeAsRenderedImage(i);
File f = new File("C:\\Final_FAX\\"+dateFormat+ file +i + ".tif");
System.out.println("Saving " + f.getCanonicalPath());
ParameterBlock pb = new ParameterBlock();
pb.addSource(page);
pb.add(f.toString());
pb.add("tiff");
pb.add(param);
RenderedOp r = JAI.create("filestore",pb);
r.dispose();
}
}
TIFF_Sepreator.infoBox("Find your splitted TIFF images in location 'C:/Final_FAX/' " , "Done :)");
WriteListOFFilesIntoExcel();
}
else
{
TIFF_Sepreator.infoBox("No files was found in location 'C:/FAX/' " , "Empty folder");
System.out.println("No files found");
}
}
catch(Exception e)
{
TIFF_Sepreator.infoBox("Unabe to run due to this error: " +e , "Error");
System.out.println("Error: "+e);
}
}
public void WriteListOFFilesIntoExcel(){
File[] listOfFiles = folder.listFiles();
ArrayList<File> files = new ArrayList<File>(Arrays.asList(folder.listFiles()));
try {
String filename = "C:/Final_FAX/List_Of_Fax_Files.xls" ;
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("FirstSheet");
for (int file=0; file<listOfFiles.length; file++) {
System.out.println(listOfFiles[file]);
Row r = sheet.createRow(file);
r.createCell(0).setCellValue(files.get(file).toString());
}
FileOutputStream fileOut = new FileOutputStream(filename);
workbook.write(fileOut);
fileOut.close();
System.out.println("Your excel file has been generated!");
}
catch(Exception ex){
TIFF_Sepreator.infoBox("Unabe to run due to this error: " +ex , "Error");
System.out.println("Error: "+ex);
}
}
public static void main(String[] args) throws IOException, AWTException {
new TIFF_Sepreator().splitting();
}
}
答案 6 :(得分:0)
它可以将压缩设置为default param.setCompression(32946);
。
public static void doitJAI(String mutitiff) throws IOException {
FileSeekableStream ss = new FileSeekableStream(mutitiff);
ImageDecoder dec = ImageCodec.createImageDecoder("tiff", ss, null);
int count = dec.getNumPages();
TIFFEncodeParam param = new TIFFEncodeParam();
param.setCompression(32946);
param.setLittleEndian(false); // Intel
System.out.println("This TIF has " + count + " image(s)");
for (int i = 0; i < count; i++) {
RenderedImage page = dec.decodeAsRenderedImage(i);
File f = new File("D:/PSN/SCB/SCAN/bin/Debug/Temps/test/single_" + i + ".tif");
System.out.println("Saving " + f.getCanonicalPath());
ParameterBlock pb = new ParameterBlock();
pb.addSource(page);
pb.add(f.toString());
pb.add("tiff");
pb.add(param);
RenderedOp r = JAI.create("filestore",pb);
r.dispose();
}
}
&#13;