PDFsharp mm size is smaller when printed - c#

I need to print an image on a PDF file, that when printed, is exactly 80 mm high. I know the page sizes, I know the DPI of the image I am putting on the PDF. But when i print it, it comes out at 78.5 mm... and the task I am doing needs to be exact.
I load the image from disk, I know the DPI and I know the pixel height/width. I load it into an Image object (setting the vertical and horizontal dpi to 300). And then add it to he PDF.
public static void SavePdf(Image img, string filename)
{
// Create a new PDF document
PdfDocument document = new PdfDocument();
document.Info.Title = "Test";
// Create an empty page
PdfPage page = document.AddPage();
page.Width = SharedMethods.MmToPixel(520);
page.Height = SharedMethods.MmToPixel(110);
// Get an XGraphics object for drawing
XGraphics gfx = XGraphics.FromPdfPage(page);
XImage image = XImage.FromGdiPlusImage(img);
gfx.DrawImage(image, 0, 0, image.PixelWidth, image.PixelHeight);
// Save the document...
document.Save(filename);
}
The image has to start at the top left of the page.
But it seems to start a few mm in from the top, and seems to reduce in size from 80 mm to 78.5.
I heard PDFs resize by 98% due to ... something. Can this be the issue and I need to upscale my image to 102%?
Note, I know the mm size I want, so I convert that to pixels based on my DPI and a constant I found online:
const double milimetresPerInch = 25.4; // as one inch is 25.4 mm
const double dpi = 300;
public static int MmToPixel(double mm)
{
double pixel = mm * dpi / milimetresPerInch;
return (int)Math.Round(pixel);
}
Edit:
I am using the XUnit.FromMillimeter now, but is this correct?
page.Width = XUnit.FromMillimeter(520);
page.Height = XUnit.FromMillimeter(110);
I am then loading the image, which is the same size as the paper size (in mm) like this:
XImage image = XImage.FromGdiPlusImage(img);
gfx.DrawImage(image, 0, 0, image.PixelWidth, image.PixelHeight);
Is that right? It should fit the entire page, but I notice I am using pixels, but maybe I need to use FromPixels or somehow, FromMillimteres?

I heard PDFs resize by 98% due to ... something.
Sources for that info?
Printers often have non-print areas, typically a few mm on each side with modern printers. By default Adobe Reader reduces the page size while printing to fit the whole page into the printing area. Disable automatic scaling when printing with Adobe Reader.
If the image starts at the top left position, parts of the image may be cut-off due to the non-printing area.
Adobe Reader can measure items on the PDF page. Thus you can easily verify whether your image has the dimensions it should have, This will tell you whether there is a problem with printing or with embedding the image into the PDF.
Adobe Reader can also show you the size of the page - maybe the page has a different mm size than you expect.
You should use PDFsharp's methods like Unit.FromMillimeter to convert units. Your method MmToPixel may do more harm than good. PDF pages do not have pixel and measurements are in points.

Related

How to draw image to pdf and still maintain its original size?

I'm using PDF4NET library to convert image that uploaded by user into a pdf for printing. What i want to achieve is draw the exact same size of image into the pdf. For example, user uploaded a 16px x 16px image, and the pdf will show the same size image at the center.
The code that I'm using is like below:
var canvas = page.Canvas;
var hRatio = page.Width / objImage.Width;
var vRatio = page.Height / objImage.Height;
var ratio = Math.Min(hRatio, vRatio);
page.Canvas.DrawImage(decodedPath, 0, 0, objImage.Width * ratio, objImage.Height * ratio, 0, PDFKeepAspectRatio.KeepWidth);
The problem is when user upload a small image, it will stretch to fit the pdf when draw image.
** The result must be align in center of the pdf
When you draw an image on the PDF page, the drawing size is specified in PDF points. PDF files do not use pixels.
For your situation you should test the 'ratio' and if it is greater than 1 (page is greater than the image) then you should draw the image as it is (no multiplication by ratio).
Disclaimer: I work for the company that develops the PDF4NET library.

ZedGraph to PDF using MigraDoc

