hpdj - Ghostscript device driver for printers understanding PCL 3+


gs [options] [files] option ::= prn_option | hpdj_option

prn_option can be any option defined for ghostscript’s prn (printer) device. This includes all device-independent options described in gs(1). You should also look into ghostscript’s extended documentation (file

and the section Device parameters in
). hpdj does not support the
parameter and it determines the correct value for

hpdj_option ::= -dBlackLevels=integer | -dCMYLevels=integer | -sColorMode=mode | -sColourMode=mode | -dCompressionMethod=method | -dDryTime=seconds | -dManualFeed[=boolean] | -sMarginFile=pathname | -sMediaType=type | -sModel=model | -sPagecountFile=pathname | -sPrintQuality=quality mode ::= mono | CMY | CMY+K | CMYK method ::= 0 | 1 | 2 | 3 | 9 boolean ::= false | true type ::= plain | bond | Premium | glossy | transparency | photo | integer model ::= 500 | 500C | 510 | 520 | 540 | 550C | 560C | 850C | 855C | unspec quality ::= draft | normal | presentation | integer

Case is significant. Note that some options must be passed as strings (-s) and others as general tokens (-d). You should also keep in mind that gs effectively ignores every option it does not recognize, hence some care in spelling parameter names is necessary.

Some options have synonyms for values which are listed only in the detailed description below.



The ghostscript device driver hpdj is a ghostscript backend for printers understanding Hewlett-Packard’s Printer Command Language, level 3+ (PCL 3+). It is intended to support in particular the following printer models:

HP DeskJet 500 HP DeskJet 500C HP DeskJet 510 HP DeskJet 520 HP DeskJet 540 HP DeskJet 550C HP DeskJet 560C HP DeskJet 850C HP DeskJet 855C

The driver does not support DeskJet printers understanding only HP PPA (Printing Performance Architecture) commands. If a printer’s documentation does not say anything about its printer command language or you find a statement like "... is designed for Microsoft Windows" or "DOS support through Windows only", the printer is almost certainly a PPA printer and hence is intended exclusively for systems running Microsoft Windows. There exist ways of using a PPA printer with ghostscript, but not through hpdj.

Different printer models usually implement model-specific subsets of all PCL-3+ commands or arguments to commands. You must therefore tell the driver by means of the Model option for which model the generated PCL code is intended. The model-dependent difference in the generated code is not great. Apart from margin specifications and colour capabilities, one can consider three groups of models which are treated with significant differences:

500, 5xx except 500 and 540, 540 and 8xx.

The third group is the one I refer to as the "new DeskJets" below.

If you have a PCL-3 printer not appearing in the list above, the likelihood is still good that it will accept the files generated by hpdj. You can specify one of the supported models in these cases (it is sufficient to try one each from the groups just mentioned), or use the special model name unspec which is treated like a new DeskJet with all model-dependent checks having been turned off.

I have received reports that hpdj works with the following printers:

HP DeskJet 340 HP DeskJet 500 HP DeskJet 500C (tested for mono only) HP DeskJet 520 HP DeskJet 540 HP DeskJet 560C HP DeskJet 600 HP DeskJet 660C/660Cse HP DeskJet 670C HP DeskJet 672C HP DeskJet 680C HP DeskJet 690C HP DeskJet 690C+ HP DeskJet 693C HP DeskJet 694C HP DeskJet 850C HP DeskJet 855C HP DeskJet 870Cse/870Cxi HP DeskJet 880C HP DeskJet 890C HP DeskJet 895Cse/Cxi HP DeskJet 1100C HP DeskJet 1120C HP OfficeJet 590 HP OfficeJet 600 HP OfficeJet 625 HP 2000C/Cse/CN Professional Series Color Printer Lexmark 3000 Color Jetprinter

Usually the people who send me reports do not state to which extent hpdj "works" for their printer model.

I should like to extend this section with more specific information. Therefore, if you want to report success for a particular printer model not explicitly supported by hpdj, please mention the following items in your answer:

o printer model o gs version o hpdj version o option combinations successfully tested (specify at least model, resolution, colour mode and, if used, the number of intensity levels) o printer-specific functionality you could not access

