SoFunction
Updated on 2025-03-03

How to achieve PDF to high-quality pictures through Java

In Java, converting PDF files to high-quality images can use different libraries, one of the most commonly used libraries isApache PDFBox. Through this library, you can read PDF files and convert each page into an image file. To improve the quality of the image, you can specify parameters such as resolution. In addition, it can also be combinedJava ImageIOto save the generated image file.

How to implement it

Below, Brother V uses a detailed case to show how to use itPDFBoxImplement PDF to high-quality pictures:

Dependency required

First, make sure you have added it to the projectPDFBoxrely. You can add it via Maven:

<dependency>
    <groupId></groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.29</version> <!-- Make sure to use the latest version -->
</dependency>

Implementation steps

Let’s look at the implementation steps first.

  • Load PDF files
  • Set rendering parameters (such as DPI to control image resolution)
  • Render each page PDF as an image
  • Save the picture

Through the above 1, 2, 3, and 4 steps, let’s implement the code in detail:

import ;
import ;

import ;
import ;
import ;
import ;

public class VGPdfToImage {

    public static void main(String[] args) {
        // PDF file path        String pdfFilePath = "path/to/your/pdf/vg_doc.pdf";
        // Output picture folder path        String outputDir = "path/to/output/images/";

        // Set DPI (the higher the picture is clearer, but the file will be larger)        int dpi = 300;

        try (PDDocument document = (new File(pdfFilePath))) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            
            // traverse each page of PDF and convert it into an image            for (int page = 0; page < (); ++page) {
                // Use BufferedImage to represent images                BufferedImage bim = (page, dpi);
                
                // Generate file name                String fileName = outputDir + "pdf_page_" + (page + 1) + ".png";
                
                // Save the image in PNG format                (bim, "png", new File(fileName));
                
                ("Saved page " + (page + 1) + " as image.");
            }
        } catch (IOException e) {
            ();
        }
    }
}

Let's explain

  • PDFRenderer: PDFBoxProvidedPDFRendererClasses are used to render PDF document pages as image objects (BufferedImage)。
  • renderImageWithDPI: This method can specify DPI (dots per inch), which directly affects the resolution of the image. Typically, 72 DPI is the default resolution for screen displays, while 300 DPI is considered the resolution for high-quality printing.
  • ImageIO: JavaImageIOUsed toBufferedImageSave it as common image formats such as PNG and JPEG.

Output effect

  • The PDF of each page will be rendered separately as a picture, and the quality of the picture will be higher through high DPI parameters.
  • The output file path isoutputDirThe specified path will be saved in PNG format. You can also change the save format to JPEG, etc.

Adjustable items are

  • DPI settings: If you want to output higher quality pictures, you can set DPI to 300 or higher. If fast rendering is required and the quality requirements are not high, you can set it to 72 DPI.
  • Image format: ()Different formats can be used, such as"jpg""png", adjust according to needs.

Note that you make sure your PDFBox library version is newer, such as series, to ensure that it supports more PDF features and fixes potential issues.

The above is a simple implementation process DEMO. In actual applications, there must be specific problems. When the problem comes, if you want to deal with a larger PDF file or a larger number of pages, you must consider performance issues. For these two issues, Brother V will optimize it.

Two possible performance optimization problems

  • Cache Policy: For larger PDF files, you can use certain cache strategies to optimize performance.
  • Parallel processing: If you need to process PDFs of many pages, you can process each page in parallel through multiple threads to improve speed.

Cache strategy optimization

When dealing with larger PDF files, we use caching strategies to significantly optimize performance, especially for situations where multiple pages are required or repeated renderings are required. For PDF rendering operations, the cache strategy is mainly to reduce repeated access to disk or memory, thereby speeding up reading and rendering and saving memory.

In Java, cache optimization can be achieved in the following ways:

  • Memory cache: Save processed pages in memory and get them directly from the cache when you need to access these pages repeatedly.
  • Disk Cache: If the memory is insufficient to cache all pages, you can cache the page rendering results or some intermediate data to disk.
  • Page-by-page processing: Only load and process certain pages when needed, rather than loading the entire PDF file at once.

A case of implementing memory caching

Using memory cache, we can useConcurrentHashMapTo implement it, store the rendered PDF page in memory to avoid repeated rendering.

Let’s take a look at a detailed implementation case using memory cache:

import ;
import ;

import ;
import ;
import ;
import ;
import ;

public class PdfToImageWithCache {

