I have made a video slicer in processing. It takes a single line of pixels from a quicktime movie. The line can be moved around in an interactive manner, and the slices of video appear in the sketch area below the movie display. By using 2 mice (mouses?), the line can be a vertical or a diagonal one.

The movie can be started, stopped, and have it’s speed varied. Backwards play would be possible with some debugging of the PMovie class, as playback stops at the loop point (I think) of the movie. For now it doesn’t allow backwards playback. Slicing can be turned on and off, and the line can be locked to vertical or the current diagonal if required. The bottom pointer (for the mouse designated mouse 2) is the dominant mouse, so when the vertical or diagonal lock is engaged the line moves according to mouse 2’s movements.
Procontroll is required to operate 2 mice for this sketch (and obviously a second USB mouse would be of benefit too…). It can be obtained from here.
The modified processing.video library that I tweaked is also required to support the PMovie class and a couple of extra features. The zip of the library is available here
Code follows:
//processing libraries
//note: processing.video.* is customised and available
//from http://members.webone.com.au/~fox/video.zip
import processing.video.*;
import procontroll.*;
//quicktime libraries
import quicktime.*;
import quicktime.std.*;
import quicktime.qd.*;
//java libraries (for file I/O)
import java.io.*;
import java.util.*;
import java.io.ObjectOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//video variables and objects
PMovie m;
float pos = 0;
float step;
float rateIncrement;
int frames;
float fps;
int movWidth;
int movHeight;
int currSlice;
boolean slicing;
boolean diagonalLock, verticalLock;
PImage drawingArea;
//int drawingAreaOrigin;
//int[] drawingArea;
String movieName;
//mouse variables and objects
ControllIO controll;
ControllSlider slider_m1X, slider_m1Y;
ControllSlider slider_m2X, slider_m2Y;
float m1X, m1Y;
float m2X, m2Y;
float m1Xdl;
boolean miceSwapped;
float slope, dlVal;
void setup()
{
/////////////////////movie code\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
movieName = “station”;//don’t include the .mov extension, it’s added where req’d
m = new PMovie(this, movieName + “.mov”);
frames = m.calcTotalFrames();
fps = m.getAverageFPS();
boolean arbitraryWidthSet = false;
int arbitraryWidth = 400;
try
{
movWidth = m.movie.getNaturalBoundsRect().getWidth();
movHeight = m.movie.getNaturalBoundsRect().getHeight();
//these values seem to include a border area
//(which I can’t be arsed removing)
}
catch(StdQTException e)
{
System.err.println(“Movie exception”);
e.printStackTrace();
}
step = 1.0 / fps;
currSlice = 0;
slicing = false;
rateIncrement = 0.2;
m.speed(0);
m.loop();
m.play();
println(“frames: ” + frames);
println(“fps: ” + fps);
println(“movWidth: ” + movWidth + ” movHeight: ” + movHeight);
/////////////////////mouse/proControll code\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
controll = ControllIO.getInstance(this);
controll.printDevices();
//get one mouse
ControllDevice device = controll.getDevice(1);
slider_m1X = device.getSlider(0);
slider_m1Y = device.getSlider(1);
m1X = movWidth/2;//set the starting posn to the middle
m1Y = movHeight/2;
//get another mouse
device = controll.getDevice(2);
slider_m2X = device.getSlider(0);
slider_m2Y = device.getSlider(1);
m2X = movWidth/2;//set the starting posn to the middle
m2Y = movHeight/2;
miceSwapped = false;
verticalLock = false;
diagonalLock = false;
/////////////////////sketch settings\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
if(arbitraryWidthSet)
{
size(arbitraryWidth, movHeight * 2);
} else {
if(movWidth > frames)
{
size(movWidth, movHeight * 2);
} else {
size(frames, movHeight * 2);
}
}
drawingArea = new PImage(width, movHeight);
//drawingAreaOrigin = movWidth * movHeight;
background(0);
stroke(255);
noFill();
frameRate(fps);
noCursor();//works, but not always in this app.
}//end setup()
void draw()
{
//background(255);
mouseUpdate();
slope = movHeight / (m2X – m1Xdl);
//x = (y – m1Y) / slope + mX1;
int pixelIndex;
if(m.available())
{
m.read();
image(m, 0, 0);
if(slicing)
{
//copy a vertical line into the + drawingArea array
drawingArea.loadPixels();
//loadPixels();
for(int i = 0; i = 0 && pixelIndex = width)
{
currSlice = 0;
}
}//end if slicing
}//end if m.available()
//display the slices
image(drawingArea, 0, movHeight);
//draw 5 pixel tracking line for mouse 1
//(this shows where each slice is taken from)
if(diagonalLock)
{
if(m1Xdl > 0 && m1Xdl = movWidth) m2X = movWidth – 1;
if(m2Y >= movHeight) m2Y = movHeight -1;
if(verticalLock)
{
m1X = m2X;
m1Y = m2Y;
} else {
if(m1X = movWidth) m1X = movWidth – 1;
if(m1Y >= movHeight) m1Y = movHeight – 1;
}
if(diagonalLock)
{
m1Xdl = m2X + dlVal;
if(m1Xdl = movWidth) m1Xdl = movWidth – 1;
} else {
m1Xdl = m1X;
}
}//end mouseUpdate()
void mousePressed()
{
}
void keyPressed()
{
//regular keys
switch(key)
{
case ‘ ‘:
//space bar toggles mouse assignments
miceSwapped = !miceSwapped;
break;
case ‘/’:
//toggle slicing (determines if any video slices are drawn to the drawing area)
slicing = !slicing;
break;
case ‘|’:
//toggle lock to vertical
verticalLock = !verticalLock;
diagonalLock = false;
break;
case ‘\\’:
//toggle lock to diagonal
diagonalLock = !diagonalLock;
verticalLock = false;
dlVal = m1X – m2X;
break;
case ’s’:
//save the current screen
saveFrame(movieName + “-####.tif”);
break;
case ESC:
//catch the escape key so the default message is not displayed
break;
default:
//not assigned
if(key != CODED) println(“key ‘” + key + “‘ is not assigned”);
}
//CODED keys
//note the keys BACKSPACE, TAB, ENTER, RETURN, ESC, and DELETE
//do NOT require checking – they can be treated as normal keys
if(key == CODED)
{
switch(keyCode)
{
case DOWN:
//pause movie
m.speed(0);
break;
case UP:
//resume regular speed
m.speed(1);
break;
case RIGHT:
//increase playback speed
try
{
m.speed(m.movie.getRate() + rateIncrement);
}
catch(StdQTException e)
{
System.err.println(“Movie exception”);
e.printStackTrace();
}
break;
case LEFT:
//decrease playback speed
//note1: this could go negative which plays the movie backwards
//which is OK for a bit until the movie just stops (probably at frame 0)
//so for now this prevents backwards playback with an if statement
//note2: something screwy is going on with the rate and rateIncrement values
//they should produce regular values like 0, 0.2, 0.4 … 1.0, 1.2 etc
//but instead they’re off by a bit e.g: 0.39997864, 0.59999084 etc.
try
{
float rate = m.movie.getRate();
if(rate – rateIncrement > 0)
{
m.speed(rate – rateIncrement);
}
else
{
m.speed(0);
}
}
catch(StdQTException e)
{
System.err.println(“Movie exception”);
e.printStackTrace();
}
break;
default:
//no default
}//end switch
}//end if key == CODED
}//end keyPressed()