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

相关推荐
aramae7 分钟前
模拟实现strcmp()(C语言)
c语言·开发语言·后端
根目录下的猫2 小时前
RK3588适配的轻量级AI模型推荐
人工智能·后端·python·目标检测
星栈3 小时前
用 Rust 写 Agent 服务 -- adk-rust 上手记
后端·agent
杨运交3 小时前
[071][验证码模块]基于Spring拦截器的验证码认证设计思想
java·后端·spring
LucianaiB4 小时前
我用豆包工作 Seed-2.1-pro,复刻了 QQ 时代爆红的魔术图片
后端
码事漫谈4 小时前
智谱 ZCode 静默上传 Git 历史:48 小时信任危机复盘
后端
掘金码甲哥5 小时前
当对话模型遇上向量模型,vllm production stack 又该如何应对?
后端
传奇开心果编程5 小时前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
IT_陈寒5 小时前
Java线程池用错参数,我的服务居然悄悄崩溃了
前端·人工智能·后端