You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用iText7与ImageMagick拆分PDF为图片的性能优化求助

问题:PDF转JPG性能瓶颈优化疑问
  • 用C#实现PDF拆分为JPG格式的MemoryStream列表,其中iText7拆分PDF效率极高,100页处理不到1秒就能生成单页PDF流;但单页PDF转图片的性能极差。
  • ImageMagick依赖GhostScript完成转换,推测每次调用GhostScript的启动开销是性能瓶颈,想确认是否支持批量调用。
  • 尝试过MagickImageCollection,但发现它一次只能处理一页,所以单独编写了转换方法。
  • 目前也在考虑更换转换工具(比如BlackIce,正在等待许可)。

代码实现

namespace PDFTools;

using ImageMagick;
using iText.Kernel.Pdf;
using iText.Layout;

public class PDFUtilities(string temporaryDirectory)
{
    private readonly string TemporaryDirectory = temporaryDirectory;

    public async Task<List<byte[]>> ConvertPdfToImageAsync(Stream stream)
    {
        List<byte[]> results = new List<byte[]>();
        MagickNET.SetTempDirectory(this.TemporaryDirectory);
        List<MemoryStream> pdfPages = this.SplitPdf(stream);

        var tasks = pdfPages.Select((pdfPage, index) => new OrderedTask
        {
            Index = index,
            Task = this.ConvertPageToImageStreamAsync(pdfPage)
        }).ToList();

        _ = await Task.WhenAll(tasks.Select(static t => t.Task));
        OrderedTask[] orderedTask = tasks
            .OrderBy(static s => s.Index)
            .ToArray();

        foreach (OrderedTask task in orderedTask)
        {
            MemoryStream ms = await task.Task;
            byte[] bytes = ms.ToArray();
            results.Add(bytes);
        }
        return results;
    }


    private async Task<MemoryStream> ConvertPageToImageStreamAsync(MemoryStream file)
    {
        MemoryStream outputStream = new MemoryStream();
        MagickImageCollection images = new MagickImageCollection();
        await images.ReadAsync(file);   // 尝试传入多个PDF时只会获取最后一张图片,所以一次只能处理一页

        foreach (MagickImage image in images)
        {
            image.Quality = 100;
            await image.WriteAsync(outputStream, MagickFormat.Jpg);
        }

        outputStream.Position = 0;
        file.Close();
        return outputStream;
    }

    private List<MemoryStream> SplitPdf(Stream stream)
    {
        List<MemoryStream> pdfPages = new List<MemoryStream>();

        using (PdfDocument pdfDocument = new PdfDocument(new PdfReader(stream)))
        {
            for (int pageNumber = 1; pageNumber <= pdfDocument.GetNumberOfPages(); pageNumber++)
            {
                using (MemoryStream tempStream = new MemoryStream())
                {
                    using (PdfWriter writer = new PdfWriter(tempStream))
                    {
                        using (PdfDocument newPdf = new PdfDocument(writer))
                        {
                            _ = pdfDocument.CopyPagesTo(pageNumber, pageNumber, newPdf);
                        }
                    }

                    MemoryStream outputStream = new MemoryStream(tempStream.ToArray());
                    pdfPages.Add(outputStream);
                }
            }
        }

        return pdfPages;
    }
}

internal class OrderedTask
{
    required public int Index { get; set; }

    required public Task<MemoryStream> Task { get; set; }
}

内容的提问来源于stack exchange,提问作者adc90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:21:00