PDFsharp & MigraDoc Foundation
https://forum.pdfsharp.net/

PdfSharp: Different results when saving as file or stream
https://forum.pdfsharp.net/viewtopic.php?f=2&t=3649
Page 1 of 1

Author:  polarkreis [ Fri Aug 25, 2017 6:59 am ]
Post subject:  PdfSharp: Different results when saving as file or stream

Hi,

using below code (PDFSharp 3.5 beta 4) leads to different file sizes (after saving byte array resp stream to file) and different quality of graphics. But ... there's no difference in creation of pdf document.
Saving via bytearray or stream result in the same pdf quality, saving direct as file is slightly bigger and has a good quality. Attached zip contains 3 pdf's, please look at page 3 on each pdf - there you see my logo with described quality problems.

Code:
public partial class PdfBuilder
    {
        // default: 1 cm border on each side (except left side to have space for punch holes)
        private XUnit _leftBorder = new XUnit(2, XGraphicsUnit.Centimeter);
        private XUnit _topBorder = new XUnit(1, XGraphicsUnit.Centimeter);
        private XUnit _rightBorder = new XUnit(1, XGraphicsUnit.Centimeter);
        private XUnit _bottomBorder = new XUnit(1, XGraphicsUnit.Centimeter);


        private void SetBorder(double left, double top, double right, double bottom, XGraphicsUnit xGraphicsUnit)
        {
            _leftBorder = new XUnit(left, xGraphicsUnit);
            _topBorder = new XUnit(top, xGraphicsUnit);
            _rightBorder = new XUnit(right, xGraphicsUnit);
            _bottomBorder = new XUnit(bottom, xGraphicsUnit);
        }


        private void CreatePdfFromImages(IEnumerable<Image> images, string fileName)
        {
            var doc = new PdfDocument(fileName);

            CreatePdf(images, doc);
            doc.Close(); // this will save the document
        }


        private void CreatePdfFromImages(IEnumerable<Image> images, out byte[] pdfArray)
        {
            var h = new MemoryStream();
            var doc = new PdfDocument(h);

            CreatePdf(images, doc);

            using (var ms = new MemoryStream())
            {
                doc.Save(ms, false);
                pdfArray = ms.ToArray();
            }
        }


        private void CreatePdfFromImages(IEnumerable<Image> images, out MemoryStream pdf)
        {
            pdf = new MemoryStream();

            var h = new MemoryStream();
            var doc = new PdfDocument(h);
           

            CreatePdf(images, doc);

            doc.Save(pdf, false);
            doc.Close();

            pdf.Seek(0, SeekOrigin.Begin);
        }


        private void CreatePdf(IEnumerable<Image> images, PdfDocument document)
        {
            document.Info.CreationDate = DateTime.Now;
            document.Info.Author = "holonsoft.pdf";

            foreach (var rawImage in images)
            {
                var page = document.AddPage();
                page.Size = PageSize.A4;
                page.TrimMargins.Left = _leftBorder;
                page.TrimMargins.Right = _rightBorder;
                page.TrimMargins.Top = _topBorder;
                page.TrimMargins.Bottom = _bottomBorder;

                var graphics = XGraphics.FromPdfPage(page);
                using (var imgStream = ConvertImageToStream(rawImage))
                {
                    var image = XImage.FromStream(imgStream);
                    graphics.DrawImage(image, 0, 0);
                }
            }

        }


        private Stream ConvertImageToStream(Image rawImage)
        {
            var result = new MemoryStream();

            rawImage.Save(result, rawImage.RawFormat);

            return result;
        }
    }



Code:
_pdfBuilder.CreatePdfFromImages(imgList, out pdfStream);

            var f = new FileStream(_fileNameViaStream, FileMode.CreateNew);

            pdfStream.CopyTo(f);
            f.Close();


Code:
byte[] array;
            _pdfBuilder.CreatePdfFromImages(imgList, out array);

            File.WriteAllBytes(_fileNameViaArray, array);


Attachments:
File comment: 3 pdf's generated with the code above
pdfbuilder_examples.7z [243.48 KiB]
Downloaded 339 times

Author:  TH-Soft [ Fri Aug 25, 2017 9:43 am ]
Post subject:  Re: PdfSharp: Different results when saving as file or strea

Hi!

The large file starts with "%PDF-1.4", the smaller files start with "%PDF-0.0".
Alpha-transparency requires at least 1.4 (nice logo), with 0.0 PDFsharp does not use alpha-transparency and the logo looks edgy.

So how do you set version number to 0.0?
I don't know. Version 0.0 is not valid, 1.0 is the minimum value.
Maybe you're doing something "unusual" that leads to the 0.0 version number.

Code to set it explicitly (before calling Save()):
Code:
// Set version to PDF 1.4 (Acrobat 5) because we use transparency.
if (document.Version < 14)
  document.Version = 14;


What's the purpose of "ConvertImageToStream"? There is XImage.FromImage which takes an Image.

The "h" here makes no sense:
Code:
var h = new MemoryStream();
            var doc = new PdfDocument(h);
Why not use "var doc = new PdfDocument();" instead?

Author:  polarkreis [ Fri Aug 25, 2017 11:54 am ]
Post subject:  Re: PdfSharp: Different results when saving as file or strea

Hi Thomas,
thank you very much for your quick answer.

Setting the doc version explicitly solved the issue.
I didn't set anywhere in code the version, it seems that PDFSharp 'save to file' does it automatically but 'saving to a stream' does not set this value.

It was a relict hoping that PDFSharp does not dispose it when saving. But the stream will always diposed by PDFSharp, so: you're right, the h helper stream is useless here. Thank you :-)

Thomas wrote:
What's the purpose of "ConvertImageToStream"? There is XImage.FromImage which takes an Image.

No, I'm sorry. Just XImage.FromFile() / .FromStream() available.

Best regards
Christian

Author:  TH-Soft [ Fri Aug 25, 2017 12:33 pm ]
Post subject:  Re: PdfSharp: Different results when saving as file or strea

All samples use "new PdfDocument()" without parameter and "Save".
Alternatively you can use "new PdfDocument(<file or stream>)" and call "Close()" - but you shouldn't call "Save" in this case.
Mixing both patterns could lead to problems.

Not use if "new PdfDocument(<file or stream>)" forgets to set the version.

Only the GDI+ build has "XImage.FromImage". When using class Image in your code, you might as well use the GDI+ build.
If you create your Image objects from streams or files, then better also create the XImage objects from the same streams or files.

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/