|
I am able to create a bitmap out of the coordinates which i want to plot and also can store it in an image file (bmp,jpeg, etc). Now can you please guide me that how can i step forward.. which you said as... """and then convert such canvas into special printer codes (that can be later sent with the LinePrinter class). You convert line by line, scanning from top to bottom, turning pixels into bytes and sending them after a special ESC""".
can you please tel me how can i do this all?
|
|
|
|
|
Sorry, I don't have access to a physical Line Printer right now, so I can't write and test the code for you. More or less it should be something like this:
First, you need to be able to send "bytes" to the printer with a method like this:
public void PrintByte(LinePrinter PRN, int b)
{
byte[] buf = new byte[1];
buf[0] = (byte) b;
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
string str = enc.GetString(buf);
PRN.Print(str);
}
then you need a bitmap scanning routine that converts pixels into printer codes:
public void PrintBitmap(LinePrinter PRN, Bitmap bmp)
{
int width = bmp.Width;
int height = bmp.Height - bmp.Height % 8;
int numbytes = height;
int lo = numbytes & 255;
int hi = numbytes >> 8;
for(int y=0;y<height;y+=8)
{
PrintByte(27);
PrintByte(75);
PrintByte(lo);
PrintByte(hi);
for(int x=0;x<width;x++)
{
int b = 0;
for(int i=0;i<=7;i++)
{
Color c = bmp.GetPixel(x,y+i);
if(c==Color.Black) b = b | (1 << (7-i));
}
PrintByte(b);
}
}
}
Short explanation: scanning is done from top to bottom, each line is composed of 8 vertical pixel. All is done with the "ESC K" printer command, that enables you to define and print a single line raster bit image on a single text line. From the printer manual:
• n1 and n2 define the number of bytes that comprise the image.
• The image consists of 256*n2+n1 bytes of data, each byte representing a single vertical column of
4/30".
• Images are printed left to right.
• Images are printed at a horizontal resolution of 60 dots per inch and at an approximate vertical resolution of 72 dots per inch.
• Each byte represents a vertical column of eight dots, the most significant bit representing the dot at the top. Simply set a bit to 1 if you want a dot to appear in that position, and to 0 if you want white space to appear.
As said above, I have not tested the code on a real printer so I won't be surprised if it doesn't work at first try.
|
|
|
|
|
Thankyou so much for providing me the solution, but i am really sorry i cannot understand the logic, that what are you trying to do. I have tried to understand that but i am not getting command over it so as to use it for my purpose, i have called the PrintBitmap() at the place where there we were calling MyPrinter.Print() in the LPrinter class. But (as you already anticipated), the code is not working. It isnt printing out anything. i have tried to make some changes in it but as i dont really understand the logic behind this code so i am not succesful in making modification in the code in such a way as to serve my purpose.
Please guide me, i am new in this thing. i am sending you the code so that you may point out the point where i am making mistake, i am saying again that as i dont understand the logic so i cant make this code work to serve my purpose. please help me out.
//Code..
////////////////////////////
//This is the main function where i am creating object to your LPrinter class, here i have introduced the two functions that you indicated..
using System;
using System.Windows.Forms;
using System.Drawing.Printing;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
namespace LPrinterTest
{
public partial class Form1 : Form
{
LPrinter MyPrinter;
public Form1()
{
InitializeComponent();
MyPrinter = new LPrinter();
}
private void button1_Click(object sender, EventArgs e)
{
MyPrinter.ChoosePrinter();
}
System.Drawing.Bitmap CreateBitmap()
{ // here the bitmap is being created
int x, y;
System.Drawing.Bitmap flag = new System.Drawing.Bitmap(8, 8);
for (x = 0; x < flag.Height; ++x)
for (y = 0; y < flag.Width; ++y)
flag.SetPixel(x, y, Color.Black);
for (x = 0; x < flag.Height; ++x)
flag.SetPixel(x, x, Color.Red);
return flag;
}
private void button2_Click(object sender, EventArgs e)
{
if (!MyPrinter.Open("Test Page")) return;
PrintBitmap();
MyPrinter.Close();
}
public void PrintByte(int b)
{
byte[] buf = new byte[1];
buf[0] = (byte)b;
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
string str = enc.GetString(buf);
MyPrinter.Print(str);
}
public void PrintBitmap()
{
System.Drawing.Bitmap flag;
flag = CreateBitmap();
int width = flag.Width;
int height = flag.Height - flag.Height % 8;
int numbytes = height;
int lo = numbytes & 255;
int hi = numbytes >> 8;
for (int y = 0; y < height; y += 8)
{
PrintByte(27);
PrintByte(75);
PrintByte(lo);
PrintByte(hi);
for (int x = 0; x < width; x++)
{
int b = 0;
for (int i = 0; i <= 7; i++)
{
Color c = flag.GetPixel(x, y + i);
if (c == Color.White)
b = b | (1 << (7 - i));
}
PrintByte(b);
}
}
}
}
}
|
|
|
|
|
try with a larger bitmap (8x8 is very small), e.g. 300x300 and debug what values are being passed to the PrintByte() method. The bitmap should be monochromatic, Color.Red is not possible; use Color.Black and Color.White only. Correct also if(c==Color.White) into if(c==Color.Black) unless you want a "negative" image.
Try also running this small test:
for(int y=0;y<9;y++)
{
int lo=100;
int hi = 0;
PrintByte(27);
PrintByte(75);
PrintByte(lo);
PrintByte(hi);
for(int x = 0; x<100; x++) PrintByte(255);
}
it should come out a black square.
Sorry, this is all I can do without having access to a real Line Printer.
|
|
|
|
|
ok... Thankyou so much. but can you tell me that whether i am calling the functions correctly at the correct places?
Also one problem is that as the Line printer class does not eject paper unless we provide it with "\n\r" then how can we print the paper unless we dont give it the linefeed or so. Considering this if i write the code in such a way that after calling the PrintBitmap() i call MyPrinter.Writeprinter() then the printer just takes into account the linefeed and ejects blank paper without printing anything on it.
|
|
|
|
|
yes the function calls are seemingly correct. Please report the result of the test of my previous message: did you see a black rectangle printed on paper?
I haven't understood your question about line feeds; each TEXT line must be followed by "\r\n". The whole paper sheet can be ejected with the special code "Form Feed" (see article). If I remember well, graphics printing doesn't need line feeds (but I might be wrong).
If you have further questions please write me privately, my email is iz8bly at yahoo.it. Specify the type of printer you are using and attach the result of your print testings (jpgs,whatever).
|
|
|
|
|
Yes a dotted black square is coming out using that test code.
But my Bit map printing is not giving any results. It doesnot print out anything. So it seems that there is some problem with the handling of the bitmap image. I have displayed that bitmap into a picture box and the picture box shows the image, so it means that the bitmap has been created succesfully but there is some problem with my using that bitmap into the PrintBitmap() function. Here is my code. Can you please guide me about the problem.
I am only pasting those functions which are seemingly causing problems (not the whole form class)
//creating bitmap
System.Drawing.Bitmap CreateBitmap()
{
int x, y;
System.Drawing.Bitmap flag = new System.Drawing.Bitmap(300, 300);
for (x = 0; x < flag.Height; ++x)
for (y = 0; y < flag.Width; ++y)
flag.SetPixel(x, y, Color.White);
for (x = 0; x < flag.Height; ++x)
flag.SetPixel(x, x, Color.Black);
return flag;
}
//the print button
private void button2_Click(object sender, EventArgs e)
{
if (!MyPrinter.Open("Test Page")) return;
PrintBitmap();
MyPrinter.Print("\n\r");
MyPrinter.Close();
}
public void PrintByte(int b)
{
byte[] buf = new byte[1];
buf[0] = (byte)b;
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
string str = enc.GetString(buf);
MyPrinter.Print(str);
}
public void PrintBitmap()
{
System.Drawing.Bitmap flag;
flag = CreateBitmap(); //calling bitmap creating function
pictureBox1.Image = flag;
int width = flag.Width;
int height = flag.Height - flag.Height % 8;
int numbytes = height;
int lo = numbytes & 255;
int hi = numbytes >> 8;
for (int y = 0; y < height; y += 8)
{
PrintByte(27);
PrintByte(75);
PrintByte(lo);
PrintByte(hi);
for (int x = 0; x < width; x++)
{
int b = 0;
for (int i = 0; i <= 7; i++)
{
Color c = flag.GetPixel(x, y + i);
if (c == Color.Black)
b = b | (1 << (7 - i));
}
PrintByte(b);
}
}
}
|
|
|
|
|
ok, found 2 bugs...
First is int numbytes = width; not int numbytes = height;
Second bug is in the if(c==Color.Black) , for some reason the test fails even if the color is Black. I've changed it to if(c.GetBrightness()<0.5) so it works even with color bitmaps, not only black and white.
The method is now:
public void PrintBitmap()
{
System.Drawing.Bitmap flag = CreateBitmap();
pictureBox1.Image = flag;
int width = flag.Width;
int height = flag.Height - flag.Height % 8;
int numbytes = width;
int lo = numbytes & 255;
int hi = numbytes >> 8;
for (int y = 0; y < height; y += 8)
{
PrintByte(27);
PrintByte(75);
PrintByte(lo);
PrintByte(hi);
for (int x = 0; x < width; x++)
{
int b = 0;
for (int i = 0; i <= 7; i++)
{
Color c = flag.GetPixel(x, y + i);
if(c.GetBrightness()<0.5)
{
b = b | (1 << (7 - i));
}
}
PrintByte(b);
}
}
}
tell me if it does work.
|
|
|
|
|
I have made these changes. Sorry it is still not working. Even the printer spooler is not moving and page is not coming out. I cant figure out the problem...
|
|
|
|
|
oh it is printing out something now... but that is not my image, the shape being printed resembles my bitmap image and has a very small size,and is being printed twice in one line..
|
|
|
|
|
increase the size of the bitmap and, if you can, send me a snapshot of the output. My email is iz8bly at yahoo.it
|
|
|
|
|
Yes your test code is printing out a dotted rectangle.
but my bitmap printing is not giving any esults, it is printing out just nothing.. It shows that i am not handling the bitnmap image correctly in the PrintBitmap function. i have displayed that image into a picture box, and the picture box is showing correcrt results, it means that that bitmao has been created succesfully but there is some problem with my handling that image into the PrintBitmap() function. Kindly help me in this regard.
The printer which i am using is thermal printer, Brother pocketJet3 Plus (PJ523).
I have debugged the code to check the values of buf, b, str etc.
b=27;
buf[0]=27;
str value is something i cant understand. it is just a box displayed there, perhaps that is a garbage value or something i dont know.
Kindly guide me in this regard. i shall be very thankful.
Here is my code, i am pasting only those functions which are creating problem.
stem.Drawing.Bitmap CreateBitmap()
{
int x, y;
System.Drawing.Bitmap flag = new System.Drawing.Bitmap(300, 300);
for (x = 0; x < flag.Height; ++x)
for (y = 0; y < flag.Width; ++y)
flag.SetPixel(x, y, Color.White);
for (x = 0; x < flag.Height; ++x)
flag.SetPixel(x, x, Color.Black);
return flag;
}
//the print button
private void button2_Click(object sender, EventArgs e)
{
if (!MyPrinter.Open("Test Page")) return;
PrintBitmap();
//MyPrinter.Print("\n\r");
MyPrinter.Close();
}
public void PrintByte(int b)
{
byte[] buf = new byte[1];
buf[0] = (byte)b;
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
string str = enc.GetString(buf);
MyPrinter.Print(str);
}
public void PrintBitmap()
{
System.Drawing.Bitmap flag;
flag = CreateBitmap(); //calling the function which creates bitmap
pictureBox1.Image = flag;
int width = flag.Width;
int height = flag.Height - flag.Height % 8;
int numbytes = height;
int lo = numbytes & 255;
int hi = numbytes >> 8;
for (int y = 0; y < height; y += 8)
{
PrintByte(27);
PrintByte(75);
PrintByte(lo);
PrintByte(hi);
for (int x = 0; x < width; x++)
{
int b = 0;
for (int i = 0; i <= 7; i++)
{
Color c = flag.GetPixel(x, y + i);
if (c == Color.Black)
b = b | (1 << (7 - i));
}
PrintByte(b);
}
}
}
}
|
|
|
|
|
what this can printing for image ?
|
|
|
|
|
How to print unicode characters and set the printing font size?
Do I have to send the .Print("\x0e") first before printing the rest of the texts?
|
|
|
|
|
yes, use the "\x0e" code (or any other, see below) before the rest of the text.
As for printing unicode characters, the Print method already does the conversion from char to Ansi. So if you have a string of plain text there is no conversion to do. The problem arises when you try to print non-Ansi characters (e.g. foreign languages characters) because line printers are only able to output standard Ascii characters.
Some useful codes:
* 14 = enlarged on
* 20 = enlarged off
* 15 = compress on
* 18 = compress off
* ESC + "E" = bold on
* ESC + "F" = bold off
|
|
|
|
|
Thanks a lot. But one thing I am still unclear is how to print in different font size. After issuing
.Print("\X0E")
what is the statement to set the font size?
|
|
|
|
|
the font size is implicit, e.g. "compressed" means font size=17 cpi; "enlarged" means fonts size=6 cpi and so on. You have to work only with these sizes, you cannot set arbitrary sizes like in truetype fonts (unless you switch to graphics mode).
|
|
|
|
|
Have tried "\x0E" but the printer still prints with the normal character. I print to the HP laser printer. Nothing wrong with the codes below, right?
Printer.Print("\x0E");
for (int i = 0; i < 100; ++i)
{
Printer.Print("Line " + i.ToString() + ControlChars.CrLf.ToString());
}
Printer.Close();
|
|
|
|
|
Is it just because the laser printer is a graphical printer, the \x0E is not recognized? How about Epson LQ-300+ dot matrix printer?
|
|
|
|
|
yes, it won't work on laser printers, although there are some models that offer an emulation mode mode (quite rare).
Any other dot matrix printer should work.
|
|
|
|
|
Thanks for the info. Will wait to try it on the dot matrix printer sometime later this week!
|
|
|
|
|
Seems that this code doesnt work as only the first line gets to be printed in enlarged font.
Printer.Print("\x0E");
for (int i = 0; i < 100; ++i)
{
Printer.Print("Line " + i.ToString() + ControlChars.CrLf.ToString());
}
Printer.Close();
Enlarged font means for Epson LQ-300+ means the height of each character remains the same. What is changed is the width of each character.
To make the code above works I did this:
for (int i = 0; i < 100; ++i)
{
Printer.Print("\x0E" + "Line " + i.ToString() + ControlChars.CrLf.ToString());
}
Printer.Close();
Thanks for your wisdom!
|
|
|
|
|
it looks like your printer is resetting the font command on every new line. Rather strange. From what I remember, the font size command stays active until next command is issued or printer is reset (ESC @) or turned off-on.
As regards the height remaining the same, this is by design. The printing head can only print one single horizontal line at time, so you can't print something that spawns across two lines.
|
|
|
|
|
Hello there. This is a piece of great code. It would be a perfect one for me if you can point to me the way to set the font and font size. the font cuold be a TrueType fonts also.
Thanks a lot!
|
|
|
|
|
Font selection is not a standard feature, so you have to find its escape code sequence (if supported by your printer). Usually the font list is rather limited, e.g. Draft (quick but low quality), Roman, Courier or LQ (letter quality, slow but very readable).
Also, there is no way to print True Type fonts unless you switch from "text" mode to graphics mode. But if you want to use graphics mode, there is no need for the C# class, as the standard Windows printer driver already prints in graphics mode.
|
|
|
|