Scroll one column of pixels per frame

Hi, im new with openframeworks, i have this code made in processing and i need to rewrite it in openframeworks.

I was wondering if there is an easy way in openframeworks to do this?

Is there something like the arrayCopy function in of? or which way should be the better for this?

the code scroll the pixels to the right one pixel per frame:

thank you

  
  
  
      loadPixels();  
      for (int r = 0; r < height; r++)  
      {  
        arrayCopy(pixels, width * r, pixels, width * r + 1, width - 1);  
      }  
      updatePixels();  
  
  
  
  

Hi

You can use the memmove command. http://www.cplusplus.com/reference/clibrary/cstring/memmove/ it should be faster:

  
unsigned char* pixels = img.getPixels();  
memmove(pixels+img.getWidth()*3, pixels, img.getWidth()*img.getHeight()*3-img.getWidth()*3);  
img.update();  

Hi undergoeg, ive tried but it seems theres an error, it seems you cant add char with float, im getting this message:

invalid operands of types ‘unsigned char*’ and 'float ’ to binary ‘operator+’

class ofxCvColorImage has no member named ‘update’

You probably want to be working with either ofPixels or an ofImage instead directly with the ofxCvColorImage. You can just do:

  
ofPixels pix = img.getPixelsRef();  

or

  
ofImage image;  
image.setFromPixels(img.getPixelsRef());  

and the work with the ofPixels using memove and not have to cast floats to chars (which is going to lose data precision and be kind of gnarly).

with ofPixels the function seems to work but then how can i update and display my image? ofPixels doesnt has the method update, do i need to copy into a OfImage for updating?

i been using a ofxCvColorImage and i was displaying in this way:

img.draw(0,0,ofGetWidth(),ofGetHeight());

I would like to still use ofxCvColorImage, so how can i update the ofPixels? or should copy into a ofxCvColorImage in order to display it?

thanks

  
  
  
//img is my ofxCvColorImage    
  
  
 ofPixels image = img.getPixelsRef();   
      
unsigned char* pixels = img.getPixels();    
memmove(pixels + image.getWidth()* 3, pixels, image.getWidth() * image.getHeight()* 3 - image.getWidth() * 3);    
  
image.update();   //-------> This doesnt work , how to update this and then draw?  
  
  
  

ofPixels doesn’t have an update() because it lives entirely on the CPU, no need to push it to the GPU or into a texture to display. You can just copy it into an ofImage or ofTexture to show it, which handles uploading it. This might seem like a little more work, but it’s actually what the update method does when you manipulate the pixels of an image.

  
  
tex.loadData(pix); // assumes you have an ofTexture named tex in your app  
  

that works, now i can display the texture , but it seems that the function memmove is not doing anything because the pixels are not moving. Any idea?

  
  
  
  
void testApp::setup()  
{		  
  ...  
imago.allocate(camWidth,camHeight,GL_RGB);   /// this is my texture  
}  
  
  
void testApp::draw()  
{		  
    
  
  ofPixels image = img.getPixelsRef();       
      
    unsigned char* pixels = img.getPixels();     
  
   memmove(pixels + image.getWidth() * 3, pixels, image.getWidth() * image.getHeight() * 3 - image.getWidth() * 3);    
  
  
    imago.loadData(image);    //imago is my texture  
  
  
  
  imago.draw(0,0,ofGetWidth(),ofGetHeight());   
  
  
  
}  
  
  
  
  

Because you’re modifying your ofImage, not your ofPixels, they aren’t pointing to the same things.

You want:

  
  
ofPixels image = img.getPixelsRef();  
unsigned char* pixels = image.getPixels();  
memmove(pixels + image.getWidth() * 3, pixels, image.getWidth() * image.getHeight() * 3 - image.getWidth() * 3);  
imago.loadData(image);    //imago is my texture    
  

also, just as a suggestion, usually data manipulation should be done in update() not in draw(), so you would move your pixels around in update and then actually draw them in draw(). This makes your app a little bit more efficient and more OF-like :slight_smile:

It doesnt work either, the pixels doesnt move, does it work for you?

Ah, my bad:

  
imago.loadData(pixels);    //imago is my texture  

That’s what I get for doing that on my phone :slight_smile:

now It doesnt work, it doesnt compile now, it seems loadData is expecting different data than “pixels”

Im getting this:

No matching function to call to ‘ofTexture::loadData(unsigned char*&)’
No matching member function for call to 'loadData.

I really need to stop replying on my phone.

  
tex.loadData(pixels, pix.getWidth(), pix.getHeight(), GL_RGB); // or whatever type RGB or RGBA your image is  

Actually, you probably don’t need the ofPixels at all since you’re just moving the pixels around, this works just as well:

  
    unsigned char* pixels = img.getPixels();   
    memmove(pixels + (unsigned char) img.getWidth() * 3, pixels, (int) img.getWidth() * img.getHeight() * 3 - img.getWidth() * 3);   
    tex.loadData(pixels, pix.getWidth(), pix.getHeight(), GL_RGB);  

