Search code examples
pythonpython-3.xprintingescp

Use full page width with Brother P950NW


I would like to use the full width of the 18mm strips in my Brother P950NW printer for an image. At the moment, I am using ESC/P (not ESC/POS, which this printer does not seem to support), but if it's not possible with that I'm fine with any other protocol this printer supports. (Update: with Brother's Windows software, full-width printing is possible, but it uses the LPR protocol, for which there don't seem to be any Python libraries.)

I'm using the ESC/P command ESC* with density 72 (the highest available according to the printer's documentation), which only allows filling up the width in steps of 48 dots.

How do I print 200 pixels wide on a strip in ESC/P-speak an image with height 200? That should easily fit onto the strip. However, due to ESC*72 only accepting blocks of 48, everything beyond 192 is output on another strip.

Here's my demo code:

import socket
import struct

def escp(density_code=72):
    stack_size_in_bytes = {72: 6}[density_code]
    height = 200
    width = 130

    yield b'\x1bia\x00'  # ESC/P command mode: ESC/P standard
    yield b'\x1b@'  # Initialize
    yield b'\x1bim\x00\x00'  # margin: 0
    yield b'\x1biXE2\x00\x00\x00'  # barcode margin: 0
    yield b'\x1b3' + struct.pack('!B', 24)  # line feed length: 24 dots (i.e. no space between lines)

    for y_offset in range(0, height, 8 * stack_size_in_bytes):
        yield b'\x1b*' + struct.pack('!B', density_code) + struct.pack('<H', width)
        yield b'\xff' * width * stack_size_in_bytes
        yield b'\x0a'  # linefeed (move position 24 dots down)
    yield b'\x0c' # Print start

c = socket.create_connection(('10.222.2.206', 9100))
c.sendall(b''.join(escp()))
c.close()

I'm fine with solutions in raw binary; here is the binary file and shortened hexdump generated by the above program.


Solution

  • Both the Brother PT-P950NW and Borther PT-9800PCN support a "raster protocol" (code 1 instead of 0 after ESC iA). With this protocol, it is possible to print raster graphics at full width.

    However, I could not find any documentation (the closest was this PDF for another printer), so I reverse-engineered it (and tried out a lot). The result is the project rasterprynt, available as a PyPi package. With rasterprynt, you can print arbitrary images, like this:

    import rasterprynt
    
    import PIL.Image
    
    # Enter the IP address of your printer below
    printer_ip = '192.168.1.123'
    
    img1 = PIL.Image.open('example1.png')
    img2 = PIL.Image.open('example2.png')
    data = rasterprynt.prynt([img1, img2, img1], printer_ip)