[itext7] Use itext7 to merge multiple PDF files and pictures into one PDF file, rotate and zoom the pictures

This article mainly introduces the use of itext7 to merge multiple PDF files and pictures into one PDF file, image rotation and image scaling.

Table of Contents

1. itext7 merge PDF

1.1. Introducing dependencies

1.2. Introduction to merging PDFs

1.3. Read PDF files using byte array method

1.4. Merge multiple PDF files

1.5. Merge images into PDF files

1.6. Rotate pictures

1.7. Complete case code

(1) PDFUtil tool class

(2) Test code

(3) Merger effect


1. itext7 merge PDF

1.1, introduce dependencies

I am using itext-core version 7.1.16 here. I only need to introduce an itext-core dependency, because this dependency has already introduced the dependencies required by itext for us.

<!--Introduce itext7-core dependency -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.1.16</version>
    <type>pom</type>
</dependency>

1.2. Introduction to merging PDFs

The simplest way to merge is to read two PDF files and then merge them into a new PDF file. After saving it to the server, merge this new PDF file with the next PDF file to be merged. By analogy, you can finally get a complete PDF file. However, the disadvantage of this method is that after each merge, a new PDF file needs to be generated, and after the next merge, the PDF file must be read again. This is It will lead to the process of reading the file multiple times, and the efficiency is not very ideal.

In this article, I mainly read the PDF into the memory as a byte array, and then merge the byte data of the two PDFs in the memory. This can reduce the number of times of reading and generating PDF files, and the execution efficiency will also be improved. Even better, the method of merging two PDF byte arrays is as follows:

/**
 * Merge PDF documents based on byte array in memory
 * @param firstPdf The first PDF document
 * @param secondPdf The second PDF document
 */
private static byte[] mergePdfBytes(byte[] firstPdf, byte[] secondPdf) throws IOException {
    if (firstPdf != null & amp; & amp; secondPdf != null) {
        // Create byte array and merge based on memory
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfDocument destDoc = new PdfDocument(new PdfWriter(baos));
        //Merge pdf file object
        PdfDocument firstDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(firstPdf)));
        PdfDocument secondDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(secondPdf)));
        // merge objects
        PdfMerger merger = new PdfMerger(destDoc);
        merger.merge(firstDoc, 1, firstDoc.getNumberOfPages());
        merger.merge(secondDoc, 1, secondDoc.getNumberOfPages());
        // Close the document stream
        merger.close();
        firstDoc.close();
        secondDoc.close();
        destDoc.close();
        return baos.toByteArray();
    }
    return null;
}

1.3. Read PDF files using byte array method

When merging PDF files, some PDF files may be on the network, and some may be on the local disk, so you need to make a judgment here. If they are PDF files on the network, you need to access the network first, and then save them to the PDF file. In the section array, if it is a local disk file, you need to read the local file.

/**
 * Convert pdf document into byte array
 * @param pdf PDF document path
 * @return Returns the byte array corresponding to the PDF document
 */
private static byte[] getPdfBytes(String pdf) throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    InputStream is;
    if (pdf.startsWith("http://") || pdf.startsWith("https://")) {
        is = new URL(pdf).openStream();
    } else {
        is = new FileInputStream(pdf);
    }
    byte[] data = new byte[2048];
    int len;
    while ((len = is.read(data)) != -1) {
        out.write(data, 0, len);
    }
    return out.toByteArray();
}

1.4. Merge multiple PDF files

When merging PDFs, just pass the path of the PDF files that need to be merged. Call the following method to complete the merge.

/**
 * Merge the PDF documents in the given List collection in order to generate the final target PDF document
 * @param pdfPathLists A collection of PDF document paths to be merged, which can be local PDF documents or PDF documents on the network.
 * @param destPath The PDF document path generated by the target merge
 */