just tried both approaches , they run but the pixels dont move.

I was wondering if you tried this in your computer?

I did yes, and they do move but maybe in a different way than you’re expecting. If you could you post your whole example I’ll see what might be going wrong.

ok, thanks, here is the code, basically im generating a gradient and i would like to scroll those pixels from my gradient. The code works without errors but pixels dont move.

  
  
  
void testApp::setup()  
{		  
  
    ofBackground(0, 0, 0);  
  
	camWidth = 1024;  
	camHeight = 768;  
      
      
      
      
    imago.allocate(camWidth,camHeight,GL_RGB);  // ----> this is my texture   ofTexture ;   
      
  
    film.allocate(camWidth, camHeight);     // this is     ofxCvColorImage			  
    temporal.allocate(camWidth, camHeight);   // this is     ofxCvColorImage  
      
  
      
    unsigned char * filmPixels = temporal.getPixels();  
      
    int lenght = camWidth * camHeight * 3;  
  
      
      
    // here im creating a gradient image  
      
      
	for( int i=0; i<camWidth; i++ ){  
		for( int j=0; j<camHeight; j++ ){  
			int p = j * camWidth + i;	  
			  
				filmPixels[p * 3 + 0] = 0;  
                filmPixels[p * 3 + 1] = 1;  
				filmPixels[p * 3 + 2] = p * 0.0001;  
			  
		}  
	}  
      
      
      
    temporal.setFromPixels( filmPixels, camWidth, camHeight );  
      
      
  
  
      
  
}  
  
  
//--------------------------------------------------------------  
void testApp::update()  
  
  
{  
    film = temporal ;  
      
    unsigned char* pixels = film.getPixels();           
      
      
    memmove(pixels + (unsigned char) film.getWidth() * 3, pixels, (int) film.getWidth() * film.getHeight() * 3 - film.getWidth() * 3);   
      
    imago.loadData(pixels, film.getWidth(), film.getHeight(), GL_RGB);  
      
  
  
}  
  
  
void testApp::draw()  
{  
      
  
      
      
    imago.draw(0,0,ofGetWidth(),ofGetHeight());   
    
      
  
      
	  
}  
  
  
  
  
  
  
  
  

I think I’m misunderstanding something: you want to scroll the gradient image that you created? i.e. you want to move it down one pixel and then draw it? The memove thing is neat if you really know what it’s doing, but right now, you have a block of pixels that you’re creating that you want to move, just move them:

  
#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);  
      
    ofPixels film, temporal;  
    ofTexture image;  
    int camWidth, camHeight;  
    int scrollAmount;  
};  

  
void testApp::setup(){  
      
    camWidth = 1024;    
    camHeight = 768;    
      
    image.allocate(camWidth,camHeight,GL_RGB);  // ----> this is my texture   ofTexture ;     
      
    film.allocate(camWidth, camHeight, OF_IMAGE_COLOR);     // this is ofPixels              
    temporal.allocate(camWidth, camHeight, OF_IMAGE_COLOR);   // this is ofPixels  
      
    img = temporal.getPixels();  
    img2 = new unsigned char[1024 * 768 * 3];  
    // here im creating a gradient image    
    for( int i=0; i<camWidth; i++ ){    
        for( int j=0; j<camHeight; j++ ){    
            int p = j * camWidth + i;       
              
            img[p * 3 + 0] = 0;    
            img[p * 3 + 1] = 1;    
            img[p * 3 + 2] = p * 0.0001;  
              
        }    
    }    
      
    film.setFromPixels(img, camWidth, camHeight, OF_IMAGE_COLOR);  
      
    scrollAmount = 0;  
      
}  
  
void testApp::update()  
{  
    temporal.pasteInto(film, 0, scrollAmount);  
    scrollAmount++;  
      
    image.loadData(film);  
}  
  
void testApp::draw(){  
     
    image.draw(0,0);  
}  

When you’re working with blocks of pixel data in OF, changing colors, moving things around, etc, that’s what the ofPixels class is for and it has a lot of convenient methods to help you do that. The documentation might be helpful: http://www.openframeworks.cc/documentation/graphics/ofPixels.html

also if you want to move an image the fastest is to use an ofMesh to draw a quad with tex coordinates:

  
  
ofMesh quad;  
quad.addVertex(0,scroll);  
quad.addVertex(img.getWidth(),scroll);  
quad.addVertex(img.getWidth(),img.getHeight());  
quad.addVertex(0,img.getHeight());  
for(int i=0;i<quad.getNumVertices();i++){  
    quad.addTexCoord(quad.getVertex(i));  
}  
quad.setMode(OF_PRIMITIVE_TRIANGLE_FAN);  
img.getTextureReference().bind();  
quad.drawFaces();  
img.getTextureReference().unbind();  
scroll++;  
  

that will scroll the image 1 pixel per frame

can you do addVertex(0,scroll)?

i think ofMesh only has:

  
  
void addVertex(const ofVec3f& v);  
  

so you need to say:

  
  
mesh.addVertex(ofVec2f(0, scroll));