I'm trying to print my language characters to a POS printer. The Printer prints well but the result's so bad. This is what I tried:
using (MemoryStream ms = new MemoryStream())
using (BinaryWriter bw = new BinaryWriter(ms))
{
bw.Write(AsciiControlChars.Escape);
bw.Write('#');
//ESCCMD.RenderBitmap(bw, logo);
bw.Write("Đây là Tiếng Việt");
bw.Write(AsciiControlChars.Escape);
bw.Write('d');
bw.Write((byte)3);
// Feed 3 vertical motion units and cut the paper with a 1 point uncut
bw.Write(AsciiControlChars.GroupSeparator);
bw.Write(AsciiControlChars.V);
bw.Write((byte)66);
bw.Write((byte)3);
bw.Flush();
RawPrinterHelper.SendToSerialPort(ms.ToArray(), txtPortTest.Text, Convert.ToInt32(cbbBaudRate.SelectedValue));
}
So how can I print my language characters using ESC/POS command?
Thanks so much!
Before printing international characters you need to check if your specific model supports the corresponding codepage and then set it with the ESC t command. The list of supported code pages for EPSON printers and the command syntax info is available here: https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=32 (registration required)
For example, in order to print Greek (ISO-8859-7) text, you need to do something like this:
private void PrintGreekIsoText(BinaryWriter bw, string text)
{
// ESC t 15
bw.Write("\x1bt\x15");
// Convert the text to the appropriate encoding
var isoEncoding = Encoding.GetEncoding(28597);
var bytes = Encoding.Unicode.GetBytes(text);
byte[] output = Encoding.Convert(Encoding.Unicode, isoEncoding, bytes);
bw.Write(output);
}
Related
I'm trying to create a QR barcode in .NET using IronBarcode.
I'm following their tutorial for writing binary data, but it isn't working working with Arabic text for some reason. It works great with any English that I input, but with Arabic the console output is ?????. I've tried UTF8, UTF7 but nothing seems to be working.
Tutorial:
https://ironsoftware.com/csharp/barcode/tutorials/csharp-qr-code-generator/#reading-and-writing-binary-data
My code is:
using IronBarCode;
var Msg = "مرحبا";
byte[] BinaryData = System.Text.Encoding.UTF8.GetBytes(Msg);
var bitmap = IronBarCode.QRCodeWriter.CreateQrCode(BinaryData,500, IronBarCode.QRCodeWriter.QrErrorCorrectionLevel.Highest).ToBitmap();
var barcodeResult = IronBarCode.BarcodeReader.ReadASingleBarcode(bitmap);
var stringResult = System.Text.Encoding.UTF8.GetString(barcodeResult.BinaryValue);
Console.WriteLine(stringResult) // outputs '?????'
Please can someone advise what I'm missing?
var Msg = "هذا لا يعمل";
byte[] BinaryData = System.Text.Encoding.UTF8.GetBytes(Msg);
var bitmap = IronBarCode.QRCodeWriter.CreateQrCode(BinaryData, 500, IronBarCode.QRCodeWriter.QrErrorCorrectionLevel.Highest).ToBitmap();
var barcodeResult = IronBarCode.BarcodeReader.ReadASingleBarcode(bitmap);
var stringResult =
System.Text.Encoding.UTF8.GetString(barcodeResult.BinaryValue);
// stringResult is "هذا لا يعمل"
The issue you are seeing is that Console.WriteLine doesn’t support Arabic characters in Visual Studio. It prints "?????" for all non-Roman characters.
You can verify the correct result by saving to file, or putting in a debugging breakpoint and hover over the variable in Visual Studio.
This video explains the issue, and also has a work-around:
https://m.youtube.com/watch?v=rTqBnJ8HrSc
Console.OutputEncoding = System.Text.Encoding.Unicode;
I am very new in ESC POS command. I have uploaded images to printer memory. I am able to print required image with utility comes with printer. I want to print image from my application. I don't know really how to print it using C#. I am using below code to print but it is not printing anything. Can you please guide me how to print image using C#.
public void PrintImage()
{
const string FS = "\u001C";
string command = FS + "p11";
WriteLine(command);
}
public void WriteLine(string text)
{
WriteToBuffer(text);
_writeByte(10);
System.Threading.Thread.Sleep(WriteLineSleepTimeMs);
}
private void _writeByte(byte valueToWrite)
{
byte[] tempArray = {valueToWrite};
_serialPort.Write(tempArray,0,1);
}
Basically, ESC/POS prints with byte[] instead of string(Unicode).
Actually, WriteToBuffer() seems to send the character string and command of the print request, but if there is no source for this part, an accurate answer cannot be made.
The command you are going to use is this one, which prints the NV image defined by the "FS q" command.
This is a deprecated(non-recommended?/obsolete?) mode in the included utility and should not be used.
FS p [obsolete command] : Print NV bit image
FS q [obsolete command] : Define NV bit image
However, if you really want to use the "FS p" command, the byte data sent to the printer will be:
byte[] NVimageCmd = { 0x1c, 0x70, 0x01, 0x31 };
The NV image number that should be specified is the numeric value 1 (0x01), not the character '1'.
Another command is currently recommended for use, as described below in the command description above.
[Recommended Functions]
This function is supported only by some printer models and may not be supported by future models. It is recommended that NV graphics function (GS ( L / GS 8 L: GS ( L <Function 51> and GS ( L <Function 64> – GS ( L <Function 69>) be used because they offer the following additional features:
Use the following command to print the NV image registered with the supplied utility.
kc1 and kc2 are the key codes specified when registering.
GS ( L <Function 69> : Print the specified NV graphics data.
By the way, if the printer and utility are in Advanced Printer Driver mode, send the control font according to the explanation of that mode.
I use tesseract for detecting characters on image.
try
{
using (var engine = new TesseractEngine(#"C:\Users\ea\Documents\Visual Studio 2015\Projects\ocrtTest", "eng", EngineMode.Default))
{
using (var img = Pix.LoadFromFile(testImagePath))
{
Bitmap src = (Bitmap)Image.FromFile(testImagePath);
using (var page = engine.Process(img))
{
var text = page.GetHOCRText(1);
File.WriteAllText("test.html", text);
//Console.WriteLine("Text: {0}", text);
//Console.WriteLine("Mean confidence: {0}", page.GetMeanConfidence());
int p = 0;
int l = 0;
int w = 0;
int s = 0;
int counter = 0;
using (var iter = page.GetIterator())
{
iter.Begin();
do
{
do
{
do
{
do
{
do
{
//if (iter.IsAtBeginningOf(PageIteratorLevel.Block))
//{
// logger.Log("New block");
//}
if (iter.IsAtBeginningOf(PageIteratorLevel.Para))
{
p++;//counts paragraph
//logger.Log("New paragraph");
}
if (iter.IsAtBeginningOf(PageIteratorLevel.TextLine))
{
l++;//count lines
//logger.Log("New line");
}
if (iter.IsAtBeginningOf(PageIteratorLevel.Word))
{
w++;//count words
//logger.Log("New word");
}
s++;//count symbols
//logger.Log(iter.GetText(PageIteratorLevel.Symbol));
// get bounding box for symbol
Rect symbolBounds;
if (iter.TryGetBoundingBox(PageIteratorLevel.Symbol, out symbolBounds))
{
Rectangle dueDateRectangle = new Rectangle(symbolBounds.X1, symbolBounds.Y1, symbolBounds.X2 - symbolBounds.X1, symbolBounds.Y2 - symbolBounds.Y1);
rect = dueDateRectangle;
PixelFormat format = src.PixelFormat;
Bitmap cloneBitmap = src.Clone(dueDateRectangle, format);
MemoryStream ms = new MemoryStream();
cloneBitmap.Save(ms, ImageFormat.Png);
ms.Position = 0;
Image i = Image.FromStream(ms);
//i.Save(ms,System.Drawing.Imaging.ImageFormat.Png);
i.Save("character" + counter + ".bmp", ImageFormat.Png);
counter++;
}
} while (iter.Next(PageIteratorLevel.Word, PageIteratorLevel.Symbol));
// DO any word post processing here (e.g. group symbols by word)
} while (iter.Next(PageIteratorLevel.TextLine, PageIteratorLevel.Word));
} while (iter.Next(PageIteratorLevel.Para, PageIteratorLevel.TextLine));
} while (iter.Next(PageIteratorLevel.Block, PageIteratorLevel.Para));
} while (iter.Next(PageIteratorLevel.Block));
}
Console.WriteLine("Pragraphs = " + p);
Console.WriteLine("Lines = " + l);
Console.WriteLine("Words = " + w);
Console.WriteLine("Symbols = " + s);
}
And it works when I have an image with a lot of text, but when I have an image with only one letter it does not.
It found a symbol, I see it in input. Symbols = 1. But it cant get BoundingBox. Why?
The same whem I use alphabet image
You may need to test the OCR with different page segmentation mode and OCR Engine mode to get the best result. Below is the usage information available in Tesseract 4.0.
Page segmentation modes:
0 Orientation and script detection (OSD) only.
1 Automatic page segmentation with OSD.
2 Automatic page segmentation, but no OSD, or OCR.
3 Fully automatic page segmentation, but no OSD. (Default)
4 Assume a single column of text of variable sizes.
5 Assume a single uniform block of vertically aligned text.
6 Assume a single uniform block of text.
7 Treat the image as a single text line.
8 Treat the image as a single word.
9 Treat the image as a single word in a circle.
10 Treat the image as a single character.
11 Sparse text. Find as much text as possible in no particular order.
12 Sparse text with OSD.
13 Raw line. Treat the image as a single text line,
bypassing hacks that are Tesseract-specific.<br>
OCR Engine modes:
0 Original Tesseract only.
1 Neural nets LSTM only.
2 Tesseract + LSTM.
3 Default, based on what is available.
For example,
psm 8 would give the best result for OCR a single word
psm 6 may give the best result of a block of text
In your code, it showed you have used the default engine mode and not specified segmentation mode. You may do some more tests to find out which modes give the correct result.
For images as bellow, use --psm 9 in your tesseract command
I have a text file that is written in C# using ascii encoding and when I attempt to read the file using a java project I get a ZERO WIDTH NO-BREAK SPACE character at the beginning of the file. Has anybody ever had this happen to them?
private static void SavePrivateKey(object key)
{
if (logger.IsInfoEnabled) logger.Info("SavePrivateKey - Begin");
string privatekey = (string)key;
string strDirName = Utility.RCTaskDirectory;
string strFileName = "PrivateKey.PPK";
string strKeyPathandName = Path.Combine(strDirName, strFileName);
//if (File.Exists(strKeyPathandName))
//{
// File.Create(strKeyPathandName);
//}
if (!string.IsNullOrEmpty(privatekey))
{//Save private key file
if (!Directory.Exists(strDirName))
Directory.CreateDirectory(strDirName);
FileStream fileStream = new FileStream(strKeyPathandName, FileMode.OpenOrCreate);
//TODO: Save File as ASCII
using (StreamWriter sw = new StreamWriter(fileStream, Encoding.ASCII))
{
if (logger.IsDebugEnabled) logger.DebugFormat("Saving the private key to {0}.", strKeyPathandName);
sw.Write(privatekey);
sw.Close();
if (logger.IsDebugEnabled) logger.DebugFormat("Saved private key to {0}.", strKeyPathandName);
}
}
if (logger.IsInfoEnabled) logger.Info("SavePrivateKey() - End");
}
It seems that the text is written with a BOM which is usually done when you write Unicode files... this specific character is the BOM for UTF16 files, so there must be something in your C# writing this file as UTF16...
see http://de.wikipedia.org/wiki/Byte_Order_Mark
As others have said, it is almost certainly a Unicode Byte Order Mark. If you have a look at the actual bytes in the file (not the characters) you can tell which encoding was used to write the file:
UTF-8 -> EF BB BF
UTF-16 BE -> FE FF
UTF-16 LE -> FF FE
Yes, it's quite normal, See Wikipedia. It's a optional character, which you simply should handle. So most likely you didn't write the file correctly as ASCII, since BOM only should appear if the file is encoded as unicode.
That's a Byte Order Mark indicating its a UTF-16 encoded text file.
Clearly its not writing the file in true ASCII, probably your code simply copying bytes, event though they are outside of the ASCII range. Can you post your code?
I am working on write a program that reads and writes from the barcode
my problem when writing (send command to barcode)
I read in pdf manufacturer barcode that the command of capturing the image is IMGSNP so i pass it to write function as follows serialPortObj.write ("IMGSNP")
But Why does not have a barcode to respond to the command ? and did not capture the image :(
Is this wrong way
(I have in some cases may need to take image Not for barcode it self but image for passport or product etc.. Which doesn't contains a barcode )
Barcode manufacturer is HandHeld (4800p)
Thanks for any help
here is my code
private SerialPort Com ;
private delegate void DataReadDel(string Text);
private void Form1_Load(object sender, EventArgs e)
{
Com = new SerialPort("COM4");
Com.Open();
Com.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
private void port_DataReceived(object sender,SerialDataReceivedEventArgs e)
{
Com.Encoding = Encoding.Default;
this.BeginInvoke(new DataReadDel(DataReceived), new object[] {Com.ReadExisting() });
}
private void DataReceived(string dR)
{
textBox1.Text = dR;
}
private void button1_Click(object sender, EventArgs e)
{
if (! Com.IsOpen )
{
Com.Open();
}
Com.Write("IMGSNP1B1L");
Com.Write("IMGSHP");
string imgbytes = Com.ReadExisting();// return ""
}
You need to send the Serial command header along with the IMGSNP command to have the scanner capture and send the image. The header is three ASCII characters: SYN M CR (ASCII 22,77,13).
Are you sure that the barcode reader is not capturing the image? According to the documentation:
An image is taken when the Image Snap (IMGSNP) command is processed. The last image is always stored in memory. You may “ship” the image by using the IMGSHP command.
So you may be taking the image using IMGSNP, but all that's happening is that its storing the image in memory, and not sending it back to you as a response. Try then issuing the IMGSHP command, and see if there's any data to be read from your serial port.
You need to send the SYN M CR first before the device considers taking your request in.
The following information is obtained with my own barcode reader while trying to do something quite similar.
When using IMGSHP, the device will reply with a SYN (0x16) followed by 0xfe [4 bytes of data length, little endian] 0x0d [some data] 0x1d [image data]
As well as the command itself, do you have to provide any termination characters?
A common method is to wrap the command packet in STX and ETX characters so the barcode reader will know when a full command has been received, or possibly just terminate with a carriage return (CR) and linefeed characters (LF). You need to check the specs.
Also, since you are sending a string, encoding may be important, and I would expect the barcode reader needs ASCII characters sent to it, but again, you should check the unit to be sure.
I suspect the easiset way to send a command is to send it as an array of bytes, which makes it easier to use the STX, ETX, CR or LF characters if necessary, as these are non-printable characters and have the following values:
STX = 0x02, ETX = 0x03, CR = 0x0D, LF = 0x0A