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, stretch and buster 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 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.
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 etc. CUPS, PWG and Apple raster output viewing is a little harder to accomplish because there is no Debian package for the viewer. RasterView will handle PWG and Apple raster files because the PWG format is based on CUPS raster and Apple Raster is very similar to PWG raster.
The source code for RasterView can 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:
mkdir rasterview mv rasterview-1.7.1.tar.gz rasterview cd rasterview tar zvxf rasterview-1.7.1.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 pcl6-916-linux_x86 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 stretch version of cupsfilter and its documentation, but there is very little difference in the utility's behaviour on jessie and buster.
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 operation of a particular print queue. As root on jessie, stretch and buster 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.
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.
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, application/postscript, application/vnd.cups-pdf, application/vnd.cups-postscript and application/vnd.cups-raster are also likely to be wanted. vnd.cups-* indicates a printer-ready file; that is, a file which has print options using -o 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
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. But filters can also be specified in the PPD file with a *cupsFilter line. This will be the last filter applied in the filter chain; laserjet.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 a PDF viewer and RasterView.
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 an Ubuntu bug report.
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