Crop Fbo to bounding box

Hi, I have a drawing inside fbo, and trying to decrease fbo size by cropping to the visible parts using bounding box. I found solution: pass fbo data to pixels and then write crop algorithm, and then allocate new fbo with new size . In the following part of code I’m trying to detect the bottom intersection. But I’ve got a weird problem with pixels.

    int w = 4;
    int h = 4;
    
    fbo.allocate(w, h, GL_RGBA);
    fbo.begin();
    ofClear(0, 0);
    fbo.end();
    
    fbo.begin();
    ofSetColor(255, 0, 0);
    ofDrawRectangle(0, 0, 4, 2);
    fbo.end();
    
    pixels.allocate(w, h, GL_RGBA);
    
    fbo.readToPixels(pixels);
    
    for(auto line = pixels.getLines().end(); line != pixels.getLines().begin(); --line){
        for(auto pixel: line.getPixels()){
            cout <<  "line: " << line.getLineNum() << " color: " << pixel.getColor() << endl;
        }
    }

output:

line: 4 color: 24, 215, 83, 118
line: 4 color: 255, 127, 0, 0
line: 4 color: 173, 7, 0, 0
line: 4 color: 1, 0, 0, 0
line: 3 color: 0, 0, 0, 0
line: 3 color: 0, 0, 0, 0
line: 3 color: 0, 0, 0, 0
line: 3 color: 0, 0, 0, 0
line: 2 color: 0, 0, 0, 0
line: 2 color: 0, 0, 0, 0
line: 2 color: 0, 0, 0, 0
line: 2 color: 0, 0, 0, 0
line: 1 color: 255, 0, 0, 255
line: 1 color: 255, 0, 0, 255
line: 1 color: 255, 0, 0, 255
line: 1 color: 255, 0, 0, 255

line:1 looks fine but what is wrong with line:4, what is the random colors doing there? After rebuilding app they may have gone, but with the random chance. Maybe there is another way to crop fbo?
This solution doesn’t work for me.

Hi,

depending on what you’re trying to achieve, you may use the drawSubsection() function. Something like :

fbo2.allocate(w2,h2,GL_RGBA);
fbo2.begin();
    fbo.getTexture().drawSubsection(0,0,w2,h2,crooped_x,cropped_y,cropped_w,cropped_h);
fbo2.end();

Thanks for your reply oxillo! But this is the second step for cropping fbo. I need to find cropped_x and cropped_y first. It depends of the first pixel occurrence on the left, right, top and bottom side of the drawing.
Here is a visual representation what I’m trying to achieve:

It was an out of index mistake. Here is final code for cropping fbo:
ofApp.h

    ofFbo fbo;
    ofFbo croppedFbo;
    ofPixels pixels;
    int top, bottom, left, right;
    int w = ofGetWidth();
    int h = ofGetHeight();

ofApp::setup()

    pixels.allocate(w, h, GL_RGBA);
    fbo.allocate(w, h, GL_RGBA);
    fbo.begin();
    ofClear(0, 0);
    ofSetColor(255, 0, 0);
    ofDrawCircle(w/2, h/2, 10);
    fbo.end();

ofApp::update()

    fbo.readToPixels(pixels);
    // top
    for(auto line: pixels.getLines()){
        bool isStop = false;
        for(auto pixel: line.getPixels()){
            if ((int)pixel[3]>0) {
                top = line.getLineNum();
                isStop = true;
                break;
            }
        }
        if(isStop) break;
    }
    // bottom
    auto line = pixels.getLines().end();
    line--;
    for(;line != pixels.getLines().begin(); --line){
        bool isStop = false;
        for(auto pixel: line.getPixels()){
            if (pixel[0]!=0) {
                bottom = line.getLineNum()+1;
                isStop = true;
                break;
            }
        }
        if(isStop) break;
    }
    // left
    int row = 0;
    for (unsigned int i = 0; i < w; i++) {
        bool isStop = false;
        for(auto line = pixels.getLine(top); line < pixels.getLine(bottom); ++line){
            auto pixel = line.getPixels().begin()+row;
            if ((int)pixel[3]>0) {
                left = row;
                isStop = true;
                break;
            }
            if(line.getLineNum()==bottom-1) {
                row++;
            }
        }
        if(isStop) break;
    }
    // right
    row = w-1;
    for (unsigned int i = w-1; i != 0; i--) {
        bool isStop = false;
        for(auto line = pixels.getLine(top); line < pixels.getLine(bottom); ++line){
            static int counter = 0;
            auto p = line.getPixel(row);
            if ((int)p[3]>0) {
                right = row+1;
                isStop = true;
                break;
            }
            if(line.getLineNum()==bottom-1) {
                row--;
            }
            counter++;
        }
        if(isStop) break;
    }

    int croppedH = bottom - top;
    int croppedW = right - left;

    croppedFbo.allocate(croppedW,croppedH,GL_RGBA);
    croppedFbo.begin();
    ofClear(0, 0);
    fbo.getTexture().drawSubsection(0,0,croppedW,croppedH,left ,top, croppedW, croppedH);
    croppedFbo.end();

ofApp::draw()

    ofSetColor(255);
    fbo.draw(0, 0);
    ofSetColor(0);
    ofDrawLine(0, top, ofGetWidth(), top);
    ofDrawLine(0, bottom, ofGetWidth(), bottom);
    ofDrawLine(left, 0, left, ofGetHeight());
    ofDrawLine(right, 0, right, ofGetHeight());
    ofDrawBitmapString(ofGetFrameRate(), 20, 20);
    ofSetColor(255, 120);
    croppedFbo.draw(0, 0);

ofApp::mouseDragged(int x, int y, int button)

    fbo.begin();
    ofSetColor(255, 0, 0);
    ofDrawCircle(x, y, 10);
    fbo.end();

Crop is very expensive, so it should be called whenever it needed. I put it into update just for demonstration.