So far I have not heard of a PCL-3+ printer which cannot be driven by hpdj. Hence the really interesting part of success reports is the list of working option combinations, but since I included the above request in this manual page in December 1997, hardly anyone has sent me such a report. Possibly, users find this information unnecessary.

Colour Modes

Ignoring photo cartridges, DeskJet printers can be classified in four categories:

 The printer has only a black ink cartridge.
 The printer can print with either a black or a cyan/magenta/yellow (CMY) cartridge.
 The printer holds a CMY and a black cartridge simultaneously, but the inks are chemically incompatible and should not be overlayed. (Don’t worry: the printer is not going to explode if they do. You merely get poorer results because the black ink will spread further than it should.)
 The printer holds a CMY and a black cartridge simultaneously and the inks can be mixed.

This leads to four colour modes for the driver:

 Print in black.
 Print in cyan, magenta and yellow only. In this mode, "composite black" consisting of all three inks is used to stand in for true black.
 Print with all four inks, but never mix black with one of the others.
 Print with all four inks.

Depending on the category of the model chosen, the driver will accept one or more of these modes. The possibilities are:

ModelColour Modes
500, 510, 520mono
500C, 540mono, CMY
550C, 560Cmono, CMY, CMY+K
850C, 855C, unspecall

Note that a printer capable only of CMY might accept CMY+K or CMYK data, remapping them to CMY, and a printer capable of CMY+K might remap CMY data to CMY+K.

Print Quality Selection for Older DeskJets

With the introduction of the DeskJet 540, HP added two new PCL commands to the language: Media Type and Print Quality. For older DeskJets (500, 500C, 510, 520, 550C and 560C), similar effects can be achieved by specifying some technical aspects of the printing process in detail.

The hpdj driver accepts only the new Media Type and Print Quality specifications as options. For printers not understanding the new commands, these specifications are mapped to the older Depletion, Shingling, and Raster Graphics Quality commands based on recommendations from HP.

Media Sizes and Orientations

Ghostscript looks at several sources to determine the page size for a document:

o the default size set for gs (usually US Letter or ISO A4) o the value given to -sPAPERSIZE in the invocation o the size requested by the document, unless you specify -dFIXEDMEDIA

The last applicable item in this list overrides the others.

The driver knows which media sizes are supported by each printer model and will refuse to print if an unsupported one is requested. The model unspec normally accepts all sizes, and it assumes the printer to understand all size commands which can be sent to one of the supported series-800 DeskJets. This can be changed with a margin file specification; see the CONFIGURATION section below for details.

Each supported size is available in portrait and landscape orientation. Media should however always be put into the input tray independent of the intended orientation. Ghostscript and hpdj will take care of the rest. Hewlett-Packard’s information on the required orientation of media in the input tray is not quite clear, but hpdj assumes it to be always "short edge first" with respect to the feeding direction. You should check your printer’s manual whether this is correct, in particular if you have a DeskJet 400, 500 or 500C and wish to print on envelopes. Note that hpdj has no information about the dimension or orientation of the medium in the input tray: you must ensure yourself that this is appropriate.

In setting up the PostScript default user space, hpdj does not treat envelope sizes differently.

Diagnostic Messages

Error messages issued by hpdj start with "

? Device hpdj:
", warnings with "
?-W Device hpdj:
". Both are written on the standard error stream.


The following options are not specific to the hpdj device but have specific meaning or restrictions:

 This option specification selects this driver.
 This option specifies the resolution in pixels per inch (ppi). The driver checks whether the model selected accepts the given resolution unless the model is unspec. Resolutions supported by at least some of the models in some of the colour modes are 75, 100, 150, 300 and 600 ppi. Only unspec permits unequal horizontal and vertical resolutions. For this case read the subsection on the Configure Raster Data command in the LIMITATIONS section below first. The default resolution for hpdj is set at compile time, usually to 300 ppi.

The following options are specific to hpdj:

-dBlackLevels=levels and -dCMYLevels=levels
 Warning! These options are not based on HP documentation! Read the subsection on the Configure Raster Data command in the LIMITATIONS section below before using them.

These options set the number of intensity levels per pixel and colorant to use when printing with black or CMY inks, respectively, and must be consistent with the colour mode. They permit access to the Colour Resolution Enhancement technology (C-REt) feature available in some series-800 DeskJets. The defaults are 0 or 2, depending on the colour mode chosen. Other values are only accepted for the models 850C, 855C and unspec. I strongly suggest that you apply gamma correction and modify the halftone screens whenever you use non-default values for these options (see the CONFIGURATION section below).

