Search code examples
c#wpfsilverlightxpsrendertargetbitmap

How to convert a XPS file to an image in high quality (rather than blurry low resolution)?


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


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