Биллинг инопланетян через принтер POS и печать изображений

Я пытаюсь создать прототип для печати растровых данных для текстового файла на моем локальном принтере epson pos TM-T88V с поддержкой локальной сети.

Хотя у меня нет проблем с отправкой текста и инструкций по форматированию текста, я не понимаю, что мне нужно делать, чтобы мой принтер печатал данные сообщения Аресибо.

первые несколько строк:

00000010101010000000000
00101000001010000000100
10001000100010010110010
10101010101010100100100
00000000000000000000000
00000000000011000000000
00000000001101000000000
00000000001101000000000
00000000010101000000000
00000000011111000000000
00000000000000000000000
11000011100011000011000
10000000000000110010000
11010001100011000011010
11111011111011111011111
00000000000000000000000
00010000000000000000010
00000000000000000000000
00001000000000000000001

Сообщение содержит 73 строки и 23 столбца, в результате чего получается 1679 элементов изображения. Каждый из этих элементов определяется как 1 для черного или 0 для белого и должен быть напечатан в виде квадрата 8x8 (или 16x16) точек. результат приведет к

Arecibo message
(источник: satsig.net)

Из спецификации принтера:

enter image description here

Хотя, как я уже сказал, подключение и отправка на принтер не проблема, я просто не понимаю, что эта инструкция хочет мне сказать. Что в случае с сообщением Аресибо будет

Какие номера мне нужно отправить на принтер? Нужно ли отправлять каждую точку? Что означает nL, nH specify the number of dots of the image data in the horizontal direction as (nL + nH × 256).?

Вот моя простая программа на Python, которую я использую для создания прототипов:

# -*- coding: utf-8 -*-
import struct
import socket

def sendInstructions(mySocket,l):
    for x in l:
        mySocket.send(struct.pack('h', *[x]),1)


def emphasizeOn(mySocket):
    sendInstructions(mySocket,[27,33,48])


def emphasizeOff(mySocket):
    sendInstructions(mySocket,[27,33,0])


def lineFeed(mySocket,number):
    for i in range(number):
        sendInstructions(mySocket,[0x0a,])


def paperCut(mySocket):
    sendInstructions(mySocket,[29,86,0])

def sendText(mySocket,string):
    mySocket.send(string.encode('UTF-8'))


def main():
    mySocket = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
    mySocket.connect(('192.168.1.15',9100))    


    lines = ["Hello,","World!"]
    emphasizeOff(mySocket)
    lineFeed(mySocket,2)
    for l in lines: 
        if lines.index(l) == 0:
            emphasizeOn(mySocket)
        else:
            emphasizeOff(mySocket)

        sendText(mySocket,l)
        lineFeed(mySocket,2)

    lineFeed(mySocket,4)
    paperCut(mySocket)

    mySocket.close()

if __name__=="__main__":
    main()

Ответы

Ответ 1

Эта команда генерирует одну горизонтальную полосу изображения за раз. Полоса имеет 8 или 24 точки в высоту, в зависимости от значения m.

nL и nH - это байты с низким и высоким байтами целого числа, которые определяют ширину в точках горизонтальной полосы изображения. Эта ширина вычисляется как nL + nH * 256, поэтому, если вы хотите, чтобы изображение было шириной 550 точек, тогда nH = 2 и nL = 38.

Аргумент d - данные растрового изображения; если полоса изображения имеет высоту 8 точек, то каждый байт представляет собой один столбец в полосе. Если полоса имеет 24 точки, то три байта представляют один столбец.

Итак, скажем, у вас есть iscibo в массиве WxH numpy от ints, 1 или 0. Вы бы:

data = np.zeros((W, H), dtype=np.ubyte)
## (fill in data here)

## Use m=33 since this is apparently the only mode with 
## square pixels and also the highest resolution 
## (unless it prints too slowly for your liking)
m = 33

nH = W // 256  ## note this is integer division, but SO 
               ## syntax hilighting thinks it looks like a comment.
nL = W % 256

## Divide the array into sections with shape Wx24:
for n in range(data.shape[1] // 24):
    ## Note that if the image height is not a multiple of 24, 
    ## you'll have to pad it with zeros somehow.

    strip = data[:, n*24:(n+1)*24]

    ## Convert each strip into a string of bytes:

    strip = strip.reshape(W, 3, 8)
    bytes = (strip * (2**np.arange(8)[np.newaxis, np.newaxis, :])).sum(axis=2) # magic
    byteString = bytes.astype(np.ubyte).tostring()

    ## Send the command to POS