使用PDFBox/itText调整PDF每页格式

目录

一、内容没有图片

二、内容有图片

三、改进

四、内容有多张图片

(一)pdfBox

(二)itText


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的,长度就是原图片的长度了

以上内容参考以下博客【PDFBox】PDFBox操作PDF文档之添加本地图片、添加网络图片、图片宽高自适应、图片水平垂直居中对齐-支持Android_pdfbox缩放比例-CSDN博客文章浏览阅读322次,点赞2次,收藏3次。PDImageXObject类中提个了一些静态方法createFromFile(imagePath,doc)方法:采用File文件的方式读取本地磁盘中的图片。imagePath参数:图片的路径。doc参数:PDF文档对象。getImage()方法:返回BufferedImage图片对象。getSuffix()方法:返回图片的后缀类型,例如:jpg、png等。_pdfbox缩放比例https://blog.csdn.net/qq_27489007/article/details/134451128

四、内容有多张图片

上面的代码如果遇到一页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..");
    }

}

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
你可以使用 Apache PDFBox 库将 HTML 转换为 PDF。下面是一个使用 PDFBox 的示例代码: ```java import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageTree; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.common.PDStream; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.tools.imageio.ImageIOUtil; public class HTMLtoPDFConverter { public static void main(String[] args) { String htmlFilePath = "path/to/input.html"; String pdfFilePath = "path/to/output.pdf"; // Load HTML file File htmlFile = new File(htmlFilePath); try { // Create a new PDF document PDDocument document = new PDDocument(); PDPage page = new PDPage(PDRectangle.A4); document.addPage(page); // Create a PDPageContentStream object PDPageContentStream contentStream = new PDPageContentStream(document, page); // Load the HTML file into a PDStream FileInputStream inputStream = new FileInputStream(htmlFile); PDStream pdStream = new PDStream(document, inputStream); // Set the media box of the page PDRectangle mediaBox = page.getMediaBox(); contentStream.addRect(mediaBox.getLowerLeftX(), mediaBox.getLowerLeftY(), mediaBox.getWidth(), mediaBox.getHeight()); contentStream.clip(); // Create a PDF renderer PDFRenderer renderer = new PDFRenderer(document); renderer.setDocument(document); // Render the HTML file to PDF renderer.renderPageToStream(renderer.getCurrentPageNo(), pdStream); // Close the content stream and the document contentStream.close(); document.save(new FileOutputStream(pdfFilePath)); document.close(); System.out.println("HTML converted to PDF successfully."); } catch (IOException e) { e.printStackTrace(); } } } ``` 请确保将 `path/to/input.html` 替换为要转换的 HTML 文件的路径,将 `path/to/output.pdf` 替换为保存生成的 PDF 文件的路径。运行此代码将生成一个包含 HTML 内容的 PDF 文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zoeil

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值