unspec accepts any non-negative number of levels except 1 up to 256. The models 850C and 855C accept the levels 0, 2, 3 and 4 with the following restrictions if any of the levels is larger than 2: o You can’t use this feature with draft quality. o You can’t use a colour mode of CMY. o You must use a resolution of 300 ppi. o If you are using a non-monochrome mode, you must use 4 levels for black. When using the model unspec you should expect the printer to similarly limit the possibilities. So far I have not heard of a PCL-3+ printer supporting more than four intensity levels per colorant.

Unfortunately, there is a problem here because ghostscript’s internal colour model is not prepared for the situation where a device can render different small (< 32) numbers of intensity levels for different colorants. In this situation gs will in general assume that the number of black levels available is equal to that for CMY levels. Depending on which of the numbers is smaller, there will then either be unused black levels or some will be used more than once.

Regrettably, best results on a DeskJet 850C seem to me to be achieved with 4 black and 3 CMY levels, at least on plain paper. (4 CMY levels might be right for presentation quality on glossy paper or transparencies.) The CONFIGURATION section below presents a slightly dirty path out of this difficulty.

-sColorMode=mode or -sColourMode=mode
 This selects the colour mode to be used by the driver: mono (or monochrome), CMY, CMY+K or CMYK. The default is mono. Which colour modes are accepted depends on the model, see Colour Modes in the section DESCRIPTION above.

A value of CMY for this option also sets BlackLevels to zero, and if CMYLevels is zero when you demand any of CMY, CMY+K or CMYK, it is set to two. For all other situations you must ensure yourself that colour mode and intensity levels are consistent or hpdj will complain. This rule implies that you can ignore the level options unless you want to use a non-default number of levels.

The PostScript page device dictionary entry

will not be correct for a colour mode of CMY or CMY+K.
 PCL interpreters understand several compression methods for raster graphics data in order to speed up host-printer communication. The possible choices are:

0 Unencoded, non-compressed 1 Runlength encoding 2 Tagged Image File Format (TIFF) 3 Delta Row Compression 9 Compressed Replacement Delta Row Encoding

The default method is set at compile time, usually to 9. Requesting method 3 actually leads to a combination of methods 2 and 3. The DeskJet 500 does not support method 9. The driver may temporarily choose method 0 if a compressed data sequence would be longer than its uncompressed version.

Compression rates can vary drastically, depending on the structure of the input. However, although the absolute values change, the relative order of efficiency between the methods is usually the order of increasing method. In short: use method 9 (3 for the DeskJet 500).

 With the exception of the DeskJets 500 and 500C, DeskJet printers can be told to guarantee a minimum drying time of delay seconds before the next page of the same print job is dropped on a newly printed page. (This interval can be terminated by pressing the Load/Eject button.) The printer will choose default values depending on the current print quality, hence it is normally not necessary to specify this option and the feature is even considered obsolete for newer DeskJets although it is still supported by some of them.

Permissible values for delay are integers in the range -1 to 1200, where -1 instructs hpdj not to send a corresponding command, 0 establishes default values for the current print quality, and all other values explicitly request the duration in seconds. The default is -1.

 It is possible to request a DeskJet printer to wait before each page of a document until the Load/Eject button is pressed on the printer. This is mostly intended for situations where some special medium is used or the medium has to be inserted into an input slot holding only one sheet at a time. The default setting for this option is false except for series-500 DeskJets printing on envelope sizes when it is true.

Note that for current ghostscript versions this setting is independent of the value of the PostScript operator

. If you want to set manual feeding from the PostScript code you must therefore use the
entry in the page device dictionary.
 This option must specify an existing file containing a list of supported media sizes and corresponding margin descriptions for the printer. This will take precedence over the builtin model-specific lists of sizes and margins. The format of the file is described in the CONFIGURATION section below. The default is not to use a margin file but the builtin lists. This option is primarily intended to be used with the model unspec.

A margin file path can also be specified at compile time overriding the default behaviour for unspec only. Using the MarginFile option in addition will override the compiled-in margin file path.

 This option selects (you guessed it) the type of medium you wish to print on. The possible choices are: 0 plain paper 1 bond paper 2 HP Premium paper 3 glossy paper 4 transparency film 5 photo paper

