Ghostscript.NET Rasterizer内存不足

时间:2015-11-03 20:49:39

标签: c# asp.net out-of-memory ghostscript ghostscript.net

我正在使用Ghostscript.NET,一个方便的C#包装器,用于Ghostscript功能。我从客户端发送了一批PDF,以便在ASP .NET WebAPI服务器上转换为图像并返回给客户端。

public static IEnumerable<Image> PdfToImagesGhostscript(byte[] binaryPdfData, int dpi)
{
    List<Image> pagesAsImages = new List<Image>();

    GhostscriptVersionInfo gvi = new GhostscriptVersionInfo(AppDomain.CurrentDomain.BaseDirectory + @"\bin\gsdll32.dll");

    using (var pdfDataStream = new MemoryStream(binaryPdfData))
    using (var rasterizer = new Ghostscript.NET.Rasterizer.GhostscriptRasterizer())
    {
        rasterizer.Open(pdfDataStream, gvi, true);

        for (int i = 1; i <= rasterizer.PageCount; i++)
        {
            Image pageAsImage = rasterizer.GetPage(dpi, dpi, i); // Out of Memory Exception on this line
            pagesAsImages.Add(pageAsImage);
        }
    }
    return pagesAsImages;
}

这通常工作正常(我通常使用500 dpi,我知道它很高,但即使降到300我也可以重现这个错误)。但是,如果我从客户端提供许多PDF(例如150个1页PDF),它通常会在Ghostscript.NET Rasterizer中遇到内存不足异常。我怎么能克服这个?这应该是线程吗?如果是这样,那将如何运作?使用64位版本的GhostScript会有帮助吗?提前谢谢。

2 个答案:

答案 0 :(得分:0)

我自己也是新手,在这里寻找技巧。

根据文档here中的示例,他们显示了这一点:

for (int page = 1; page <= _rasterizer.PageCount; page++)
{
    var docName = String.Format("Page-{0}.pdf", page);
    var pageFilePath = Path.Combine(outputPath, docName);
    var pdf = _rasterizer.GetPage(desired_x_dpi, desired_y_dpi, pageNumber);
    pdf.Save(pageFilePath);
    pagesAsImages.Add(pdf);
}

看起来您没有保存文件。

我仍然在努力获得与此类似的东西,以便在我的最后工作。目前,我有两种方法可以尝试,先使用 GhostscriptProcessor

private static void GhostscriptNetProcess(String fileName, String outputPath)
{
    var version = Ghostscript.NET.GhostscriptVersionInfo.GetLastInstalledVersion();
    var source = (fileName.IndexOf(' ') == -1) ? fileName : String.Format("\"{0}\"", fileName);
    var gsArgs = new List<String>();
    gsArgs.Add("-q");
    gsArgs.Add("-dNOPAUSE");
    gsArgs.Add("-dNOPROMPT");
    gsArgs.Add("-sDEVICE=pdfwrite");
    gsArgs.Add(String.Format(@"-sOutputFile={0}", outputPath));
    gsArgs.Add(source);
    var processor = new Ghostscript.NET.Processor.GhostscriptProcessor(version, false);
    processor.Process(gsArgs.ToArray());
}

下面这个版本与你的版本类似,在我开始寻找其他代码示例之前我开始使用的版本:

private static void GhostscriptNetRaster(String fileName, String outputPath)
{
    var version = Ghostscript.NET.GhostscriptVersionInfo.GetLastInstalledVersion();
    using (var rasterizer = new Ghostscript.NET.Rasterizer.GhostscriptRasterizer())
    {
        rasterizer.Open(File.Open(fileName, FileMode.Open, FileAccess.Read), version, false);
        for (int page = 0; page < rasterizer.PageCount; page++)
        {
            var img = rasterizer.GetPage(96, 96, page);
            img.Save(outputPath);
        }
    }
}

这会让你到任何地方吗?

答案 1 :(得分:0)

您不必在同一GhostscriptRasterizer实例上光栅化所有页面。在每页上使用一次性光栅化器,并在“列表图像”或“列表字节[]”中收集结果。 结果示例Jpeg编码的字节数组列表。

List<byte[]> result = new List<byte[]>();

for (int i = 1; i <= pdfPagesCount; i++)
{
    using (var pageRasterizer = new GhostscriptRasterizer())
    {
        pageRasterizer.Open(stream, gsVersion, true);

        using (Image tempImage = pageRasterizer.GetPage(dpiX, dpiY, i))
        {
            var encoder = ImageCodecInfo.GetImageEncoders().First(c => c.FormatID == System.Drawing.Imaging.ImageFormat.Jpeg.Guid);
            var encoderParams = new EncoderParameters() { Param = new[] { new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 95L) } };

            using (MemoryStream memoryStream = new MemoryStream())
            {
                tempImage.Save(memoryStream, encoder, encoderParams);
                result.Add(memoryStream.ToArray());
            }
        }
    }
}

如果您不知道PDF中的页数,则可以一次调用光栅化程序,并获取PageCount属性。