GetPixels() - tearing my hair out.

I have a video grabber and I want to get the pixels from a certain range and load them up into another image file or texture.

// this is not real code  
if (grabber.isFrameNew()) {  
		unsigned char * pixels = grabber.getPixels();  
		for (int i = y; i <= cropheight; i++) {  
			for (int j = x; j <= (cropwidth*3); j+=3) {  
				// pixel number  
				int pix1 = (i*cropwidth*3) + j;  
				int pix2 = (i*cropwidth*3) + (j+1);  
				int pix3 = (i*cropwidth*3) + (j+2);  
				// swap pixels  
				videocrop[pix1] = pixels[pix1];  
				videocrop[[pix2] = pixels[pix2];  
				videocrop[pix3] = pixels[pix3];	  
		newTexture.loadData(videocrop, cropwidth, cropheight, GL_RGB);	  

x and y being the start points of the image, and cropheight and cropwidth the respective width and height I want to take.

If I draw the new texture you can kind of see it is trying to do what I am asking it to do, it just isn’t correct.

What am I doing wrong?

very quickly, this:

int pix1 = (i*cropwidth*3) + j;  
int pix2 = (i*cropwidth*3) + (j+1);  
int pix3 = (i*cropwidth*3) + (j+2);  

looks wrong, try:

int pix1 = (i*grabber.width + j) * 3;  
int pix2 = (i*grabber.width + j) * 3 + 1;  
int pix3 = (i*grabber.width + j) * 3 + 2;  

(changed both the *3 location and the width, which should be based on the width of the source of pixels)

also, this:


definitely looks wrong to me – isn’t pix1, pix2, pix3 just for addressing the pixels array? you’ll need to calcluate the positions also in the cropped array, which should be different, ie:

((i-y)*cropWidth + (j-x)) * 3;  

I hope that helps…
take care,

ps: in the above code, you use i for y and j for x – it’s kind of common practice AFAIK to use the opposite:

for (int i = 0; i < width; i++){
for (int j = 0; j < height; j++){


obviously you can use them in any order, but to me (i,j) makes a bit more sense on first glance then (j,i) as you have…

I’m getting bad access runtime errors. Here is how I have it setup.

//in testapp.h  
        ofTexture mirrorTexture;  
	unsigned char * videoMirror;  

// in testapp.cpp  
unsigned char * pixels = vidGrabber.getPixels();  
		for (int i = y; i <= (y+h); i++) {  
			for (int j = x; j <= (x+w)*3; j+=3) {  
				// pixel number  
				int pix1 = (i*vidGrabber.width + j) * 3;  
				int pix2 = (i*vidGrabber.width + j) * 3 + 1;  
				int pix3 = (i*vidGrabber.width + j) * 3 + 2;  
				// swap pixels  
				videoMirror[(i-y) + 3*(j-x)] = pixels[pix1];  
				//videoMirror[] = pixels[pix2];  
				//videoMirror[] = pixels[pix3];  
		mirrorTexture.loadData(videoMirror, w, h, GL_RGB);	  

when it gets to this line videoMirror[(i-y) + 3*(j-x)] = pixels[pix1]; there is an EXC_BAD_ACCESS which I imagine has to do with where the array is pointing to.

I know the variables are named “mirror” but I’m not trying to do that.

this looks wrong:

for (int j = x; j <= (x+w)*3; j+=3)

should be:

for (int j = x; j <= (x+w); j++) {  

and this looks wrong also:

videoMirror[(i-y) + 3*(j-x)]  

maybe something like this:

videoMirror[ ((i-y) * WIDTHOFCROPPEDIMAGE + (j-x)) * 3]  

can you post a very simple example of what you’d like to do?

take care,

What I’m trying to do is detect a face in a video and crop the image (given the bounding rectangle on the face. I can grab the screen itself, but that is an undesirable workaround. I really should get my head around getpixels(). I even tried just putting videomirror[0] or videomirror[1] into that function and it still says bad access.

just post a **very simple** example of what you would like to do, and we can help you out.

the pixel math always takes a bit of time to get used to, but once you do it will be like second nature.

I even tried just putting videomirror[0] or videomirror[1] into that function and it still says bad access.

again, we need to see your whole code, but as simple as possible. it could be that something isn’t allocated, or some accessing elsewhere is off?

just post a small, concise example and we’ll take a look.

take care,

I attached my code.

I tried to start from scratch.

[getpixels practice]( practice

I defeated my bad access problems by loading up an initial image into the unsigned char. In the example I posted I have not added the variables to place the array position for the cropped image to start at zero.

        int w = 640; // width of the image  
	int h = 480; // height of the image  
	int x = 0; // coordinates where I want to start cropping  
	int y = 0;  
	int cw = 640; // width and height of the crop itself  
	int ch = 480;  
	for (int i = y; i < ch+y; i++){ // height  
		for (int j = x; j < ((cw+x) * 3); j+=3){ // width  
			int pix1 = (3*i*w)+j;  
			int pix2 = pix1+1;  
			int pix3 = pix1+2;  
			int dest1 = (3*(i-y)*cw)+(j-x);  
			int dest2 = dest1+1;  
			int dest3 = dest1+2;  
			loader[dest1] = pixels[pix1];  
			loader[dest2] = pixels[pix2];  
			loader[dest3] = pixels[pix3];  
	ctexture.loadData(loader, cw, ch, GL_RGB);  

This works now in this form, but if I change x, cw, y, or ch it doesn’t work correctly.

can you please upload a zip / example of this?

edit: sorry! I just saw it… didn’t notice it earlier. will take a look

any progress with this? also trying to crop ofVideoGrabber, having probs - memphistechno did you see this? -


I’m really with you about wanting to pull all hair out over pixel operations!

Your problem is this line:

int pix1 = (3*i*w)+j;  

which should read something like

int pix1 = (3*j*tryload.width)+i*3;  

I modified your project and attached it. Now the texture is as big as your crop area and you can change x, y, cw and ch.

[getpixels practice]( practice