My program generates an invoice as a pdf. The problem I’m having is I want to have a header image at the top but the resolution of the image in the pdf is low. Is there a way to sharpen the image? I have tried setting pic.horizontalresolution and pic.verticalresolution to 300 but it still comes out low res on the pdf.
Looks like PDFDocument doesn’t handle Pictures nice. Maybe @Javier_Menendez can tell you more about this.
PDFDocument Drawing LowRes Images: <https://xojo.com/issue/63039>
That is a shame… I wish Xojo inc would sweat the details to a more professional level when they introduce new capabilities …
For business PDFs, letterheads would need to look good both on screen and printed!!!
I use the Einhugur plugins to generate PDFs. If the original picture (chemical structures usually) have sufficient resolution (I use PNGs BTW) , the embedded images in the PDF come out sharp both when printed or displayed on screen.
Looks like I will be sticking with that!
-Karen
How do you place the image in the pdf ?
This is what I’m using:
if gInvoiceGraphic <> nil then
gInvoiceGraphic.HorizontalResolution = 300
gInvoiceGraphic.VerticalResolution = 300
g.DrawPicture(ginvoiceGraphic, 50, 50)
Are-you using PDFDocument or Print to PDF (the OS feature).
If you use the later, you have to set the Resolution (72, 144, 300) at Picture creation time.
if you print a 300 dpi image (usng g.FrawPicture) into a 72 dpi “g” (Picture created at 72 dpi), you still have a 72 dpi image.
So (pseudo code)
Var Pict As New Picture(A4_Width, A4_Height, 300)
if gInvoiceGraphic <> nil then
gInvoiceGraphic.HorizontalResolution = 300
gInvoiceGraphic.VerticalResolution = 300
g.DrawPicture(ginvoiceGraphic, 50, 50)
will allow you to print your image at 300 dpi.
You could try MBS Xojo DynaPDF Plugin instead.
We can embed pictures as is or recompress them as JPEG and limit resolution.
But if you like, you can include 600 dpi pictures easily.
When the program opens it gets gInvoiceFile from a file’s native path (a jpeg 500 x 75 pixels saved at 300 dpi).
It then creates gInvoiceGraphic using Picture.Open(gInvoiceFile) like this:
If gInvoiceFile <> Nil And gInvoiceFile.Exists Then
gInvoiceGraphic = Picture.Open(gInvoiceFile)
gInvoiceGraphic.HorizontalResolution = 300
gInvoiceGraphic.VerticalResolution = 300
end if
I then try to use gInvoiceGraphic in my MakeInvoice method.
Var pdf As New PDFDocument
Var g As Graphics = pdf.Graphics
var Pict as New Picture(gInvoiceGraphic.width, gInvoiceGraphic.Height,300)
Pict.Graphics.DrawPicture(gInvoiceGraphic, 50, 50)
g.DrawPicture(pict,50,50)
I must be missing something. Can you see what I’m doing wrong?
Attached is the result.
Try to set the resolution to 300 (dpi) before oading the file:
If gInvoiceFile <> Nil And gInvoiceFile.Exists Then
gInvoiceGraphic.HorizontalResolution = 300
gInvoiceGraphic.VerticalResolution = 300
gInvoiceGraphic = Picture.Open(gInvoiceFile)
end if
Did you tried with a logo ?
You do nothing wrong. It’s the way how the PDF implementation currently handles pictures. They create a new Picture from the source in the background. The trouble is that if you use PDFGraphics.DrawPicture with all parameters, the image in the PDF may get white borders on the left and right/top and bottom. This is suboptimal implementation. The image resize algorithm for PDF needs to be reworked by Xojo.
In the background, they try to generate an image in the “best possible” resolution and with the smallest possible file size for the PDF, so that the documents do not become too large. I would prefer a property like PDFDocument.PictureQuality
. Then we would have options.
Why are you drawing the picture twice, first to an intermediate picture (Pict) and then on the pdfdocument’s graphics?
In my (quick and limited) tests that two step drawing resulted in a more blurred image in the pdf.
Julen
As you know, PDF is an independent resolution format, what means that (including images) it doesn’t handle fixed resolution. That is, the images stored in the document itself lack any resolution information.
That said, there are several ways to generate the images PDF stream from the source data (the image), one of which is using DCTEncode to compress the data stream (that result in more compact images) and offering the same quality (at a 100% percentage) you would get when saving that same image to a JPEG file using any image processing app. In addition, the image data stream has associate a color rendering intent that may affect how the final image is visually displayed in the output device (i.e. more or less color shift in some cases), and a transformation matrix is also applied, what may vary slightly the position/visually appearance of the points in the document itself.
Anyway, we are looking forward to improve this and other features in the PDFDocument class (for example, creating the output image stream in an uncompressed way, similar to the quality you would expect from a PNG file).
As for your example for the “Invoice” image, a question arises to my. Being the content of that image a text… why you don’t simply include that word as a string instead of graphic in your PDF? That would keep the vectorial representation of the text, avoiding also any image quality anoyance.
Thank you for your feedback!
I imagine it was a place holder for a real logo (customer) in the invoice.
Ah, ok (haven’t thought on that, sorry).
Thanks for this thorough explanation. Much appreciated! I’ll look into DCTEncode.
The word “Invoice” image was just a placeholder as Emile suspected.
This makes sense to get a fast run with something to test. Now, is the time to use a real logo (something graphic) to be sure the result is bad n real condition.
What you may also test is the good old “Print to PDF” feature in case you will get better result (until a better PDFDocument version is released).