Java에서 PDF 이미지 변환 및 표시 방법

문제점

웹 프로젝트에서 PDF 문서를 표시해야 할 때가 있습니다. 하지만 브라우저에 PDF 플러그인을 직접 추가하는 경우, 호환성 문제가 발생하여 특정 브라우저에서 제대로 표시되지 않는 문제가 있습니다. 이럴 때 PDF를 이미지로 변환하여 표시하면 훨씬 더 안정적인 결과를 얻을 수 있습니다.

PDF를 이미지로 변환하는 방법은 주로 두 가지가 있습니다:

제품 특징
Apache PDFBox 무료; 속도는 다소 느리지만 사용 가능한 수준
E-iceblue Spire.PDF for Java 변환 품질 우수; 빠른 속도; 다양한 형식 지원; 유료

참고: Spire.PDF for Java는 변환 품질이 우수하지만, 라이선스를 구매하지 않으면 변환된 이미지에 워터마크가 추가됩니다.

PDFBox 사용 방법

의존성 추가

<dependency>
	<groupId>org.apache.pdfbox</groupId>
	<artifactId>pdfbox</artifactId>
	<version>2.0.24</version>
</dependency>
<dependency>
	<groupId>org.apache.pdfbox</groupId>
	<artifactId>pdfbox-tools</artifactId>
	<version>2.0.24</version>
</dependency>

다중 페이지 PDF를 여러 이미지로 변환

다음은 PdfUtil 도구 클래스를 생성하여 PDF를 이미지로 변환하는 예제입니다:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class PdfConverter {

    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PdfConverter.class);

    /**
     * PDF 파일을 PNG 이미지로 변환 (모든 페이지)
     *
     * @param pdfFilePath PDF 파일의 전체 경로
     * @param dpi DPI가 높을수록 변환된 이미지가 더 선명하지만 변환 속도는 느려집니다
     */
    public static void convertPdfToImages(String pdfFilePath, int dpi) {
        File file = new File(pdfFilePath);
        try {
            String imgDirectory = file.getParent();
            int dotIndex = file.getName().lastIndexOf('.');
            // 이미지 파일명 생성
            String baseImageName = file.getName().substring(0, dotIndex);

            PDDocument document = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(document);
            
            // 총 페이지 수 확인
            int totalPages = document.getNumberOfPages();
            
            for (int i = 0; i < totalPages; i++) {
                String imagePath = imgDirectory + File.separator + baseImageName + 
                                  "_" + (i + 1) + ".png";
                
                File outputFile = new File(imagePath);
                BufferedImage image = renderer.renderImageWithDPI(i, dpi);
                ImageIO.write(image, "png", outputFile);
            }
            
            document.close();
            log.info("PDF 문서가 PNG 이미지로 성공적으로 변환되었습니다!");
        } catch (IOException e) {
            log.error("PDF 변환 중 오류 발생", e);
        }
    }
}

다중 페이지 PDF를 단일 이미지로 결합

다음은 여러 페이지 PDF를 단일 이미지로 결합하는 방법입니다:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class PdfConverter {

    public static final int DEFAULT_DPI = 150;

    /**
     * PDF를 이미지로 변환
     * 다중 페이지 PDF는 각 페이지를 별도 이미지로 변환 후 단일 이미지로 결합
     *
     * @param pdfFile PDF 파일 경로
     * @param outputImagePath 이미지 출력 경로
     * @param dpi 이미지 해상도에 해당하는 값, 값이 클수록 선명하지만 변환 시간이 증가
     */
    public static void convertPdfToSingleImage(String pdfFile, String outputImagePath, Integer dpi) {
        if (dpi == null) {
            // DPI가 설정되지 않은 경우 기값으로 150 설정
            dpi = DEFAULT_DPI;
        }
        
        try (PDDocument pdf = PDDocument.load(new FileInputStream(pdfFile))) {
            int pageCount = pdf.getNumberOfPages();
            List<BufferedImage> imageList = new ArrayList<>();
            
            // 각 페이지를 이미지로 변환
            for (int i = 0; i < pageCount; i++) {
                BufferedImage image = new PDFRenderer(pdf)
                    .renderImageWithDPI(i, dpi, ImageType.RGB);
                imageList.add(image);
            }
            
            // 이미지들을 하나로 결합
            ImageCombiner.combineImagesVertically(imageList, outputImagePath);
        } catch (IOException e) {
            log.error("PDF 변환 중 오류 발생", e);
        }
    }
}

ImageCombiner 클래스

이미지들을 결합하는 ImageCombiner 클래스입니다:

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class ImageCombiner {

    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ImageCombiner.class);

    /**
     * 너비가 동일한 이미지들을 세로로 결합합니다
     *
     * @param images 이미지 리스트
     * @param outputPath 출력 경로
     */
    public static void combineImagesVertically(List<BufferedImage> images, String outputPath) {
        if (images == null || images.isEmpty()) {
            log.info("이미지 리스트가 비어있습니다!");
            return;
        }
        
        try {
            int totalHeight = 0;
            int width = 0;
            int[] heights = new int[images.size()];
            
            // 총 너비와 높이 계산
            for (int i = 0; i < images.size(); i++) {
                BufferedImage img = images.get(i);
                heights[i] = img.getHeight();
                if (i == 0) {
                    width = img.getWidth();
                }
                totalHeight += heights[i];
            }
            
            // 새로운 이미지 생성
            BufferedImage resultImage = new BufferedImage(width, totalHeight, BufferedImage.TYPE_INT_RGB);
            int currentHeight = 0;
            
            // 각 이미지를 결과 이미지에 병합
            for (int i = 0; i < images.size(); i++) {
                BufferedImage img = images.get(i);
                int imgHeight = heights[i];
                
                // 이미지 데이터를 결과 이미지에 설정
                resultImage.setRGB(0, currentHeight, width, imgHeight, 
                                  img.getRGB(0, 0, width, imgHeight, null, 0, width), 0, width);
                
                currentHeight += imgHeight;
            }
            
            // 결과 이미지 파일로 저장
            File outputFile = new File(outputPath);
            ImageIO.write(resultImage, "png", outputFile);
            
            log.info("이미지가 성공적으로 결합되었습니다: " + outputPath);
        } catch (IOException e) {
            log.error("이미지 결합 중 오류 발생", e);
        }
    }
}

태그: java PDFBox PDF변환 이미지처리 PDF이미지

7월 3일 20:49에 게시됨