    // Used to cache rendered PDF pages (use ConcurrentHashMap to ensure thread safety)    private static final ConcurrentHashMap<Integer, BufferedImage> imageCache = new ConcurrentHashMap<>();
    private static final int dpi = 300; // High-quality DPI settings    
    public static void main(String[] args) {
        // PDF file path        String pdfFilePath = "path/to/your/large/pdf/ vg_doc.pdf";
        // Output picture folder path        String outputDir = "path/to/output/images/";

        try (PDDocument document = (new File(pdfFilePath))) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            
            // Get the total number of pages            int totalPages = ();
            ("Total pages: " + totalPages);
            
            // Render and cache every page            for (int page = 0; page < totalPages; ++page) {
                BufferedImage image = renderPageWithCache(pdfRenderer, page);
                
                // Save the picture                String fileName = outputDir + "pdf_page_" + (page + 1) + ".png";
                (image, "png", new File(fileName));
                
                ("Saved page " + (page + 1) + " as image.");
            }
        } catch (IOException e) {
            ();
        }
    }

    /**
      * Render PDF pages using cache
      * @param pdfRenderer PDFRenderer instance
      * @param page page number (starting from 0)
      * @return BufferedImage after cache or rendering
      */
    private static BufferedImage renderPageWithCache(PDFRenderer pdfRenderer, int page) throws IOException {
        // Check whether the cache already has the image of the page        if ((page)) {
            ("Page " + (page + 1) + " found in cache.");
            return (page);
        }

        // If the cache does not exist, render and store it in the cache        ("Rendering page " + (page + 1) + "...");
        BufferedImage image = (page, dpi);
        (page, image);
        return image;
    }
}

Explain the code

Memory cache (ConcurrentHashMap):

  • useConcurrentHashMap<Integer, BufferedImage>As a cache structure,IntegerRepresents the index of the page (starting from 0),BufferedImageRepresents the rendered image.
  • Before each rendering of the page, check whether the image of the page exists in the cache. If it already exists, it will directly return the cached image, otherwise it will be rendered and saved to the cache.

renderPageWithCachemethod:

  • This method first checks whether the page is in the cache, and if so, it is directly retrieved from the cache.
  • If the image of the page does not exist in the cache, render and save it to the cache.

DPI settings:

dpiThe parameter is set to 300 to ensure that the output image quality is high enough.

Rendering page by page:

useforLooping page by page to avoid loading all pages into memory at once. For rendering of images per page, if the page has been rendered, it will be retrieved directly from the cache.

What are the benefits of this optimization

Benefits of memory caching:

  • When you need to access or save certain pages multiple times, memory caches can avoid repeated renderings, thereby improving performance.
  • For larger PDF files, if you repeatedly operate the same page, the cache can significantly reduce processing time.

Concurrent support:

ConcurrentHashMapIt ensures the security of cache operations in a multi-threaded environment and can be used safely in multi-threaded.

Control memory usage:

If memory usage is too large, you can clean the cache periodically according to the situation, or limit the maximum number of saves in the cache, using a similar LRU (latestly used) strategy to clear the old cache.

A case for implementing disk caching

Next, let’s see how to implement it using disk cache. If the PDF file is large and the memory cannot save all page images, my god, what should I do? That is, you can use disk cache to temporarily save the rendering results to disk.

Let’s take a look at the following disk cache strategy implementation, save the rendered image as a temporary file, and load it from disk if needed:

import ;
import ;

import ;
import ;
import ;
import ;

public class PdfToImageWithDiskCache {

    private static final int dpi = 300; // High-quality DPI settings    private static final String cacheDir = "path/to/cache/";

    public static void main(String[] args) {
        // PDF file path        String pdfFilePath = "path/to/your/large/pdf/vg_doc.pdf";
        // Output picture folder path        String outputDir = "path/to/output/images/";

        try (PDDocument document = (new File(pdfFilePath))) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            int totalPages = ();

            for (int page = 0; page &lt; totalPages; ++page) {
                BufferedImage image = renderPageWithDiskCache(pdfRenderer, page);

                // Save the picture                String fileName = outputDir + "pdf_page_" + (page + 1) + ".png";
                (image, "png", new File(fileName));
                ("Saved page " + (page + 1) + " as image.");
            }
        } catch (IOException e) {
            ();
        }
    }

    /**
      * Render PDF pages using disk cache
      * @param pdfRenderer PDFRenderer instance
      * @param page page number (starting from 0)
      * @return BufferedImage after cache or rendering
      */
    private static BufferedImage renderPageWithDiskCache(PDFRenderer pdfRenderer, int page) throws IOException {
        //Disk cache file path        File cachedFile = new File(cacheDir + "page_" + page + ".png");

        // If the cache file already exists, load from disk        if (()) {
            ("Loading page " + (page + 1) + " from disk cache.");
            return (cachedFile);
        }

        // If the cache file does not exist, render and save to disk        ("Rendering page " + (page + 1) + "...");
        BufferedImage image = (page, dpi);
        (image, "png", cachedFile);
        return image;
    }
}