The default is plain paper. For type, you can specify the full strings, the one-word strings resulting from dropping "paper", "film", and "HP", or an integer. Out-of-range numerical values generate a warning but are passed through to the printer if it is a model understanding the PCL command "Media Type". If it isn’t, the effect is the same as specifying plain paper. The value 5/photo paper is only understood by some recent DeskJets (e.g., the DeskJet 690C) and will be ignored by older ones.

 This option identifies the printer model for which the generated file is intended. The following names are accepted for model:

500, 500C, 510, 520, 540, 550C, 560C, 850C, 855C, unspec.

The choice of model primarily determines which resolutions, colour modes, intensity levels and media sizes the driver will accept, where the output will appear on the page, and to some extent what PCL code the driver will generate. Some of the models are treated identically. A default model can be set at compile time. If this has not been done, you must specify the Model option in every invocation.

unspec is intended to be a stop-gap for DeskJet-compatible printers not presently supported by this driver. For unspec, all model-specific checks (e.g., supported resolutions) are turned off. Supported media sizes and margin settings are assumed to be identical with those for the DeskJets 850C/855C/870C/890C, but you can use the MarginFile option or its compile-time equivalent to override this. The PCL code generated assumes a "new" DeskJet in the sense that it should be at least at the level of a DeskJet 540 supporting the PCL commands Media Type and Print Quality. If you specify unequal horizontal and vertical resolutions or more than two levels of intensity per colour and pixel, the printer must in addition understand the Configure Raster Data command. Read the subsection on that command in the LIMITATIONS section below.

If you choose to use unspec it is your responsibility to ensure that hpdj is only called with parameter values the printer can handle. This applies in particular to the resolution and the intensity levels.

 The pathname must specify either a non-existent file in a directory with write permission or a writable file with a single line containing a non-negative integer. In the first case, hpdj will create the file and insert the number of pages processed, in the second case the number will be incremented by that amount. Parallel invocations of gs are permitted to use the same file. hpdj will also make the initial page count available in its page device dictionary. Note that in present ghostscript versions the PostScript operator
always returns
and is not based on the value of
in the page device dictionary.

This option is mainly intended for spooler backends calling hpdj. It can be used to keep track of the total number of pages printed and also for per-job accounting. I recommend using this option for the first purpose and to make a note of the values in the resulting files whenever you insert a new ink cartridge. This will enable you to get an indication of how much a printed page costs and why it is a good idea to use draft quality whenever possible.

The driver can be compiled without this option present but on a UNIX system I would not expect this to be done unless gs offers the same functionality in a driver-independent manner which it currently does not.

hpdj is distributed with an example

of a BSD spooler backend using this option.
 There are three print quality settings:

1presentation or best

The default is normal. You may specify the strings or an integer. Out-of-range numerical values will generate a warning but are passed through to the printer if it is a model understanding the PCL command "Print Quality". If it isn’t, the effect is the same as specifying normal.

Looking up Compile-Time Defaults

Some default values for options can be chosen at compile time. If you later want to know these values, run gs on the following PostScript code:

dup /Name get (hpdj) eq not
  (ERROR: You have not selected the hpdj driver.) =
  (Model: ) print
  dup /Model get =

(Resolution: ) print dup /HWResolution get ==

(Compression method: ) print dup /CompressionMethod get =

(Margin file: ) print dup /MarginFile get dup () eq {pop (none)} if =

(PagecountFile is ) print dup /PagecountFile known not {(not ) print} if (supported.) = } ifelse pop quit

Note that this will not necessarily return the compile-time defaults but only the values current at the time of execution. Therefore you should not specify any options except -sDEVICE=hpdj and, if your ghostscript executable has been compiled without a default model for hpdj or if you want to find out whether there is a compiled-in margin file path, -sModel=unspec. You should also make sure that you have not set environment variables modifying ghostscript’s behaviour.


Margin Description File

A margin description file (margin file for short) can be used to override the builtin model-specific lists of supported media sizes and the margins in force for each. This feature is mainly intended to be used in conjunction with -sModel=unspec: if you have a model not directly supported by this driver, look up the supported page sizes and corresponding printable regions in your printer’s manual and enter them in a margin file.

