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 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 isn't 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 reasonabl 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 or NOTES section in the filter manual.
When tracking down a problem with printing the cupsfilter utilty is a useful tool to complement what is produced by an error_log.
A user can access much of what cupsfilter offers when it is executed as /usr/sbin/cupsfilter. However, when a PPD is called for, as it is with the -e option, root privileges may be required.
The ease of examining the output from cupsfilter at a particular stage of a filtering process depends on the file type produced. PDF and PostScript can be viewed by gv, xpdf, mupdf, evince, okular or zathura. CUPS, PWG and Apple raster output viewing is handled by rasterview. The PWG format is based on CUPS raster and Apple Raster is very similar to PWG raster.
The source code for RasterView may be downloaded from the principal CUPS developer's web site. For successful compiling you are advised to obtain source code which has a version greater than v1.5. The following command would do this for you:
The executable can be compiled after installing the g++ and libfltk1.3-dev packages and doing
mkdir rasterview mv rasterview-1.8.tar.gz rasterview cd rasterview tar zvxf rasterview-1.8.tar.gz ./configure make
The rasterview executable produced would be put in /usr/local/bin.
Using RasterView isn't too hard. Zooming in and out is mouse-driven with its left and right buttons; or the - and = keys can be used. The bottom left of the window has buttons < and > for moving forwards and backwards in a document; or use the SPACE and BACK keys from the keyboard. 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, raster data or vendor-specific data. Ghostpcl is a PCL viewer. It is sufficient to put the binary in /usr/local/bin for it to function. Often the only way to view a file which is classified by the file utility 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 on this page use the Debian 11 (bullseye) version of cupsfilter and its documentation, but there is very little difference in the utility's behaviour on previous distributions.
The pdfinfo Utility
pdfinfo is in the poppler-utils package. It is a useful tool for examining information extracted from a PDF submited to CUPS and comparing it to a PDF produced by the filtering system. The pdftopdfandPageRotation wiki page uses this technique to track rotation of pages in a PDF document from the Page rot: attribute.
By default pdfinfo <PDF> will display only information about the first page in a PDF file. The -f and -l options specify the range of pages to examine.
For the number of pages, N, in a file:
pdfinfo <PDF> | grep Pages
For information on a range of pages in the file:
pdfinfo -f 4 -l 12 <PDF>
For information on all the pages in the file:
pdfinfo -l N <PDF>
Using a PPD File with cupsfilter
You almost certainly want to use a PPD file with cupsfilter to test the detailed operation of a particular print queue. As root you will have access to the PPD for the queue in /etc/cups/ppd; as a user you will not because the PPD files in /etc/cups/ppd/ are, by default, not world-readable. If you want to test the filtering of an installed print queue as a user you can, however, get its PPD file using cups-driverd.
- This technique applies only to legacy printing. That is, printing with those printers having print queues set up with vendor drivers.
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 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.
For a modern printer a PPD may be obtained from
gives the URI.
Commands using /usr/sbin/cupsfilter are intended for a user who has obtained a PPD as described above. For a user with root privileges the command cupsfilter would suffice. In this case the -p option would be /etc/cups/ppd/<PPD> because <PPD> is readable by such a user.
Specifying the Destination File Type
The cupsfilter -m option allows files at each stage of the filtering process to be produced and examined. application/pdf is the default output without anything for -m specified, but, depending on the filtering chain,
are also possibly wanted for this option.
In other words:
/usr/sbin/cupsfilter -p laserjet2200.ppd -m application/vnd.cups-raster -o number-up=2 test.ps > out.ps 2> log
would give a raster file output if that was appropriate for the print queue. The filters used with a particular queue may be obtained with (see below):
/usr/sbin/cupsfilter -p laserjet2200.ppd -m printer/foo -e --list-filters
vnd.cups-* indicates a printer-ready file; that is, a file which has print options using the -o option incorporated in it. 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,test.ps, which you can use. As a user:
/usr/sbin/cupsfilter -p laserjet2200.ppd -m application/postscript -o number-up=2 test.ps > out.ps 2> log
You should find out.ps looks no different from test.ps. In fact, it is also the same size as test.ps. 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. The -o option has not been applied. Nothing much has happened here.
/usr/sbin/cupsfilter -p laserjet2200.ppd -m application/pdf -o number-up=2 test.ps > out.ps 2> log ?
From the log we see Ghostscript converting PostScript to PDF with pstopdf. The output looks no different from the input though. Again, the -o has not been taken account of. That's to be expected for conversion to MIME media type application/pdf. Progessing to
/usr/sbin/cupsfilter -p laserjet2200.ppd -m application/vnd.cups-pdf -o number-up=2 test.ps > out.pdf 2> log
to convert to a file suitable to be sent to a printer, probably after some further processing. pstopdf is 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 in a PDF viewer.
Obtaining the File which is Sent to the Printer
A number of the previous commands has relied solely on the *.convs files in /usr/share/cups/mime to determine the filters used in the filtering chain. But filters can also be specified in the PPD file with a *cupsFilter or *cupsFilter2 line. This will be the last filter applied in the filter chain; laserjet2200.ppd has
*cupsFilter "application/vnd.cups-raster 100 rastertogutenprint 5.2"
To use this filter with cupsfilter
- the -e option to cupsfilter is required and
the destination file type has to indicate that conversion to a format suitable to be sent to the printer is necessary.
The command to ascertain which filters will be used:
/usr/sbin/cupsfilter -p laserjet2200.ppd -m printer/foo -e -o number-up=2 --list-filters test.ps
gstopdf pdftopdf gstoraster rastertogutenprint.5.2
+---------+ +----------+ +------------+ +------------------------+ | | pdf | | vnd.cups-pdf | | vnd.cups-raster | | test.ps=>| gstopdf |====>| pdftopdf |=============>| gstoraster |================>| rastertogutenprint.5.2 |=>PCL | | | | | | | | +---------+ +----------+ +------------+ +------------------------+
An output file and a log of the process is obtained with:
/usr/sbin/cupsfilter -p laserjet2200.ppd -m printer/foo -o number-up=2 test.ps -e > out.pcl 2> log
out.pcl, identified as HP PCL printer data by file, should be viewable with ghostpcl. The file outputs for the intermediate stages can be obtained as indicted earlier and are viewable with a PDF viewer and RasterView.
As another example: the everywhere PPD for an HP ENVY 4500 contains the lines
*cupsFilter2: "image/jpeg image/jpeg 0 -" *cupsFilter2: "image/urf image/urf 100 -"
/usr/sbin/cupsfilter -p ENVY4500.ppd -m printer/foo -e /etc/services --list-filters
shows all the filters to be employed:
texttopdf pdftopdf gstoraster rastertopwg
The output of the final filter is Apple raster, viewable with RasterView.