Wiki

Clone wiki

Pipsta / Banner Print Python Code Tutorial

Difficulty Level

pipsta_mono.pngpipsta_mono.pngpipsta_mono.pngpipsta_mono.pngpipsta_mono_empty.png

  • This tutorial assumes the user has some Python programming experience
  • This tutorial builds on USB configuration code discussed in the Basic Print Python Code Tutorial
  • This code uses additional, sophisticated imaging libraries
  • This code requires a level of programming competence to understand the conversion of a bitmap image into a bit array and subsequent packaging into bespoke printer commands.

Time to Complete

pipsta_mono.pngpipsta_mono.pngpipsta_mono.pngpipsta_mono_empty.pngpipsta_mono_empty.png

  • Some aspects are complex and require significant time to explain and comprehend.

Who Should Read This Document

This tutorial is beneficial to those who have completed Basic Print Python Code Tutorial and wish to develop their understanding of the simple text application into something that produces more advanced prints, using the powerful and freely-available Python libraries.

This tutorial would also be of interest to those wishing to explore other aspects of the font rendering capabilities of the system: perhaps to render images containing multiple fonts or produce fonts in other orientations.

How it Works

The script uses the same methods of establishing a USB connection, and argument-parsing techniques as seen in the Basic Print Python Code Tutorial. For brevity, these aspects will not be covered again in this tutorial. Those wishing to understand such aspects should read the Basic Print Python Code Tutorial.

The script takes two command-line arguments (optional), detailing:

  • The text to print
  • The font used in conjunction with the text to generate the banner image

In overview:

  • The Python Imaging Library, Pillow is used extensively:
    • It uses text and font information and create a bitmap image.
    • Pillow also permits the rotation of the image (to suit the banner orientation) and
    • Scaling to give the best fit on the paper
  • Once the bitmap image is created in the Raspberry Pi’s RAM, a library called bitarray is used to manipulate/convert this data into an array of bytes, sequenced for easy use with the graphics printing commands
  • The graphical data is then sent to the Pipsta printer over the USB connection.
  • As the resultant image is larger than the Pipsta’s data buffer, the data needs to be marshalled to ensure that data is not lost/ignored. This is performed by polling the status of the printer by means of a special (bespoke) control transfer query.

Code Overview

TIP: The banner.py script is available to both the command-line and NFC Server. This does not introduce significant complexity, but it does mean that the file in:

/home/pi/pipsta/Examples/6_Banner_Print

is effectively only a shortcut to that in:

/home/pi/pipsta/Examples/nfc/pipsta/banner_print

This is betrayed when a directory listing is produced by typing (in LXTerminal):

ls

You will note that banner.py is cyan coloured (indicating a linked file or shortcut). You should also notice this in the form of a little arrow over the file icon when viewed in File Manager on the GUI desktop.

Whilst Linux is clever enough to redirect you to the real file when you try to edit it, you should be aware of this structure when considering moving or copying files.

The banner.py USB connection code is enhanced slightly with respect to BasicPrint.py, with connection code being encapsulated in its own function, rather than being in main(). USB functions are thus:

  • setup_usb()

where this functionality is almost identical to that in BasicPrint.py.

Also similar is:

  • parse_arguments()

though this now accepts two optional arguments: text and font.

A Note on Command Line Parameters

Note that –as mentioned in Pipsta Banners—these arguments are positional, so

#!
pi@raspberrypi ~ $ python banner.py

…would produce the default text in the default font,

#!
pi@raspberrypi ~ $ python banner.py 'another message' '/usr/share/fonts/type1/gsfonts/z003034l.pfb'

…would produce a banner with the message 'another message' in the system font ‘Chancery’.

#!

pi@raspberrypi ~ $ python banner.py 'yet another message'

…would produce a banner with the message 'yet another message' in the default font.

#!
pi@raspberrypi ~ $ python banner.py '/usr/share/fonts/type1/gsfonts/z003034l.pfb'

…would produce a banner with the message '/usr/share/fonts/type1/gsfonts/z003034l.pfb' in the default font (which is almost certainly not the desired functionality!)

A Note on Quotes and Apostrophes

Whilst it is often acceptable to use single-quotes and double-quotes, e.g.:

#!

python banner.py 'Test'

...would give the same results as:

#!

python banner.py "Test"

(note the double-quotes), you may find the command-line interpreter or 'shell' complains if you introduce an exclamation mark, for example:

#!

python banner.py 'Hello!'

...will work, whereas:

#!

python banner.py "Hello!"

...will not. The bash shell will complain with '!: event not found'. This is because '!' has a special meaning in bash (it is used to execute commands previously entered on the command line.)

Single-quotes should therefore be used if you are to use exclamation marks. They will also allow you to produce double-quotes in your banner:

#!

python banner.py '"Do not quote me on this," he said.'

A consequence of single-quotes is that you may then fall-foul of apostrophes as these will be interpreted as the end of the string:

#!

python banner.py '"This won't work", she said.'

..will fail very ungracefully (press [CTRL]+[C] to get back to the command line if you tried this!)

The following command will permit the use of the apostrophe (note the shift back to double-quotes here):