Note: Entering a page size in the margin file which is not really supported by your printer is not useful: the PCL interpreter will simply ignore the request to set this page size, and printer and driver may have diverging opinions about what the margins will be. If you need to print on a medium of a size not supported by your printer, choose a larger and printer-supported size in PostScript or via -dFIXEDMEDIA, shift the image if necessary, establish properly-positioned clipping regions within the real size, and print. However, if you have a newer DeskJet supporting custom page sizes, this is not necessary (see below).

Margin specifications are important for two reasons: the values for the left and top margins determine how the output is positioned on the page, and sufficiently large values for the right and bottom margins prevent the print head being caught at the paper’s edge and printing beyond the sheet, respectively. Because DeskJet printers often have an inconveniently large bottom margin (usually 0.4-0.8 inches or 10-20 mm), one might be tempted to specify smaller values than listed in the printer’s manual. However, one user reported that this led to the printer depositing a large wet blob of black ink at the bottom of the page. Specifying a smaller margin on the right is in contrast probably harmless because, according to HP, DeskJet printers always clip at that margin.

A line in the margin file can be blank, a comment line (first non-blank character is ’

’), or one of the following:

unit code left bottom right top


line specifies in which units margin specifications in the following lines should be interpreted. unit can be either
being the default. A unit specification remains in force until overridden by a following

The second kind of line states that the model supports a particular page size, identified by its PCL page size code, and specifies the margins in force for that size when printing in black, in raster graphics mode, and in portrait orientation for the medium (width <= height). Be careful with envelopes: older (pre-1997) HP documentation frequently gives their margins in landscape orientation; you can check this by looking for the largest margin value: in portrait orientation it should be at the bottom. The margins have to be specified as floating point numbers in inches or millimetres as announced by the last preceding

line. The floating point format is that of the "C" locale. Depending on the model, hpdj will either assume that the same margins apply for colour printing (this is the case for unspec) or increase the bottom margin by a model-specific amount in that case.

The code must be one of the following PCL page size codes (entries marked with an asterisk are those used by the model unspec if no margin file is employed):

*1US Executive (7.25 × 10.5 in)
*2US Letter (8.5 × 11 in)
*3US Legal (8.5 × 14 in)
6US Tabloid (11 × 17 in, also called "Ledger")
15US Statement (5.5 × 8.5 in)
16Super B (305 × 487 mm)
*24ISO/JIS A6 (105 × 148 mm)
*25ISO/JIS A5 (148 × 210 mm)
*26ISO/JIS A4 (210 × 297 mm)
27ISO/JIS A3 (297 × 420 mm)
*45JIS B5 (182 × 257 mm).
 This is distinct from ISO B5 (176 × 250 mm).
46JIS B4 (257 x 364 mm).
 This is distinct from ISO B4 (250 × 353 mm).
*71Hagaki card (100 × 148 mm)
*74US index card 4 × 6 in
*75US index card 5 × 8 in
*81US no. 10 envelope (4.125 × 9.5 in).
*90ISO DL envelope (110 × 220 mm)
*92ISO C6 envelope (114 × 162 mm)
*101custom page size
109US A2 envelope (4.375 × 5.75 in)

The page size code 101 (custom page size) is not understood by older printers and may be used in a margin file only for the models 540, 850C, 855C, and unspec. In these cases you can print, within certain limits, on arbitrarily sized media. The driver knows these limits and refuses to generate a file if you exceed them. For unspec, there are no limits. hpdj will tell the printer to expect a custom page size only if there is no fitting discrete entry.

Every margin file must contain at least an entry which fits ghostscript’s default page size, usually ISO A4 or US Letter. Only those sizes which are listed will be accepted by hpdj.

hpdj is distributed with an example of a margin description file,


PostScript Configuration File

Sometimes it is desirable to execute additional PostScript commands for a particular file or possibly all files sent to a particular printer or print queue. With ghostscript this is easily possible because gs accepts several files in the invocation and executes them sequentially. This is particularly appropriate for those PostScript operators which affect device-specific features and should therefore not appear in a portable page description.

The hpdj distribution contains an example of an input filter

for the BSD spooler lpr(1) permitting the use of a print-queue-specific configuration file.

Correcting Offsets