public static boolean mergeMultiplePdfs(List<String> pdfPathLists, String destPath) {
    try {
        int size = pdfPathLists.size();
        byte[] pdfData = getPdfBytes(pdfPathLists.get(0));
        for (int i = 1; i < size; i + + ) {
            pdfData = mergePdfBytes(pdfData, getPdfBytes(pdfPathLists.get(i)));
        }
        if (pdfData != null) {
            FileOutputStream fis = new FileOutputStream(destPath);
            fis.write(pdfData);
            fis.close();
        }
        return true;
    } catch (Exception e) {
        logger.error("Exception when merging PDF:", e);
    }
    return false;
}

1.5, merge pictures into PDF files

How to merge pictures into PDF files? ? ? Here I added the picture directly to the blank page of the PDF file. One picture occupies one page. Of course, you can also set it to be displayed on the same page. After the page height is exceeded, the picture will automatically be displayed on the next page.

/**
 * Merge images in a given collection into a pdf document
 * @param imagePathList image path collection
 * @param destPath The merged PDF document
 */
public static boolean mergeImagesToPdf(List<String> imagePathList, String destPath) {
    try {
        PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destPath));
        Document document = new Document(pdfDocument);
        if (imagePathList != null & amp; & amp; imagePathList.size() > 0) {
            int size = imagePathList.size();
            for (int i = 0; i < size; i + + ) {
                String imgPath = imagePathList.get(i);
                ImageData imageData;
                if (imgPath.startsWith("http://") || imgPath.startsWith("https://")) {
                    imageData = ImageDataFactory.create(new URL(imgPath));
                } else {
                    imageData = ImageDataFactory.create(imgPath);
                }
                Image image = new Image(imageData);
                /*
                    Set the arc value of rotation. The default is counterclockwise rotation.
                    Radian and angle conversion formula:
                    1° = PI / 180°
                    1 rad = 180°/PI
                */
                image.setRotationAngle(- Math.PI / 2); // Rotate 90° clockwise
                //Set the image to automatically scale, that is: the image width and height are adaptive
                image.setAutoScale(true);
                document.add(image);
                if (i != size - 1) {
                    // There is no need to add a blank page to the last page
                    document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
                }
            }
        }
        pdfDocument.close();
        return true;
    } catch (Exception e) {
        logger.error("Exception when merging pictures into PDF:", e);
    }
    return false;
}

1.6, rotate image

Under certain requirements, you may want to place certain pictures vertically and some pictures horizontally. At this time, you can call the [setRotationAngle()] method of the [Image] picture object in itext7 to rotate it. , it should be noted that: the setRotationAngle method sets the rotation arc, not the rotation angle, and it rotates counterclockwise. There is a conversion formula between radians and degrees as follows:

1.7, complete case code

(1)PDFUtil tool class

package com.gitcode.itext.util;

import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.utils.PdfMerger;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.property.AreaBreakType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URL;
import java.util.List;

/**
 * @version 1.0.0
 * @Date: 2023/10/04 10:07
 * @Author ZhuYouBin
 * @Description: PDF tool class [implemented based on itext7 component]
 */
public class PDFUtil {
    private static final Logger logger = LoggerFactory.getLogger(PDFUtil.class);

    /**
     * Merge the PDF documents in the given List collection in order to generate the final target PDF document
     * @param pdfPathLists A collection of PDF document paths to be merged, which can be local PDF documents or PDF documents on the network.
     * @param destPath The PDF document path generated by the target merge
     */
    public static boolean mergeMultiplePdfs(List<String> pdfPathLists, String destPath) {
        try {
            int size = pdfPathLists.size();
            byte[] pdfData = getPdfBytes(pdfPathLists.get(0));
            for (int i = 1; i < size; i + + ) {
                pdfData = mergePdfBytes(pdfData, getPdfBytes(pdfPathLists.get(i)));
            }
            if (pdfData != null) {
                FileOutputStream fis = new FileOutputStream(destPath);
                fis.write(pdfData);
                fis.close();
            }
            return true;
        } catch (Exception e) {
            logger.error("Exception when merging PDF:", e);
        }
        return false;
    }

