Search code examples
xamarin.formsxamarin.androidthermal-printerescpos

Printing PDF doc to esc/pos Thermal printer


We are developing a POS APP using xamarin.forms, in that we need to print the receipt to an esc/pos thermal printer connected via LAN. We have multi language support with the App, printing multiple language with the esc/pos commands by changing code page works perfectly. But its working for some supported language only, for other language its printing garbage characters(unreadable ones).

so we thought of creating a pdf for the receipt and print that one. we tried to create the pdf and then convert to bitmap and then send to the printer by using esc pos commands, but its not printing anything.

    public BitImage(String filename)
    {
        Java.IO.File file = new Java.IO.File(filename);
        var pdfRenderer = new PdfRenderer(ParcelFileDescriptor.Open(file, ParcelFileMode.ReadOnly));
        PdfRenderer.Page page = pdfRenderer.OpenPage(0);
        Bitmap bmp = Bitmap.CreateBitmap(page.Width, page.Height, Bitmap.Config.Argb8888);
        page.Render(bmp, null, null, PdfRenderMode.ForPrint);
        load(bmp);
    }


private void load(Bitmap bmp)
{
    int w = bmp.Width;
    int h = bmp.Height;

    int bw = (w + 7) / 8;
    if (bw > 255)
        bw = 255;

    int bh = h / 8;
    if (bh > 24)
    {
        bh = 24;
    }

    initData(bw * 8, bh * 8);

    for (int y = 0; y < h; y++)
    {
        for (int x = 0; x < w; x++)
        {
            if (bmp.GetPixel(x, y) == Color.Black)
                setPixel(x, y);
        }
    }
}

private void initData(int w, int h)
{
    width = w;
    height = h;
    pitch = h / 8;
    data = new byte[w * pitch];
}

private void setPixel(int x, int y)
{
    if (x >= width || y >= height)
    {
        return;
    }
    int mask = (0x0080 >> (y % 8));
    data[(x * pitch) + (y / 8)] |= (byte)mask;
}


public void PrintData() 
{
    byte[] CMD_INIT = { 0x1B, 0x40 };
    byte[] CMD_UPLOAD_IMAGE = { 0x1D, 0x2A, 0, 0 };
    byte[] CMD_PRINT_IMAGE = { 0x1D, 0x2F, 0 };
    byte[] CMD_CUT = { 0x1D, 0x56, 0x01 };
    CMD_UPLOAD_IMAGE[2] = (byte)(width / 8);
    CMD_UPLOAD_IMAGE[3] = (byte)(height / 8);

    #region Print Via Lan
    Socket pSocket = new Socket(SocketType.Stream, ProtocolType.IP);
    pSocket.SendTimeout = 1500;
    pSocket.Connect("192.168.15.168", 9100);
    pSocket.Send(CMD_INIT);
    pSocket.Send(CMD_UPLOAD_IMAGE);
    pSocket.Send(data);
    pSocket.Send(CMD_PRINT_IMAGE);
    pSocket.Send(CMD_CUT);
    pSocket.Close();
    #endregion
}

Please help me, whether i am doing it in correct way? or is there any better way to do the same?


Solution

  • You can use libraries like SkiaSharp to make Image/PDF from your data in any language and print them properly using any printer.

    I've created a sample to demonstrate how to print images properly with ESC\POS printers in C#: GitHub code repo