I am trying to print an image (from file) to a the printer using a PrintDocument.
I am re-sizing my image so that it is scaled to be full page on the printout when I print this the image is cropped slightly.
EDIT 2
I am using the margins to calculate the area to use:
With printSettings.DefaultPageSettings
Dim areaWidth As Single = .Bounds.Width - .Margins.Left - .Margins.Right
Dim areaHeight As Single = .Bounds.Height - .Margins.Top - .Margins.Bottom
End With
The bounds of the page are 1169x827 (A4) and with the margins it is 1137x795.
After resize my image size is 1092x682 and I am using the following code to draw it:
e.Graphics.DrawImage(printBitmap, .Margins.Left, .Margins.Top)
The annoying thing is that when I print to the PrintPreviewDialog it is scaled perfectly but when I print the exact same code to the actual printer it does not fit.
EDIT 3
Full code can be found at this url
Usage:
Dim clsPrint As New clsPrinting
With clsPrint
.Landscape = True
.SetMinimumMargins()
If .ShowPrintDialog Then
.Documentname = "Some doc name"
.Preview = False 'When True shows ok
.PrintImage("filename of a png file")
End If
End With
Try using e.graphics.VisibleClipBounds for the printable page size in the PrintPage function. As Hans said, it's better not to resize your image before printing.
You must work with MarginBounds:
in C#:
e.Graphics.DrawImage(your_image, e.MarginBounds);
in C++/CLI:
e->Graphics->DrawImage(your_image, e->MarginBounds);
Note: If your image doesn't have the same aspect ratio you'll need to adjust. In this example width of the image exceeded the page width:
Dim adjustment As Double = img.Width / e.MarginBounds.Width
e.Graphics.DrawImage(img, New Rectangle(New Point(0, 0), New Point(img.Width / adjustment, img.Height / adjustment)))
Sounds like you are wanting to print a page with a full bleed which most personal printers are not capable of. As one of the comments above mentions, factor in the margins to re-size the image to the appropriate size.
I did not find a solution to this problem. I worked around it by using the printer margins when performing a print preview and ignoring the margins (start at 0,0 origin) when actually printing. I believe that this is possibly a bug in the printer driver? But I can't confirm.
Related
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.
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.
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.
Hi I am using PDF sharp to print user input onto positions in a template document.
The data (fields) are collected from user (web page) and written at appropriate positions on the document using drawstring method.
Currently I am finding the Pixel position of each templated field in each page by trial and error .It would be much easier if there is a way to determine pixel position of each field in pdf page.
Any suggestion would be most helpful.
thanks
I had the same issue as you, josephj1989, and I found what I believe to be our answer.
According to this page in the PDFSharp documentation,
The current implementation of PDFsharp has only one layout of the graphics context. The origin (0, 0) is top left and coordinates grow right and down. The unit of measure is always point (1/72 inch).
So, say I want to draw an image 3 inches from the left and 7.5 inches from the top of an 8.5 x 11 page, then I would do something like this:
PdfDocument document = GetBlankPdfDocument();
PdfPage myPage = document.AddPage();
myPage.Orientation = PdfSharp.PageOrientation.Portrait;
myPage.Width = XUnit.FromInch(8.5);
myPage.Height = XUnit.FromInch(11);
XImage myImage = GetSampleImage();
double myX = 3 * 72;
double myY = 7.5 * 72;
double someWidth = 126;
double someHeight = 36;
XGraphics gfx = XGraphics.FromPdfPage(myPage);
gfx.DrawImage(myBarcode, myX, myY, someWidth, someHeight);
I tested this out myself with a barcode image, and I found that when you use their formula for measuring positioning, you can get a level of precision at, well, 1/72 of an inch. That's not bad.
So, at this point, it'd be good to create some kind of encapsulation for such measurements so that we're focused mostly on the task at hand and not the details of conversion.
public static double GetCoordinateFromInch(double inches)
{
return inches * 72;
}
We could go on to make other helpers in this way...
public static double GetCoordinateFromCentimeter(double centimeters)
{
return centimeters * 0.39370 * 72;
}
With such helper methods, we could do this with the previous sample code:
double myX = GetCoordinateFromInch(3);
double myY = GetCoordinateFromInch(7.5);
double someWidth = 126;
double someHeight = 36;
XGraphics gfx = XGraphics.FromPdfPage(myPage);
gfx.DrawImage(myBarcode, myX, myY, someWidth, someHeight);
I hope this is helpful. I'm sure you will write cleaner code than what is in my example. Additionally, there are probably much smarter ways to streamline this process, but I just wanted to put something here that would make immediate use of what we saw in the documentation.
Happy PDF Rendering!
When I used PDF Sharp, my approach was to make use the XUnit struct and to reference the top left point of the document as my starting point for X/Y positions.
Obviously referencing the top left point of the document (0,0) for every element on a PdfPage will get messy. To combat this, I used the XRect class to create rectangles for elements to sit within. Once the XRect is drawn onto the page, you are then able to reference the X/Y position of the rectange via the XRect's properties. Then with some basic maths using those coordinates and the width/height of the XRect, you should be able to calculate the coordinates for the position of the next element you want to add to the PdfPage.
Follow this code sample, I've provided a rough sketch of what the end result would be. The code is untested but is very heavily based on code in production right now.
// Create a new PDF document
PdfDocument document = new PdfDocument();
// Create an empty page with the default size/orientation
PdfPage page = document.AddPage();
page.Orientation = PageOrientation.Landscape;
page.Width = XUnit.FromMillimeter(300);
page.Height = XUnit.FromMillimeter(200);
// Get an XGraphics object for drawing
XGraphics gfx = XGraphics.FromPdfPage(page);
// Add the first rectangle
XUnit horizontalOffset = XUnit.FromMillimeter(5);
XUnit verticalOffset = XUnit.FromMillimeter(5);
XUnit columnWidth = XUnit.FromMillimeter(100);
XUnit columnHeight = page.Height - (2 * verticalOffset);
XRect columnRect = new XRect(horizontalOffset, verticalOffset, columnWidth, columnHeight);
gfx.DrawRectangle(XBrushes.Teal, columnRect);
// Insert an image inside the rectangle, referencing the Left and Top properties of the rectangle for image placement
XImage topLogo = XImage.FromFile(GetFilePath(#"content\img\pdfs\standard\logo-no-strapline.jpg")); // GetFilePath is a private method, not shown for brevity
gfx.DrawImage(topLogo,
columnRect.Left + XUnit.FromMillimeter(5),
columnRect.Top + XUnit.FromMillimeter(5),
columnRect.Width - XUnit.FromMillimeter(10),
XUnit.FromMillimeter(38));
And the output:
Lastly, I'm sure you're aware, but there's a good resource of PdfSharp samples here.
PDF files have no pixels and no pixel positions.
You can print PDF pages (use the "Actual size" size option) and measure positions with a ruler (this works pretty good with our printers).
Or you can use Adobe Acrobat to measure the positions of items on the PDF pages.
A bit of trial and error remains as you may have to give or take half a millimeter.
Depending on your ruler you can use XUnit.FromMillimeter or XUnit.FromInch to get the point positions for PDFsharp (but points are no pixels).
The current PDFsharp samples are here:
http://www.pdfsharp.net/wiki/PDFsharpSamples.ashx
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.