    /**
     * Merge images in a given collection into a pdf document
     * @param imagePathList image path collection
     * @param destPath The merged PDF document
     */
    public static boolean mergeImagesToPdf(List<String> imagePathList, String destPath) {
        try {
            PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destPath));
            Document document = new Document(pdfDocument);
            if (imagePathList != null & amp; & amp; imagePathList.size() > 0) {
                int size = imagePathList.size();
                for (int i = 0; i < size; i + + ) {
                    String imgPath = imagePathList.get(i);
                    ImageData imageData;
                    if (imgPath.startsWith("http://") || imgPath.startsWith("https://")) {
                        imageData = ImageDataFactory.create(new URL(imgPath));
                    } else {
                        imageData = ImageDataFactory.create(imgPath);
                    }
                    Image image = new Image(imageData);
                    /*
                        Set the arc value of rotation. The default is counterclockwise rotation.
                        Radian and angle conversion formula:
                        1° = PI / 180°
                        1 rad = 180°/PI
                    */
                    image.setRotationAngle(- Math.PI / 2); // Rotate 90° clockwise
                    //Set the image to automatically scale, that is: the image width and height are adaptive
                    image.setAutoScale(true);
                    document.add(image);
                    if (i != size - 1) {
                        // There is no need to add a blank page to the last page
                        document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
                    }
                }
            }
            pdfDocument.close();
            return true;
        } catch (Exception e) {
            logger.error("Exception when merging pictures into PDF:", e);
        }
        return false;
    }

    /**
     * Merge PDF documents based on byte array in memory
     * @param firstPdf The first PDF document
     * @param secondPdf The second PDF document
     */
    private static byte[] mergePdfBytes(byte[] firstPdf, byte[] secondPdf) throws IOException {
        if (firstPdf != null & amp; & amp; secondPdf != null) {
            // Create byte array and merge based on memory
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfDocument destDoc = new PdfDocument(new PdfWriter(baos));
            //Merge pdf file object
            PdfDocument firstDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(firstPdf)));
            PdfDocument secondDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(secondPdf)));
            // merge objects
            PdfMerger merger = new PdfMerger(destDoc);
            merger.merge(firstDoc, 1, firstDoc.getNumberOfPages());
            merger.merge(secondDoc, 1, secondDoc.getNumberOfPages());
            // Close the document stream
            merger.close();
            firstDoc.close();
            secondDoc.close();
            destDoc.close();
            return baos.toByteArray();
        }
        return null;
    }

    /**
     * Convert pdf document into byte array
     * @param pdf PDF document path
     * @return Returns the byte array corresponding to the PDF document
     */
    private static byte[] getPdfBytes(String pdf) throws Exception {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        InputStream is;
        if (pdf.startsWith("http://") || pdf.startsWith("https://")) {
            is = new URL(pdf).openStream();
        } else {
            is = new FileInputStream(pdf);
        }
        byte[] data = new byte[2048];
        int len;
        while ((len = is.read(data)) != -1) {
            out.write(data, 0, len);
        }
        return out.toByteArray();
    }
}

(2) Test code

package com.gitcode.itext;

import com.gitcode.itext.util.PDFUtil;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

/**
 * @version 1.0.0
 * @Date: 2023/10/4 11:12
 * @Author ZhuYouBin
 * @Description:
 */
public class ImageDemo {
    public static void main(String[] args) throws FileNotFoundException {
        //The PDF path generated after merging images
        String imagePath = "F:\pdf-demo\imagePath.pdf";
        List<String> imageList = new ArrayList<>();
        imageList.add("F:\pdf-demo\01.jpg");
        imageList.add("F:\pdf-demo\02.jpg");
        // Merge images first
        PDFUtil.mergeImagesToPdf(imageList, imagePath);

        // Merging PDF
        String destPath = "F:\pdf-demo\merge.pdf";
        List<String> pdfPath = new ArrayList<>();
        pdfPath.add("F:\pdf-demo\demo01.pdf");
        pdfPath.add("F:\pdf-demo\demo02.pdf");
        pdfPath.add(imagePath);
        PDFUtil.mergeMultiplePdfs(pdfPath, destPath);
    }
}

(3) Merge effect

At this point, the introduction to itext7 merging PDF files is complete.

In summary, this article is over. It mainly introduces the use of itext7 to merge multiple PDF files and pictures into one PDF file, image rotation, and image scaling.