A margin description file is intended to adapt hpdj to the difference in margin settings between printer models and should usually contain "official" information, preferably taken from the model’s manual.

A different situation arises if a particular printer’s output is not properly positioned on the page even if the margin information is correct for this model. PostScript defines two arrays in the page device dictionary for correcting such misadjustments, both containing two numbers describing a desired shift of the page image with respect to device space coordinate axes but in different units. The values in the ‘

’ array are interpreted with respect to a canonical default resolution, the newer ‘
’ array (supported by ghostscript since probably gs 3.50) is taken to be in units of 1/72 inch ("big points", bp). For hpdj the device coordinate system has an x axis pointing to the right and a y axis pointing downwards in portrait orientation, and the canonical default resolution is the default resolution chosen at compile time (see the OPTIONS section above).

As an example, assume your printer shifts its output 1 mm to the right and 0.5 mm upwards and the default resolution of your version of hpdj is 300 ppi. Now create a file containing either the PostScript code

<< /Margins [-11.8 5.9] >> setpagedevice

("shift 11.8 pixels to the left and 5.9 pixels down") or

<< /PageOffset [-2.8 1.4] >> setpagedevice

("shift 2.8 bp to the left and 1.4 bp down") and have it executed by ghostscript before the file to be printed. If you specify both,

, the total shift performed by gs will be the sum of the two.

The file
in the ghostscript distribution or the margin test files distributed with hpdj can be used to determine the necessary correction. You should be aware that you have to expect fluctuations between individual print jobs, in particular in the horizontal direction.

Gamma Correction

DeskJets usually produce colour prints which are too dark (too much ink on the page). In this case you should perform gamma correction by modifying what PostScript calls transfer functions. In the simplest case, create a file containing the PostScript command

exp} settransfer

where a good value for number is usually in the range

, and specify this file in ghostscript’s command line before the file you wish to print. Now the intensities of all colorants will be rescaled by exponentiation with number. Because PostScript intensity values are in the range zero to one with zero meaning dark and one meaning light (additive interpretation), a value of number < 1 will lead to lighter colours and number > 1 results in darker colours.

You can also set independent transfer functions for the four colorants by using the operator

which expects four routines as arguments. Consult a PostScript manual if you want to learn more about transfer functions.

For a device with less than 32 intensity levels per colorant, at resolutions below 800 ppi, and unless you explicitly set transfer functions, gs applies a default gamma correction roughly corresponding to a value of

for number.

Different Numbers of Black and CMY Intensities

DeskJets supporting C-REt apparently achieve more than two intensities per colorant by putting a variable number of layers of the same ink on top of each other. This happens during several passes of the print head. The number of levels which can be achieved is therefore determined by the number of passes which in turn is influenced by the print quality and the media type (that is apparently the reason why using C-REt in draft quality is useless). It is now likely that if one uses more levels than can be supported by the number of passes, the higher levels will look the same. This is what seems to happen if one prints with 4 intensity levels for CMY on plain paper with a DeskJet 850C: the fourth level is accepted by the printer but to me it looks indistinguishable from the third.

In this situation we can compensate for ghostscript not correctly dealing with different numbers of black and CMY intensity levels by using PostScript’s transfer functions. The idea is to specify in the invocation the higher number of levels for both, black and CMY, but to map the range for those components where actually only a smaller number of levels is distinguishable to a reduced range which gs will divide into the required (smaller) number of intervals. Although the printer will be told to expect the higher number of intensities, it will never receive them. However, if the assumptions above are correct, the highest level it does receive will anyway look like the highest level possible!

For the case of 4 black and 3 intended CMY levels the CMY intensities must be remapped from the range [0, 1] to the range [1/3, 1]. Here’s the code, including an equal gamma value number for all four components:

number exp 2 mul 1 add 3 div} dup dup {number exp} setcolortransfer

In the call to gs you must now specify a value of 4 for both, BlackLevels and CMYLevels.


Most printers offer only a small number of intensities per colorant and pixel. In order to generate a larger range of colours, one therefore employs halftoning which consists of dividing the pixel array into halftone cells, each of which represents one effective pixel which can now display more shades. This method trades resolution for the number of shades and applies to all structures which have to be painted with a colour which cannot be represented exactly. At 300 ppi and with a bi-level device a typical choice is to use halftone cells of 5×5 pixels leading to an effective resolution of 60 ppi and 26 shades per component. These are also ghostscript’s default values at 300 ppi.