Code explanation

  • Cache to disk: pass()Save the rendered image to disk and read directly from disk if the page already has a cache file.
  • Cache file path: Each page has a corresponding cache file name to avoid repeated rendering and saving.
  • Suitable for insufficient memory: When memory is insufficient, the memory burden can be reduced through disk cache while still retaining better access speed.

With such an optimization strategy, we can significantly improve performance and reduce resource consumption when processing larger PDF files.

Parallel processing optimization

Next, let’s look at the second question: When processing PDF files on many pages, processing each page in parallel through multi-threading can significantly improve the processing speed, especially when the rendering operation per page takes a long time. Java provides a multi-threading mechanism, so we use itExecutorServiceMultithreaded tasks can be easily managed and executed.

Let’s take a look at how to implement it. Use multi-threading to process each page of a PDF file in parallel and convert it into a high-quality picture.

There are three main steps

  • Use ExecutorService to create a thread pool.
  • Each thread processes a page of PDF independently and renders it as an image.
  • After the thread task is executed, the thread pool is closed uniformly.

Specific code implementation

import ;
import ;

import ;
import ;
import ;
import ;
import ;
import ;
import ;

public class PdfToImageWithMultithreading {

    // Set DPI for high-quality rendering    private static final int dpi = 300;

    public static void main(String[] args) {
        // PDF file path        String pdfFilePath = "path/to/your/large/pdf/vg_doc.pdf";
        // Output picture folder path        String outputDir = "path/to/output/images/";

        // Thread pool size (can be adjusted according to the number of CPU cores or the number of tasks that need to be parallel)        int numThreads = ().availableProcessors();
        ExecutorService executorService = (numThreads);

        try (PDDocument document = (new File(pdfFilePath))) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            int totalPages = ();
            ("Total pages: " + totalPages);

            // Create a parallel processing task for each page            for (int page = 0; page &lt; totalPages; page++) {
                final int currentPage = page;  // You need to use final modification for use in multi-threading                (() -&gt; {
                    try {
                        renderAndSavePage(pdfRenderer, currentPage, outputDir);
                    } catch (IOException e) {
                        ();
                    }
                });
            }
        } catch (IOException e) {
            ();
        } finally {
            // Close the thread pool            ();
            try {
                // Wait for all thread tasks to complete                if (!(60, )) {
                    ("Some tasks did not finish within the timeout.");
                }
            } catch (InterruptedException e) {
                ();
            }
        }
    }

    /**
      * Render PDF page and save as image
      * @param pdfRenderer PDFRenderer instance
      * @param page page number (starting from 0)
      * @param outputDir output directory
      * @throws IOException If an IO error occurs
      */
    private static void renderAndSavePage(PDFRenderer pdfRenderer, int page, String outputDir) throws IOException {
        // Rendering the page is a high-quality picture        BufferedImage image = (page, dpi);
        
        // Save the picture file        String fileName = outputDir + "pdf_page_" + (page + 1) + ".png";
        (image, "png", new File(fileName));
        ("Saved page " + (page + 1) + " as image.");
    }
}

Let's explain the code and ideas in detail

1. Use of thread pool

  • ExecutorService:We use(numThreads)to create a fixed-size thread pool wherenumThreadsis the number of threads. pass().availableProcessors()Get the number of CPU cores as the basis for the thread pool size, usually this value is the number of processor cores.
  • submit(): Submit the task to the thread pool,submit()The method will return immediately and will not block the main thread, allowing multiple pages to be processed simultaneously.

2. Task assignment

  • The rendering task for each page is assigned to a thread, through()Submit rendering task. Each task will be calledrenderAndSavePage()Method, handle rendering and saving of specific pages.

3. Rendering and saving

  • Used by each threadrenderAndSavePage()Method renders a PDF with a specified page number and saves the generated image as a PNG file. Used here()to save the rendering result.
  • The output file name is dynamically generated based on the page number.

4. Close the thread pool

  • shutdown(): The main thread calls after submitting all tasksshutdown()Method, notify the thread pool to stop receiving new tasks.
  • awaitTermination(): The main thread waits for all thread tasks to complete. A longer timeout time (60 minutes) is set here. You need to adjust it according to the actual situation to ensure that all pages can be processed.

Let's summarize

By multithreading each page of a PDF, processing time can be significantly shortened, especially when processing PDFs with large files or large pages. Tasks in thread pools can run on multiple CPU cores at the same time, maximizing the utilization of hardware resources. For super large PDF files or when you need to process a large number of PDFs, you have to process them in a distributed way. Each node processes a part of the page to solve them. I won't go into details here.

This is the article about how to achieve PDF to high-quality pictures through Java. For more related Java PDF to image content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!