Looking for a little help with ofPixels with ofvideo player

Hi All

I’ve been doing quite a bit of reading tonight looking at unsigned chars and ofpixels. I think ive gotten my head around some of the different syntaxes to begin with.

can someone confirm im reading this right, some projects creating a pointer to videoplayer.getpixels(), some people just referencing it with a “&” before, this is esstially the same right? (ive been tryning to get my head around pointers too)

in this snippet of code from the examples, the author creates a varible called pixels which referers to fingerMovie.getPixels()…so what ever happens to fingerMovie.getPixels() also happens to pixels; pixels is not a copy right?

void ofApp::draw(){

	ofSetHexColor(0xFFFFFF);

    fingerMovie.draw(20,20);
    ofSetHexColor(0x000000);
    ofPixels & pixels = fingerMovie.getPixels();

    int vidWidth = pixels.getWidth();
    int vidHeight = pixels.getHeight();
    int nChannels = pixels.getNumChannels();
    
    // let's move through the "RGB(A)" char array
    // using the red pixel to control the size of a circle.
    for (int i = 4; i < vidWidth; i+=8){
        for (int j = 4; j < vidHeight; j+=8){
            unsigned char r = pixels[(j * 320 + i)*nChannels];
            float val = 1 - ((float)r / 255.0f);
			ofDrawCircle(400 + i,20+j,10*val);
        }
    }

in this snippet of code from the ofbook videoplayer::getpixels(), the author creats a pointer called pixels which has the memory address where myMovie.getPixels() is stored right? same thing happening in a different way?

unsigned char * pixels = myMovie.getPixels();
int nChannels = movie.getPixelsRef().getNumChannels();
int widthOfLine = myMovie.width;  // how long is a line of pixels
int red     = pixels[(20 * widthOfLine + 100) * nChannels    ];
int green   = pixels[(20 * widthOfLine + 100) * nChannels + 1];
int blue    = pixels[(20 * widthOfLine + 100) * nChannels + 2];

so im pretty confused about the pointer stuff above but im much more confused about whats going on after that in the different snippets of code.

when i had the idea of messing around with video i thought it was as easy as iterating through every pixel, which would have a 3 values between 0 and 255, manipulating those values, and then reasigning them in the pixel.

i found this https://github.com/ofcourseio/SPRING2016/blob/master/week4/pixels.md which was suppppper helpful explaining how images are stored

but it didnt quite explain the maths for the pixels array index in the [ ] brackets and the maths with the number of channels (this is referencing the second snippet of code) my feeling is it has something to do with memory address’ and arrays but i have no idea at this point.

If anyone could give me a nudge in the right direction i would be very grateful! ive completley hit a brick wall.

Thanks!

I was going to point you to that text I wrote long ago. :slight_smile:

right. as it uses & it is just a reference. Think of it as a shortcut or so instead of having to write fingerMovie.getPixels() each time you want to access the pixels you just write pixels.

Not really.
That code uses a deprecated form. Which is why confuses you. It was removed because it was confusing.
The correct thing there would be

unsigned char * pixels = myMovie.getPixels().getData();
int nChannels = movie.getPixels().getNumChannels();
int widthOfLine = myMovie.getWidth();  

getPixels() returns a reference to the ofPixels object stored inside the myMovie object. Thus you can access any of its functions, as getData() or getNumChannels();
where getData() returns the actual data array where pixels are stored. It is the pixels raw data.
Take a look at ofPixels functions so you get an idea of what stuff it can do. (Instead of looking at the online docs I prefer looking at the header files, in this case ofPixels.h, as the documentation comes from there. it should be shown in your IDE. (which IDE are you using?)

for instance you could use ofPixels::setColor to set each color but it can be a bit slower than just accessing the raw data.
in such case you can do


ofPixels& pixels = myMovie.getPixels();  
for(size_t y = 0; y<pixels.getHeight(); y++){
    for(size_t x = 0; x<pixels.getHeight(); x++){
        pixels.setColor(x, y, ofColor(some color you want to assign to the pixel));
    }
}

instead, when using the raw data, as it is stored all in a single array, where each horizontal line of pixels is concatenated one after the other you can do

unsigned char * data = myMovie.getPixels().getData();
//say you want to assign a value to pixel at x, y
int width = myMovie.getWidth();
int nChannels = movie.getPixels().getNumChannels();
data[(x + (width * y))* nChannels ] = some value for the Red channel;
// the next stored pixel value
data[(x + (width * y))* nChannels  + 1 ] = some value for the Green channel;
data[(x + (width * y))* nChannels  + 2 ] = some value for the BLue channel;

it might be clearer in this form (and faster as well as there are less calculations done

size_t i = (x + (width * y))* nChannels;
data[i] = some value for the Red channel;
data[i + 1 ] = some value for the Green channel;
data[i + 2 ] = some value for the BLue channel;

if you want to iterate over the data array and you want to know the x and y position of a certain pixel you can do the following.


size_t dataSize = movie.getPixels().size();
for(size_t i = 0; i < dataSize; i+= nChannels){
int x = i % width;
int y = int(float(i)/width);
// then apply the same logic as before.
}

let me know if this helps or if you have more doubts

Thank. you. so. much!!

that was incredibly helpful - That clicking feeling is sooooo good!

Yo have cleared everything up for me except 1 thing…

unsigned char * pixels = myMovie.getPixels().getData();

In my mind, this line is creating a pointer called pixels, pointing at the usigned char data in myMovie.getPixels().getData()

i thought you could only point to a single item in the array and not the whole array, or is this pointing to the 0th item in the array??

i feel like im on the cusp of knowing enough about pointers to get by haha

Oh and im using visual studio code, i see you can right mouse click somethings and go to their definitions, is this what you’re getting at?

Yes, that should work too. It will probably show you the .h file where a certain function or class is defined. In the .h file you should be able to read the inline documentation, from which the documentation in the OF website is generated.

Right it is creating a pointer pointing to the first element of the array. But, this is how you access arrays in C (and C++). kinda weird.
Esentially, a pointer just points to a specific memory address, and arrays are contiguous memory regions, thus you can move through the array using the [ ] syntax. Be aware of not going out of bounds as that will create an error and most probably make your app to crash.

look at this ofBook chapter where it explains arrays and memory.

Kinda unrelated. when allocating an array, the memory is not erased, it is simply reserved for you to use. As it was not erased it might have data from other applications that were runnig on your computer, and you can access that data. It is fun doing it with images after doing a lot of internet browsing. :slight_smile:

Thanks so much! you’re a hero

after a lot of reading, i think im getting the hang of it. one more question i cant seem to find the answer to - why dont you have to call the data like this:

*pixels [ i ] = some value

is it because the brackets tells c++ that this is actually a pointer to an array?

sorry to keep asking questions!

:heart_eyes:

No, actually c++ does not care if the pointer is an array or not. Thus, you can use a regular pointer and the [ ] operator to access any part of memory as long as that memory belongs to your program.

no problem. That’s what this place is for. :slight_smile: