Как загрузить и распечатать изображение на принтере TSC?

Использую TSPL2. Код обработчика: <br/> <br/> <pre><code class="cs">private void button_Click(object sender, RoutedEventArgs e)
  • 12 мая 2026 г. 12:00
Ответы на вопрос 2
Коротко — нужно: 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).
base64 тут сломан сразу — принтер получает текстовую строку вместо PNG-байт, поэтому PUTPNG не видит валидного файла. <br/> <br/> Команда DOWNLOAD после длины ждёт сырые байты, а SendCommand(string) тут не подходит: нулевые байты в PNG обрежет или перекодирует. <br/> <br/> Правильный вариант: склеить ASCII-заголовок и сырые байты, отправить raw-записью: <br/> <pre><code>var bytes = File.ReadAllBytes(path);
var header = Encoding.ASCII.GetBytes($"DOWNLOAD \"{name}\",{bytes.Length},");
var raw = header.Concat(bytes).Concat(new byte[]{0x0D,0x0A}).ToArray();
// WriteFile/BeginDocPrinter, не SendCommand</code></pre> <br/> <br/> Если TscLibWrapper не умеет raw-write, либо пиши напрямую в порт, либо конвертируй PNG в PCX и используй downloadpcx.
Похожие вопросы