FAQ
Cover
This is the archive Discourse for the Processing (ALPHA) software.
Please visit the new Processing forum for current information.

   Processing 1.0 _ALPHA_
   Topics & Contributions
   Sound
(Moderators: pitaru, REAS)
   timestruct
« Previous topic | Next topic »

Pages: 1 
   Author  Topic: timestruct  (Read 522 times)
swannodette

swannodette WWW
timestruct
« on: Dec 28th, 2003, 11:45pm »

Using footage from my brand new Canon PowerShot SD100 i made a project that samples different points of a video buffer- resulting in a fractured time study.  There's lots of possibilities here for creating interesting film/video projects.
 
to see quicktime movies of the results link to:
 
http://www.onager.org/~dnolen/timestruct.html
 
if anybody has any pointers on making this code faster that would be greatly appreciated-  there's a lot of pixel copying; Thus the applet is only really good for rendering and not realtime.  Also it seems that copying a Bvideo.pixels field to a BImage.pixels field results in just passing a pointer to the video- also it would be nice if there was a method like image(BVideo, 0, 0) that returned a BImage.
 
anyways:
 
//12-25-03 dissecting time by the pixel
 
int FPS = 30;
int BUFSIZE = 48;
BVideo myvid;
BImage[] vidBuffer = new BImage[BUFSIZE];
int counter = 0;
 
void setup() {
  framerate(30);
  myvid = loadVideo("momma.mov");
  size(320, 240);
  repeat(myvid);
  
  //create a buffer of the first 96 images of the movie
  //init the buffer since processing doesn't allow for  
  //creating empty BImage objects
  
  for(int i = 0; i<BUFSIZE; i++)
    vidBuffer[i] = loadImage("initframe.jpg");
}
 
void loop() {
  BImage modframe = loadImage("initframe.jpg");
  int frameinc = 0, curframe = 0, cp=0;
  
  background(0);
  
  if(counter < BUFSIZE) {
    //load first 48 frames
    for(int i = 0; i< myvid.width*myvid.height; i++)
      vidBuffer[counter].pixels[i] = myvid.pixels[i];
  } else {
    //get a frame from buffer
    modframe = vidBuffer[0];
 
    //modify the modframe
    //the fun and tricky part
    
    for(int r = 0; r<modframe.height; r++) {
      //split into rows, inelegant I know
      if(cp<modframe.width*(modframe.height/4))
        curframe = 0;
      else if(cp<modframe.width*2*(modframe.height/4))
        curframe = BUFSIZE/4;
      else if(cp<modframe.width*3*(modframe.height/4))
        curframe = 2*BUFSIZE/4;
      else
        curframe = 3*BUFSIZE/4;
      
      //draw columns    
      for(int n=0; n<6; n++) {
        for(int m=0; m<modframe.width/6; m++) {
          cp = r*modframe.width+n*(modframe.width/6)+m;
          modframe.pixels[cp] = vidBuffer[curframe].pixels[cp];
        }
        curframe+=BUFSIZE/24;
      }
    }
    
    //display the new frame
    image(modframe, 0, 0);
    
    //move all frames in the video buffer up one
    //have to copy all the pixel one by one since copying just
    //the .pixels field actually just passes a reference to the video
    for(int j = 1; j < BUFSIZE; j++)
      for(int i = 0; i< myvid.width*myvid.height; i++)
        vidBuffer[j-1].pixels[i] = vidBuffer[j].pixels[i];
    
    //copy current vidframe into last fram of buffer  
    for(int i = 0; i< myvid.width*myvid.height; i++)
      vidBuffer[BUFSIZE-1].pixels[i] = myvid.pixels[i];
    }
    
    //save an image so I can make a .mov of this nonsense
    saveFrame();
    counter++;
}
« Last Edit: Dec 28th, 2003, 11:46pm by swannodette »  
TomC

WWW
Re: timestruct
« Reply #1 on: Dec 29th, 2003, 1:49am »

Hey, that's neat. Reminds me of a slide puzzle, but that's a sketch for another day
 
Playing around, I reckon you can get a bit of a speed nudge by replacing...
 
Code:

    for(int i = 0; i< video.pixels.length; i++)  
 vidBuffer[counter].pixels[i] = video.pixels[i];  

 
with
 
Code:

 vidBuffer[counter] = video.copy(width,height);  

 
Also, I think there is an as yet undocumented constructor for BImage which might help you out.  Rather than
 
Code:

vidBuffer[i] = loadImage("initframe.jpg");  

 
Try
 
Code:

vidBuffer[i] = new BImage(width, height);  

 
 
After that, things get a little more complex, but bear with me.  Rather than always having the same place in your buffer as the current frame (shuffling your buffer down one frame each time), you can just keep track of which buffer is current, and then add that to the index when accessing the array, modulo buffer length.
 
Erm... I'll try an example.
 
Rather than:
 
Code:

 
// remember 100 frames,  
// (buffer[0] is most recent, buffer[99] is oldest)
BImage[] buffer = new BImage[100];
 
void setup() {
  size(320,240);
  beginVideo(width,height,30);
  for (int i = 0; i < buffer.length; i++)
    buffer[i] = new BImage(width,height);
}
 
void loop() {
  // copy each buffer image back one place
  for (int i = 1; i < buffer.length; i++)
    buffer[i-1] = buffer[i];
  // store current
  buffer[buffer.length-1] = video.copy();
  // display last
  image(buffer[0],0,0);  
}
 

 
Do this:
 
Code:

// remember 100 frames
BImage[] buffer = new BImage[100];
// remember where the oldest frame is
int oldestFrame = 0;
 
