Printing direct from OF (via CUPs, OSX example)

Hey All,

I couldn’t find any examples of how to print from OF, so I spent today working out how to do it.

Download gutenprint-5.2.3.tar.bz2 from

And the DMG if you want to install the drivers, but it should all be there.


How to print here:

Probably should be using their native api for file IO but couldn’t be bothered.]

opened it up, went in and typed




sudo make install

Then added it to an OF project by:
In the project window, double-click on the Targets group and control-click on the simple target to show the context menu. Choose Existing Framework… from the Add submenu. When the file chooser sheet appears, press the / key and enter “/usr/lib”. Scroll down the file list and select the libcups.dylib file. Click the Add button in the file chooser and attributes sheets.

Then the following source, with a JPG file in the data folder called bikers.jpg in it, should work. You’ll have to comment out the printing bits the first time around - to get the correct name of the printer. Don’t forget to change it, as it will be different from mine.

All done using a duplicated version of the alladdons project from:…

Source follows:


#include "testApp.h"  
void testApp::setup(){	  
	int i;  
	cups_dest_t *dests, *dest, *correctPrinter;  
	int num_dests = cupsGetDests(&dests);  
	string theRightPrinterName = string("MP620_series__00_00_85_ee_44_3e_");  
	for (i = num_dests, dest = dests; i > 0; i --, dest ++)  
		const char *value;  
		value = cupsGetOption("printer-info", dest->num_options, dest->options);  
		printf("%s (%s)\n", dest->name, value ? value : "no description");	  
		if(theRightPrinterName == dest->name)  
			correctPrinter = dest;  
	int job_id;  
	/* Print a single file */  
	//job_id = cupsPrintFile(correctPrinter->name, "/usr/share/cups/data/",  
	//					   "Test Print JGL", correctPrinter->num_options, correctPrinter->options);  
	string thePath = ofToDataPath("bikers.jpg");  
	char * cstr;  
	cstr = new char [thePath.size()+1];  
	strcpy (cstr, thePath.c_str());  
	job_id = cupsPrintFile(correctPrinter->name, cstr ,  
						   "Test Print JGL3", correctPrinter->num_options, correctPrinter->options);  
	if (job_id == 0)  
		cout << "Printer error is " << cupsLastError() << endl;  
	cupsFreeDests(num_dests, dests);  
	delete[] cstr;  
void testApp::update(){  
void testApp::draw(){  
	ofDrawBitmapString("This app just prints. Have a look at the console for feedback on printer names.", 100,100);  
void testApp::keyPressed  (int key){   
void testApp::keyReleased  (int key){   
void testApp::mouseMoved(int x, int y ){  
void testApp::mouseDragged(int x, int y, int button){  
void testApp::mousePressed(int x, int y, int button){  
void testApp::mouseReleased(){  


#ifndef _TEST_APP  
#define _TEST_APP  
#include "ofMain.h"  
#include "ofAddons.h"  
#include <cups/cups.h>  
class testApp : public ofSimpleApp{  
		void setup();  
		void update();  
		void draw();  
		void keyPressed  (int key);  
		void keyReleased (int key);  
		void mouseMoved(int x, int y );  
		void mouseDragged(int x, int y, int button);  
		void mousePressed(int x, int y, int button);  
		void mouseReleased();  
		// we don't actually use these  
		// just checking to see if they   
		// all work in the same place :)  
		ofxCvGrayscaleImage cvGray;  
		ofxObjLoader obj;  
		ofxDirList dirList;  
		ofxVec2f p;  
		ofxTCPClient client;  
		ofxTCPServer server;  
		ofxOscSender osc_sender;  
		ofxThread thread;  
		ofxXmlSettings settings;  

If CUPs is working correctly then you should be able to type:


Into your browser to look at the printer names, and various print queues, as well as running test prints.



that’s really awesome –

I just wanted to quickly mention a simple alternative, if you could output whatever you want to print, would be command line printing via the system command, ie:

system  (  "lp ../../../data/blah.jpg"  );  

or something like that –

some info on lp:…-/lp.1.html

and more detailed info: (this uses lpr, not lp)…-4071837531

take care!

Great, nice to have the command line option too.

Is there a windows alternative to this?

Windows is what I have been using it on.

Or do you mean the command line option?


i’ve read the thread:
But i haven’t found out how to print image.
I created a HBITMAP like this:
HBITMAP hbit = CreateDIBitmap(hDC,&bmih,CBM_INIT,image.getPixels(),&bmi,DIB_RGB_COLORS);
where image is an instance of ofImage, but the result is tricky.

A long way around but that doesn’t require any win32 knowledge (or love) is to save out \temp\imageToPrint.jpg and then call:

system("\\Windows\\System32\\rundll32.exe \\Windows\\System32\\shimgvw.dll, ImageView_PrintTo \\temp\\imageToPrint.jpg <PrinterName>");  

If you’re running this on Vista or 7 then you also need to go into the app properties and find the switch for “Run as Administrator” otherwise all the print requests will just get thrown away with no error or indication that anything has gone wrong.

Not pretty but does the job - check your printer defaults.


Sorry for reopening this thread, but didn’t manage to get this working in latest OF version.

I want to send a generated image to my printer!

can anyone help?

Just printed a.png file inside OF by calling:

system("rundll32.exe c:\\Windows\\System32\\shimgvw.dll, ImageView_PrintTo c:\\temp\\a.png \"HP Officejet Pro K850 Series\"");  

i put this code in setup() to check.
it worked.

HP Officejet Pro K850 Series is my default printer connected to my computer ( where OF is running) locally.
and i put a.png file in c:\temp folder.

some more functions

void testApp::listPrinters() {   
    int i;  
    cups_dest_t *dests, *dest;  
    int num_dests = cupsGetDests(&dests);  
    for (i = num_dests, dest = dests; i > 0; i --, dest ++)  
        if (dest->instance)  
            printf("%s/%s\n", dest->name, dest->instance);  
    printf("\noptions - - - - %s - - - -\n\n", printerName.c_str());  
    cups_dest_t *mydest = cupsGetDest(printerName.c_str(), NULL, num_dests, dests);  
    cups_option_t *option;  
	if (mydest){  
        for(i = mydest->num_options, option = mydest->options; i > 0; i--, option ++) {  
            if (option->value)  
            printf("%s : %s\n", option->name, option->value);  
            else printf("  - - %s\n", option->name);  
    cupsFreeDests(num_dests, dests);  

void testApp::printImage() {   
    int num_options = 0;  
    cups_option_t *options = NULL;  
    string path = "../../../data/";  
    string currentFile = "test.jpg";  
    string printFile = path + currentFile;  
    string optionen = "landscape";  
    //optionen = "media=DS_PC_size"; //ds40  
    //num_options = cupsParseOptions(optionen.c_str(), num_options, &options);  
    last_job_id = cupsPrintFile( printerName.c_str(), printFile.c_str(), "Test Print", num_options, options);  

void testApp::clearAllJobs() {   
    cups_job_t *jobs;  
    int num_jobs = cupsGetJobs(&jobs, printerName.c_str(), 1, -1);  
    for (int i = 0; i < num_jobs; i ++) {  
        cupsCancelJob2(CUPS_HTTP_DEFAULT, printerName.c_str(), jobs[i].id, 1);  
    cupsFreeJobs(num_jobs, jobs);  
    cupsCancelJob2(CUPS_HTTP_DEFAULT, printerName.c_str(), CUPS_JOBID_ALL, 1);  

void testApp::checkPrinterStatus() {   
    //cups_dest_t *dest;  
    cups_job_t *jobs;  
    info = "lastJob " + ofToString(last_job_id)+ "\n";  
    /* Get my jobs (1) with any state (-1) */  
    int num_jobs = cupsGetJobs(&jobs, printerName.c_str(), 0, CUPS_WHICHJOBS_ALL);  
    for (int i = 0; i < num_jobs; i ++) {  
        ipp_jstate_t job_state = jobs[i].state;  
        switch (job_state)  
            case IPP_JOB_PENDING :  
                info += "Job " + ofToString(jobs[i].id) + " is pending.\n";  
            case IPP_JOB_HELD :  
                info += "Job " + ofToString(jobs[i].id) + " is held.\n";  
            case IPP_JOB_PROCESSING :  
                info += "Job " + ofToString(jobs[i].id) + " is processing.\n";  
            case IPP_JOB_STOPPED :  
                info += "Job " + ofToString(jobs[i].id) + " is stopped.\n";  
            case IPP_JOB_CANCELED :  
                info += "Job " + ofToString(jobs[i].id) + " is pending.\n";  
            case IPP_JOB_ABORTED :  
                info += "Job " + ofToString(jobs[i].id) + " is aborted.\n";  
            case IPP_JOB_COMPLETED :  
                info += "Job " + ofToString(jobs[i].id) + " is completed.\n";  
    /* Free the job array */  
    cupsFreeJobs(num_jobs, jobs);  
    last_err_info = cupsLastErrorString();  
    // get printer state  
    //3 = idle;  
    //4 = processing  
    //5 = stopped  
    cups_dest_t *dests;  
    int num_dests = cupsGetDests(&dests);  
    cups_dest_t *mydest = cupsGetDest(printerName.c_str(), NULL, num_dests, dests);  
    const char *value;  
	if (mydest){  
        printerState = cupsGetOption("printer-state", mydest->num_options, mydest->options);  
        printerStateReason = cupsGetOption("printer-state-reasons", mydest->num_options, mydest->options);  
        printer_info = printerStateReason;  
    else printer_info="no printer info\n";  
    cupsFreeDests(num_dests, dests);  

bool testApp::isPrinterSane() {   
    bool printerOK = true;  
    // printer has stopped  
    if(printerState == "5") printerOK = false;  
    // printer is offline  
    size_t found=printerStateReason.find("offline");  
    if (found!=string::npos) printerOK = false;    
    // printer has anything to tell  
    if (printerStateReason!="none") printerOK = false;    
    // there was another error  
    if (last_err_info!="successful-ok") printerOK = false;   
    return printerOK;  

commited a simple CUPS wrapper.

I’m also trying to print with the system function on
Windows 8.1
OF 0.8.4
visual studio 12

When I run this instruction with cmd prompt (cmd.exe), it works

rundll32 C:\WINDOWS\system32\shimgvw.dll,ImageView_PrintTo        c:\Users\taprik\Desktop\selection\IMG_1178.JPG DS-RX1

My printer is a DS-RX1

When I try to run it in the setup of an OF app, nothing happens, even If I ran the app ass an administrator.
I pass this to the system function.

rundll32.exe   C:\\WINDOWS\\System32\\shimgvw.dll,ImageView_PrintTo
c:\\Users\\taprik\\Bureau\\selection\\IMG_1178.JPG DS-RX1"

And the curious thing is when I try to run the same (first) command line with the windows powershell coming with the application Github for windows, it doesn’t work too.

Is the system() function related to the cmd application ?
Any ideas are welcome


Take a look at this

I print in a win8 with just this printer DS-RX1

ofSystem("rundll32.exe c:\\Windows\\System32\\shimgvw.dll, ImageView_PrintTo c:\\temp\\test.png \"DS-RX1 (Copiar 2)\"");

Thanks Pandereto,

I can confirm that it’s also working on Win 8.1

I’ve just made a mistake with Bureau and Desktop name (the Bureau folder is called Desktop) :wink:

On thing to consider is that the printer get a name distint on each usb, so truy to plug it all the times in the same usb port, if not you will get multiples names for the printer. Take that in mind because it gives me some hours of frustration until i see this.

Absolutly !
When it’s connected on the first port it’s DS-RX1
on the second DS-RX1 (Copie 1)
on the third DS-RX1 (Copie 2)

I also spend sometimes on that :wink:

Best Regards Panderoto