Issue exporting graphics as a single screenshot to PDF

Hello everyone,

I’m trying to export some graphics as a single screenshot to PDF.

The issue is that with my current code I am exporting a single frame of the window at a time (picture 1 below). I would like to export all of the graphics as one single vector file (picture 2 below).

Picture 1 - what I have :

Picture 2 - what I want :

Currently I’m following this tutorial from the oF book and my code looks like this :

I’ve added bool isSaving to the header (.h) file.

In setup() and draw() :

void ofApp::setup(){

ofSetBackgroundAuto(false); // turns off automatic bg clearing
ofBackground(0); 
isSaving = false;
}


void ofApp::draw(){

if (isSaving) {

    ofBeginSaveScreenAsPDF("screenshot_"+ofGetTimestampString()+".pdf");
}

ofNoFill();
ofDrawEllipse(ofGetMouseX(), ofGetMouseY(), 20, 20);

if (isSaving) {
    ofEndSaveScreenAsPDF();
    isSaving = false;
}
}

And finally I’ve added an event listener :

void ofApp::keyPressed(int key){

if (key == 'c') {
    isSaving = true;
}

My first thought was to switch on/off ofSetBackgroundAuto to see if the background being redrawn or not had an effect on the output and it did not.

I’m a little lost, any ideas ? :confused:

hello,

did you try to draw into an FBO and then render this in a PDF ?

@Gallo I think this is what you mean by drawing into an FBO ?

void ofApp::setup(){

ofSetBackgroundAuto(false); 
ofBackground(0);
isSaving = false;

fbo.allocate(ofGetWidth(), ofGetHeight());
fbo.begin();
ofClear(255,255,255);
fbo.end();    
}

//--------------------------------------------
void ofApp::draw(){

fbo.draw(0,0);

fbo.begin();

if (isSaving) {
    
    ofBeginSaveScreenAsPDF("screenshot_"+ofGetTimestampString()+".pdf");
}

ofNoFill();
ofDrawEllipse(ofGetMouseX(), ofGetMouseY(), 20, 20);

if (isSaving) {
    ofEndSaveScreenAsPDF();
    isSaving = false;
}

fbo.end();
}

//--------------------------------------------
void ofApp::keyPressed(int key){

if (key == 's') {
    isSaving = true;
}
} 

With in the header file ofFbo fbo;

Still I get this result (screenshot) :confused:

no, you need to draw your shape inside the FBO and then save your pdf

fbo.begin();
ofNoFill();
ofDrawEllipse(ofGetMouseX(), ofGetMouseY(), 20, 20);
fbo.end();

fbo.draw(0,0);

if (isSaving) {
    ofBeginSaveScreenAsPDF("screenshot_"+ofGetTimestampString()+".pdf");
    ofEndSaveScreenAsPDF();
    isSaving = false;
}

@Gallo I implemented the code but this time I get a complete black canvas in the export PDF:

Whereas this is what shows up on my screen :

void ofApp::setup(){

ofSetBackgroundAuto(false); 
ofBackground(0);
isSaving = false;

fbo.allocate(ofGetWidth(), ofGetHeight());
fbo.begin();
ofClear(255,255,255);
fbo.end();

}

void ofApp::draw(){

fbo.begin();
ofNoFill();
ofDrawEllipse(ofGetMouseX(), ofGetMouseY(), 20, 20);
fbo.end();

fbo.draw(0,0);

if (isSaving) {
    ofBeginSaveScreenAsPDF("screenshot_"+ofGetTimestampString()+".pdf");
    ofEndSaveScreenAsPDF();
    isSaving = false;
}
}

void ofApp::keyPressed(int key){

if (key == 's') {
    isSaving = true;
    cout << "pdf has been saved" << endl;
}
}

I assume that is the case because ofBeginSaveScreenAsPDF() and ofEndSaveScreenAsPDF() need to be before and after the drawing code (ofBook rules).

yes my bad. I guess it should read

if (isSaving) {
    ofBeginSaveScreenAsPDF("screenshot_"+ofGetTimestampString()+".pdf");
}

fbo.draw(0,0);

if (isSaving) {
    ofEndSaveScreenAsPDF();
    isSaving = false;
}

@Gallo still the black canvas :sob:

@Gallo This example works smoothly for me and the export PDF is perfect. They aren’t using any FBO. I tried adding my own drawing and it broke the example giving me the same single-ellipse output. I’m confused as to what is so different between the drawings ?

drawing into an FBO allows you to keep track of what you are drawing. If not, screen is cleared every frame.

i think you need to specify some colors before drawing

if (isSaving) {
    ofBeginSaveScreenAsPDF("screenshot_"+ofGetTimestampString()+".pdf");
}

ofSetBackground(0);
ofSetColor(255);
fbo.draw(0,0);

if (isSaving) {
    ofEndSaveScreenAsPDF();
    isSaving = false;
}

@Gallo Yes agreed on the screen clearing. That’s why I had ofSetBackgroundAuto(false) in my initial code.
oF paints the background black and sets the color of shapes white by default so I didn’t add those purposefully to keep the code to a minimum.

I think you can’t use ofSetBackgroundAuto() because ofBeginSaveScreenAsPDF changes the drawing context and is only saving what is being drawn at the saving moment, hence the simple circle you end up with. You need to draw every circles at once. The name “SaveScreen” is misleading though.

As for the FBO solution this should have to deal with the way FBO is working. I guess drawing into the PDF directly is different than drawing an FBO into it.

Try to convert the FBO into an image before saving the PDF

img being an ofImage declared in the header

void ofApp::setup(){
    
    ofBackground(0);
    isSaving = false;
    
    fbo.allocate(ofGetWidth(), ofGetHeight());
    fbo.begin();
    ofClear(0);
    fbo.end();
    
    img.allocate(ofGetWidth(), ofGetHeight(), OF_IMAGE_COLOR);        
}

    void ofApp::draw(){
        
        fbo.begin();
        ofNoFill();
        ofDrawEllipse(ofGetMouseX(), ofGetMouseY(), 20, 20);
        fbo.end();
        
        fbo.draw(0, 0);
        
        if (isSaving) {
            ofBeginSaveScreenAsPDF("screenshot_"+ofGetTimestampString()+".pdf");
            
            fbo.readToPixels(img);
            img.draw(0, 0);
            
            ofEndSaveScreenAsPDF();
            isSaving = false;
        }
    }

    void ofApp::keyPressed(int key){
        
        if (key == 's') {
            isSaving = true;
        }
    }

@Gallo it works !

This screenshot is a PDF -

However when I try to import it into Illustrator it crashes the software every time. Do you have an idea as to why that is ?

hum… i don’t have Illustrator right here, but it should be fine

if you need to edit the file you’d better end saving it as svg

Yes that’s true. For now I’m just playing and trying to understand how it all works :slight_smile:

I tried opening an export PDF from the code example mentioned above (from the oF book) and it opened fine in Illustrator. So my guess is Illustrator doesn’t like FBO much.

Thank you so much for your help @Gallo !

Avec plaisir :wink:

Out of curiosity i tried to export a PDF and everything is doing well under Inkscape if that matters

Interesting, then maybe I’ll go ahead and download Inkscape then ! Bonne soirée :wink:

Stay free and keep coding :wink:

Hello, actually what I am getting is truly raster image - pixelated, that is saved in PDF format, so all advantages of having vector file format are lost. Tried with standard PDF export and getting following message: [warning] ofCairoRenderer: draw(): cairo mesh rendering doesn’t support colors, textures, or normals. drawing wireframe … PDF file contains only wireframes, no colors, no fills… any idea for good and efficient vector format export PDF, SVG or EPS?