I have been trying to print a barcode image via the label printer. but the image that is printing using the SATO CG408 printer is very small. Here is the code as it is currently.
static void Main(string[] args)
{
try
{
PrintDocument pd = new PrintDocument();
pd.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("Custom", 100, 77);
//We want potrait.
pd.DefaultPageSettings.Landscape = false;
pd.PrintPage += PrintPage;
pd.Print();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
private static void PrintPage(object o, PrintPageEventArgs e)
{
//System.Drawing.Image img = System.Drawing.Image.FromFile(#"c:\test\test.png");
//img.RotateFlip(RotateFlipType.Rotate90FlipNone);
//e.Graphics.DrawImage(img,0,0);
int printHeight = 450;
int printWidth = 400;
int leftMargin = 20;
int rightMargin = 0;
System.Drawing.Image img = System.Drawing.Image.FromFile(#"c:\test\test.png");
img.RotateFlip(RotateFlipType.Rotate90FlipNone);
e.Graphics.DrawImage(img, new Rectangle(leftMargin, rightMargin, printWidth, printHeight));
}
Not really sure why the image is displaying small. The image that is being printed is generated at a different server. The image size is 2480px by 1748px.
Can some one please help. Trying to solve this for the past few days. Thanks in advance.
maybe you should set your direction ...
try this:
pd.DefaultPageSettings.Landscape = true;
Try to remove margins
int leftMargin = 0;
int rightMargin = 0;
and check imgage ratio: 2480px / 1748px ~ 1.419, 400px / 450px~ 0,889. So maybe try:
int printHeight = 420;
int printWidth = 596;
The problem was that the printer had the wrong dimensions set up for the paper. Thats why it was printing so small. Feel silly now. Thanks all for help.
Related
In C#, I am trying to print an image using PrintDocument class with the below code. The image is of size 1200 px width and 1800 px height. I am trying to print this image in a 4*6 paper using a small zeebra printer. But the program is printing only 4*6 are of the big image. that means it is not adjusting the image to the paper size !
PrintDocument pd = new PrintDocument();
pd.PrintPage += (sender, args) =>
{
Image i = Image.FromFile("C://tesimage.PNG");
Point p = new Point(100, 100);
args.Graphics.DrawImage(i, 10, 10, i.Width, i.Height);
};
pd.Print();
When i print the same image using Window Print (right click and select print, it is scaling automatically to paper size and printing correctly. that means everything came in 4*6 paper.) How do i do the same in my C# program ?
The parameters that you are passing into the DrawImage method should be the size you want the image on the paper rather than the size of the image itself, the DrawImage command will then take care of the scaling for you. Probably the easiest way is to use the following override of the DrawImage command.
args.Graphics.DrawImage(i, args.MarginBounds);
Note: This will skew the image if the proportions of the image are not the same as the rectangle. Some simple math on the size of the image and paper size will allow you to create a new rectangle that fits in the bounds of the paper without skewing the image.
Not to trample on BBoy's already decent answer, but I've done the code that maintains aspect ratio. I took his suggestion, so he should get partial credit here!
PrintDocument pd = new PrintDocument();
pd.DefaultPageSettings.PrinterSettings.PrinterName = "Printer Name";
pd.DefaultPageSettings.Landscape = true; //or false!
pd.PrintPage += (sender, args) =>
{
Image i = Image.FromFile(#"C:\...\...\image.jpg");
Rectangle m = args.MarginBounds;
if ((double)i.Width / (double)i.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)i.Height / (double)i.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)i.Width / (double)i.Height * (double)m.Height);
}
args.Graphics.DrawImage(i, m);
};
pd.Print();
The solution provided by BBoy works fine. But in my case I had to use
e.Graphics.DrawImage(memoryImage, e.PageBounds);
This will print only the form. When I use MarginBounds it prints the entire screen even if the form is smaller than the monitor screen. PageBounds solved that issue. Thanks to BBoy!
You can use my code here
//Print Button Event Handeler
private void btnPrint_Click(object sender, EventArgs e)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += PrintPage;
//here to select the printer attached to user PC
PrintDialog printDialog1 = new PrintDialog();
printDialog1.Document = pd;
DialogResult result = printDialog1.ShowDialog();
if (result == DialogResult.OK)
{
pd.Print();//this will trigger the Print Event handeler PrintPage
}
}
//The Print Event handeler
private void PrintPage(object o, PrintPageEventArgs e)
{
try
{
if (File.Exists(this.ImagePath))
{
//Load the image from the file
System.Drawing.Image img = System.Drawing.Image.FromFile(#"C:\myimage.jpg");
//Adjust the size of the image to the page to print the full image without loosing any part of it
Rectangle m = e.MarginBounds;
if ((double)img.Width / (double)img.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)img.Height / (double)img.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)img.Width / (double)img.Height * (double)m.Height);
}
e.Graphics.DrawImage(img, m);
}
}
catch (Exception)
{
}
}
Answer:
public void Print(string FileName)
{
StringBuilder logMessage = new StringBuilder();
logMessage.AppendLine(string.Format(CultureInfo.InvariantCulture, "-------------------[ START - {0} - {1} -------------------]", MethodBase.GetCurrentMethod(), DateTime.Now.ToShortDateString()));
logMessage.AppendLine(string.Format(CultureInfo.InvariantCulture, "Parameter: 1: [Name - {0}, Value - {1}", "None]", Convert.ToString("")));
try
{
if (string.IsNullOrWhiteSpace(FileName)) return; // Prevents execution of below statements if filename is not selected.
PrintDocument pd = new PrintDocument();
//Disable the printing document pop-up dialog shown during printing.
PrintController printController = new StandardPrintController();
pd.PrintController = printController;
//For testing only: Hardcoded set paper size to particular paper.
//pd.PrinterSettings.DefaultPageSettings.PaperSize = new PaperSize("Custom 6x4", 720, 478);
//pd.DefaultPageSettings.PaperSize = new PaperSize("Custom 6x4", 720, 478);
pd.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
pd.PrinterSettings.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
pd.PrintPage += (sndr, args) =>
{
System.Drawing.Image i = System.Drawing.Image.FromFile(FileName);
//Adjust the size of the image to the page to print the full image without loosing any part of the image.
System.Drawing.Rectangle m = args.MarginBounds;
//Logic below maintains Aspect Ratio.
if ((double)i.Width / (double)i.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)i.Height / (double)i.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)i.Width / (double)i.Height * (double)m.Height);
}
//Calculating optimal orientation.
pd.DefaultPageSettings.Landscape = m.Width > m.Height;
//Putting image in center of page.
m.Y = (int)((((System.Drawing.Printing.PrintDocument)(sndr)).DefaultPageSettings.PaperSize.Height - m.Height) / 2);
m.X = (int)((((System.Drawing.Printing.PrintDocument)(sndr)).DefaultPageSettings.PaperSize.Width - m.Width) / 2);
args.Graphics.DrawImage(i, m);
};
pd.Print();
}
catch (Exception ex)
{
log.ErrorFormat("Error : {0}\n By : {1}-{2}", ex.ToString(), this.GetType(), MethodBase.GetCurrentMethod().Name);
}
finally
{
logMessage.AppendLine(string.Format(CultureInfo.InvariantCulture, "-------------------[ END - {0} - {1} -------------------]", MethodBase.GetCurrentMethod().Name, DateTime.Now.ToShortDateString()));
log.Info(logMessage.ToString());
}
}
Agree with TonyM and BBoy - this is the correct answer for original 4*6 printing of label. (args.PageBounds). This worked for me for printing Endicia API service shipping Labels.
private void SubmitResponseToPrinter(ILabelRequestResponse response)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += (sender, args) =>
{
Image i = Image.FromFile(response.Labels[0].FullPathFileName.Trim());
args.Graphics.DrawImage(i, args.PageBounds);
};
pd.Print();
}
all these answers has the problem, that's always stretching the image to pagesize and cuts off some content at trying this.
Found a little bit easier way.
My own solution only stretch(is this the right word?) if the image is to large, can use multiply copies and pageorientations.
PrintDialog dlg = new PrintDialog();
if (dlg.ShowDialog() == true)
{
BitmapImage bmi = new BitmapImage(new Uri(strPath));
Image img = new Image();
img.Source = bmi;
if (bmi.PixelWidth < dlg.PrintableAreaWidth ||
bmi.PixelHeight < dlg.PrintableAreaHeight)
{
img.Stretch = Stretch.None;
img.Width = bmi.PixelWidth;
img.Height = bmi.PixelHeight;
}
if (dlg.PrintTicket.PageBorderless == PageBorderless.Borderless)
{
img.Margin = new Thickness(0);
}
else
{
img.Margin = new Thickness(48);
}
img.VerticalAlignment = VerticalAlignment.Top;
img.HorizontalAlignment = HorizontalAlignment.Left;
for (int i = 0; i < dlg.PrintTicket.CopyCount; i++)
{
dlg.PrintVisual(img, "Print a Image");
}
}
I guess I miss something when it comes to printing files. I read all bytes out of a png image and send them to printer's job stream. However I get bytes printed out and not the image itself. I guess I need proper print format.
This is the link containing code I am using:
http://support.microsoft.com/kb/322091/en
Any ideas?
Sending raw data to a printer doesn't mean just dumping the contents of a file to the printer queue. To send raw data to a printer you would need to be sending PCL, PS or some other equivalent data which tells the printer how to print your document.
You'll likely need to use the System.Drawing.Printing.PrintDocument class.
Edit: There is a good example of how to print an image here on SO:
Printing image with PrintDocument. how to adjust the image to fit paper size
PrintDocument pd = new PrintDocument();
pd.DefaultPageSettings.PrinterSettings.PrinterName = "Printer Name";
pd.DefaultPageSettings.Landscape = true; //or false!
pd.PrintPage += (sender, args) =>
{
Image i = Image.FromFile(#"C:\...\...\image.jpg");
Rectangle m = args.MarginBounds;
if ((double)i.Width / (double)i.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)i.Height / (double)i.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)i.Width / (double)i.Height * (double)m.Height);
}
args.Graphics.DrawImage(i, m);
};
pd.Print();
I think you can use my code here:
//Print Button Event Handeler
private void btnPrint_Click(object sender, EventArgs e)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += PrintPage;
//here to select the printer attached to user PC
PrintDialog printDialog1 = new PrintDialog();
printDialog1.Document = pd;
DialogResult result = printDialog1.ShowDialog();
if (result == DialogResult.OK)
{
pd.Print();//this will trigger the Print Event handeler PrintPage
}
}
//The Print Event handeler
private void PrintPage(object o, PrintPageEventArgs e)
{
try
{
if (File.Exists(this.ImagePath))
{
//Load the image from the file
System.Drawing.Image img = System.Drawing.Image.FromFile(#"C:\myimage.jpg");
//Adjust the size of the image to the page to print the full image without loosing any part of it
Rectangle m = e.MarginBounds;
if ((double)img.Width / (double)img.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)img.Height / (double)img.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)img.Width / (double)img.Height * (double)m.Height);
}
e.Graphics.DrawImage(img, m);
}
}
catch (Exception)
{
}
}
I am using the PrintDocument class to print to my Brother label printer. When I execute the Print() method, the printer starts flashing a red error light, but everything else returns successful.
I can run this same code on my laser printer and everything works fine.
How can I see what is causing the error on my label printer?
Code:
public class Test
{
private Font printFont;
private List<string> _documentLinesToPrint = new List<string>();
public void Run()
{
_documentLinesToPrint.Add("Test1");
_documentLinesToPrint.Add("Test2");
printFont = new Font("Arial", 10);
var pd = new PrintDocument();
pd.DefaultPageSettings.Margins = new Margins(25, 25, 25, 25);
pd.DefaultPageSettings.PaperSize = new PaperSize("Label", 400, 237);
var printerSettings = new System.Drawing.Printing.PrinterSettings();
printerSettings.PrinterName ="Brother QL-570 LE";
pd.PrinterSettings = printerSettings;
pd.PrinterSettings.Copies = 1;
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();
}
// The PrintPage event is raised for each page to be printed.
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
float linesPerPage = 0;
float yPos = 0;
int count = 0;
float leftMargin = ev.MarginBounds.Left;
float topMargin = ev.MarginBounds.Top;
string line = null;
// Calculate the number of lines per page.
linesPerPage = ev.MarginBounds.Height /
printFont.GetHeight(ev.Graphics);
// Print each line of the file.
while ((count < linesPerPage) && (count < _documentLinesToPrint.Count))
{
line = _documentLinesToPrint[count];
yPos = topMargin + (count *
printFont.GetHeight(ev.Graphics));
ev.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
line = null;
count++;
}
// If more lines exist, print another page.
if (line != null)
ev.HasMorePages = true;
else
ev.HasMorePages = false;
}
}
PrintDocument is a very basic API. You get simple generic printing, but it comes at the cost of reduced functionality not specific to the print driver. My HP printer usually gives me a printed error rather than an Exception. Its not surprising to see something similar happening to you.
The blinking is likely a code that you can lookup. If that fails you can try saving to an Image format, PDF or XPS. Or use a 3rd party library or write your own PCL file. There's a ton of options. Creating an output you can view as opposed to one in memory should debugging calculations like margins. You can look at a PDF and see if it looks wacky. Just keep in mind the way it looks on the PC may be slightly different than the output especially when printing near the edges.
I could be completely wrong on this, but my understanding is that when you print with this code, it has nothing to do with the printer itself, but with the operating system. Windows sets up a print queue, places the output in it, and your code returns.
Then Windows takes items off of the queue and sends them through the printer driver and to your printer. If there's an error in printing, it should show up as a failed document in the print queue. I think it's too late to trap the error as an exception at this stage.
Please correct me if I am mistaken.
I would surround your the method bodies using a Try/Catch Block then handle the exception(s) within the catch of each method. As an example:
public class Test
{
private Font printFont;
private List<string> _documentLinesToPrint = new List<string>();
public void Run()
{
try
{
_documentLinesToPrint.Add("Test1");
_documentLinesToPrint.Add("Test2");
printFont = new Font("Arial", 10);
var pd = new PrintDocument();
pd.DefaultPageSettings.Margins = new Margins(25, 25, 25, 25);
pd.DefaultPageSettings.PaperSize = new PaperSize("Label", 400, 237);
var printerSettings = new System.Drawing.Printing.PrinterSettings();
printerSettings.PrinterName = "Brother QL-570 LE";
pd.PrinterSettings = printerSettings;
pd.PrinterSettings.Copies = 1;
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();
}
catch (InvalidPrinterException exc)
{
// handle your errors here.
}
catch (Exception ex)
{
// handle your errors here.
}
}
// The PrintPage event is raised for each page to be printed.
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
try
{
float linesPerPage = 0;
float yPos = 0;
int count = 0;
float leftMargin = ev.MarginBounds.Left;
float topMargin = ev.MarginBounds.Top;
string line = null;
// Calculate the number of lines per page.
linesPerPage = ev.MarginBounds.Height /
printFont.GetHeight(ev.Graphics);
// Print each line of the file.
while ((count < linesPerPage) && (count < _documentLinesToPrint.Count))
{
line = _documentLinesToPrint[count];
yPos = topMargin + (count *
printFont.GetHeight(ev.Graphics));
ev.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
line = null;
count++;
}
// If more lines exist, print another page.
if (line != null)
ev.HasMorePages = true;
else
ev.HasMorePages = false;
}
catch (InvalidPrinterException exc)
{
// handle your errors here.
}
catch (Exception ex)
{
// handle your errors here.
}
}
}
I am trying to print a multidimensional tiff. This tiff is having 3 Pages using variable imagetoprint. So I wrote following code, that unfortunately only prints the first dimension. All others are printed on empty paper. If I save the image from memory to file, irfanview shows all pages correctly...
Who can give me a hint ?
public void print(Bitmap imageToPrint, string printerName, int pagesToPrint)
{
try
{
printmap = imageToPrint;
cur_page = 0;
max_pages = pagesToPrint;
m.Top = 1 * dpi; // Set a 1' margin, from the top
m.Left = 1.25f * dpi; // Set a 1.25' margin, from the left
m.Bottom = printmap.Height - m.Top; // 1', from the bottom
m.Right = printmap.Width; // rechter Rand so weit wie es eben geht
m.Width = printmap.Width - (m.Left * 2); // Get the width of our working area
m.Height = printmap.Height - (m.Top * 2); // Get the height of our working area
pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
if (printerName != "")
pd.DefaultPageSettings.PrinterSettings.PrinterName = printerName;
pd.DefaultPageSettings.Color = true;
pd.DefaultPageSettings.PrinterSettings.PrintFileName = "tiffprint";
pd.DocumentName = "InstantFormsPrinting";
if (m.Width > m.Height)
{
pd.DefaultPageSettings.Landscape = true;
}
pd.Print(); // Print
}
catch (Exception ex)
{
Console.WriteLine("Error during print preparation:" + ex.Message);
}
}
// Our printing event
public void pd_PrintPage(object sender, PrintPageEventArgs e)
{
Rectangle crop = new Rectangle(1, 1, 200, 200);
try
{
printmap.SelectActiveFrame(FrameDimension.Page, cur_page);
e.Graphics.DrawImageUnscaled(printmap, new Point(0, 0));
++cur_page;
e.HasMorePages = (cur_page < max_pages);
}
catch (Exception ex)
{
Console.WriteLine("Error during print operation:" + ex.Message);
}
}
On Page 2 pd_PrintPage thows an exception with "general gdi problem"
I have no idea so far. It would be very nice if somebody can help.
You could extract the pages into single bitmaps before you start printing.
Okay, before you spam me with StringFormat.Alignment = StringAlignment.Center ... hear my whole issue:
When I draw text with the following code, the string is centered in the PrintPreview, but NOT CENTERED on the actual paper when it prints. The whole page is off to the right just a little, thus some stuff shows as printing on the print preview, but falls off the paper (not just outside the margin range, but OFF the paper) when printed.
private void button1_Click(object sender, EventArgs e)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
PrintPreviewDialog ppd = new PrintPreviewDialog();
((Form)ppd).WindowState = FormWindowState.Maximized;
ppd.Document = pd;
ppd.ShowDialog();
}
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
for (int y = 100; y < 400; y += 25)
{
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(5, y, 840, 25));
}
e.HasMorePages = false;
}
Any thoughts as to why it's off? This should be trivial, but it isn't.
EDIT: I've found that it's not just text... It's printing EVERYTHING off just a little. I've updated the code above to provide a better example of the issue. Just drop this in a form with a button on it.
EDIT 2: With the answer given, I've modified the code and this now works. I'm providing the final code for those that may want to see it. I have to recognize whether i'm seeing this in the PrintPreview dialog or on paper, so I have a IsPreview flag to handle this.
public partial class Form1 : Form
{
bool IsPreview = true;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
IsPreview = true;
PrintDocument pd = new PrintDocument();
pd.EndPrint += new PrintEventHandler(pd_EndPrint);
pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
PrintPreviewDialog ppd = new PrintPreviewDialog();
((Form)ppd).WindowState = FormWindowState.Maximized;
ppd.Document = pd;
ppd.ShowDialog();
}
void pd_EndPrint(object sender, PrintEventArgs e)
{
IsPreview = false;
}
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
Rectangle b3 = e.PageBounds;
if (IsPreview)
{
e.Graphics.TranslateTransform(e.PageSettings.HardMarginX, e.PageSettings.HardMarginY);
}
b3.Width -= (int)e.PageSettings.HardMarginX * 2;
b3.Height -= (int)e.PageSettings.HardMarginY * 3;
int y = b3.Y;
int x=0;
while ((y + 25) < b3.Bottom)
{
x++;
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
Rectangle R = new Rectangle(b3.X, y, b3.Width, 25);
e.Graphics.DrawRectangle(Pens.Black, R);
e.Graphics.DrawString(x.ToString(), this.Font, Brushes.Black, b3.X + 5, y + 5);
y += 25;
}
// draw the last little bit
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(b3.X, y, b3.Width, b3.Height - y));
e.HasMorePages = false;
}
}
Being off towards the right tends to be explainable by the value of the PageSettings.HardMarginX property. A value produced by the printer driver. Printer drivers are however typically not very good at guessing what the actual paper route through the printer might look like. That's mechanical, pinch rollers, tray alignment and whatnot. Software and Mechanical engineers don't have lunch together often enough.
But a software engineer can almost always fix a mechanical engineer's problem. You'll need an Options dialog to allow the user to fix the mechanical engineer's problem. Use the value in e.Graphics.TranslateTransform call.
The reason the preview doesn't match up to the paper is because you haven't selected a printer yet. Every printer is a bit different for things like unprintable areas, forced margins, etc. It's been a while since I've done winforms printing, but I do recall that the passed graphics object has a way to account for that.