Translation(s): none

cupsfilter uses the CUPS printing system filters to convert a file to another format.


cupsfilter comes with the cups package. The idea behind it is to use the filter subsystem (provided on Jessie in the cups, cups-server-common, cups-daemon, cups-filters and cups-filters-core-drivers packages) to convert a file to a specific format. The processing is identical to that done by CUPS and the filter subsystem when a file makes its way to the printer and ink or toner is put on paper; except there is no paper output.

We can use cupsfilter to examine the state of the filter conversions at each stage of the filtering process and determine whether behaviour is reasonable and correct. The filters in /usr/lib/cups/filter can also be used as standalone programs to examine the conversions but this is not generally encouraged. Please see the warning on the filter manual page.

When tracking down a problem with printing the cupsfilter utilty is a useful tool to have to complement what is produced by an error_log.

File Viewers

The ease of examining the output from cupsfilter at a particular stage of a filtering process depends on the file type. PDF and PostScript can be viewed by gv, xpdf, mupdf, Evince, Okular etc. CUPS raster output viewing is a little harder to accomplish because there is no Debian package for the viewer. The source code for RasterView can be downloaded from the principal CUPS developer's web site. The executable can be compiled after installing the g++ and libfltk1.3-dev packages and doing ./configure plus make. The rasterview executable produced would be put in /usr/local/bin. Alternatively, the RPM package can be converted to a Debian package with alien and installed with dpkg -i. Note that rasterview will also handle PWG raster files because this format is based on CUPS raster.

Using RasterView isn't too hard. Zooming in and out is mouse-driven; or the - and = keys can be used. The bottom left of the window has a button |>| for moving on a page. From the keyboard SHIFT+SPACE does the same job. The ESC key exits the program.

Viewing the file which is actually sent to the printer (the printer-ready file) may or may not be possible because it depends on whether it is PostScript, PDF, PCL or just data. ghostPCL is a PCL viewer. It is sufficient to put the pcl6-916-linux_x86 binary in /usr/local/bin for it to function. The only way to view a file which is classified by the file utilty as data is to send it to the printer without passing through the filtering system. One way is:

   lp -d <print_queue> -o raw <final_file>

The use examples described here use the Jessie version of cupsfilter and its documentation. The version which comes with cups 2.0.2-2 has acquired a useful --list-filters option. If extracted from that cups package and used to replace the Jessie version you should find it works without detracting from any of the existing functionality.

The pdfinfo Utility

pdfinfo is in the poppler-utils package. Wheezy users are advised to use the version from wheezy-backports to get the benefit of recent changes in the program.

By default pdfinfo will only display information about the first page in a PDF file. The -f and -l options specify the range of pages to examine.

  pdfinfo -f 1 -l 1000 <PDF>

is quite useful if you want to look at all pages but have forgotten how many there are or cannot be bothered to find out!

Using a PPD File with cupsfilter

You almost certainly want to use a PPD file with cupsfilter. As root on Jessie you will have access to one in /etc/cups/ppd; as a user you may not as it depends on the configuration of CUPS whether the PPD files in /etc/cups/ppd/ are world-readable. If you want to test the filtering of an installed print queue as a user you can get its PPD file using cups-driverd.

Let's suppose the print queue is for a LaserJet 2200 using the Gutenprint PPD. A searchable list of PPDs on the system is available to a user with

  /usr/sbin/lpinfo -m | less

and we find the URI for the PPD is



  /usr/lib/cups/daemon/cups-driverd cat gutenprint.5.2://hp-lj_2200/expert > laserjet2200.ppd

gives you the PPD.

Specifying the Destination File Type

The -m option allows files at each stage of the filtering process to be produced and examined. application/pdf is the default output but application/postscript, application/vnd.cups-pdf, application/vnd.cups-postscript and application/vnd.cups-raster are also likely to be wanted. application/vnd.cups-* indicates a printer-ready file. Print options, for example, N-up, scaling and rotation, are applied to the pages in the submitted file by a filter, usually pdftopdf.

Here is a small PostScript file,, which you can use. As a user:

  /usr/sbin/cupsfilter -p laserjet2200.ppd -m application/postscript -o number-up=2 > 2> log

You should find looks no different from In fact, it is also the same size as The log shows the only filter which runs is gziptoany. gziptoany is designed to Copy (and uncompress) files to stdout. The result is not unexpected because conversion is from MIME meda type PostScript to MIME media type PostScript. Nothing much has happened here.

How about

  /usr/sbin/cupsfilter -p laserjet2200.ppd -m application/pdf -o number-up=2 > 2> log ?

From the log we see Ghostscript converting PostScript to PDF with pstopdf. The output looks no different from the input though. That's also expected, so we progress to

  /usr/sbin/cupsfilter -p laserjet2200.ppd -m application/vnd.cups-pdf -o number-up=2 > out.pdf 2> log

to convert to a file suitable to be sent to a printer, maybe with some further processing.

We see pstopdf invoked again but it is followed by pdftopdf. The latter filter performs the very important task of page management; the application of N-up is obvious.

Now we will alter the destination mime type:

  /usr/sbin/cupsfilter -p laserjet2200.ppd -m application/vnd.cups-postscript -o number-up=2 > 2> log

The only filter used is pstops and (in this example) it performs the same function as pdftopdf. This illustrates the older PostScript-centric workflow in action. Except for ?one or two situations, this will not be the workflow on a Jessie printing system.

Note that looks the same as out.pdf from previously; but do not run away with the idea that pstops does exactly the same thing as pdftopdf.

Obtaining the File which is Sent to the Printer

The last three commands have relied solely on the *.convs files in /usr/share/cups/mime to determine the filters used in the filtering chain. Each filter has a cost. In the last command conversion to application/vnd.cups-postscript with pstops costs 66. This is the same cost as (pstopdf + pdftopdf +pdftops) but the number of filters is fewer. The former becomes the preferred route.

But filters can also be specified in the PPD file with a *cupsFilter line. This is the last filter applied in the filter chain. The laserjet.ppd has

  *cupsFilter "application/vnd.cups-raster 100 rastertogutenprint 5.2"

To use this filter with cupsfilter the -e option is required and the destination file type has to indicate that conversion to the format to be sent to the printer is necessary.

  /usr/sbin/cupsfilter -p laserjet2200.ppd -m printer/foo -o number-up=2 -e > out.pcl 2> log

out.pcl should be viewable with ghostpcl.

A Problem with the hpcups Filter

Any use of an hpcups PPD file with the previous command on Jessie results in hpcups crashing. The reason is explained in LP #1395676.

One way round this is to use cupsfilter up to the application/vnd.cups-raster stage and then produce the printer-ready file with

  DEVICE_URI="" PPD="hpcups_ppd" /usr/lib/cups/filter/hpcups 0 0 0 0 0 <raster_file> > out.pcl

See Also