java將pdf文件轉換為圖片工具類

一、相關依賴

	<!-- PDFBox for PDF processing --><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.27</version></dependency>

二、工具類

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.rendering.PDFRenderer;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** @ClassName: PdfConvertImage* @Description: PDF文件轉圖片* @Author: zhanghui* @Date: 2025-06-06* @Version: 1.0**/
public class PdfConvertImage {/*** 默認圖片格式*/private static final String DEFAULT_IMAGE_FORMAT = "png";/*** 默認圖片分辨率 - 保持原始比例的高清輸出*/private static final double DEFAULT_SCALE = 2.0;/*** 將多個PDF文件轉換為圖片,使用平衡的高清分辨率* * @param pdfFiles PDF文件列表* @param outputDir 輸出根目錄* @return 生成的圖片路徑列表* @throws Exception 轉換異常*/public static List<String> convertPdfsToImagesWithBalancedResolution(List<File> pdfFiles, String outputDir) throws Exception {// 使用2K分辨率,平衡質量和文件大小return convertPdfsToImagesWithBalancedResolution(pdfFiles, outputDir, 2560, 1440);}/*** 將多個PDF文件轉換為圖片,使用平衡的高清分辨率(可配置)* * @param pdfFiles PDF文件列表* @param outputDir 輸出根目錄* @param targetWidth 目標寬度(推薦:1920-2560)* @param targetHeight 目標高度(推薦:1080-1440)* @return 生成的圖片路徑列表* @throws Exception 轉換異常*/public static List<String> convertPdfsToImagesWithBalancedResolution(List<File> pdfFiles, String outputDir, int targetWidth, int targetHeight) throws Exception {if (pdfFiles == null || pdfFiles.isEmpty()) {throw new IllegalArgumentException("PDF文件列表不能為空");}// 創建項目文件夾String projectDir = createProjectDirectory(outputDir);List<String> allImagePaths = new ArrayList<>();// 處理每個PDF文件for (int i = 0; i < pdfFiles.size(); i++) {File pdfFile = pdfFiles.get(i);if (!pdfFile.exists() || !pdfFile.isFile()) {System.err.println("警告:文件不存在或不是有效文件: " + pdfFile.getPath());continue;}String pdfName = getFileNameWithoutExtension(pdfFile.getName());// 將所有圖片保存到同一個目錄中,通過文件名前綴區分不同的PDFList<String> imagePaths = convertSinglePdfToImagesWithBalancedResolution(pdfFile, projectDir, pdfName, targetWidth, targetHeight);allImagePaths.addAll(imagePaths);}return allImagePaths;}/*** 轉換單個PDF文件為圖片,使用平衡的高清分辨率* * @param pdfFile PDF文件* @param outputDir 輸出目錄* @param pdfNamePrefix PDF名稱前綴,用于區分不同PDF的圖片* @param targetWidth 目標寬度* @param targetHeight 目標高度* @return 生成的圖片路徑列表* @throws Exception 轉換異常*/private static List<String> convertSinglePdfToImagesWithBalancedResolution(File pdfFile, String outputDir, String pdfNamePrefix, int targetWidth, int targetHeight) throws Exception {List<String> imagePaths = new ArrayList<>();try (PDDocument document = PDDocument.load(pdfFile)) {PDFRenderer pdfRenderer = new PDFRenderer(document);int pageCount = document.getNumberOfPages();for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) {// 獲取PDF頁面尺寸PDRectangle pageSize = document.getPage(pageIndex).getBBox();double originalWidth = pageSize.getWidth();double originalHeight = pageSize.getHeight();// 根據原始比例調整目標尺寸double originalRatio = originalWidth / originalHeight;double targetRatio = (double) targetWidth / targetHeight;int finalWidth = targetWidth;int finalHeight = targetHeight;if (originalRatio > targetRatio) {// 原始更寬,以寬度為準finalHeight = (int) Math.round(targetWidth / originalRatio);} else {// 原始更高,以高度為準finalWidth = (int) Math.round(targetHeight * originalRatio);}// 計算縮放比例double scale = Math.min((double) finalWidth / originalWidth, (double) finalHeight / originalHeight);System.out.println("PDF頁面 " + (pageIndex + 1) + " 原始尺寸:" + originalWidth + "x" + originalHeight);System.out.println("目標尺寸:" + finalWidth + "x" + finalHeight);System.out.println("縮放比例:" + String.format("%.2f", scale));// 渲染PDF頁面為圖片BufferedImage image = pdfRenderer.renderImageWithDPI(pageIndex, (float) (scale * 72));// 創建最終尺寸的圖片BufferedImage finalImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_RGB);Graphics2D graphics = finalImage.createGraphics();// 設置高質量渲染參數graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);graphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);// 填充白色背景graphics.setColor(Color.WHITE);graphics.fillRect(0, 0, finalWidth, finalHeight);// 計算居中位置int x = (finalWidth - image.getWidth()) / 2;int y = (finalHeight - image.getHeight()) / 2;// 繪制圖片graphics.drawImage(image, x, y, null);graphics.dispose();// 保存圖片String imagePath = outputDir + File.separator + pdfNamePrefix + "_page_" + (pageIndex + 1) + "." + DEFAULT_IMAGE_FORMAT;File imageFile = new File(imagePath);writeHighQualityImage(finalImage, imageFile, DEFAULT_IMAGE_FORMAT);imagePaths.add(imagePath);// 顯示文件大小信息if (imageFile.exists()) {long fileSizeKB = imageFile.length() / 1024;System.out.println("圖片 " + (pageIndex + 1) + " 大小:" + fileSizeKB + " KB");}}}return imagePaths;}/*** 創建項目目錄* * @param baseDir 基礎目錄* @return 項目目錄路徑*/private static String createProjectDirectory(String baseDir) {String projectDir = baseDir + File.separator;File directory = new File(projectDir);if (!directory.exists()) {directory.mkdirs();}return projectDir;}/*** 獲取不包含擴展名的文件名* * @param fileName 文件名* @return 不包含擴展名的文件名*/private static String getFileNameWithoutExtension(String fileName) {int lastDotIndex = fileName.lastIndexOf('.');if (lastDotIndex > 0) {return fileName.substring(0, lastDotIndex);}return fileName;}/*** 高質量圖片輸出方法* * @param image 要保存的圖片* @param imageFile 輸出文件* @param format 圖片格式* @throws IOException IO異常*/private static void writeHighQualityImage(BufferedImage image, File imageFile, String format) throws IOException {// 使用PNG格式確保無損壓縮,保持原PDF質量if ("png".equalsIgnoreCase(format)) {ImageIO.write(image, format, imageFile);} else {// 如果是其他格式,也使用高質量設置ImageIO.write(image, format, imageFile);}}public static void main(String[] args) {try {// 測試:將多個PDF文件轉換為圖片,所有圖片保存到一個文件夾中String outputDir = "/Users/engine/Desktop/img";List<File> pdfFiles = new ArrayList<>();// 添加你的PDF文件路徑pdfFiles.add(new File("/Users/engine/Desktop/小程序注冊全流程_1749436018969.pdf"));pdfFiles.add(new File("/Users/engine/Desktop/演示文稿1.pdf"));// 使用平衡分辨率方法(推薦:解決文字擠壓且控制文件大小)System.out.println("=== 使用平衡分辨率模式轉換(2K分辨率) ===");List<String> imagePaths = PdfConvertImage.convertPdfsToImagesWithBalancedResolution(pdfFiles, outputDir);System.out.println("=== PDF轉圖片完成 ===");System.out.println("輸出目錄:" + outputDir);System.out.println("轉換模式:平衡分辨率模式(2K分辨率平衡質量與文件大小)");System.out.println("總共生成了 " + imagePaths.size() + " 張圖片:");// 按順序顯示所有圖片路徑(前端輪播可以直接使用這個列表)for (int i = 0; i < imagePaths.size(); i++) {System.out.println((i + 1) + ". " + imagePaths.get(i));}System.out.println("前端輪播提示:");System.out.println("- 所有圖片都在同一個文件夾中");System.out.println("- 圖片命名格式:[PDF文件名]_page_[序號].png");System.out.println("- 可以直接使用返回的圖片路徑列表進行輪播展示");System.out.println("- 圖片采用高質量無損PNG格式,保持原PDF文字布局和顯示效果");System.out.println("- 渲染改進:使用2K分辨率平衡質量與文件大小,解決文字擠壓問題");System.out.println("- 文件大小:每張圖片顯示實際大小,便于監控");} catch (Exception e) {System.err.println("轉換失敗:" + e.getMessage());e.printStackTrace();}}
} 

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/909578.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/909578.shtml
英文地址,請注明出處:http://en.pswp.cn/news/909578.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

零門檻探索國產數據庫硬核實力 —— 金倉數據庫在線體驗平臺體驗記

1、 金倉數據庫在線體驗平臺 最近&#xff0c;我發現了一個超棒的數據庫寶藏 —— 金倉數據庫在線體驗平臺。它在金倉社區上線后&#xff0c;憑借 “零門檻體驗 多場景交互” 的特點&#xff0c;迅速吸引了眾多數據庫愛好者的目光&#xff0c;我也忍不住去體驗了一番。 2、 …

Linux基本操作指令和vim編譯器

基本指令 查看日期與日歷 data 指令 顯示日期 用法1&#xff1a;data CST&#xff1a;China Standard Time 時區&#xff0c;中國標準時間 用法2&#xff1a; data 指定格式 常用格式&#xff1a; “%Y-%m-%d”(%F): 2025-06-16“%H:%M:%S”(%T): 20:19:45“%F%T”用法3&am…

“從HTTP到TCP/IP的旅程“-----深入淺出Java Web通信

先放結構圖&#xff1a; 一、引言&#xff1a;網絡通信就像寄快遞 想象一下我們在網上買了一本書&#xff0c;整個配送過程是這樣的&#xff1a; 應用層&#xff1a;你在購物網站填好收貨地址&#xff08;HTTP請求&#xff09;傳輸層&#xff1a;快遞公司把包裹打包&#xf…

docker build使用代理以實現構建過程中下載Github源碼等操作

在通過Dockerfile構建docker容器的過程中&#xff0c;經常會需要在構建過程中拉取Github上的代碼。當宿主機配好代理&#xff0c;但容器內是一個隔離的環境&#xff0c;若想在容器內訪問&#xff0c;則需再打通容器和宿主機之間的代理配置。 方法一&#xff1a; 若宿主機上的…

Docker 快速搭建一個基于 GPT-Vis 組件的統計圖表生成服務

以下是對工具簡單介紹&#xff1a; 可以在服務端使用 GPT-Vis 統計圖表組件直接渲染成圖片支持Docker一鍵部署&#xff0c;提供統計圖表渲染生成API接口支持多種GPT-Vis支持的組件&#xff0c;包括折線圖、柱形圖、餅圖、面積圖、條形圖、直方圖、散點圖、詞云圖、雷達圖、思維…

hal庫練習1

要求&#xff1a;一個按鍵實現呼吸燈的控制&#xff0c;一個按鍵控制LED燈的閃爍&#xff0c;串口發送數據控制燈的開關 定時器配置 1.選擇需要的定時器2.配置基礎參數&#xff08;根據時鐘樹給定時器輸入的時鐘&#xff09;3.打開中斷4.在主函數里打開中斷 定時器掃描按鍵 …

java線程(4)

程序(program) 是為完成制定任務,用某種語言編寫的一組指令的集合.簡單的話說:就是我們寫的代碼. 進程 1.進程是指進行中的程序,比如我們使用QQ,就啟動了一個進程,操作系統就會為該進程分配內存空間,當我們使用迅雷,又啟動了一個進程,操作系統將為迅雷分配新的內存空間. 2、…

02《F8Framework》核心入口 FF8.cs

FF8.cs類是 F8Framework的核心入口 采用單例模式 提供對各個功能模塊的全局訪問 【特點】通過靜態類FF8統一訪問所有功能 1.模塊化設計&#xff1a; 每個功能獨立 通過 ModuleCenter 統一管理 2.懶加載機制&#xff1a; …

【硬件】相機的硬件測試

相機測試 author: Alla Imatest 提供超過 30 種測試項目&#xff0c;主要包括&#xff1a; 1&#xff09;圖像基礎參數?&#xff1a;MTF&#xff08;調制傳遞函數&#xff09;、畸變、均勻性、動態范圍 2&#xff09;色彩與光學特性?&#xff1a;白平衡誤差、飽和度、gamma …

Profinet與Modbus TCP協議轉換技術:西門子S7-1500(主站)和歐姆龍NJ PLC的高效數據交換

一、項目背景 某大型現代化智慧農業養殖場致力于打造全方位智能化的養殖環境。其養殖系統中&#xff0c;環境監測與調控部分選用了西門子S7-1500PLC作為Profinet協議主站。該PLC憑借強大的運算能力和豐富的功能模塊&#xff0c;能夠精準地采集和處理養殖場內的溫度、濕度、空氣…

希爾伯特變換,實信號轉復信號的FPGA實現思路

希爾伯特變換將實信號轉復信號的原理 將實信號的相位推遲90度后作為復信號的虛部。 錯誤實現方式 實信號經過希爾伯特濾波后得到復信號的虛部&#xff0c;之后直接與實信號組成復信號。而由于濾波器本身會對信號延時&#xff0c;故I路與Q路并不是相差90度&#xff0c;所以此方…

多模態大語言模型演進:從視覺理解到具身智能的技術突破

多模態大語言模型演進:從視覺理解到具身智能的技術突破 多模態大語言模型(MLLMs)正在重塑人工智能的邊界,實現從"看見"到"理解"再到"行動"的全鏈條智能。本文將深入解析蘋果最新多模態研究進展,揭示視覺-語言模型十年演進的技術脈絡,剖析…

window顯示驅動開發—渲染管道

支持 Direct3D 版本 10 的圖形硬件可以使用共享可編程著色器核心進行設計。 GPU) (圖形處理單元可以編程著色器核心&#xff0c;這些著色器核心可以跨構成呈現管道的功能塊進行計劃。 這種負載均衡意味著硬件開發人員不需要使用每種著色器類型&#xff0c;而只需要使用執行呈現…

時序數據庫Apache IoTDB核心技術深度解析

一、引言 ?背景?&#xff1a;5G技術加速了IoT領域的發展&#xff0c;物聯網設備數據的收集、存儲和計算需求日益增長。Apache IoTDB作為一款專為物聯網時序數據設計的軟件系統&#xff0c;在2020年被Apache基金會認可為頂級項目。 二、IoT領域發展趨勢 ?5G與IoT?&#x…

Next.js面試題:API深度解析

Next.js面試題&#xff1a;API深度解析 Next.js 通過 App Router 的引入徹底改變了 Web 開發范式。在這個新時代&#xff0c;深入理解 Next.js 的 API 函數不再只是錦上添花&#xff0c;而是技術面試中的關鍵區分點。這些函數構成了構建高性能、可擴展、現代化 Web 應用的基石…

Docker-MCP quickstart

項目概述 Docker-MCP 是一個 支持mcp的Docker 管理服務器&#xff0c;它允許 客戶端 通過 MCP&#xff08;Model Control Protocol&#xff09;接口直接與 Docker 進行交互。該項目提供了一套工具&#xff0c;使 AI 助手能夠創建容器、部署 Docker Compose 、獲取容器日志以及…

git 的變基操作(適合一個功能進行了多次commit提交,提交記錄過多不美觀)

git提交的 commit 的記錄很多&#xff0c;想多個 commit 進行合并&#xff0c;對代碼進行整理&#xff0c;幫助更好的閱讀代碼 IDEA 的操作步驟&#xff1a; 這里&#xff0c;給出你想進行合并的記錄 hash 值&#xff0c;完了點擊“Rebase”進行合并 點擊后&#xff0c;會進行…

【完整源碼+數據集+部署教程】路邊廣告牌實例分割系統源碼和數據集:改進yolo11-SEAMHead

研究背景與意義 研究背景與意義 隨著城市化進程的加快&#xff0c;路邊廣告牌作為重要的商業宣傳媒介&#xff0c;越來越多地出現在城市的各個角落。它們不僅承擔著信息傳播的功能&#xff0c;還對城市的視覺環境產生了深遠的影響。然而&#xff0c;隨著廣告牌數量的激增&…

C++ 中文件 IO 操作詳解

在C中&#xff0c;文件操作是通過流(stream)來實現的。標準庫提供了三種主要的文件流類來處理文件IO操作&#xff1a; ofstream&#xff1a;用于寫入文件&#xff08;output file stream&#xff09;ifstream&#xff1a;用于讀取文件&#xff08;input file stream&#xff0…

第32節 Node.js 全局對象

在Node.js中我們可以直接訪問到全局對象。 這些對象在所有模塊里都是可用的&#xff0c;有些對象不是在全局作用域而是在模塊作用域里&#xff0c;這些情況將在本文的內容中進行介紹。 global {Object} 全局命名空間對象。 在瀏覽器中&#xff0c;全局作用域就是頂級域。如…