C# PDF转图片工具类 - 基于Docnet和SkiaSharp的实现

简介

在 .NET 开发中,PDF 转图片是一个常见需求。本文介绍如何使用 Docnet.Core 和 SkiaSharp 实现一个跨平台的 PDF 转图片工具类。

核心代码

csharp 复制代码
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 }
}

使用示例

csharp 复制代码
PdfSplitter.SplitPdfToImages(
    @"C:\input.pdf", 
    @"C:\output", 
    dpi: 150, 
    imageFormat: ImageFormat.Png
);

依赖包

xml 复制代码
<PackageReference Include="Docnet.Core" Version="2.6.0" />
<PackageReference Include="SkiaSharp" Version="2.88.8" />

总结

本文介绍了一个基于 Docnet.Core 和 SkiaSharp 的 PDF 转图片工具类,支持自定义 DPI、多种图片格式和背景色设置。

相关推荐
葫芦和十三39 分钟前
图解 MongoDB 23|两地三中心:跨可用区部署怎么扛机房故障
后端·mongodb·agent
勇哥java实战分享2 小时前
PaddleOCR 太慢?我换成 RapidOCR 后,速度直接起飞
后端
苏三说技术7 小时前
LangChain4j 和 LangGraph4j,哪个更好?
后端
ServBay8 小时前
7 个AI开发中真正用得上的 MCP Server,配合Claude Code食用效果更佳
后端·claude·mcp
妙码生花8 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十五):优化细节、网络请求封装
前端·后端·ai编程
用户6757049885029 小时前
Go 语言里判断字符串为空,90% 的人都写错了!
后端·go
用户6757049885029 小时前
Go 进阶必修:90% 的人都没用对的“表驱动法”
后端·go
小兔崽子去哪了9 小时前
Java 生成二维码解决方案
java·后端
苍何9 小时前
懂事的 Agent 已经开始自己看屏幕干活了,效率起飞!
后端