Which kind of halftoning is appropriate depends not only on the printer but also on the document to be printed. For this reason PostScript offers access to the halftoning parameters. You should use this feature in particular if your printer supports more than two intensity levels because ghostscript does not recognize by itself that it can now obtain a higher effective resolution without a loss in the number of shades. However, should your printer support at least 32 intensity levels you need not bother about this point because in that case hpdj will not cause halftoning to be used.

For those not familiar with PostScript, here’s some code to redefine ghostscript’s default halftoning state for non-monochrome colour modes to use an array of halftone cells with a resolution of frequency cells per inch (hence the resolution divided by frequency is the size of the halftone cells in pixels):

currenthalftone dup /HalftoneType get 2 eq
frequency def /GreenFrequency frequency def /BlueFrequency frequency def /GrayFrequency frequency def currentdict end sethalftone } {pop} % Not prepared for this case. ifelse

For general applications, reasonable values for frequency on a 3- or 4-level device at 300 ppi are

. You can use the file
in the ghostscript distribution to gain some impression of the effects on the size of halftone cells and the number of shades you can distinguish. Consult a PostScript manual if you want to learn more about how to specify halftones.

If you are using the colour mode CMYK and more than 2 black levels you should not set merely a single halftone screen (

, a type-1 or a type-3 halftone dictionary) because ghostscript’s dithering routine can in this case return non-monotonic levels of black for monotonic input intensities. However, if you specify independent halftone information for the colour components, gs uses a slower but more accurate algorithm instead which does not lead to the wrong behaviour. It is not necessary for the halftone information to be different for different components to achieve this. Note that ghostscript installs separate halftone screens for CMYK devices by default if the resolution is at least 150 ppi.


Ghostscript Version

This manual page contains statements relying on undocumented features of ghostscript. These statements are to my best knowledge and belief correct for at least ghostscript 5.50, and I hope I’ve not missed significant deviations when testing with older versions. But I can’t of course guarantee anything for newer ones.

The Rendering Algorithm

In ghostscript’s internal architecture the ghostscript kernel calls on a device driver for basic drawing operations and to ship out completed pages. For most if not all print devices this process can be separated into rendering in memory and transferring the resulting array of pixels to a file or directly to a printer.

Ghostscript has an abstract printer device (prn) which uses a "memory" or "command list" device for rendering and transfers the completed page to a printer-specific backend for output. Such a backend must supply several parameters for the rendering process but its main purpose is the conversion from ghostscript’s internal pixel data structure to a printer-specific format. hpdj is such a prn-derived backend. This means in particular that hpdj does not have much influence on the rendering but also that a user can influence the rendering process by the usual methods available in PostScript.

I do not claim that this leaves nothing to be desired. For example, there is no possibility in this implementation to perform Floyd-Steinberg dithering. Of course, one can implement error diffusion in a ghostscript device driver and a number of people have done so in printer-specific backends. I do not believe, though, that such an implementation belongs there: it should better be implemented in an improved rendering device. In that way, it could be used for other printer-specific backends as well. This is also true for every other kind of modification of the rendering process. I have therefore deliberately restricted hpdj to be a "purely printing" backend: it knows about PCL but not about rendering.

Therefore, if you need better visual quality for documents with shades of grey or non-primary (non-CMYK) colours, this cannot be achieved by giving some tricky combination of option values to hpdj. Instead you should experiment with the relevant PostScript operators (see chapter 6 of the PostScript Language Reference), or ultimately extend ghostscript’s prn device.

The Configure Raster Data Command

There is a new PCL-3+ command called "Configure Raster Data" for which until recently I had not been able to obtain documentation. This command is apparently the basis for supporting unequal resolutions in horizontal and vertical directions and for HP’s Color Resolution Enhancement technology (C-REt). Some option values supported by hpdj lead to Configure Raster Data being used and must therefore be considered unsafe!

