14

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

Steffen Opel
  • 63,899
  • 11
  • 192
  • 211
Ricardo Pons
  • 249
  • 1
  • 2
  • 8
  • You are trying to render at 1800 dpi. That is complete overkill - anything beyond 300 dpi is going to be excessive unless you plan on zooming way in on the screen. – Jon Jul 03 '11 at 16:37
  • you're right is at 300 dpi was just experimenting with different values ​​any suggestions? – Ricardo Pons Jul 03 '11 at 18:57
  • 1
    If you are willing to do it offline (and crossplatform), then you may use ghostscript, which has xps support in later editions. See: http://www.ghostscript.com/GPL_Ghostscript_8.61.html – Dov Grobgeld Jul 03 '11 at 19:50
  • Do you have a sample xps document that this produces blurry images for? I get nice crisp images out of this. – Jon Jul 05 '11 at 14:15
  • yes I attached the file!. Thanks. – Ricardo Pons Jul 06 '11 at 04:23
  • It seems to work fine with that file as well. What OS are you on? How are you viewing the result image? – Jon Jul 06 '11 at 14:14
  • I have Windows 7 Ultimate.I see the images loaded directly into the bookcontrol, this control is found in the example XPSReader http://xpsreader.codeplex.com/ – Ricardo Pons Jul 07 '11 at 04:27

4 Answers4

7

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/

Community
  • 1
  • 1
Alexandru Dicu
  • 1,151
  • 1
  • 16
  • 24
  • +1 This one is free and got the job done! No watermark or naughty thing included. In my case I convert from Word's docx, converting to xps somehow gives better font rendering than to pdf (then to image). – Wappenull Jun 11 '19 at 12:20
6

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();
                }
            }
        }
    }
Mihajlo M.
  • 76
  • 1
  • 1
2

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

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

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();
        }
    }
Majid
  • 11
  • 1
  • @TheLethalCoder It's the the 3rd and 4rd argument to the RenderTargetBitmap constructor that give it the resulation, however we need to increase the initial size as well (1st and 2nd) otherwise the image will be enlarged. At the end of the day it works and that's all that matters... – yoel halb Feb 26 '19 at 09:34