This term, for the first time, we used some video in our introductory Processing class. This came from requests from students; I admit I hadn’t really played much with this part of Processing.

I was actually pretty impressed by how fast it is. It even works, up to a point, for carrying out real-time transformations on a live video feed. Today’s experiment was simple enough: it takes the feed from the webcam on my laptop but scrambles the pixels around according to a mathematical transformation.

We’ll definitely do more of this sort of thing next term,in part of course because there’ll be another intro class. But also, as part of the Three Pillars of the Digital, we’ll be running a workshop on the most useful maths for programming visual work. That includes the modulus operator and the trigonometric functions sine and cosine, all of which are in the mix here. They help us break the tyranny of straight lines that the organisation of a computer’s visual display tends to impose.

This code is parameterized, allowing the warping algorithm itself to warp in response to the position of the mouse. This makes for an interactive experience that’s positively addictive. It’s even more fun when, in addition to waving things at the webcam and moving the mouse, you get to intervene at the code level too.

This particular experiment is really just a bit of idle fun, but I’m half-thinking about ways to hook it up to something more responsive. I’m also wondering whether my new phone will have enough power to do this kind of thing in VR. But another lesson is that coding can be be playful and exploratory. I probably only continued with this because the effects made me smile.

Anyway, below are some more screen captures from my “warped” webcam, and at the bottom is the code so you can try it yourself. Let me know if you make something cool with it!

 

   

 

_______________________________________________________________________

 

import processing.video.*;

Capture cam;
int camWidth;
int camHeight;
boolean newFrame=false;
float[] xCosArr;
float scalar = 1.0;
float offset = 0.0;

void setup(){
size(displayWidth, displayHeight);
cam = new Capture(this);
cam.start();
camWidth = cam.width;
camHeight = cam.height;
xCosArr = new float[width];
initXCosArr();
}

void captureEvent(Capture cam){
cam.read();
camWidth = cam.width;
camHeight = cam.height;
newFrame = true;
}

void draw(){
if (newFrame){
warp();
}
}

void warp(){
setParams();
loadPixels();
for(int y = 0; y < height; y = y + 1){
float sinVal = abs(sin(float(y)/scalar)*cos(scalar));
for(int x = 0; x < width; x = x + 1){
color c = cam.get(int(x*sinVal) % camWidth, int(y*xCosArr[x]) % camHeight);
pixels[y*width + x] = c;
}
}
updatePixels();
}

void mouseClicked(){
saveFrame("##########.png");
}

void setParams(){
scalar = map(float(mouseX), 0, float(width), 0.1, 350.0);
offset = map(float(mouseY), 0, float(height), -10, 10);
initXCosArr();
}

void initXCosArr(){
if(scalar == 0){
scalar = 1;
}
for(int x = 0; x < width; x = x + 1){
xCosArr[x] = abs(cos(float(x)/scalar)*sin(scalar));
}
}