At least some of the series-500 DeskJets as well as newer models claim to permit unequal resolutions in horizontal and vertical directions, in particular 600 × 300 ppi. The corresponding implementation in hpdj, available only for the model unspec, is based on Configure Raster Data. It seems to work at least for the DeskJet 690C; it does not work for the DeskJet 870C (see below). I would however strongly advise against using these resolutions for printing on a series-500 DeskJet because, although these models have a 600 dpi addressable horizontal resolution grid they do not permit neighbouring pixels to be activated (and the dots printed still have a diameter of about 1/300 in). The raster data generated by gs does not obey this restriction. In addition, it is likely that the higher resolution is anyway only supported for the printer’s builtin fonts and not for general raster data.

Concerning the DeskJet 870C, my impression is that although some HP documents and drivers use expressions like "600x300 dpi C-REt color" for this printer, the model does not really support a resolution of 600 × 300 ppi. First, it does not accept hpdj’s output with this resolution, and second, if one redirects the best output of HP’s Windows driver for this printer to a file, the result is a file with what I’ve called a mixed resolution, i.e., 600 ppi for black and 300 ppi for CMY. To me it looks therefore as if Hewlett-Packard has been sloppy in formulating its documentation.

I am not quite certain what HP means by C-REt or PhotoREt but it seems to be a combination of hardware functionality and properties of HP printer drivers. The hardware part makes it possible to specify more than the two basic intensities, on or off, per colorant and pixel. As far as I know, this capability is only available in series-800 DeskJets and it has to be accessed by Configure Raster Data. The implementation of non-default values for hpdj’s options BlackLevels and CMYLevels is therefore based on Configure Raster Data. It works at least with the DeskJets 850C, 870C and 890C.

Performance for Larger Numbers of Intensity Levels

This could be improved by replacing some generic routines by more specialized ones for particular parameter values. There does not seem much sense in doing this, though, until I know that the code in question is needed for some printer model.

Mixed Resolutions

Newer DeskJets are able to print with different resolutions for black and CMY on the same region of a page. For example, the best quality on a DeskJet 850C is achieved with 600 ppi for black and 300 ppi for CMY. This is also due to the new Configure Raster Data command and is not supported. I suspect that implementing this really well in ghostscript is not a simple task and probably requires modifying the ghostscript kernel.

Photo Cartridges

From what I’ve heard, DeskJet printers with photo cartridges installed do not use a CMYK palette but instead one with 6 components. I have no official information on this interface and ghostscript currently does not support ‘

’ as a native colour space.

Cartridge Alignment

DeskJet printers with more than one ink cartridge present should usually be configured for the proper relative alignment of these cartridges. Apparently, this information is stored in not-immediately-volatile memory in the printer together with some default settings like the default media size which are not relevant for printing with hpdj. As I do not have information on how this is done, you will need to use one of HP’s programs for this purpose.

On a Linux system, try installing and running HP’s DOS DeskJet control panel

in the DOS emulator. I did not get it to work, but you might have more luck (or skill).
should be present on one of the installation media you received with your printer.


I intend to release a new version in a few months for which I am going to change the name of the driver from hpdj to (probably) pcl3. The new name will more accurately reflect what this driver is for.

This new version will be based on more extensive HP documentation, will therefore support more printers, and it will add some new functionality.


There are no known bugs in hpdj proper, but there do exist restrictions or bugs in gs which can lead to faulty behaviour when printing with hpdj. As far as I noticed them they are mentioned in the body of this manual page at the relevant points.



Adobe Systems PostScript Language Reference Third edition, 1999.

A First Guide to PostScript programming/ postscript/ 

Hewlett-Packard Technical Reference Guide for the HP DeskJet 500 Series Printers First edition, October 1994. Manual Part Number: C2170-90099.

Unfortunately, this guide does not describe all valid commands. I was told in October 1997 by the German firm distributing HP manuals that there is no newer HP manual on PCL 3 and that they had even considered writing one themselves for this reason.


Copyright © 1996, 1997, 1998, 1999 by Martin Lottermoser, Metzgerfeldweg 9, 85737 Ismaning, Germany. E-mail:

This is free software, released under the terms of the GNU Library General Public License (LGPL), Version 2. USE IT AT YOUR OWN RISK.

hpdj has a home page at ghostscript/ pcl3/ pcl3.html
. The source code for the driver is available in the same directory, file
. You should, however, keep in mind that the name of the driver will change in the future (see FUTURE DIRECTIONS) and this will of course be reflected in the names of files.

openSUSE Logo