I want to blur an image using shader, and then save the resulting image. I started from an example of openframework v0.10.1, that is, shader/09_gaussianBlurFilter. I added an ofPixels (called inputPixels) and ofImage (called outputImage) to achieve my objective. Below are my codes, where I added comments for what I added by “added by me.”
The program works. It can save an image file, same as the screen shows. However, I don’t want to draw anything to screen. I wanted to blur an image and save the result in a more clean way. So I tried to remove “fboBlurOnePass.draw(0, 0);” and “fboBlurTwoPass.draw(0, 0);.” However, the program failed to save a meaningful image file if I remove the two.
I was wondering if someone can tell me how to modify the codes, so as to blur an image without drawing anything to screen. Thank you very much.
void ofApp::draw(){
float blur = ofMap(mouseX, 0, ofGetWidth(), 0, 4, true);
//----------------------------------------------------------
fboBlurOnePass.begin();
shaderBlurX.begin();
shaderBlurX.setUniform1f("blurAmnt", blur);
image.draw(0, 0);
shaderBlurX.end();
fboBlurOnePass.end();
//----------------------------------------------------------
fboBlurTwoPass.begin();
shaderBlurY.begin();
shaderBlurY.setUniform1f("blurAmnt", blur);
fboBlurOnePass.draw(0, 0);
fboBlurOnePass.readToPixels(inputPixels); // added by me
shaderBlurY.end();
fboBlurTwoPass.end();
//----------------------------------------------------------
ofSetColor(ofColor::white);
fboBlurTwoPass.draw(0, 0);
fboBlurTwoPass.readToPixels(inputPixels); // added by me
outputImage.setFromPixels(inputPixels); // added by me
outputImage.saveImage("screenshot.png"); // added by me
}
I have not tested the code but, you should not readToPixels in the middle of fboBlurTwoPass
fboBlurTwoPass.begin();
shaderBlurY.begin();
shaderBlurY.setUniform1f("blurAmnt", blur);
fboBlurOnePass.draw(0, 0);
//fboBlurOnePass.readToPixels(inputPixels); // added by me
shaderBlurY.end();
fboBlurTwoPass.end();
To do not draw comment
//fboBlurTwoPass.draw(0, 0);
Later on keypress for example add, if you that in draw the image is overwriten on every cycle and thats not good
fboBlurTwoPass.readToPixels(inputPixels); // added by me
outputImage.setFromPixels(inputPixels); // added by me
outputImage.saveImage("screenshot.png"); // added by me
Thanks for your suggestions. I moved the codes about “readToPixels” and codes about saving files, to keyPressed(), as follows. But, still I cannot remove fboBlurOnePass.draw(0, 0); and fboBlurTwoPass.draw(0, 0);. That is, I can save the content of fbo only after I do drawing. It’s so weird. It means that draw() is not just drawing…
image.draw(0, 0);
shaderBlurX.end();
fboBlurOnePass.end();
//----------------------------------------------------------
fboBlurTwoPass.begin();
shaderBlurY.begin();
shaderBlurY.setUniform1f("blurAmnt", blur);
**fboBlurOnePass.draw(0, 0);**
shaderBlurY.end();
fboBlurTwoPass.end();
//----------------------------------------------------------
ofSetColor(ofColor::white);
**fboBlurTwoPass.draw(0, 0);**
}
void ofApp::keyPressed(int key){
fboBlurOnePass.readToPixels(inputPixels); // added by me
fboBlurTwoPass.readToPixels(inputPixels); // added by me
outputImage.setFromPixels(inputPixels); // added by me
outputImage.saveImage("screenshot.png"); // added by me
}
When used between shader.begin() and shader.end(), the draw() method will call your shader with the texture of your Fbo (or image) as the texture input of your shader.
That is why you need to have fboBlurOnePass.draw() between shader.begin() and shader.end().
The fboBlurTwoPass may be considered as a virtual screen. With fboBlurTwoPass.begin(), you’re just telling the system that you want to work in this virtual screen.
As pandereto said, it’s not need to draw the fboBlurTwoPass as it already has your blurred image inside.