使用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
相关产品推荐
相关产品推荐

