查看: 55|回复: 0

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

[复制链接]

0

主题

0

回帖

0

积分

积极分子

金币
0
阅读权限
220
精华
0
威望
0
贡献
0
在线时间
0 小时
注册时间
2009-10-29
发表于 6 天前 | 显示全部楼层 |阅读模式

目录
  • 简介
  • 核心代码
  • 使用示例
  • 依赖包
  • 总结
  • 讨论

简介

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

核心代码


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 }
}

使用示例

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

依赖包

<ItemGroup>
  <PackageReference Include="Docnet.Core" Version="2.6.0" />
  <PackageReference Include="SkiaSharp" Version="3.119.0" />
</ItemGroup>

总结

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

讨论

尝试过使用其它库来切图,效果不是很理想!



来源:https://www.cnblogs.com/kkff/p/19956710
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

相关侵权、举报、投诉及建议等,请发 E-mail:qiongdian@foxmail.com

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部