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、多种图片格式和背景色设置。

相关推荐
烂蜻蜓1 小时前
Flask入门教程(十二):表单处理——从基础到Flask-WTF完整实践
后端·python·flask
2601_962055978 小时前
跟据spring boot版本,查看对应的tomcat,并查看可支持的tomcat的版本范围
spring boot·后端·tomcat
Lost of 程序猿9 小时前
ASP.NET Core API 幂等性设计深度实战:从一次重复申领事故说起
后端·asp.net
QQ_216962909610 小时前
【源码编号:project79475】SpringBoot校内二手交易平台:商品发布、分类检索、留言交流、订单管理全流程实战
java·spring boot·后端
郑州光合科技余经理12 小时前
本地生活服务系统:模块边界与结算字段怎么拆
java·开发语言·前端·后端·系统架构·uni-app·php
IT_陈寒12 小时前
Vue的嵌套组件竟然吃掉了我的事件?
前端·人工智能·后端
大辉狼_音频架构13 小时前
进阶:从源码编译 SOF 固件与 topology
后端
大辉狼_音频架构13 小时前
上板:让 SOF 在 FRDM-i.MX8MP 上跑起来
后端
大辉狼_音频架构13 小时前
FRDM-IMX8MP UUU 烧录 eMMC 指南
后端
运行时异常14 小时前
【WMS 仓储系统集成 AI Agent 实战】第 3 讲:Spring Security 6 + JWT——addFilterBefore 一词之差,全站 401
java·后端