目录
maven依赖,这里使用的是pdfbox的2.0.30版本
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.30</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.30</version>
</dependency>
一、内容没有图片
如果内容没有图片,可以直接将纸张改为A4大小
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
public class AdjustPdfPageWidthToA4 {
public static void main(String[] args) {
// 输入的PDF文件路径
String inputFilePath = "input.pdf";
// 输出的PDF文件路径
String outputFilePath = "output.pdf";
try {
// 加载PDF文件
PDDocument document = PDDocument.load(new File(inputFilePath));
// 遍历每一页
for (PDPage page : document.getPages()) {
// 将页面宽度调整为A4尺寸
page.setMediaBox(PDRectangle.A4);
}
// 保存修改后的PDF文件
document.save(outputFilePath);
document.close();
System.out.println("PDF页面宽度已调整为A4尺寸,并保存为新的PDF文件。");
} catch (IOException e) {
e.printStackTrace();
}
}
}
但是如果有图片的话,会出现图片被截断,显示不全的情况出现,所以我们需要对图片元素按比例缩放
二、内容有图片
首先要对页面内容进行判断,如果页面是图片的话,对图片进行比例缩放,比如A4,就缩放到可以放进A4
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.text.PDFTextStripper;
import javax.imageio.ImageIO;
/**
* @author zjy
* @describe 调整PDF每页为A4格式
*/
public class AdjustPdfPageWidthToA4Util {
static String inputFilePath = "C:\\xxx\\xxx\\xx.pdf";
// 输出的PDF文件路径
static String outputFilePath = "D:\\result.pdf";
public static void main(String[] args) {
try {
// 加载PDF文件
PDDocument document = PDDocument.load(new File(inputFilePath));
// 遍历每一页
int totalPages = document.getNumberOfPages();
for (int i = 0; i < totalPages; i++) {
// 获取当前Page页面
PDPage page = document.getPage(i);
// 获取对应页面的资源对象
PDResources resources = page.getResources();
// 遍历当前页面所有内容,找出图片对象
for (COSName cosName : resources.getXObjectNames()) {
PDXObject pdxObject = resources.getXObject(cosName);
// 判断是不是图片对象
if (pdxObject instanceof PDImageXObject) {
// 获取图片对象
PDImageXObject pdxObject1 = (PDImageXObject) pdxObject;
BufferedImage image = pdxObject1.getImage();
// 4、创建页面内容流,指定操作哪个文档中的哪个页面
PDPageContentStream stream = new PDPageContentStream(document, page);
float[] imageWH = getImageWH(image, PDRectangle.A4);
stream.drawImage(pdxObject1, imageWH[0], imageWH[1], imageWH[2], imageWH[3]); // 绘制图片到PDF页面里面
stream.close(); // 关闭页面内容流
page.setMediaBox(PDRectangle.A4);
} else {
page.setMediaBox(PDRectangle.A4);
}
}
}
// 保存修改后的PDF文件
document.save(outputFilePath);
document.close();
System.out.println("PDF页面宽度已调整为A4尺寸,并保存为新的PDF文件。");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取图片的宽度、高度,单位是【pt】
*
* @param box PDF文档页面矩形区域对象,可以获取到矩形区域的宽高
* @return 返回缩放之后的图片宽高
*/
public static float[] getImageWH(BufferedImage img, PDRectangle box) {
try {
// px 转换成 pt 单位
float xAxis;
float yAxis;
int w = img.getWidth();
int h = img.getHeight();
float width = (float) (w * 3.0 / 4); // 这里是因为 1pt = 3/4 px,pt和px单位转换
float height = (float) (h * 3.0 / 4);
float pw = box.getWidth() - 60; // 设置图片与文档边缘的空白间距
float ph = box.getHeight() - 60; // 设置图片与文档边缘的空白间距
if (width > pw) {
float scale = pw / width; // 缩放比列
width = pw; // 宽度等于页面宽度
height = height * scale; // 高度自动缩放
} else {
float scale = ph / height; // 缩放比列
height = ph; // 高度等于页面高度
width = width * scale; // 宽度自动缩放
}
// 计算图片在X、Y轴上的显示位置
xAxis = (box.getWidth() - width) / 2; // X轴居中对齐
// yAxis = box.getHeight() - height - 10; // 距离页面顶部10个pt
yAxis = (box.getHeight() - height) / 2; // Y轴垂直居中对齐
return new float[]{xAxis, yAxis, width, height};
} catch (Exception e) {
e.printStackTrace();
}
return new float[]{0, 0, 0, 0};
}
}
运行完如下图所示,图片缩小至能放入A4,放在正中间
三、改进
上面的代码是将图片等比例缩小到A4能够放得下,也就是上下或者左右可能有很大的空白,图片比较小,难以看清,因此改进
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.text.PDFTextStripper;
import javax.imageio.ImageIO;
/**
* @author zjy
* @describe 调整PDF每页为A4格式
*/
public class AdjustPdfPageWidthToA4Util {
static String inputFilePath = "C:\\xxx\\xxx\\xx.pdf";
// 输出的PDF文件路径
static String outputFilePath = "D:\\result.pdf";
public static void main(String[] args) {
try {
// 加载PDF文件
PDDocument document = PDDocument.load(new File(inputFilePath));
// 遍历每一页
int totalPages = document.getNumberOfPages();
for (int i = 0; i < totalPages; i++) {
// 获取当前Page页面
PDPage page = document.getPage(i);
// 获取对应页面的资源对象
PDResources resources = page.getResources();
// 遍历当前页面所有内容,找出图片对象
for (COSName cosName : resources.getXObjectNames()) {
PDXObject pdxObject = resources.getXObject(cosName);
// 判断是不是图片对象
if (pdxObject instanceof PDImageXObject) {
// 获取图片对象
PDImageXObject pdxObject1 = (PDImageXObject) pdxObject;
BufferedImage image = pdxObject1.getImage();
// 4、创建页面内容流,指定操作哪个文档中的哪个页面
PDPageContentStream stream = new PDPageContentStream(document, page);
float[] imageWH = getImageWH(image, PDRectangle.A4);
stream.drawImage(pdxObject1, 0, 0, imageWH[0], imageWH[1]); // 绘制图片到PDF页面里面
stream.close(); // 关闭页面内容流
// page.setMediaBox(PDRectangle.A4);
page.setMediaBox(new PDRectangle(imageWH[0], imageWH[1]));
} else {
page.setMediaBox(PDRectangle.A4);
}
}
}
// 保存修改后的PDF文件
document.save(outputFilePath);
document.close();
System.out.println("PDF页面宽度已调整为A4尺寸,并保存为新的PDF文件。");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取图片的宽度、高度,单位是【pt】
*
* @param box PDF文档页面矩形区域对象,可以获取到矩形区域的宽高
* @return 返回缩放之后的图片宽高
*/
public static float[] getImageWH(BufferedImage img, PDRectangle box) {
try {
// px 转换成 pt 单位
float xAxis;
float yAxis;
int w = img.getWidth();
int h = img.getHeight();
float width = (float) (w * 3.0 / 4); // 这里是因为 1pt = 3/4 px,pt和px单位转换
float height = (float) (h * 3.0 / 4);
float pw = box.getWidth() ;
float ph = box.getHeight() ;
if (width > pw) {
float scale = pw / width; // 缩放比列
width = pw; // 宽度等于页面宽度
height = height * scale; // 高度自动缩放
} else {
float scale = ph / height; // 缩放比列
height = ph; // 高度等于页面高度
width = width * scale; // 宽度自动缩放
}
// 计算图片在X、Y轴上的显示位置
return new float[]{width, height};
} catch (Exception e) {
e.printStackTrace();
}
return new float[]{0, 0};
}
}
这样子图片的宽度是A4的,长度就是原图片的长度了
四、内容有多张图片
上面的代码如果遇到一页pdf内有多张图片,或者一页pdf内同时有文本和图片,会出现错误。这里有两种解决方法:
第一种是使用pdfbox直接将每页pdf转为图片,然后将图片按比例去缩小(pdfbox对于文本好像没发缩,也可能是我太菜了)
第二种是使用itText将pdf的内容按比例去缩(itText比pdfbox更好用,就是不能用于商业用途,要收钱)
(一)pdfBox
maven依赖,这里使用的是pdfbox的2.0.30版本
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.30</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.30</version>
</dependency>
代码如下:
/**
* @author zjy
* @describe 使用PDFBox,暴力,直接将每一页转化为图片,然后调整PDF每页为A4格式
*
*/
public class AdjustPdfPageWidthToA4Util {
static String inputFilePath = "D:\\test\\test.pdf";
// 输出的PDF文件路径
static String outputFilePath = "D:\\test\\adjusted2.pdf";
public static void main(String[] args) throws Exception {
try {
// 加载PDF文件
PDDocument document = PDDocument.load(new File(inputFilePath));
PDFRenderer renderer = new PDFRenderer(document);
// 遍历每一页
int totalPages = document.getNumberOfPages();
for (int i = 0; i < totalPages; i++) {
// 获取当前Page页面
PDPage page = document.getPage(i);
PDFTextStripper stripper = new PDFTextStripper();
stripper.setStartPage(i + 1);
stripper.setEndPage(i + 1);
String pageText = stripper.getText(document);
if (pageText.trim().isEmpty()) { // 内容无文本,是图片对象
// 获取对应页面的资源对象
PDResources resources = page.getResources();
// 遍历当前页面所有内容,找出图片对象
for (COSName cosName : resources.getXObjectNames()) {
PDXObject pdxObject = resources.getXObject(cosName);
// 判断是不是图片对象
if (pdxObject instanceof PDImageXObject) {
// 获取图片对象
PDImageXObject pdxObject1 = (PDImageXObject) pdxObject;
BufferedImage image = pdxObject1.getImage();
// 4、创建页面内容流,指定操作哪个文档中的哪个页面
PDPageContentStream stream = new PDPageContentStream(document, page);
float[] imageWH = getImageWH(image, PDRectangle.A4);
stream.drawImage(pdxObject1, 0, 0, imageWH[0], imageWH[1]); // 绘制图片到PDF页面里面
stream.close(); // 关闭页面内容流
page.setMediaBox(new PDRectangle(imageWH[0], imageWH[1]));
}
}
} else {
// 将本页转化为图片
int dpi = 300;
BufferedImage image = renderer.renderImageWithDPI(i, 300);
PDImageXObject pdImage = LosslessFactory.createFromImage(document, image);
float[] imageWH = getImageWH(image, PDRectangle.A4);
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.drawImage(pdImage, 0, 0, imageWH[0], imageWH[1]); // 绘制图片到PDF页面里面
contentStream.close(); // 关闭页面内容流
page.setMediaBox(new PDRectangle(imageWH[0], imageWH[1]));
// 这个是将image保存到本地
// ImageIOUtil.writeImage(image, "d:/test/" + i + ".png", dpi);
}
}
// 保存修改后的PDF文件
document.save(outputFilePath);
document.close();
System.out.println("PDF页面宽度已调整为A4尺寸,并保存为新的PDF文件。");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取图片的宽度、高度,单位是【pt】
*
* @param box PDF文档页面矩形区域对象,可以获取到矩形区域的宽高
* @return 返回缩放之后的图片宽高
*/
public static float[] getImageWH(BufferedImage img, PDRectangle box) {
try {
// px 转换成 pt 单位
int w = img.getWidth();
int h = img.getHeight();
float width = (float) (w * 3.0 / 4); // 这里是因为 1pt = 3/4 px,pt和px单位转换
float height = (float) (h * 3.0 / 4);
float pw = box.getWidth();
float ph = box.getHeight();
if (width > pw) {
float scale = pw / width; // 缩放比列
width = pw; // 宽度等于页面宽度
height = height * scale; // 高度自动缩放
} else {
float scale = ph / height; // 缩放比列
height = ph; // 高度等于页面高度
width = width * scale; // 宽度自动缩放
}
// 计算图片在X、Y轴上的显示位置
return new float[]{width, height};
} catch (Exception e) {
e.printStackTrace();
}
return new float[]{0, 0};
}
}
(二)itText
maven依赖,这里使用的是7.2.5版本
<!-- https://mvnrepository.com/artifact/com.itextpdf/kernel -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>7.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/layout -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>7.2.5</version>
</dependency>
代码如下:
import com.itextpdf.kernel.geom.AffineTransform;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Document;
import java.io.IOException;
/**
* @author zjy
* @describe 使用itText, 然后调整PDF每页为A4格式
*
*/
public class PdfPageSizeAdjuster {
static String inputFilePath = "D:\\test\\test.pdf";
// 输出的PDF文件路径
static String outputFilePath = "D:\\test\\adjusted3.pdf";
public static void main(String[] args) throws IOException {
PdfWriter writer = new PdfWriter(outputFilePath);
// Creating a PdfReader
PdfReader reader = new PdfReader(inputFilePath);
// Creating a PdfDocument objects
PdfDocument destpdf = new PdfDocument(writer);
PdfDocument srcPdf = new PdfDocument(reader);
for(int i = 1; i <= srcPdf.getNumberOfPages(); i ++) {
// Opening a page from the existing PDF
PdfPage origPage = srcPdf.getPage(i);
// Getting the page size
Rectangle orig = origPage.getPageSizeWithRotation();
float bili = PageSize.A4.getWidth() / orig.getWidth();
// Adding a page to destination Pdf
PdfPage page = destpdf.addNewPage(new PageSize(PageSize.A4.getWidth(), bili * orig.getHeight()));
// Scaling the image in a Pdf page
AffineTransform transformationMatrix = AffineTransform.getScaleInstance(
page.getPageSize().getWidth()/orig.getWidth(),
page.getPageSize().getHeight()/ orig.getHeight());
// Shrink original page content using transformation matrix
PdfCanvas canvas = new PdfCanvas(page);
canvas.concatMatrix(transformationMatrix);
// Add the object to the canvas
PdfFormXObject pageCopy = origPage.copyAsFormXObject(destpdf);
canvas.addXObject(pageCopy, 0, 0);
}
// Creating a Document object
Document doc = new Document(destpdf);
// Closing the document
doc.close();
System.out.println("Table created successfully..");
}
}