flip an image array (data, not display)

I’ve got a image coming in via videoGrabber.

I then convert it to grayscale and store it in a char array.

I’d like to easily flip the pixels in the array either vertically or horizontally. It seems like I should be able to do this via ofPixel or ofImage, but I don’t understand how to load a raw array of integers into these objects.

Right now my image lives in:

  
videoGrayScale  = new unsigned char[camWidth*camHeight];  
  

and I can display it onscreen via:

  
  
videoGrayTex.allocate(camWidth,camHeight,GL_LUMINANCE);  
videoGrayTex.loadData(videoGrayScale, camWidth, camHeight, GL_LUMINANCE);  
videoGrayTex.draw(20+camWidth,20,camWidth,camHeight);  
  

What I’d like to do is manipulate the actual array data, not just the display texture. I am using the flip/manipulated data later in the processing chain that’s not show here. I’m assuming there must be an easy way to do this. (I’m very new to C/C++ and the documentation seems to only list the methods and their arguments, but most often does not give working examples for newbies.)

I’ve managed to do the flip ‘the hard way’ by writing an algorithm from scratch to flip the image vertically, but want to know the ‘easy’ way that I’m pretty sure must be built into OF.

use the ofxCVImage classes (include the ofxCV addon, OF 071 includes some good ofxCV examples).
ofxCV images have a lot more pixel processing options.

http://www.openframeworks.cc/documentation/ofxOpenCv/ofxCvImage.html (see mirror)
http://www.openframeworks.cc/documentation/ofxOpenCv/ofxCvGrayscaleImage.html

Then you can load the pixeldata of the movie in an ofxCVColorImage, then convert to ofxCVGrayscale (or do it directly by copying only certain chars from the pixel array). I did it as follows:

  
  
//player is the videoPlayer  
ofxCvColorImage color;  
ofxCvGrayscaleImage gray;  
color.allocate(player.getWidth(),player.getHeight());  
color.setFromPixels(player.getPixelsRef());  
gray = color; //one of the nicest things about ofxCVImages!  
  
//now you can flip!  
gray.mirror(true, false);  
  

nice codes.

Im new with OF .the codes above works well . Btw ,I have several years’ experiences of C programming .here ,I would to share something with you. sample codes of flippling-Image-Using-Visual-C#. hope it contributes.AND if someone need tutotail-about-image-processing ,you can follow the link above.

  
  
using RasterEdge.Imaging.Basic;  
using RasterEdge.Imaging.Basic.Core;  
using RasterEdge.Imaging.Processing;  
using RasterEdge.Imaging.Basic.Codec;  
  
namespace RE__Test  
{  
    public partial class Form1 : Form  
    {  
        public Form1()  
        {  
            InitializeComponent();  
        }  
  
        private void button1_Click(object sender, EventArgs e)  
        {  
            string fileName = "c:/Sample.png";  
  
            REImage reImage = REFile.OpenImageFile(fileName);  
  
            ImageProcessing.ApplyFlip(reImage);  
  
            REFile.SaveImageFile(reImage, "c:/reimage.png", new PNGEncoder());  
        }  
    }  
}  

I do this with the videoGrabber example :

  
  
#include "testApp.h"  
  
