Billing aliens via POS printer and image print
Question: 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](http://en.wikipedia.org/wiki/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](http://www.satsig.net/seti/message-to-gliese-581.gif)

From the printer's specifications:

[![enter image description
here](http://i.stack.imgur.com/AvZUp.jpg)](http://i.stack.imgur.com/AvZUp.jpg)

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()
    


Answer: 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
    

