Cannot maintain a constant 60 fps when doing color filtering on ofImage

Hello every,

I have a problem that no matter my app is running on constant 30 or 60 fps, it has a slightly less frame rate when doing the following color filtering function applyFilter().

e.g. if I set the app to be 30fps, it will fall to 28 or 29 whenever it performs the applyFilter().
Likewise it has a frame rate of 58 or 59 when set to 60.

void ofApp::applyFilter() {
    int w = imageBuffer.getWidth();
    int h = imageBuffer.getHeight();
    
    int channelCount = imageBuffer.getPixelsRef().getNumChannels();
    
    for (int y = 0; y < h; y++) {
        
        unsigned char * cursor = imageBuffer.getPixels() + ((w * channelCount) * y);
        
        for (int x = 0; x < w - 1; x++) {
            
            double tintPercentage = .25;
            ofColor filterColor = ofColor::green;
            
            // cout << "Before: " << cursor[0] << " " << cursor[1] << " " << cursor[2] << endl;
            
            int a0 = cursor[0];
            int a1 = cursor[1];
            int a2 = cursor[2];
            
            cursor[0] = cursor[0] + (tintPercentage * (filterColor.r - cursor[0]));
            cursor[1] = cursor[1] + (tintPercentage * (filterColor.g - cursor[1]));
            cursor[2] = cursor[2] + (tintPercentage * (filterColor.b - cursor[2]));
            
            // cout << "After: " << cursor[0] << " " << cursor[1] << " " << cursor[2] << endl;
            
            int b0 = cursor[0];
            int b1 = cursor[1];
            int b2 = cursor[2];
            cursor += channelCount;
        }
    }
    imageBuffer.update();
}

Bascially my app is to load an image sequence dynamically and do applyFilter() on each loaded image.

I’ve tried switched to release mode instead of debug for compiling the app. It helps the frame rate a bit but the problem is still there.

I think it is because I cannot make full use of my CPU resource (2 core 4 thread) since I do not know how to use ofThread. (I am just using ofxThreadedImageLoader to preload a bunch of images.)
Or is there any workaround to the problem?

Thanks!

Is there a reason you need to lock it to 30/60 frames? I would imagine if you took off vertical syncing it would probably shoot up into the 100s as I doubt your CPU is not powerful enough to perform that operation. though it is running that loop a lot and there is probably a more efficient way of applying a filter which may help reduce your cpu load, i.e. unloading it onto your gpu since the whole operation is parallelizable. You might want to look into using textures instead of applying things pixel by pixel if your worried about speed and fps
http://www.openframeworks.cc/documentation/gl/ofTexture.html

if you are using openFrameworks 0.9 you can do:

ofColor filterColor = ofColor::green;
for(auto line: imageBuffer.getPixels().getLines()){
    for(auto pixel: line.getPixels()){
            float tintPercentage = .25;
            pixel[0] = pixel[0] + (tintPercentage * (filterColor.r - pixel[0]));
            pixel[1] = pixel[1] + (tintPercentage * (filterColor.g - pixel[1]));
            pixel[2] = pixel[2] + (tintPercentage * (filterColor.b - pixel[2]));
    }
}

which is slightly faster than the method you are using. in any case the fastest way to do this would be to use a shader to apply the tint to the images.

Also drawing an image like:

ofSetColor(filterColor);
image.draw(x,y);

applies a tint to the image when drawing it although not exactly with the same algorithm you are using

Thank you DomAmato and arturo so much for the help!

I tried arturo’s method and it works like a charm!
Why is this so much faster and will you consider adding a color tint method to ofImage?

1 Like

do you mean the first method i posted?