Коротко — нужно: 1) перевести изображение в монохром (1 бит на пиксель), 2) упаковать строки в байты (по 8 пикселей в байт, старший бит = левый пиксель), 3) послать в принтер команду TSPL BITMAP с размерами и затем самые бинарные данные, 4) вызвать PRINT. Ниже пример на C# (WPF) для отправки через COM-порт или TCP (в зависимости от вашего подключения).
Пример (вариант для SerialPort, аналогично по NetworkStream для TCP):
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
private void button_Click(object sender, RoutedEventArgs e)
{
// Путь к изображению или используйте Bitmap из другого источника
using (Bitmap bmp = new Bitmap("test.png"))
{
// Подгоните ширину/высоту под возможности принтера
// Обычно ширина в пикселях ~ 384, 576 и т.д. зависит от модели.
int maxWidth = 576; // пример
Bitmap bmpResized = ResizeIfNeeded(bmp, maxWidth);
// Конвертация в монохром и упаковка в TSC-формат
byte[] imageData = ConvertBitmapToTscBytes(bmpResized, out int widthBytes, out int height);
// Формируем TSPL команду
// x,y — позиция в точках; widthBytes — количество байт в строке; height — высота в пикселях
string header = $"CLS\r\nBITMAP 0,0,{widthBytes},{height},1,"; // после запятой идет бинарный поток
string printCmd = "\r\nPRINT 1\r\n";
// Открываем порт (пример для COM)
using (SerialPort port = new SerialPort("COM3", 9600))
{
port.Open();
// Отправляем текстовую часть
port.Write(header);
// Отправляем бинарные данные
port.Write(imageData, 0, imageData.Length);
// Отправляем команду печати
port.Write(printCmd);
port.Close();
}
}
}
private Bitmap ResizeIfNeeded(Bitmap src, int maxWidth)
{
if (src.Width <= maxWidth) return new Bitmap(src);
int newW = maxWidth;
int newH = src.Height * newW / src.Width;
Bitmap outBmp = new Bitmap(newW, newH);
using (Graphics g = Graphics.FromImage(outBmp))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(src, 0, 0, newW, newH);
}
return outBmp;
}
private byte[] ConvertBitmapToTscBytes(Bitmap bmp, out int widthBytes, out int height)
{
int width = bmp.Width;
height = bmp.Height;
widthBytes = (width + 7) / 8;
byte[] result = new byte[widthBytes * height];
// Проход пикселей: MSB = левый пиксель в байте
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Color c = bmp.GetPixel(x, y);
// Градация серого и порог (можно регулировать)
int gray = (c.R * 30 + c.G * 59 + c.B * 11) / 100;
bool isBlack = gray < 128; // если true — печатаемый пиксель (1)
if (isBlack)
{
int index = y * widthBytes + (x / 8);
result[index] |= (byte)(0x80 >> (x % 8)); // ставим соответствующий бит (MSB first)
}
}
}
return result;
}
Важные замечания и подсказки:
- Убедитесь, что ширина изображения в пикселях не превышает физическую ширину принтера. Иначе картинка обрежется.
- Некоторые примеры отправляют перед картинкой команды SIZE/GAP/CLS — полезно выставить нужный формат страницы.
- В команду BITMAP вы передаёте width в байтах (widthBytes), а не в пикселях.
- После заголовка BITMAP вы должны отправлять БИНАРНЫЕ данные — не переводите их в hex-строку. Для SerialPort используйте Write(byte[], ...). Для TCP — NetworkStream.Write.
- Альтернативный способ: загрузить BMP в память принтера (DOWNLOAD), а затем вызвать PUTBMP <name>,x,y или USEBMP/… — но проще и надёжнее отправлять через BITMAP.
- Если изображение содержит тонкие градиенты, предварительно порог и/или дизеринг улучшит качество. Можно использовать алгоритмы Floyd–Steinberg для лучшего результата.
Если пришлёте ваш текущий код обработчика (весь метод) и способ подключения (COM/USB/TCP), могу подправить пример под ваш проект и показать точную последовательность команд (SIZE/GAP/CLS/BITMAP/PRINT).