使用C#在.NET中實現(xiàn)高效提取PDF文檔中的圖片
在文檔處理、內(nèi)容分析、數(shù)據(jù)遷移或自動化測試等場景中,開發(fā)者常常需要從 PDF 文件中提取嵌入的圖像資源——無論是產(chǎn)品手冊中的示意圖、發(fā)票上的二維碼,還是報告中的圖表。.NET 生態(tài)提供了多種庫來實現(xiàn)這一目標。本文將詳細介紹如何使用 C# 從 PDF 中提取所有圖片,并對比主流方案(如 iText 7 和 PdfiumViewer / PdfPig),提供可直接運行的代碼示例。
一、為什么提取 PDF 中的圖片并不簡單
PDF 并非簡單的“圖片容器”,而是一種復雜的文檔格式,其中的圖像可能以不同方式存儲:
- 嵌入為 JPEG、PNG、CCITT(傳真格式)、JBIG2、JPX 等編碼;
- 被壓縮或加密;
- 作為 XObject(Form XObject 或 Image XObject)存在;
- 甚至被分割成多個片段。
因此,通用、健壯的圖片提取依賴于成熟的 PDF 解析庫,而非正則表達式或字節(jié)掃描。
二、技術選型:主流 .NET 庫對比
| 庫名 | 類型 | 圖片提取支持 | 開源 | 推薦度 |
|---|---|---|---|---|
| iText 7 | 商業(yè)/AGPL | ? 完整支持 | 部分開源 | ????☆ |
| UglyToad.PdfPig | MIT 開源 | ? 支持主流格式 | ? | ???? |
| PdfiumViewer | BSD 開源(基于 Chromium 的 PDFium) | ? 可渲染頁面截圖,但非原始圖 | ? | ??☆ |
| Aspose.PDF | 商業(yè) | ? 強大 | ? | ????(需授權) |
本文重點介紹 PdfPig(純托管、開源) 和 iText 7(功能全面) 兩種方案。
三、方案一:使用 PdfPig(推薦用于開源項目)
PdfPig 是一個純 C# 編寫的 PDF 解析庫,無需本地依賴,支持提取原始圖像數(shù)據(jù)。
1. 安裝 NuGet 包
Install-Package UglyToad.PdfPig
2. 提取圖片代碼示例
using UglyToad.PdfPig;
using UglyToad.PdfPig.Content;
using System.Drawing.Imaging;
using System.IO;
class PdfImageExtractor
{
public static void ExtractImagesFromPdf(string pdfPath, string outputFolder)
{
if (!Directory.Exists(outputFolder))
Directory.CreateDirectory(outputFolder);
using (var document = PdfDocument.Open(pdfPath))
{
int imageIndex = 0;
foreach (var page in document.GetPages())
{
foreach (var image in page.GetImages())
{
// 獲取原始字節(jié)和格式
var bytes = image.Data;
var format = GetImageFormat(image);
if (format != null)
{
string fileName = Path.Combine(outputFolder, $"image_{imageIndex++}.{format}");
File.WriteAllBytes(fileName, bytes);
Console.WriteLine($"Saved: {fileName}");
}
}
}
}
}
private static string? GetImageFormat(XObjectImage image)
{
return image.Type switch
{
"Jpeg" => "jpg",
"Png" => "png",
"Jpx" => "jp2", // JPEG2000
"CCITTFax" => "tiff", // 常見于掃描文檔
_ => null // 未知格式暫不處理
};
}
}
3. 調(diào)用示例
PdfImageExtractor.ExtractImagesFromPdf("report.pdf", @"./extracted_images");
優(yōu)點:無外部依賴、跨平臺(.NET Core/.NET 5+)、MIT 許可證。
局限:對某些特殊編碼(如內(nèi)聯(lián)圖像、掩碼圖像)支持有限。
四、方案二:使用 iText 7(適合復雜 PDF)
iText 7 提供更底層的訪問能力,可處理幾乎所有 PDF 圖像類型。
1. 安裝 NuGet 包
Install-Package itext7
2. 自定義圖像提取策略
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas.Parser;
using iText.Kernel.Pdf.Canvas.Parser.Data;
using iText.Kernel.Pdf.Canvas.Parser.Listener;
using System.IO;
public class ImageExtractor : IRenderListener
{
private readonly string _outputDir;
private int _imageCount = 0;
public ImageExtractor(string outputDir)
{
_outputDir = outputDir;
Directory.CreateDirectory(outputDir);
}
public void BeginTextBlock() { }
public void EndTextBlock() { }
public void RenderText(TextRenderInfo renderInfo) { }
public void RenderImage(ImageRenderInfo renderInfo)
{
try
{
var image = renderInfo.GetImage();
if (image != null)
{
byte[] bytes = image.GetImageAsBytes();
string extension = GetExtension(renderInfo);
string path = Path.Combine(_outputDir, $"itext_img_{_imageCount++}.{extension}");
File.WriteAllBytes(path, bytes);
Console.WriteLine($"Extracted: {path}");
}
}
catch (System.Exception ex)
{
Console.WriteLine($"Failed to extract image: {ex.Message}");
}
}
private string GetExtension(ImageRenderInfo info)
{
var filter = info.GetImage().GetPdfObject().GetAsStream().GetAsName(iText.Kernel.Pdf.PdfName.Filter);
if (filter == null) return "png";
if (filter.Equals(iText.Kernel.Pdf.PdfName.DCTDecode)) return "jpg";
if (filter.Equals(iText.Kernel.Pdf.PdfName.FlateDecode)) return "png";
if (filter.Equals(iText.Kernel.Pdf.PdfName.JPXDecode)) return "jp2";
if (filter.Equals(iText.Kernel.Pdf.PdfName.CCITTFaxDecode)) return "tiff";
return "bin";
}
}
// 使用方法
public static void ExtractWithItext(string pdfPath, string outputDir)
{
using var reader = new PdfReader(pdfPath);
using var pdfDoc = new PdfDocument(reader);
var extractor = new ImageExtractor(outputDir);
for (int i = 1; i <= pdfDoc.GetNumberOfPages(); i++)
{
PdfCanvasProcessor processor = new PdfCanvasProcessor(extractor);
processor.ProcessPageContent(pdfDoc.GetPage(i));
}
}
注意:iText 7 在閉源商業(yè)項目中需購買許可證。
五、常見問題與優(yōu)化建議
Q1:提取的圖片模糊?
- 原因:PDF 中圖像本身分辨率低,或為矢量圖轉(zhuǎn)柵格。
- 建議:優(yōu)先提取原始嵌入圖像,而非頁面截圖。
Q2:無法提取掃描版 PDF 中的圖片?
掃描 PDF 通常整頁為一張圖像。此時可使用 PdfiumViewer 渲染整頁為 PNG:
var bitmap = PdfiumViewer.PdfDocument.Load("scan.pdf").Render(0, 300, 300, true);
bitmap.Save("page.png", ImageFormat.Png);
Q3:如何只提取特定區(qū)域的圖片?
PdfPig 支持獲取圖像的邊界框(image.Rectangle),可結(jié)合坐標過濾。
六、總結(jié)
| 方案 | 適用場景 | 優(yōu)勢 | 劣勢 |
|---|---|---|---|
| PdfPig | 開源項目、簡單到中等復雜 PDF | 純 C#、無依賴、免費 | 對高級圖像格式支持有限 |
| iText 7 | 企業(yè)級應用、復雜 PDF | 功能全面、標準兼容 | 商業(yè)授權成本 |
| PdfiumViewer | 掃描文檔、整頁圖像 | 渲染質(zhì)量高 | 無法提取原始嵌入圖 |
對于大多數(shù) .NET 開發(fā)者,PdfPig 是首選的開源解決方案;若需處理高度復雜的 PDF 或已有 iText 授權,則選擇 iText 7。
通過本文提供的代碼,你可以快速集成 PDF 圖片提取功能,賦能文檔智能處理、內(nèi)容審核或數(shù)據(jù)歸檔等應用場景。
到此這篇關于使用C#在.NET中實現(xiàn)高效提取PDF文檔中的圖片的文章就介紹到這了,更多相關C#提取PDF圖片內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
UpdateLayeredWindow實現(xiàn)任意異形窗口使用詳解
這篇文章主要為大家介紹了UpdateLayeredWindow實現(xiàn)任意異形窗口使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09
C#使用struct類型作為泛型Dictionary<TKey,TValue>的鍵
這篇文章介紹了C#使用struct類型作為泛型Dictionary<TKey,TValue>鍵值的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08

