在工作中,遇到一个需要将pdf转为tif并将图片大小限制到30kb以内的需求。在网上看了一圈,也因为依赖版本等等踩了一些坑,为此记录下来学习的过程。
点击查看代码
import com.github.jaiimageio.impl.plugins.tiff.TIFFImageWriterSpi;
import com.github.jaiimageio.plugins.tiff.BaselineTIFFTagSet;
import com.github.jaiimageio.plugins.tiff.TIFFDirectory;
import com.github.jaiimageio.plugins.tiff.TIFFField;
import com.github.jaiimageio.plugins.tiff.TIFFTag;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.*;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class TifUtils {
private static Logger logger = Logger.getLogger(TifUtils.class);
public static void main(String[] args) throws FileNotFoundException {
// 初始化 Log4j
BasicConfigurator.configure();
File file = new File("/Users/xu/testpdf/test.pdf");
FileInputStream fileInputStream = new FileInputStream(file);
String dir = "/Users/xu/testpdf";
pdf2tif(file, new File(dir), 200);
}
public static List pdf2tif(File file1, File dir, int dpi) {
try (PDDocument pdf = PDDocument.load(file1)) {
BufferedImage[] images = new BufferedImage[pdf.getNumberOfPages()];
PDFRenderer pdfRenderer = new PDFRenderer(pdf);
List files = new ArrayList<>();
long suffix = System.currentTimeMillis();
for (int i = 0; i < images.length; i++) {
// PDPage page = (PDPage) pdf.getDocumentCatalog().getAllPages().get(i);
PDPage page1 = pdf.getPage(i);
BufferedImage image;
//tif需要黑白二进制图像 所以使用ImageType.BINARY
BufferedImage binaryImage = pdfRenderer.renderImageWithDPI(i, 300, ImageType.BINARY);
images[i] = binaryImage;
File file = new File(dir.getAbsolutePath() + File.separator + suffix + "-" + (i + 1) + ".tiff");
try (FileOutputStream out = new FileOutputStream(file); ImageOutputStream ios = ImageIO.createImageOutputStream(out)) {
TIFFImageWriterSpi tiffWriter = new TIFFImageWriterSpi();
ImageWriter writer = tiffWriter.createWriterInstance();
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
//转为tif设置的条件 如果需要其他格式可设置LZW,jpeg,png
param.setCompressionType("CCITT T.6");
//可以根据需要调整清晰程度 1为无损
param.setCompressionQuality(1);
//设置图像200dpi
IIOMetadata metadata = createMetadata(writer, param, 200);
writer.setOutput(ios);
writer.write(metadata, new IIOImage(binaryImage, null, metadata), param);
logger.info("第"+(i+1)+"张图片 convert success");
logger.error("第"+(i+1)+"张图片 convert success");
} catch (IOException e) {
// logger.error(e);;
}
files.add(file);
}
return files;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
//修改tif图片元数据
private static IIOMetadata createMetadata(ImageWriter writer, ImageWriteParam writerParams, int resolution) throws IIOInvalidTreeException {
// Get default metadata from writer
ImageTypeSpecifier type = writerParams.getDestinationType();
IIOMetadata meta = writer.getDefaultImageMetadata(type, writerParams);
// Convert default metadata to TIFF metadata
TIFFDirectory dir = TIFFDirectory.createFromMetadata(meta);
// Get {X,Y} resolution tags
BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();
TIFFTag tagXRes = base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION);
TIFFTag tagYRes = base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION);
// Create {X,Y} resolution fields
TIFFField fieldXRes = new TIFFField(tagXRes, TIFFTag.TIFF_RATIONAL, 1, new long[][]{{resolution, 1}});
TIFFField fieldYRes = new TIFFField(tagYRes, TIFFTag.TIFF_RATIONAL, 1, new long[][]{{resolution, 1}});
// Add {X,Y} resolution fields to TIFFDirectory
dir.addTIFFField(fieldXRes);
dir.addTIFFField(fieldYRes);
//下面这行代码我是需要将tif图片像素单位改为厘米RESOLUTION_UNIT_CENTIMETER,也可以根据自己需要改为英寸
dir.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER));
// Return TIFF metadata so it can be picked up by the IIOImage
return dir.getAsMetadata();
}
private static BufferedImage convertToBinaryImage(BufferedImage image) {
BufferedImage binaryImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = binaryImage.createGraphics();
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return binaryImage;
}
}
点击查看代码
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/fontbox -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-core</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
浙公网安备 33010602011771号