C# PDF转图片工具类 - 基于Docnet和SkiaSharp的实现
<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>简介</li><li>核心代码</li><li>使用示例</li><li>依赖包</li><li>总结</li><li>讨论</li></ul></div><p></p><h2 id="简介">简介</h2>
<p>在 .NET 开发中,PDF 转图片是一个常见需求。本文介绍如何使用 Docnet.Core 和 SkiaSharp 实现一个跨平台的 PDF 转图片工具类。</p>
<h2 id="核心代码">核心代码</h2>
<hr>
<pre><code>using Docnet.Core;
using Docnet.Core.Models;
using SkiaSharp;
namespace PdfTools
{
/// <summary>
/// PDF 页面转图片工具类
/// 基于 Docnet.Core 和 SkiaSharp 实现跨平台 PDF 渲染
/// </summary>
public class PdfSplitter
{
/// <summary>
/// 将 PDF 文件的所有页面转换为图片
/// </summary>
public static void SplitPdfToImages(
string pdfPath,
string outputDirectory,
int dpi = 150,
ImageFormat imageFormat = ImageFormat.Png)
{
if (!File.Exists(pdfPath))
throw new FileNotFoundException("PDF 文件不存在", pdfPath);
if (!Directory.Exists(outputDirectory))
Directory.CreateDirectory(outputDirectory);
double scale = dpi / 72.0;
using (var docReader = DocLib.Instance.GetDocReader(
pdfPath, new PageDimensions(scale)))
{
int pageCount = docReader.GetPageCount();
Console.WriteLine($"开始转换: {Path.GetFileName(pdfPath)}, 共 {pageCount} 页");
for (int pageIndex = 0; pageIndex < pageCount; pageIndex++)
{
using (var pageReader = docReader.GetPageReader(pageIndex))
{
int pixelWidth = pageReader.GetPageWidth();
int pixelHeight = pageReader.GetPageHeight();
byte[] imageBytes = pageReader.GetImage();
string fileName = $"{Path.GetFileNameWithoutExtension(pdfPath)}_p{pageIndex + 1}_{pixelWidth}x{pixelHeight}.{imageFormat.ToString().ToLower()}";
string outputPath = Path.Combine(outputDirectory, fileName);
SaveImageWithSkia(imageBytes, pixelWidth, pixelHeight, outputPath, imageFormat);
Console.WriteLine($"已生成: {fileName}");
}
}
}
}
private static void SaveImageWithSkia(
byte[] bgraBytes, int width, int height,
string outputPath, ImageFormat format, SKColor backgroundColor = default)
{
if (backgroundColor == default)
backgroundColor = SKColors.White;
SKImageInfo info = new SKImageInfo(width, height);
using (var surface = SKSurface.Create(info))
{
var canvas = surface.Canvas;
canvas.Clear(backgroundColor);
using (var sourceBitmap = new SKBitmap(width, height, SKColorType.Bgra8888, SKAlphaType.Premul))
{
unsafe
{
fixed (byte* src = bgraBytes)
{
Buffer.MemoryCopy(src, (void*)sourceBitmap.GetPixels(), bgraBytes.Length, bgraBytes.Length);
}
}
canvas.DrawBitmap(sourceBitmap, 0, 0);
}
using (var image = surface.Snapshot())
using (var data = EncodeImage(image, format))
{
using (var stream = File.OpenWrite(outputPath))
data.SaveTo(stream);
}
}
}
private static SKData EncodeImage(SKImage image, ImageFormat format)
{
return format switch
{
ImageFormat.Jpeg => image.Encode(SKEncodedImageFormat.Jpeg, 90),
ImageFormat.Png => image.Encode(SKEncodedImageFormat.Png, 100),
ImageFormat.Webp => image.Encode(SKEncodedImageFormat.Webp, 90),
_ => image.Encode(SKEncodedImageFormat.Png, 100)
};
}
}
public enum ImageFormat { Png, Jpeg, Webp }
}
</code></pre>
<h2 id="使用示例">使用示例</h2>
<pre><code>PdfSplitter.SplitPdfToImages(
@"C:\input.pdf",
@"C:\output",
dpi: 150,
imageFormat: ImageFormat.Png
);
</code></pre>
<h2 id="依赖包">依赖包</h2>
<pre><code><ItemGroup>
<PackageReference Include="Docnet.Core" Version="2.6.0" />
<PackageReference Include="SkiaSharp" Version="3.119.0" />
</ItemGroup>
</code></pre>
<h2 id="总结">总结</h2>
<p>本文介绍了一个基于 Docnet.Core 和 SkiaSharp 的 PDF 转图片工具类,支持自定义 DPI、多种图片格式和背景色设置。</p>
<h2 id="讨论">讨论</h2>
<p>尝试过使用其它库来切图,效果不是很理想!</p><br><br>
来源:https://www.cnblogs.com/kkff/p/19956710 顶一个!刚好最近在做PDF处理的项目,这个方案来得太及时了!
mark一下 先收藏为敬
之前我用过几种方案:
1. Ghostscript - 效果不错但依赖重,部署麻烦
2. PdfiumViewer - 体验一般般
3. 收费的商业库 - 穷鬼表示用不起
看楼主的代码结构很清晰啊,Docnet + SkiaSharp 这个组合确实很妙,一个读PDF一个画图,配合得挺完美的。
想请教几个问题:
[*]这个方案在Linux下能跑吗?我司服务器都是Linux的
[*]对于那种超大的PDF(比如几百MB的扫描件),会不会内存爆炸?
[*]有没有考虑过异步版本?UI程序里调用会卡界面
另外建议lz可以考虑加个CancellationToken支持,这样用户可以随时取消转换,毕竟大文件转换还是需要一些时间的。
总之感谢分享!耶
頁:
[1]