如何将XPS文件转换为高质量图像(而不是模糊的低分辨率)?

14

我正在尝试将一个包含WPF的XPS文件进行转换。

我的目的是可以使用Silverlight 4来加载这些图片,为此我正在使用以下代码:

 // XPS Document
            XpsDocument xpsDoc = new XpsDocument(xpsFileName, System.IO.FileAccess.Read);
            FixedDocumentSequence docSeq = xpsDoc.GetFixedDocumentSequence();

        // The number of pages
        PageCount = docSeq.References[0].GetDocument(false).Pages.Count;

        DocumentPage sizePage = docSeq.DocumentPaginator.GetPage(0);
        PageHeight = sizePage.Size.Height;
        PageWidth = sizePage.Size.Width;
        // Scale dimensions from 96 dpi to 600 dpi.
        double scale = 300/ 96;

        // Convert a XPS page to a PNG file
        for (int pageNum = 0; pageNum < PageCount; pageNum++)
        {
            DocumentPage docPage = docSeq.DocumentPaginator.GetPage(pageNum);
            BitmapImage bitmap = new BitmapImage();
            RenderTargetBitmap renderTarget =
                new RenderTargetBitmap((int)(scale * (docPage.Size.Height + 1)),
                                                               (int)(scale * (docPage.Size.Height + 1)),
                                                               scale * 96,
                                                               scale * 96, PixelFormats.Pbgra32);
            renderTarget.Render(docPage.Visual);


            PngBitmapEncoder encoder = new PngBitmapEncoder();

            encoder.Frames.Add(BitmapFrame.Create(renderTarget));

            FileStream pageOutStream = new FileStream(name + ".Page" + pageNum + ".png", FileMode.Create, FileAccess.Write);
            encoder.Save(pageOutStream);
            pageOutStream.Close();

这段代码取自http://xpsreader.codeplex.com/,一个将XPS文档转换的项目。运行得很好!但问题在于图像分辨率低且模糊。我做了一些研究,并在这个页面上找到了RenderTargetBitmap的解决方案。

问题在于您没有使用硬件RenderTargetBitmap渲染。

一种解决方案是使用DirectX与WPF来实现,但我还没有找到任何清晰的示例来指导正确的操作方式。

非常感谢您的建议。提前致谢。

更新:我附加了XPS文档,我正在尝试转换图像 请下载test.xps


你正在尝试以1800 dpi渲染。这完全是过度杀伤力 - 除非您计划在屏幕上进行大量缩放,否则超过300 dpi的任何内容都将过度冗余。 - Jon
1
如果您愿意离线(且跨平台)完成此操作,则可以使用Ghostscript,它在较新版本中支持XPS。请参阅:http://www.ghostscript.com/GPL_Ghostscript_8.61.html - Dov Grobgeld
你有一个能够产生模糊图像的 XPS 示例文档吗?我用这个代码得到的图像非常清晰。 - Jon
是的,我附上了文件!谢谢。 - Ricardo Pons
它看起来也可以在那个文件上正常工作。你使用的操作系统是什么?你是如何查看结果图像的? - Jon
显示剩余2条评论
4个回答

7
在sourceforge.net上有一个名为xps2img的项目,可以将XPS转换成图片。它使用C#编写,并包含源代码。你可以去查看一下,它会帮助你实现你想要的功能。 http://sourceforge.net/projects/xps2img/files/

+1 这个免费工具做得很好!没有水印或不良内容。在我的情况下,我将 Word 的 docx 转换为 xps,这样比转换为 pdf(然后再转换为图像)具有更好的字体呈现效果。 - Wappenull

6

我在这篇文章和许多其他文章中看到人们遇到了将DocumentPage转换为图像并保存到硬盘的问题。

这个方法可以从文档查看器中获取所有页面并将它们保存为jpg图像。

public void SaveDocumentPagesToImages(IDocumentPaginatorSource document, string dirPath)
    {
        if (string.IsNullOrEmpty(dirPath)) return;

        if (dirPath[dirPath.Length - 1] != '\\')
            dirPath += "\\";

        if (!Directory.Exists(dirPath)) return;

        MemoryStream[] streams = null;
        try
        {
            int pageCount = document.DocumentPaginator.PageCount;
            DocumentPage[] pages = new DocumentPage[pageCount];
            for (int i = 0; i < pageCount; i++)
                pages[i] = document.DocumentPaginator.GetPage(i);

            streams = new MemoryStream[pages.Count()];

            for (int i = 0; i < pages.Count(); i++)
            {
                DocumentPage source = pages[i];
                streams[i] = new MemoryStream();

                RenderTargetBitmap renderTarget =
                   new RenderTargetBitmap((int)source.Size.Width,
                                           (int)source.Size.Height,
                                           96, // WPF (Avalon) units are 96dpi based
                                           96,
                                           System.Windows.Media.PixelFormats.Default);

                renderTarget.Render(source.Visual);

                JpegBitmapEncoder encoder = new JpegBitmapEncoder();  // Choose type here ie: JpegBitmapEncoder, etc
                encoder.QualityLevel = 100;
                encoder.Frames.Add(BitmapFrame.Create(renderTarget));

                encoder.Save(streams[i]);

                FileStream file = new FileStream(dirPath + "Page_" + (i+1) + ".jpg", FileMode.CreateNew);
                file.Write(streams[i].GetBuffer(), 0, (int)streams[i].Length);
                file.Close();

                streams[i].Position = 0;
            }
        }
        catch (Exception e1)
        {
            throw e1;
        }
        finally
        {
            if (streams != null)
            {
                foreach (MemoryStream stream in streams)
                {
                    stream.Close();
                    stream.Dispose();
                }
            }
        }
    }

2

1
    private IList<byte[]> GetTifPagesFromXps(string xXpsFileName, double xQuality)
    {
        using (var xpsDoc = new XpsDocument(xXpsFileName, FileAccess.Read))
        {
            var docSeq = xpsDoc.GetFixedDocumentSequence();

            var tifPages = new List<byte[]>();
            for (var i = 0; i < docSeq.DocumentPaginator.PageCount; i++)
            {
                using (var docPage = docSeq.DocumentPaginator.GetPage(i))
                {
                    var renderTarget = new RenderTargetBitmap((int)(docPage.Size.Width * xQuality), (int)(docPage.Size.Height * xQuality), 96 * xQuality, 96 * xQuality, PixelFormats.Default);

                    renderTarget.Render(docPage.Visual);

                    var jpegEncoder = new JpegBitmapEncoder { QualityLevel = 100 };
                    jpegEncoder.Frames.Add(BitmapFrame.Create(renderTarget));

                    byte[] buffer;
                    using (var memoryStream = new MemoryStream())
                    {
                        jpegEncoder.Save(memoryStream);
                        memoryStream.Seek(0, SeekOrigin.Begin);
                        buffer = memoryStream.GetBuffer();
                    }
                    tifPages.Add(buffer);
                }
            }

            xpsDoc.Close();
            return tifPages.ToArray();
        }
    }

@TheLethalCoder,RenderTargetBitmap构造函数的第三个和第四个参数确定了其分辨率,但是我们还需要增加初始大小(第一个和第二个参数),否则图像将被放大。最终它能够工作就行了,这才是最重要的... - yoel halb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接