Adjusting video brightness

Hey everyone-

Struggling with a problem that I’m not sure how to solve. I’ve been trying to piece together video manupulation solutions I’ve found on the forum and googling around, but I haven’t figured out how to adjust the brightness of a video (based off of the videoPlayerExample).

Here’s my code:

testApp.h

  
  
#pragma once  
  
#include "ofMain.h"  
  
class testApp : public ofBaseApp{  
  
	public:  
  
		void setup();  
		void update();  
		void draw();  
		  
		void keyPressed(int key);  
		void keyReleased(int key);  
		void mouseMoved(int x, int y );  
		void mouseDragged(int x, int y, int button);  
		void mousePressed(int x, int y, int button);  
		void mouseReleased(int x, int y, int button);  
		void windowResized(int w, int h);  
		void dragEvent(ofDragInfo dragInfo);  
		void gotMessage(ofMessage msg);		  
  
		ofVideoPlayer 		fingerMovie;  
		bool                frameByframe;  
      
        void increaseBrightness();  
        void decreaseBrightness();  
        void adjustBrightness();  
          
        float brightness;  
      
        ofTexture newTexture;   
};  
  
  
  

testApp.cpp

  
  
  
#include "testApp.h"  
using namespace std;  
  
#include <iostream>;  
  
//--------------------------------------------------------------  
void testApp::setup(){  
	ofBackground(255,255,255);  
  
    brightness = 1.0;  
	frameByframe = false;  
  
	fingerMovie.loadMovie("movies/fingers.mov");  
	fingerMovie.play();  
      
    newTexture.allocate(fingerMovie.getWidth(), fingerMovie.getHeight(), GL_RGB);  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
    fingerMovie.idleMovie();  
      
    int bytes_per_pixel = 3;   
      
    unsigned char * pixels = fingerMovie.getPixels();  
      
    unsigned char * nPixels = new unsigned char[320*240*bytes_per_pixel];  
                                                     
    for (int i=0; i < fingerMovie.getWidth()*fingerMovie.getHeight(); i++){  
          
        int base = i * bytes_per_pixel;  
        int nBase = base;  
          
        unsigned char * r = &pixels[base + 0];  
        unsigned char * g = &pixels[base + 1];  
        unsigned char * b = &pixels[base + 2];  
          
        r *= brightness;  
        g *= brightness;  
        b *= brightness;  
          
        nPixels[base + 0] = r;  
        nPixels[base+1] = g;  
        nPixels[base+2] = b;  
    }  
      
    newTexture.loadData(nPixels, fingerMovie.getWidth(), fingerMovie.getHeight(), GL_RGB);  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
  
	ofSetHexColor(0xFFFFFF);  
      
  
      
    fingerMovie.draw(20,20);  
      
    newTexture.draw(20,340);  
      
    //adjustBrightness();  
  
      
    ofSetHexColor(0x000000);  
    unsigned char * pixels = fingerMovie.getPixels();  
    // let's move through the "RGB" char array  
    // using the red pixel to control the size of a circle.  
    for (int i = 4; i < 320; i+=8){  
        for (int j = 4; j < 240; j+=8){  
            unsigned char r = pixels[(j * 320 + i)*3];  
            float val = 1 - ((float)r / 255.0f);  
            ofCircle(400 + i,20+j,10*val);  
        }  
    }  
  
  
    ofSetHexColor(0x000000);  
	ofDrawBitmapString("press f to change",20,320);  
    if(frameByframe) ofSetHexColor(0xCCCCCC);  
    ofDrawBitmapString("mouse speed position",20,340);  
    if(!frameByframe) ofSetHexColor(0xCCCCCC); else ofSetHexColor(0x000000);  
    ofDrawBitmapString("keys <- -> frame by frame " ,190,340);  
    ofSetHexColor(0x000000);  
  
    ofDrawBitmapString("frame: " + ofToString(fingerMovie.getCurrentFrame()) + "/"+ofToString(fingerMovie.getTotalNumFrames()),20,380);  
    ofDrawBitmapString("duration: " + ofToString(fingerMovie.getPosition()*fingerMovie.getDuration(),2) + "/"+ofToString(fingerMovie.getDuration(),2),20,400);  
    ofDrawBitmapString("speed: " + ofToString(fingerMovie.getSpeed(),2),20,420);  
      
     ofDrawBitmapString("brightness: " + ofToString(brightness,2),20,440);  
  
    if(fingerMovie.getIsMovieDone()){  
        ofSetHexColor(0xFF0000);  
        ofDrawBitmapString("end of movie",20,440);  
    }  
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed  (int key){  
    switch(key){  
        case 'f':  
            frameByframe=!frameByframe;  
            fingerMovie.setPaused(frameByframe);  
        break;  
          
        case 't':  
            increaseBrightness();  
        break;  
              
        case 'y':  
            decreaseBrightness();  
            break;  
          
        case OF_KEY_LEFT:  
            fingerMovie.previousFrame();  
        break;  
          
        case OF_KEY_RIGHT:  
            fingerMovie.nextFrame();  
        break;  
          
        case '0':  
            fingerMovie.firstFrame();  
        break;  
    }  
}  
  
//--------------------------------------------------------------  
void testApp::keyReleased(int key){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mouseMoved(int x, int y ){  
	if(!frameByframe){  
        int width = ofGetWidth();  
        float pct = (float)x / (float)width;  
        float speed = (2 * pct - 1) * 5.0f;  
        fingerMovie.setSpeed(speed);  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::mouseDragged(int x, int y, int button){  
	if(!frameByframe){  
        int width = ofGetWidth();  
        float pct = (float)x / (float)width;  
        fingerMovie.setPosition(pct);  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::mousePressed(int x, int y, int button){  
	if(!frameByframe){  
        fingerMovie.setPaused(true);  
	}  
}  
  
  
//--------------------------------------------------------------  
void testApp::mouseReleased(int x, int y, int button){  
	if(!frameByframe){  
        fingerMovie.setPaused(false);  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::windowResized(int w, int h){  
  
}  
  
//--------------------------------------------------------------  
void testApp::gotMessage(ofMessage msg){  
  
}  
  
//--------------------------------------------------------------  
void testApp::dragEvent(ofDragInfo dragInfo){   
  
}  
  
void testApp::increaseBrightness(){  
    brightness = brightness + 0.1;  
}  
  
void testApp::decreaseBrightness(){  
    brightness = brightness - 0.1;  
}  
  
void testApp::adjustBrightness(){  
      
    unsigned char * moviePixels = fingerMovie.getPixels();  
      
    unsigned char * newPixels;  
      
    for (int x = 0; x<320; x++){  
        for (int y = 0; y<240; y++){  
          
            int loc = x + y*fingerMovie.width;  
                          
            //float r, g, b;  
              
              
  
            int pixel = pixels[loc];  
              
            pixel *= brightness;  
            //r *= brightness;  
           // g *= brightness;  
           // b *= brightness;  
              
            pixels[loc] = pixel;  
              
              
          
              
        }  
    }  
}  
  
  
  

Most of what I changed was in the setup() and update() functions. I tried writing an “adjustBrightness” function but I think I was able to figure out that adjusting the brightness should happen within update(), not draw(). Then, within draw, I should draw the newTexture, which should now be brighter. I think I’m having a lot of type errors, and I’m not sure what my approach should be. Any help would be appreciated!!

-jo

For what its worth, I tried to figure it out by reading these two posts:

Pixel manupulation: http://forum.openframeworks.cc/t/pixel-manipulation-method/1908/0

ofFbo getPixels: http://forum.openframeworks.cc/t/offbo-getpixels/5540/0

So far, I can see:

  
  
  unsigned char * r = &pixels[base + 0];    
        unsigned char * g = &pixels[base + 1];    
        unsigned char * b = &pixels[base + 2];    
            
        r *= brightness;    
        g *= brightness;    
        b *= brightness;    
            
        nPixels[base + 0] = r;    
        nPixels[base+1] = g;    
        nPixels[base+2] = b;    
  

has some issues. You’ve defined r g and b as pointers, and are then multiplying the pointer by brightness, not the data pointed to. This should work:

  
   
        nPixels[base + 0] = pixels[base + 0] * brightness;    
        nPixels[base + 1] = pixels[base + 1] * brightness;    
        nPixels[base + 2] = pixels[base + 2] * brightness;    
  

As this is clearer and there is really no need to use temporary variables.

Or you can just loop through the whole array one subpixel at a time:

  
  
for (int i=0; i < fingerMovie.getWidth()*fingerMovie.getHeight()*bytes_per_pixel; i++){    
        nPixels[i] = pixels[i] * brightness;  
    }  
  

Ah! Got it. That worked to get the app to build, and it works when decreasing the value for brightness.

But if the brightness goes below zero, I get funky results

And if brightness goes above zero, it produces even funkier results!

I think I might need to constraint the pixel values between 0 and 255, but trying this doesn’t seem to work.

  
  
  
 if(nPixels[i] < 255 ||nPixels[i] > 0){  
            nPixels[i] = pixels[i] * brightness;   
        }  
        
          

Is my “brightness” algorithm wrong? Am I trying to manipulate these pixels in the wrong way? Any help is appreciated!

Attached image of decreasing brightness “working”.

![](http://forum.openframeworks.cc/uploads/default/2576/Screen Shot 2012-10-07 at 9.13.03 PM.png)

Attached image of increase brightness not working (looks similar to decrease in brightness going below 0, so I won’t attach it).

![](http://forum.openframeworks.cc/uploads/default/2578/Screen Shot 2012-10-07 at 9.38.32 PM.png)

Jo,

You’re on the right track, but doing it a bit backwards. if you want to constrain a value, you need to calculate it first, then check to see if it is out of bounds, and fix it. This is what you want:

  
  
nPixels[i] = pixels[i] * brightness;  
if(nPixels[i] > 255){  
    nPixels[i] = 255;   
}  
if(nPixels[i] < 0){  
    nPixels = 0;  
}  
  

or, to make things even simpler, you can use the ofClamp funcion, which does this process for you: ofClamp(float value, float min, float max)

  
  
nPixels[i] = ofClamp(pixels[i] * brightness, 0, 255);  
  

Awesome! I wasn’t aware of the ofClamp function. That worked perfectly. Now to figure out contrast and saturation…

Way after the fact, but couldn’t you just do something like this:

ofEnableBlendMode(OF_BLENDMODE_ADD); 
ofSetColor(255, 255, 255, 32); 
ofRect(0, 0, ofGetWidth(), ofGetHeight()); 

Or is that more like adjusting the backlight than adjusting brightness?