Invert image with ofxToggle doesn't work


#1

I’m trying to create a GUI that holds some basic image “filters”

I load an image from my system and then store it in an vector from the example fileOpenSaveDialogExample. After this I want to invert that image when the toggle is “true”.

Currently it’s not working properly, because I have the invert code in “on mouse click”. When I then press the toggle click on the actual image afterwards, then it inverts. This is obviously one click too much as it should just invert when the toggle is clicked.
I have it this way because when I put the invert method in the draw() , it continuously flashes between the original image and the inverted version.

My code:

_ofApp.h_
//    Gui setup and main window
    ofxPanel gui;
    ofxToggle inverseSwitch;

ofApp.cpp

void ofApp::setup(){
    // for easy terminal output
    ofSetLogLevel(OF_LOG_VERBOSE);
    
//    Gui
    gui.setup();
    gui.add(inverseSwitch.setup("invert image", false));
    
}

void ofApp::draw(){
    ofBackground(255);
//    Loads image from file
    ofDrawBitmapString("Press spacebar to open an image, \"s\" to save the processed output", 20, 15);
    
//    Invert Example for Main Window
    for (int i=0; i<loadedImages.size(); i++){
        loadedImages[i].draw(0,20);
    }
    
//    Drawing the gui
    gui.draw();
}

void ofApp::mousePressed(int x, int y, int button){
    
    if(inverseSwitch){
        for (int i=0; i<loadedImages.size(); i++){
            //        loadedImages[i].setColor(0, 20, color);
            loadedImages[i] = invertImage(loadedImages[i]);
            loadedImages[i].draw(0,20);
        }
    }

}

ofImage ofApp::invertImage(ofImage img){
    Mat temp;
    temp = toCv(img);
    for(int i = 0; i < ((temp.cols)*(temp.rows))*3; i++){
        temp.data[i] = 255 - temp.data[i];
    }
    toOf(temp, img);
    img.update();
    return img;
}

#2

you should add the event to the inverseSwitch toggle not on mouse press like, in setup::

inverseSwitch.addListener(this, &ofApp::invertImages);

then create an invertImages function that has the code you have now in mousePressed as:

void ofApp::invertImages(bool & inverseSwitch){
        for (int i=0; i<loadedImages.size(); i++){
            loadedImages[i] = invertImage(loadedImages[i]);
        }
}

An even easier way to do it would be to use an ofParameter<bool> inverseSwitchand create a vector with the original and another with the inverted images from the very beginning, in setup.

Then in draw you just need to draw one or the other depending if inverseSwitch is enabled like:

// ofApp.h
ofParameter<bool> inverseSwitch{"invert image", false};
ofParameterGroup parameters{
    "settings"
    inverseSwitch,
};
ofxPanel gui{parameters};

vector<ofImage> loadedImages;
vector<ofImage> invertedImages;


//ofApp.cpp
void ofApp::setup(){
    //load images in images vector
   for(auto & img: loadedImages){
       invertedImages.push_back(invertImage(img));
   }
}

void ofApp::draw(){
    if (inverseSwitch) {
        for (auto & img; InvertedImages){
            img.draw(0,20);
        }
    }else{
        for (auto & img: loadedImages){
            img.draw(0,20);
        }
    }
}

#3

Thank you for the amazing help! That is clear!

I have a similar question but different, regarding Brightness and RGB values.
Say I have the image inverted, but afterwards I want to adjust either the RGB values individually and/or the brightness. This by using an ofxIntSlider. What would the best way be to save this image? (The final goal of this all is to be able to save this image, with the changes that are done to the local hard drive)


#4

just use img.save("path.png")