//--------------------------------------------------------------  
void testApp::setup(){  
	  
	camWidth 		= 320;	// try to grab at this size.  
	camHeight 		= 240;  
	  
	vidGrabber.setVerbose(true);  
	vidGrabber.setDeviceID(0);  
	vidGrabber.setDesiredFrameRate(60);  
	vidGrabber.initGrabber(camWidth,camHeight);  
	  
	videoRot90 	= new unsigned char[camWidth*camHeight*3];  
	videoRot180 = new unsigned char[camWidth*camHeight*3];  
	videoRot270 = new unsigned char[camWidth*camHeight*3];  
	verticalFlip = new unsigned char[camWidth*camHeight*3];  
	horizontalFlip = new unsigned char[camWidth*camHeight*3];  
	  
	videoTexture90.allocate(camHeight, camWidth, GL_RGB);  
	videoTexture180.allocate(camWidth, camHeight, GL_RGB);  
	videoTexture270.allocate(camHeight, camWidth, GL_RGB);  
	verticalFlipTexture.allocate(camWidth, camHeight, GL_RGB);  
	horizontalFlipTexture.allocate(camWidth, camHeight, GL_RGB);  
	  
	ofSetVerticalSync(true);  
}  
  
  
//--------------------------------------------------------------  
void testApp::update(){  
	  
	ofBackground(100,100,100);  
	  
	vidGrabber.update();  
	  
	if (vidGrabber.isFrameNew()){  
		unsigned char * pixels = vidGrabber.getPixels();  
		for (int i = 0; i < 3 * camWidth; i += 3){  
			for (int j = 0; j < camHeight; j++) {  
				// Rotation 90  
				videoRot90[(camWidth - (i / 3) - 1) * 3 * camHeight + 3 * j] = pixels[j * 3 * camWidth + i];  
				videoRot90[(camWidth - (i / 3) - 1) * 3 * camHeight + 3 * j + 1] = pixels[j * 3 * camWidth + i + 1];  
				videoRot90[(camWidth - (i / 3) - 1) * 3 * camHeight + 3 * j + 2] = pixels[j * 3 * camWidth + i + 2];  
				  
				// Rotation 180  
				videoRot180[(camHeight - j - 1) * 3 * camWidth + 3 * (camWidth - 1) - i] = pixels[j * 3 * camWidth + i];  
				videoRot180[(camHeight - j - 1) * 3 * camWidth + 3 * (camWidth - 1) - i + 1] = pixels[j * 3 * camWidth + i + 1];  
				videoRot180[(camHeight - j - 1) * 3 * camWidth + 3 * (camWidth - 1) - i + 2] = pixels[j * 3 * camWidth + i + 2];  
				  
				// Rotation 270  
				videoRot270[((i / 3)) * 3 * camHeight + 3 * (camHeight - j - 1)] = pixels[j * 3 * camWidth + i];  
				videoRot270[((i / 3)) * 3 * camHeight + 3 * (camHeight - j - 1) + 1] = pixels[j * 3 * camWidth + i + 1];  
				videoRot270[((i / 3)) * 3 * camHeight + 3 * (camHeight - j - 1) + 2] = pixels[j * 3 * camWidth + i + 2];  
				  
				// Vertical Flip  
				verticalFlip[(camHeight - j - 1) * 3 * camWidth + i] =     pixels[j * 3 * camWidth + i];  
				verticalFlip[(camHeight - j - 1) * 3 * camWidth + i + 1] = pixels[j * 3 * camWidth + i + 1];  
				verticalFlip[(camHeight - j - 1) * 3 * camWidth + i + 2] = pixels[j * 3 * camWidth + i + 2];  
				  
				// HorizontalFlip  
				horizontalFlip[j * 3 * camWidth + 3 * (camWidth - 1) - i] = pixels[j * 3 * camWidth + i];  
				horizontalFlip[j * 3 * camWidth + 3 * (camWidth - 1) - i + 1] = pixels[j * 3 * camWidth + i + 1];  
				horizontalFlip[j * 3 * camWidth + 3 * (camWidth - 1) - i + 2] = pixels[j * 3 * camWidth + i + 2];  
			}  
		}  
		videoTexture90.loadData(videoRot90, camHeight, camWidth, GL_RGB);  
		videoTexture180.loadData(videoRot180, camWidth, camHeight, GL_RGB);  
		videoTexture270.loadData(videoRot270, camHeight, camWidth, GL_RGB);  
		verticalFlipTexture.loadData(verticalFlip, camWidth, camHeight, GL_RGB);  
		horizontalFlipTexture.loadData(horizontalFlip, camWidth, camHeight, GL_RGB);  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	ofSetHexColor(0xffffff);  
	vidGrabber.draw(20,20);  
	videoTexture90.draw(40+camWidth,20, camHeight, camWidth);  
	videoTexture180.draw(20, 40 + camWidth, camWidth, camHeight);  
	videoTexture270.draw(40+ camWidth,40 + camWidth, camHeight, camWidth);  
	verticalFlipTexture.draw(60 + camWidth + camHeight, 20, camWidth, camHeight);  
	horizontalFlipTexture.draw(60+ camWidth + camHeight, 40 + camWidth, camWidth, camHeight);  
}  
  

testApp.h :

  
  
	ofVideoGrabber 		vidGrabber;  
	unsigned char * 	videoRot90;  
	unsigned char * 	videoRot180;  
	unsigned char * 	videoRot270;  
	unsigned char * 	verticalFlip;  
	unsigned char * 	horizontalFlip;  
	ofTexture			videoTexture90;  
	ofTexture			videoTexture180;  
	ofTexture			videoTexture270;  
	ofTexture			verticalFlipTexture;  
	ofTexture			horizontalFlipTexture;  
	int 				camWidth;  
	int 				camHeight;