Question

I'm trying to convert an XPS with WPF.

The idea is that these images can be loaded with silverlight 4, for this I am using the following code:

 // 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();

This code is taken from http://xpsreader.codeplex.com/ a project to convert an XPS document. works great! But the problem is that the image is low resolution and blurry. I researched and found that RenderTargetBitmap and find on this page: http://www.codeproject.com/Questions/213737/Render-target-bitmap-quality-issues

The issue here is you Have That does not use hardware RenderTargetBitmap rendering.

One solution is to use DirectX with WPF to do this, but have not found any clear example to show me the right way to do it.

I appreciate suggestions. Thanks in advance.

Update:I attached the XPS document, I am trying to convert the image Please download test.xps

Was it helpful?

Solution

I saw in this post and in many others that peoples have problems with conversion of DocumentPage to Image and saving it on HDD. This method took all pages from document viewer and save them on HDD as jpg images.

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();
                }
            }
        }
    }

OTHER TIPS

There is a project named xps2img on sourceforge.net which converts an xps to image. It is made in C# and also contains the source code. Check it out. It will help you to achieve what you want.

http://sourceforge.net/projects/xps2img/files/

A nuget package based on xps2img is now available: https://www.nuget.org/packages/xps2img/

Api available here: https://github.com/peters/xps2img#usage

    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();
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top