這篇文章,主要介紹PDFBox操作PDF文檔之添加本地圖片、添加網(wǎng)絡(luò)圖片、圖片寬高自適應、圖片水平垂直居中對齊。
目錄
一、PDFBox操作圖片
1.1、添加本地圖片
(1)案例代碼
(2)運行效果
(3)方法介紹
1.2、添加網(wǎng)絡(luò)圖片
(1)案例代碼
(2)運行效果
1.3、圖片寬高自適應(圖片縮放)
(1)圖片縮放代碼
1.4、讀取圖片
(1)案例代碼
(2)運行效果
一、PDFBox操作圖片
PDFBox可以向PDF文檔中添加圖片對象,使用PDImageXObject表示一個圖片對象,對PDF文檔的內(nèi)容進行操作,都需要借助于PDPageContentStream頁面內(nèi)容流對象來完成,PDFBox將每一個PDF頁面中的所有文本、圖片、表單等內(nèi)容看作一個流,通過流的方式來完成內(nèi)容的添加、刪除、修改等操作。這里首先介紹如何使用PDFBox添加圖片對象到PDF文檔里面。
1.1、添加本地圖片
(1)案例代碼
添加本地圖片,也就是讀取當前磁盤中的圖片,然后將這個圖片寫入到PDPageContentStream頁面內(nèi)容流里面,案例代碼如下:
package pdfbox.demo.image;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
/**
* @version 1.0.0
* @Date: 2023/7/15 14:51
* @Author ZhuYouBin
* @Description: PDFBox操作圖片
*/
public class PDFBoxImageUtil {
/**
* 將給定路徑的圖片,保存到pdf文件里面
* @param imgPath 圖片路徑
* @param destPdf 生成的pdf文件路徑
* @return 返回生成的pdf文件路徑
*/
public static String generateImageToPdf(String imgPath, String destPdf) {
try {
// 1、創(chuàng)建PDF文檔對象
PDDocument doc = new PDDocument();
// 2、創(chuàng)建Page頁面對象
PDPage page = new PDPage(PDRectangle.A4);
// 3、創(chuàng)建圖片對象
PDImageXObject image = PDImageXObject.createFromFile(imgPath, doc);
// 4、創(chuàng)建頁面內(nèi)容流,指定操作哪個文檔中的哪個頁面
PDPageContentStream stream = new PDPageContentStream(doc, page);
stream.drawImage(image, 10, 10); // 繪制圖片到PDF頁面里面
stream.close(); // 關(guān)閉頁面內(nèi)容流
doc.addPage(page); // 添加頁面到PDF文檔
doc.save(destPdf); // 保存PDF文檔
doc.close(); // 關(guān)閉PDF文檔
} catch (Exception e) {
e.printStackTrace();
}
return destPdf;
}
public static void main(String[] args) {
String imgPath = "E:\\demo\\001.jpg";
String destPdf = "E:\\demo\\img.pdf";
generateImageToPdf(imgPath, destPdf);
}
}
(2)運行效果
(3)方法介紹
PDImageXObject類中提個了一些靜態(tài)方法,常見的有下面這些:
- createFromFile(imagePath,doc)方法:采用File文件的方式讀取本地磁盤中的圖片。
- imagePath參數(shù):圖片的路徑。
- doc參數(shù):PDF文檔對象。
- getImage()方法:返回BufferedImage圖片對象。
- getSuffix()方法:返回圖片的后綴類型,例如:jpg、png等。
1.2、添加網(wǎng)絡(luò)圖片
PDFBox中是沒有提供讀取網(wǎng)絡(luò)圖片的方法,但是可以采用下面這種方式實現(xiàn)讀取網(wǎng)絡(luò)圖片的功能,思路如下:
- 第一步:使用URL對象將網(wǎng)絡(luò)圖片下載到本地磁盤上。
- 第二步:使用createFromFile()方法從本地磁盤讀取剛剛下載的網(wǎng)絡(luò)圖片。
(1)案例代碼
package pdfbox.demo.image;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.UUID;
/**
* @version 1.0.0
* @Date: 2023/7/15 15:01
* @Author ZhuYouBin
* @Description: PDFBox操作圖片,添加網(wǎng)絡(luò)圖片到PDF文檔
*/
public class PDFBoxImageUtil {
/**
* 將給定路徑的圖片,保存到pdf文件里面
* @param imgPath 圖片路徑
* @param destPdf 生成的pdf文件路徑
* @return 是否生成成功
*/
public static String generateImageToPdf(String imgPath, String destPdf) {
try {
// 1、創(chuàng)建PDF文檔對象
PDDocument doc = new PDDocument();
// 2、創(chuàng)建Page頁面對象
PDPage page = new PDPage(PDRectangle.A4);
// 3、創(chuàng)建圖片對象
PDImageXObject image;
boolean isTemp = false;
String tempPath = null;
if (imgPath.startsWith("http://") || imgPath.startsWith("https://")) {
isTemp = true;
tempPath = downloadImage(imgPath, null);
image = PDImageXObject.createFromFile(tempPath, doc);
} else {
image = PDImageXObject.createFromFile(imgPath, doc);
}
// 4、創(chuàng)建頁面內(nèi)容流,指定操作哪個文檔中的哪個頁面
PDPageContentStream stream = new PDPageContentStream(doc, page);
stream.drawImage(image, 10, 10); // 繪制圖片到PDF頁面里面
stream.close(); // 關(guān)閉頁面內(nèi)容流
doc.addPage(page); // 添加頁面到PDF文檔
doc.save(destPdf); // 保存PDF文檔
doc.close(); // 關(guān)閉PDF文檔
// 圖片添加成功之后需要刪除本地臨時文件
if (isTemp) {
new File(tempPath).delete();
}
} catch (Exception e) {
e.printStackTrace();
}
return destPdf;
}
/**
* 下載網(wǎng)絡(luò)圖片到本地
* @param imgPath 網(wǎng)絡(luò)圖片地址
* @param fileName 文件名稱
* @return 返回本地圖片的臨時路徑
*/
public static String downloadImage(String imgPath, String fileName) {
try {
URLConnection conn = new URL(imgPath).openConnection();
String contentType = conn.getContentType();
System.out.println(contentType);
// 創(chuàng)建臨時文件目錄保存圖片
File file = new File("temp");
if (!file.exists() && !file.mkdirs()) {
throw new RuntimeException("臨時目錄創(chuàng)建失敗");
}
if (fileName == null || fileName.trim().equals("")) {
fileName = UUID.randomUUID().toString();
}
InputStream is = conn.getInputStream();
byte[] data = new byte[1024];
int len;
// 下載文件到本地臨時目錄
switch (contentType) {
case "image/jpeg":fileName += ".jpeg"; break;
case "image/gif": fileName += ".gif"; break;
case "image/webp":
case "image/png": fileName += ".png"; break;
}
fileName = file.getAbsolutePath() + File.separator + fileName;
FileOutputStream fos = new FileOutputStream(fileName);
while ((len = is.read(data)) != -1) {
fos.write(data, 0, len);
}
fos.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return fileName;
}
public static void main(String[] args) {
String imgPath = "https://www.toopic.cn/public/uploads/small/1658043938262165804393852.jpg";
String destPdf = "E:\\demo\\img.pdf";
generateImageToPdf(imgPath, destPdf);
}
}
(2)運行效果
1.3、圖片寬高自適應(圖片縮放)
前面已經(jīng)能夠?qū)D片添加到PDF文檔中了,但是可以發(fā)現(xiàn),我們添加的圖片尺寸太大的時候,超過PDF文檔部分就會被遮擋,如何解決這個問題呢???對于這個問題,可以采用縮放圖片的方式來解決,思路如下所示:
- 第一步:獲取圖片的實際寬度、高度(JDK中獲取到的圖片寬高單位是【px】,需要將【px】轉(zhuǎn)換成【pt】單位,轉(zhuǎn)換規(guī)則:1pt?= 3/4 px)。
- 第二步:獲取到PDF文檔的寬度、高度(PDFBox中獲取到的寬度、高度是采用【pt】作為單位的)。
- 第三步:圖片的實際寬高和PDF文檔的寬高進行比較,計算縮放比例。
(1)圖片縮放代碼
package pdfbox.demo.image;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.UUID;
/**
* @version 1.0.0
* @Date: 2023/7/15 15:11
* @Author ZhuYouBin
* @Description: PDFBox操作圖片,圖片寬高自動縮放
*/
public class PDFBoxImageUtil {
/**
* 將給定路徑的圖片,保存到pdf文件里面
*
* @param imgPath 圖片路徑
* @param destPdf 生成的pdf文件路徑
* @return 返回生成的pdf文件路徑
*/
public static boolean generateImageToPdf(String imgPath, String destPdf) {
try {
// 1、創(chuàng)建PDF文檔對象
PDDocument doc = new PDDocument();
// 2、創(chuàng)建Page頁面對象
PDPage page = new PDPage(PDRectangle.A4);
// 3、創(chuàng)建圖片對象
PDImageXObject image;
if (imgPath.startsWith("http://") || imgPath.startsWith("https://")) {
String tempPath = downloadImage(imgPath, null);
image = PDImageXObject.createFromFile(tempPath, doc);
imgPath = tempPath;
} else {
image = PDImageXObject.createFromFile(imgPath, doc);
}
// 4、創(chuàng)建頁面內(nèi)容流,指定操作哪個文檔中的哪個頁面
PDPageContentStream stream = new PDPageContentStream(doc, page);
// 獲取圖片的寬高
float[] imageWH = getImageWH(imgPath, page.getMediaBox());
stream.drawImage(image, imageWH[0], imageWH[1], imageWH[2], imageWH[3]); // 繪制圖片到PDF頁面里面
stream.close(); // 關(guān)閉頁面內(nèi)容流
doc.addPage(page); // 添加頁面到PDF文檔
doc.save(destPdf); // 保存PDF文檔
doc.close(); // 關(guān)閉PDF文檔
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 獲取圖片的寬度、高度,單位是【pt】
*
* @param imgPath 圖片路徑
* @param box PDF文檔頁面矩形區(qū)域?qū)ο?,可以獲取到矩形區(qū)域的寬高
* @return 返回縮放之后的圖片寬高
*/
public static float[] getImageWH(String imgPath, PDRectangle box) {
try {
File file = new File(imgPath);
InputStream is = new FileInputStream(file);
// 判斷是不是網(wǎng)絡(luò)上的圖片
if (imgPath.startsWith("http://") || imgPath.startsWith("https://")) {
is = new URL(imgPath).openStream();
}
BufferedImage bi = ImageIO.read(is);
// px 轉(zhuǎn)換成 pt 單位
float xAxis;
float yAxis;
int w = bi.getWidth();
int h = bi.getHeight();
float width = (float) (w * 3.0 / 4); // 這里是因為 1pt = 3/4 px,pt和px單位轉(zhuǎn)換
float height = (float) (h * 3.0 / 4);
float pw = box.getWidth() - 60; // 這里減不減60沒啥關(guān)系,只是設(shè)置一下空白間距
float ph = box.getHeight() - 60; // 這里減不減60沒啥關(guān)系,只是設(shè)置一下空白間距
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};
}
/**
* 下載網(wǎng)絡(luò)圖片到本地
* @param imgPath 網(wǎng)絡(luò)圖片地址
* @param fileName 文件名稱
* @return 返回本地圖片的臨時路徑
*/
public static String downloadImage(String imgPath, String fileName) {
try {
URLConnection conn = new URL(imgPath).openConnection();
String contentType = conn.getContentType();
// 創(chuàng)建臨時文件目錄保存圖片
File file = new File("temp");
if (!file.exists() && !file.mkdirs()) {
throw new RuntimeException("臨時目錄創(chuàng)建失敗");
}
if (fileName == null || fileName.trim().equals("")) {
fileName = UUID.randomUUID().toString().replaceAll("-", "");
}
InputStream is = conn.getInputStream();
byte[] data = new byte[1024];
int len;
// 下載文件到本地臨時目錄
switch (contentType) {
case "image/jpeg":fileName += ".jpeg"; break;
case "image/gif": fileName += ".gif"; break;
case "image/webp":
case "image/png": fileName += ".png"; break;
}
fileName = file.getAbsolutePath() + File.separator + fileName;
FileOutputStream fos = new FileOutputStream(fileName);
while ((len = is.read(data)) != -1) {
fos.write(data, 0, len);
}
fos.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return fileName;
}
public static void main(String[] args) {
String imgPath = "https://www.toopic.cn/public/uploads/small/1658043938262165804393852.jpg";
String destPdf = "E:\\demo\\img.pdf";
generateImageToPdf(imgPath, destPdf);
}
}
1.4、讀取圖片
PDFBox也可以從PDF文檔中讀取圖片,然后將其保存到本地磁盤中,保存圖片可以使用JDK中提供的ImageIO類,這個類中提供了一個write()方法,可以將圖片對象寫入到File文件里面。
(1)案例代碼
package pdfbox.demo.image;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
/**
* @version 1.0.0
* @Date: 2023/7/15 15:11
* @Author ZhuYouBin
* @Description: PDFBox操作圖片,從PDF文檔中【讀取圖片】,并且保存到本地
*/
public class PDFBoxImageUtil {
/**
* 從給定的pdf文檔里面,獲取指定頁面中的所有圖片,并且保存到本地目錄下
* <p>
* pdf文檔中的圖片都是BASE64編碼,我們能夠獲取到的也就只能是圖片對應的BASE64字符串。
* 所以,還需要將圖片的BASE64字符串編碼轉(zhuǎn)換成對應的圖片文件
* </p>
* @param pdfPath PDF文檔路徑
* @param imagePath 生成的圖片路徑以及名稱
* @param pageNum 獲取第幾頁的圖片
* @return 返回提取的圖片本地路徑
*/
public static String readerImageFromPdf(String pdfPath, String imagePath, int pageNum) {
try {
// 1、加載PDF文檔
PDDocument doc = PDDocument.load(new File(pdfPath));
// 2、遍歷所有Page頁面,找到指定的page頁面獲取圖片
int pages = doc.getNumberOfPages();
for (int i = 0; i < pages; i++) {
if (i != pageNum) {
continue;
}
// 獲取當前Page頁面
PDPage page = doc.getPage(i);
// 獲取對應頁面的資源對象
PDResources resources = page.getResources();
// 遍歷當前頁面所有內(nèi)容,找出圖片對象
for (COSName cosName : resources.getXObjectNames()) {
PDXObject pdxObject = resources.getXObject(cosName);
// 判斷是不是圖片對象
if (pdxObject instanceof PDImageXObject) {
// 獲取圖片對象
BufferedImage image = ((PDImageXObject) pdxObject).getImage();
// 保存到本地磁盤里面
ImageIO.write(image, "JPEG", new File(imagePath));
}
}
}
doc.close(); // 關(guān)閉PDF文檔
} catch (Exception e) {
e.printStackTrace();
}
return imagePath;
}
public static void main(String[] args) {
String imgPath = "E:\\img\\002.jpg";
String destPdf = "E:\\demo\\img.pdf";
readerImageFromPdf(destPdf, imgPath, 0);
}
}
(2)運行效果
到此,PDFBox操作圖片就介紹完啦。文章來源:http://www.zghlxwxcb.cn/news/detail-588027.html
綜上,這篇文章結(jié)束了,主要介紹PDFBox操作PDF文檔之添加本地圖片、添加網(wǎng)絡(luò)圖片、圖片寬高自適應、圖片水平垂直居中對齊。文章來源地址http://www.zghlxwxcb.cn/news/detail-588027.html
到了這里,關(guān)于【PDFBox】PDFBox操作PDF文檔之添加本地圖片、添加網(wǎng)絡(luò)圖片、圖片寬高自適應、圖片水平垂直居中對齊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!