I am currently working on a C# application that aims to do some computation and output graphs in a pdf file.
I use the Zedgraph library to draw my graphs so something like graphPane.AddCurve(PointPairList). Now I tried to output these graphs to pdf file via MigraDoc package.
Currently, I have a script that map the Zedgraph to bitmap then paste it on the pdf file. So something like this:
private Bitmap getBitMap()
{
ZedGraphControl graph = new ZedGraphControl();
newGraph = graphPane.Clone();
SizeF s = new SizeF(3.5f, 4.5f);
newGraph.Scale(s);
newGraph.DrawToBitmap(bit, new Rectangle(0, 0, newGraph.Width, newGraph.Height));
return bit;
}
The problem is that this give me a slightly pixellated image on the pdf page. And I need this graph to be in a very high quality. So are there anything I can change the improve the quality or do i have to change my entire approach for such thing.
Thank you so much in advance.
By default a Bitmap you create has your current screen resolution which could be as low as 75dpi, more common 96dpi; more modern monitors have 120dpi or more, but a good print quality starts 150dpi. For really crips images you want 300dpi and to allow zooming you may want to have 600dpi or more..
So you need to create and fill a bitmap with a larger size and take control of its dpi resolution.
Assuming your size of 3.5f x 4.5f is inches, for 300dpi you need a Bitmap with 1050 x 1350 pixels.
So you should create such a Bitmap..:
Bitmap bmp = new Bitmap(1050, 1350);
..and set the resolution:
bmp.SetResolution(300, 300);
To fill it up your control must have the same size:
newGraph.ClientSize = bmp.Size;
Now DrawToBitmap should create an image that is crisp and fit to zoom in..
Note that it does not matter if the control is too large to fit on the screen; DrawToBitmap will still work.
Update In addidtion to a sufficient resolution it is of interest to draw quality lines etc.. A speciality of ZedGraph is that one can turn on Antialiasing, either for individual lines:
curve_x.Line.IsAntiAlias = true;
or other elements:
myPane.XAxis.Scale.FontSpec.IsAntiAlias = true;
or the whole Chart:
zedGraphControl1.IsAntiAlias = true;
All examples are taken from this post.

How to draw vector graphics and save it in PDF file?

I'm working on a project which generally is collecting data and drawing results in charts. (Using C#) I need to save my charts in a PDF file. My question is, how to save charts in a PDF file without loosing resolution? My point is how to draw vector graphics instead of raster graphics?
I tried iTextSharp to create PDF file but the result is not satisfying at all!
I'm new here, so I'm not able to upload pictures.
Here is the result after saving my file:
https://www.dropbox.com/s/ruwtc82hfosxk6y/Test.pdf?dl=0
Here is the PDF that I need to create:
https://www.dropbox.com/s/jvu5uu069imo9xc/nir%20well%20abfar.pdf?dl=0
There are two ways I know of to get high-quality images from your Chart into a PDF.
One is by using vector formats:
Use chart.SaveImage with one of the three emf formats.
Convert the resulting emf file to wmf
Insert the wmf file into your iTextSharp document.
1 and 3 are one-liners. But step 2 is not. In fact I haven't found a working c# solution at all. The best was a weird reference to an edit that has disappeared here ..
If you can use some other program to do the conversion you will get nice results like this demo pdf file.. I used Illustrator for the conversion.
Two: If you can't get step 2 to work, you can still get nice results, if you use raster images with a nice and high resolution. Here is how to do it:
First we hide the Chart, so we don't scare the user. Then we make it as large as we want the output to be. Then we DrawToBitmap and finally we reset the chart again..:
Size s = chart1.Size;
chart1.Hide();
// pick your size in pixels
// I simply multiply my screen size..:
chart1.Size = new System.Drawing.Size(s.Width * 5, s.Height * 5);
using (Bitmap bmp = new Bitmap(chart1.ClientSize.Width, chart1.ClientSize.Height))
{
// you should set the resolution,
// although I didn't find a way for iTextSharp to use it visually
bmp.SetResolution(600, 600);
using (Graphics G = Graphics.FromImage(bmp))
{
G.SmoothingMode = SmoothingMode.HighQuality;
G.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
chart1.DrawToBitmap(bmp, chart1.ClientRectangle);
bmp.Save(yourImageFile, ImageFormat.Png);
}
}
chart1.Size = s;
chart1.Show();
You could also use SaveImage and save a few lines, but you can't set the resolution of the png file there and it will be saved at the currnt screen resolution, which is 96dpi here..
Now you have a large image and will probably have to scale it down in iTextSharp:
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(yourImageFile);
img .ScalePercent(15); // scale to fit your needs..
doc.Add(img );
Note that the legend and the labels get very small this way, so you may have to enlarge them before saving. I also found that, when scaling down, the image is rather bright until you zoom in..
Here are two screenshots, one from the chart, the other from the pdf documnet after zooming in a lot (300%)..:

c# high resolution images in PDF

I'm trying to put high quality images into PDF (one per page). But if I set page size to a4, I have to resize my pictures, becouse they're too large. Then they loose their quality. Is there any way to put big image to a4 page without loosing quality?
I'm using iTextSharp library, firstly I'm creating the document
document = new Document(PageSize.A4, 0, 0, 0, 0);
FileStream output = new FileStream(pdfPath + "document.pdf", FileMode.Create);
PdfWriter writer = PdfWriter.GetInstance(document, output);
document.Open();
then I'm adding each picture
document.Add(iTextSharp.text.Image.GetInstance(toSaveImage, System.Drawing.Imaging.ImageFormat.Tiff));
and closing the document
document.Close();
First let me clear a couple of misunderstandings:
a PDF document doesn't have a resolution. The comment by spender was wrong. There is no such thing as DPI in PDF. The resolution only comes into play when a PDF is rendered (to the screen, to paper,...) and that's why there may be a DPI in a PDF viewer (but that's something completely different).
when you scale an Image object in iTextSharp, you don't lose any information: the number of pixels remains the same. Whereas PDF doesn't have a resolution, the images inside a PDF do. When you the image scale down (that is: you put the same number of pixels on a smaller canvas), the resolution increases; when you scale up, the resolution decreases.
Now for your question: you're not obliged to create A4 pages:
Image img =
iTextSharp.text.Image.GetInstance(toSaveImage,
System.Drawing.Imaging.ImageFormat.Tiff);
Rectangle pagesize = new Rectangle(img.ScaledWidth, img.ScaledHeight);
Document document = new Document(pagesize);
img.SetAbsolutePosition(0, 0);
document.Add(img);
I created the Document based on the scaled dimensions of the Image. Don't let the method names mislead you: ScaledWidth and ScaledHeight are the safest methods to use when getting the dimensions of an Image. Not only do they include any scaling operations, you may have done on the image, the also take into account the space needed for the image after rotating it.
I've set the absolute position to the lower-left corner. That's safer than setting the page margins to 0.
EDIT: If you don't want to change the page size, then you have to use the ScaleToFit() method:
Image img =
iTextSharp.text.Image.GetInstance(toSaveImage,
System.Drawing.Imaging.ImageFormat.Tiff);
img.ScaleToFit(PageSize.A4);
Note that the method to scale to fit to a Rectangle object was introduced in one of the latest iTextSharp versions. An alternative would be to use the ScaleToFit() method that requires the width and the height of the rectangle.

abcPDF is malforming my image after adding it to a pdf

I'm getting a byte array representing a TIFF file from my server, converting it into an XImage, and then adding it to a new pdf document. The image in question is 1280x800 (it was a screenshot) and is being stretched out and lengthened to fit the height and width of a standard pdf page. How do I fix this?
Try this:
doc.MediaBox.String = img.BoundingBox.String;
doc.Rect.String = doc.MediaBox.String;
where doc is Doc and img is XImage
The particular problem you have is due to having the printer set to Portrait.
Being a PDF object, you may need to emulate a page that mimics the image size you are after.
You might be better off sending your original document to an image and adding your TIFF file.
Depends on how the PDF page is being built. What you probably want to do is ensure that the PDF page that you are creating has the same aspect ratio as your image rather than defaulting to a letter sized page.
Since you don't specify how you're making the PDF page, I can't help you specifically. But in general, PDF pages are in units of 1/72 of an inch. You can figure the right size page like this:
const kPdfPageUnitSize = 72f;
float GetPdfSize(int nPixels, float dotsPerInch) {
return (nPixels / dotsPerInch) * kPdfPageUnitSize;
}
// later
float pdfwidth = GetPdfSize(image.Width, image.Resolution.X); // or however you have this
float pdfheight = GetPdfSize(image.Height, image.Resolution.Y);
As I can see, image scale coefficient is incorrect. You should divide image Height and image Width on 1,33(3) ( i.e. 96f/72f )
By default PDF user unit is 1⁄72 inch, so your image DPI should be proportional with original.

Categories