Billing aliens via POS printer and image print
Asked Answered
S

1

14

I am trying to create a prototype to print bitmap data for a text file to my LAN enabled epson pos printer TM-T88V.

While I have no problems to send text and text formatting instructions, I dont understand, what I have to do, to make my printer print the data of the Arecibo message.

first few lines:

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

The message has 73 rows and 23 columns resulting in 1679 picture elements. Each of this elements is defined by either a 1 for black or a 0 as white and should be printed as a square of 8x8 (or 16x16) dots. the result would result in

Arecibo message
(source: satsig.net)

From the printer's specifications:

enter image description here

While — as I said — the connecting and sending to the printer is no problem, I just dont get, what this instruction want to tell me. What would in the case of the Arecibo message be

What numbers do I have to send to the printer? Do I need to send every dot? What does nL, nH specify the number of dots of the image data in the horizontal direction as (nL + nH × 256). mean?

Here is my simple Python program I use for prototyping:

# -*- 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()
Semipermeable answered 14/7, 2012 at 1:41 Comment(3)
And what does this have to do with billing aliens?Oblique
@Oblique — just to raise your attention :)… No seriously: I need to print bitmap data, and as I felt that I need to illustrate that, I thought of using an famous example, the Arecibo message. But what would you send an Alien, if you us a POS printer? Bills!Semipermeable
Why is this question "too localized"? I want to print bitmap data and added a funny example. Is humor too localized?Semipermeable
A
7

This command generates one horizontal strip of the image at a time. The strip is either 8 or 24 dots tall, depending on the value of m.

nL and nH are the low and high bytes of an integer that specifies the width in dots of the horizontal strip of image. That width is computed as nL + nH * 256, so if you wanted the image to be 550 dots wide, then nH=2 and nL=38.

The argument d is the bitmap data; if the image strip is 8 dots tall, then each byte represents one column in the strip. If the strip is 24 dots tall, then three bytes represent one column.

So let's say you have arecibo in a WxH numpy array of ints, 1 or 0. You would:

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's 
               ## 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
Antevert answered 14/7, 2012 at 3:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.