Previous Table of Contents Next


Printing Considerations

Under the best of conditions, printing graphics images on high-resolution printers is slow. Thermal transfer print page cost is constant and is considered expensive for text output. Ink jet print page costs depend on how much ink is required to produce acceptable output. Bar graphs that use cyan, magenta, and yellow bars use much less ink than bar graphs using red, green, and blue bars since the latter requires multiple CMY ink coats. Dye sublimation is the most expensive printing method and is only competitive with photography. Because of high colorant and media cost, some dye sublimation printers provide thermal transfer printing for drafts.

Printer Programming

Overview

Most printers power-up in text mode. In text mode, printers print a character “A” when the printer receives a character “A” over its interface. To invoke printer features such as text underlining, superscripts, or graphics requires sending the printer an escape sequence. Unless you are working with a family of printers such as Hewlett-Packard’s DeskJet, PaintJet, and LaserJet printers, the escape sequences you send to the printer and when you send them are very dependent on the specific model of printer you are using.

An escape sequence notifies printers to interpret immediately following data differently, perhaps altering their current behavior or mode. Some temporarily place printers in graphics mode so subsequent data is treated as dot patterns to paint rather than characters to render. Others slow the print head’s horizontal speed to increase or decrease dot density as the head prints.

Escape sequences begin with the 1-byte escape character (Esc) which has a hexadecimal value of 0x1B (decimal 27). When printers receive an Esc, they know that the next few characters will not be printed but will specify some characteristic. The byte or few bytes following Esc are usually case sensitive and identify the specific sequence to the printer. These bytes may be followed by a few bytes that specify various parameters.

Here are a few IBM Proprinter escape sequences:

Escape Sequence Hexadecimal Example Meaning
EscE '\x1B', 'E' Start printing all received text in bold.
EscF '\x1B', 'F' Stop printing all received text in bold.
EscP1 '\x1B', 'P', '1' Start printing text proportionally spaced.
EscP0 '\x1B', 'P', '0' Stop printing text proportionally spaced.
Esc3.. '\x1B', '3', '\x18' Set line spacing (move head down 24/216" after receiving a line feed in the example)
EscLn1n2.... 'x1B', 'L', '\x03', '\x01' Print the following n2*256+n1 (19 in the example) characters as graphics data at 120 dpi. Then revert to character mode.

Here are a few Hewlett-Packard InkJet escape sequences:

Escape Sequence Hexadecimal Example Meaning
Esc*†75R '\x1B', '*', 'r', '7', '5', 'Q' Print graphics data at 75 dpi
Esc*†300R '\x1B', '*', 'r', '3', '0', '0', 'Q' Print graphics data at 300 dpi
Esc*rbC '\x1B', '*', 'r', 'b', 'C' Stop printing data as graphics

Because Hewlett-Packard’s printer family has many more models with many more sophisticated features than the IBM Proprinter, they have many more escape sequences with many more options. But Hewlett-Packard printer escape sequences all observe many common rules, such as always ending with capital letters, and can be combined under certain circumstances.

To navigate among the many escape sequences and their various options, PRINTPCX.C strictly observes the recommendations found in Hewlett-Packard’s DeskJet Printer Family Software Developer’s Guide (available directly from Hewlett-Packard). This well-written, essential guide explains Hewlett-Packard escape sequences in detail and specifies the order in which a printer should receive them. Any question not answered by the manual receives quick response from the printer support teams.

Sending Characters to Printers

The PRINTPCX.C program first calculates what initialization escape sequences to transmit to the printer based on user input. The program then uses the PC BIOS interrupt to transmit to the printer, assuming the printer is attached to the PC’s LPT1: parallel printer interface. PrintByte() is the routine that performs the transmission and is isolated to simplify adapting the code to serial and network attached printers. Before transmitting any character to a printer, PrintByte() first calls WaitForPrinter() which keeps checking the LPT1: PrinterBusy bit until it indicates the printer can accept a character before returning to PrintByte(). The essential programming logic follows:

#define BIOS_LPT1               0x00
#define BIOS_PRINT_CHAR          0x00
#define BIOS_PRINTER_INT        0x17
#define BIOS_RESET_PRINTER       0x01
#define BIOS_FETCH_PRINTER_STATUS 0x02

int PrintByte(char InChar)
{
    union REGS Regs;

    WaitForPrinter(0);

    Regs.h.al = InChar;
    Regs.h.ah = BIOS_PRINT_CHAR;

    Regs.x.dx = BIOS_LPT1;

    int86(BIOS_PRINTER_INT, &Regs, &Regs);

    return;
}

int WaitForPrinter(int WaitMsgFlag)
{
    union REGS Regs;

    if (WaitMsgFlag)
        printf("\n\nWaitForPrinter: Waiting for printer to come
                      online...\n");

    do {

        Regs.h.ah = BIOS_FETCH_PRINTER_STATUS;
        Regs.x.dx = BIOS_LPT1;

        int86(BIOS_PRINTER_INT, &Regs, &Regs);

    } while(!(Regs.h.ah & 0x0080));  /* test printer busy bit */

    return;
}

After initializing the printer, PRINTPCX.C determines, line by line and color by color, what graphics data to send and transmits the graphics data following the appropriate escape sequence. Both the escape sequence and graphics data can vary by printer.


Previous Table of Contents Next