ofTexture readToPixels with cropped bounds

Hello all

I’m trying to read an ofFbo texture to an ofFloatPixels object in order to check colour information. However, the ofFbo is much bigger than the area I need to sample, and I think that copying that much data across (>6m points) is crashing the readToPixels somehow. Either way it is mega slow.

What I’d like to do is just copy part of the ofFbo to the pixels array. I’ve figured this out in part, a long time ago (see here ofFbo readToPixels with selected region?)

However, I need a method that works within the #ifndef TARGET_OPENGLES statement; i.e. reading an ofTexture to ofPixels with a selected region only.

Looking at the ofTexture readToPixels function, it just seems to pull in the whole texture. Is a cropped readToPixels possible?

void ofTexture::readToPixels(ofFloatPixels & pixels) const {
#ifndef TARGET_OPENGLES
	pixels.allocate(texData.width,texData.height,ofGetImageTypeFromGLType(texData.glInternalFormat));
	ofSetPixelStoreiAlignment(GL_PACK_ALIGNMENT,pixels.getWidth(),pixels.getBytesPerChannel(),pixels.getNumChannels());
	glBindTexture(texData.textureTarget,texData.textureID);
	glGetTexImage(texData.textureTarget,0,ofGetGlFormat(pixels),GL_FLOAT,pixels.getData());
	glBindTexture(texData.textureTarget,0);
#endif
}

How would I go about adapting the above?

S

The critical part in your snippet, is the allocate call. That command tells to your computer to allocate a region of memory for your pixel object. Is the width of the texture changing while your application is running? if not, can you move that part to the setup method?

Hey, thanks for the reply

Don’t quite follow though… how would changing the allocate size allow me to specify just part of the texture to put into the pixels object?

S

Sorry, I have read too fast your question and I did not even noticed that the code that you posted is not yours but from the OF core. https://github.com/openframeworks/openFrameworks/blob/master/libs/openFrameworks/gl/ofTexture.cpp#L1217

This method does not accept any argument for cropping, you need to came up with your own solution. By the way, how are you declaring the ofFloatPixels pixel object before passing it to the readToPixels function? are you allocating it everytime in the update or draw call, or is it created just once in the header file?

You could also try to create another FBO, that has the same dimension of the selection that you want (let’s say 200x200), and then

in the ofApp.h method (pseudo code, not tested)

ofFbo mySelection;
ofPixels myCroppedPixels;

in the setup method

mySelection.allocate(200,200, GL_RGBA);
myCroppedPixels.allocate(200,200);

in the draw call

mySelection.begin();
ofClear(255, 255, 255, 0);
yourBigFbo.draw(0,0,200,200); // starting point coordinates depends on where do you want to start cropping
mySelection.end();
mySelection.readToPixels(myCroppedPixels);

What about drawing a subsection to another fbo, and then reading that to pixels? Not sure if that makes sense…
https://openframeworks.cc//documentation/gl/ofTexture/#!show_drawSubsection

Thanks both

Yeah I found the ofTexture subsection too. Took me a while to figure it out but I think the following is a workaround that does what I was asking:

    ofFbo cropped;
    cropped.allocate(bufferWidth,bufferHeight,GL_RGBA32F);
    cropped.begin();
    ofClear(255,255,255, 0);
    ofSetColor(255,255,255, 255);
    fboX.getTexture().drawSubsection(0, 0,bufferWidth, bufferHeight, xD, yD, xD+bufferWidth, yD+bufferHeight);
    cropped.end();
    cropped.readToPixels(exposurePixels);

Yes, this is more or less the same as drawing the fbo inside another fbo, as fbo.draw() draws the texture inside it, https://github.com/openframeworks/openFrameworks/blob/master/libs/openFrameworks/gl/ofFbo.cpp#L1140.
If you are looking for performance, you should try to move this part:

ofFbo cropped;
cropped.allocate(bufferWidth,bufferHeight,GL_RGBA32F);

out of the update (or draw) call, and put it in the setup.