#!

python banner.py "'This won't fail', she said."

And this, albeit convoluted command will work for both apostrophes and exclamation marks:

#!

python banner.py 'We can'"'"'t fail!'

... as the command-line parameter is then made up of the following 3 components:

  • We can
  • '
  • t fail!

This is interpreted as a single parameter as there is no white-space between each component in quotes.

TIP: The Bash Shell is powerful, but there can be consequences in some implementations!

Fonts and Images

The bespoke imaging function is:

  • get_best_fit_font() – which attempts to derive the best sized font for the paper dimensions. All font-to-image rendering functionality is conferred by Pillow; the rest of the processing for arriving at a suitably-scaled image for the Pipsta Printer's paper width is handled in the get_best_fit_font() function.

The ‘Image to Bit-Field’ conversion function is:

  • convert_image() – which takes the image and converts it into printbits in two steps:
    • Convert to a big-endian bit-array
    • Convert resultant bit-array to a byte array

Printing

Printing is handled by:

  • print_image() – which:
    • Sets the printer into Font Mode 3. The use of the word ‘font’ here has none of the connotations of banner fonts though: this is a command to the Pipsta printer to go into a mode where there are no gaps between the 24-dot-line high graphical blocks.
    • Loops through the array printbits sending printer graphics commands with trailing data until the end of the printbits array is reached (i.e. at image completion).
    • Busy is polled by a control transfer request

In the main() function itself:

  • main():
    • There is a check to ensure that Python2.x is being used. This is a requirement of the bitarray library
    • There is a check to ensure that the script is running on a Linux system
    • A function is called to look for a device of the appropriate VID and PID
    • parse_arguments() is called and to get text and font data (provided as arguments or lifted as defaults)
    • For diagnostic purposes, a logging provision is started (the log for which is stored locally on the Raspberry Pi)
    • USB is setup next
    • The optimal font size is derived based on the font and text provided
    • The image size is dimensioned appropriately in preparation for the image generation
    • Text is ‘drawn’ onto the image
    • The image is rotated through 270 degrees to be correctly oriented
    • A command is send to the printer to flash the LED green for the duration of the print
    • The image is converted to a bit-array and then a byte-array
    • The image is printed
    • 5 carriage returns are sent to feed the paper past the tearbar
    • The green LED flashing mode is turned off
    • The script exits

Single Dot Line Graphics

The Pipsta printer has a print width of 384 dots, with each dot being 0.125mm wide to give an overall width of 48mm. Note that this leaves a ~5mm unprinted left- and right-margin on (nominal) 58mm paper.

Note: To put the printer into a contiguous graphics mode (i.e. without white-space separation between character lines) the script will issue the SET_FONT_MODE_3 command.

Pipsta scripts that produce graphics prints (rather than pure text) use the printer's "Single Dot Line Graphics" command to render the dot image on the paper. The command to render a complete dot line of 384 dots takes the form:

sdl_cmd.png

Where a '1' bit in the data corresponds to a black dot.

Thus, the function convert_image() simply has to convert the bitmap image to a big-endian bit-array, and then convert this to an array of bytes to make the data sequentially accessible to the nested for-loops in print_image()

Busy Handling

print_image() uses a control transfer to request the 'busy' status prior to transmission of each graphics command to ensure that the buffer is not busy, introducing a small delay before polling 'Busy' again to ensure that the command will be successfully received.

Darkness Commands

banner.py has a modicum of control over the darkness of the rendered image, conferred by 'SET_DARKNESS_LIGHT' and 'RESTORE_DARKNESS' commands before and after the graphic image transmission; this should be used to adjust to different media and/or reduce blurring in very long and predominantly dark images.

TIP: Set Darkness commands do not confer sufficient control to give shades of grey.

Altering the Script

Previous iterations of the banner.py script used block graphics commands and this gave rise to long delays in the generation of a bit-array suited to this command. Once this was discovered to be the bottle-neck (and not the Pi's processing power), the Single Dot Line graphics command was introduced. This gives a much reduced processing time- even for very long banner prints.

Very long and black banner prints can result in the image becoming blurred towards the end of the print on some media. This is due to the thermal head's temperature gradually rising during the print, until it reaches a temperature close to that at which the media 'develops'. This has been significantly reduced in recent firmware's. Please update your firmware to the latest version. Introducing delays to the banner print can also be investigated to yield improvements.

Note that there are numerous opportunities to adjust the script for:

  • Mixed fonts
  • Mixed fonts and graphics (see also the Merit Print Tutorial (TBD))
  • Fonts in other orientations
  • Inverse fonts (using bitarray library functions)

Shutting Pipsta Down Safely

Whilst the printer is resilient when it comes to powering down, the Raspberry Pi must undergo a strict shutdown process to avoid corrupting the Micro SD card. The most straightforward method of doing this is to double-click the ‘Shutdown’ icon on the desktop.

TIP: If you are already in LXTerminal, type sudo shutdown –h now to shut-down the Raspberry Pi immediately.

.

TIP: Always make sure ALL activity on the Raspberry Pi'’s green LED (the LED on the right) has stopped before removing the power!

End of Document

Updated