void setup() {
  size(320,240);
  beginVideo(width,height,30);
  for (int i = 0; i < buffer.length; i++)
    buffer[i] = new BImage(width,height);
}
 
void loop() {
  // (now there's no need to move every frame in the buffer...)
  // store current frame, buffer.length-1 places away from oldestFrame
  buffer[(oldestFrame+buffer.length-1)%buffer.length] = video.copy();
  // display oldestFrame
  image(buffer[oldestFrame%buffer.length],0,0);  
  oldestFrame++;
}
 

 
I think it should be quicker, but it probably only depends on buffer length now, since we're using the copy method rather than doing it per pixel.
 
I'll post my modified version in a minute.
 
TomC

WWW
Re: timestruct
« Reply #2 on: Dec 29th, 2003, 2:04am »

OK, this works in just about real-time for me, at 320x240.
 
(The original version did too actually, to be fair.  That means that there's no guarantee my optimisations represent anything other than coding preferences.  Let me know how you get on.)
 
Code:

 
//12-25-03 dissecting time by the pixel (swannodette)
//12-28-03 with luck, some optimisations (TomC)
 
int FPS = 30;  
int BUFSIZE = 48;  
 
BImage[] vidBuffer = new BImage[BUFSIZE];  
BImage modframe;
int counter = 0;
 
void setup() {  
  size(640,480);  
  framerate(FPS);
  beginVideo(width,height,FPS);  
 
  //create a buffer of the first 96 images of the movie  
  //init the buffer since processing doesn't allow for  
  //creating empty BImage objects  
    
  for(int i = 0; i<vidBuffer.length; i++)  
    vidBuffer[i] = new BImage(width,height);
}  
 
void loop() {  
  if(counter < vidBuffer.length) {  
    //load first 48 frames  
    vidBuffer[counter] = video.copy();  
  }  
  else {  
    
    //get a frame from buffer  
    modframe = vidBuffer[counter%vidBuffer.length];  
  
    //modify the modframe  
    //the fun and tricky part  
    int cp = 0, curframe = 0;      
    for(int r = 0; r<modframe.height; r++) {  
      //split into rows, inelegant I know  
      if(cp<modframe.width*(modframe.height/4))  
        curframe = 0;  
      else if(cp<modframe.width*2*(modframe.height/4))  
        curframe = vidBuffer.length/4;  
      else if(cp<modframe.width*3*(modframe.height/4))  
        curframe = 2*vidBuffer.length/4;  
      else  
        curframe = 3*vidBuffer.length/4;  
        
      //draw columns    
      for(int n=0; n<6; n++) {  
        for(int m=0; m<modframe.width/6; m++) {  
          cp = r*modframe.width+n*(modframe.width/6)+m;  
          modframe.pixels[cp] = vidBuffer[(curframe+counter)%vidBuffer.length].pixels[cp];  
        }  
        curframe+=vidBuffer.length/24;  
      }  
    }  
      
    //copy current vidframe into last fram of buffer    
    vidBuffer[(counter-1)%vidBuffer.length] = video.copy(width,height);  
 
    //display the new frame  
    image(modframe, 0, 0);  
 
  }
 
  //save an image so I can make a .mov of this nonsense  
  //saveFrame();  
    
  counter++;
 
}  
 

 
 
On update:
 
Just realised there's no need for modFrame, since you can write directly to pixels.  And you always save the currentFrame into the buffer, so there's no need to have that bit of code twice.  Also, width*height is the same as pixels.length.
 
It's quite short now, neatly showcasing your algorithm.
 
Code:

//12-25-03 dissecting time by the pixel (swannodette)
//12-28-03 with luck, some optimisations (TomC)
 
int FPS = 30;  
int BUFSIZE = 48;  
 
BImage[] vidBuffer = new BImage[BUFSIZE];  
int counter = 0;
 
void setup() {  
  size(640,480);  
  framerate(FPS);
  beginVideo(width,height,FPS);  
}  
 
void loop() {  
 
  if(counter > vidBuffer.length) {  
    //the fun and tricky part  
    int cp = 0, curframe = 0;      
    for(int r = 0; r < height; r++) {  
 //split into rows, inelegant I know  
 if(cp < pixels.length/4)  
   curframe = 0;  
 else if(cp < pixels.length/2)  
   curframe = vidBuffer.length/4;  
 else if(cp < pixels.length*3/4)  
   curframe = 2*vidBuffer.length/4;  
 else  
   curframe = 3*vidBuffer.length/4;  
   
 //draw columns    
 for(int n=0; n<6; n++) {  
   for(int m=0; m<width/6; m++) {  
     cp = r*width+n*(width/6)+m;  
     pixels[cp] = vidBuffer[(curframe+counter)%vidBuffer.length].pixels[cp];  
   }  
   curframe+=vidBuffer.length/24;  
 }  
    }  
  }
     
  //copy current vidframe into last fram of buffer    
  vidBuffer[(counter+vidBuffer.length-1)%vidBuffer.length] = video.copy();  
 
  //save an image so I can make a .mov of this nonsense  
  //saveFrame();  
     
  counter++;
 
}  
 
« Last Edit: Dec 29th, 2003, 2:15am by TomC »  
swannodette

swannodette WWW
Re: timestruct
« Reply #3 on: Dec 29th, 2003, 11:09pm »

Thanks for the insights.  I actually like your optimization, it makes the code more readable and it's great to know there's a constructor for BImage.  
 
I'm running on a 400Mhz Powerbook so anything to speed things up helps.
 
Pages: 1 

« Previous topic | Next topic »