// // Simple brushing algorithm. // gever tulley - Creative Commons Attribution 3.0 United States License // import processing.video.*; final static int SHAPE_RECT = 0; final static int SHAPE_TRI = 1; final static int MAX_SHAPES = 2; // Using video camera for input (should allow for loading from an image) Capture video; int FPS = 8; // resolution of camera settings int CameraW = 320; int CameraH = 240; // size of display window int WindowW = CameraW * 2; int WindowH = CameraH * 2; float scaleX = (float)WindowW / (float)CameraW; float scaleY = (float)WindowH / (float)CameraH; // Adjust this up or down depending on output resolution int StrokesPerFrame = (WindowW + WindowH) * 2; // lame formula // "brush" size int cellW = 2; int cellH = 8; // rotation offset float deltaR = 0.0; // brush color toggle boolean inColor = true; // current brush shape int brushShape = SHAPE_RECT; void setup() { size(WindowW, WindowH); frameRate(30); colorMode(RGB,255,255,255,100); smooth(); // Using the default capture device video = new Capture(this, CameraW, CameraH, FPS); background(0); } void captureEvent(Capture camera) { video.read(); } // semi-transparent black used to partially erase previous strokes color bgfill = color(0,0,0,10); void draw() { // partially erase previous strokes fill(bgfill); noStroke(); rectMode(CORNER); rect(0, 0, WindowW, WindowH); rectMode(CENTER); for ( int i = 0; i < StrokesPerFrame; i++ ) { // pick a place to put down a brush stroke int x = round( random(CameraW - 1) ); // i*cellsize; int y = round( random(CameraH - 1) ); // j*cellsize; int loc = (video.width - x - 1) + y*video.width; // Reversing x to mirror the image int pixel = video.pixels[loc]; float r = red( pixel ); float g = green( pixel ); float b = blue( pixel ); // semi-transparent color color c = color( r, g, b, 75 ); // Using translate in order for rotation to work properly pushMatrix(); float sx = x * scaleX; float sy = y * scaleY; translate(sx, sy); // brush color if (inColor) { fill( c ); } else { fill( 200 ); } // Rotation formula based on simple combination of hue and brightness // (hue becomes less reliable at low light levels) rotate( (2 * PI * (hue(c)/2.0 + brightness(c)/2.0) / 255.0f) + deltaR ); // draw the brush noStroke(); switch(brushShape) { case SHAPE_RECT: rect( 0, 0, cellW, cellH ); break; case SHAPE_TRI: triangle(-cellW/2f, 0, cellW/2f, 0, 0, cellH); break; } popMatrix(); } } void keyPressed() { if (key == CODED) { switch(keyCode) { case UP: cellH++; break; case DOWN: cellH--; break; case RIGHT: cellW++; break; case LEFT: cellW--; break; } } else { switch(key) { case 'z': case 'Z': deltaR += PI / 30; break; case 'x': case 'X': deltaR -= PI / 30; break; case 's': brushShape = (brushShape + 1) % MAX_SHAPES; break; case 'c': inColor = !inColor; break; case 'p': saveFrame(); break; } } }