/** * Circle Painter * by Matt Katz. * Click on the image to put origin points on the face. * I'd recommend you put them on eyes and lips, as you want detail there. * press g to begin rendering out the image.. * We'll paint out the image using scatterings of concentric circles, * larger ones where don't need detail. * inspired by this image: http://www.flickr.com/photos/tsevis/2498089530/sizes/l/ * */ PImage source; int originX; int originY; pointsArray points; boolean render; int minRadius; int minStart; int strokeSpace; float distance; int x; int y; int xLeft =0; int xRight; int yTop = 0; int yBottom; int xStroke; int yStroke; int yDirection = 0; int xDirection = 1; String file = "nikki"; String ext = ".jpg"; float circleSize =0; void setup() { //size(604,404); //name of the image we want. source = loadImage(file+ext); size(source.width,source.height); noStroke(); background(source); smooth(); originX = 0; originY = 0; points = new pointsArray(); render = false; minRadius = 4; minStart = minRadius * 2; strokeSpace = minRadius; x = 0; y = 0; xStroke = strokeSpace; yStroke = strokeSpace; xRight = width; yBottom = height; } void keyPressed() { if( key=='s'){//save the screen saveFrame( file+"-####.png"); } else if (key=='c'){//clear the screen background(255); } else if (key =='g'){ render = ! render; if(!render){ background(source); renderOriginPoints(); } else{ loop(); background(255); } } } void renderOriginPoints(){ for( int i = 0; i < points.counter; i++){ oPoint current = points.points[i]; //world's coolest color fill(#BADA55); ellipse(current.x, current.y, minRadius,minRadius); } } int strokeSpaceFromDistance(int x, int y){ return int(minDist(new oPoint(x,y))/1); } void draw() { //reset it all to a new origin point if(mousePressed){ points.addPoint(new oPoint(mouseX, mouseY)); } if (render){ if(circleSize == 0){circleSize = max(strokeSpace,minDist(new oPoint(x,y))/8);} while(yTop < yBottom){ //println("x = " + x + ", y = " + y); x += (xStroke * xDirection); y += (yStroke * yDirection); if(x > xRight){ println("HIT RIGHT: " +xRight); x= xRight -= xStroke; //x = xRight-1; xDirection = 0; yDirection = 1; yStroke = strokeSpaceFromDistance(x,y); debug("y"+yStroke); }else if(y > yBottom){ println("Hit BOTTOM"); yBottom -= yStroke; y = yBottom; yDirection = 0; xDirection = -1; xStroke = strokeSpaceFromDistance(x,y); debug("x" + xStroke); }else if(x < xLeft){ println("hit LEFT"); xLeft += xStroke; x = xLeft; xDirection = 0; yDirection = -1; yStroke = strokeSpaceFromDistance(x,y); debug("y" + yStroke); }else if(y < yTop){ println("hit TOP"); yTop += yStroke; y = yTop; xDirection = 1; yDirection = 0; xStroke = strokeSpaceFromDistance(x,y); circleSize = max(strokeSpace,minDist(new oPoint(x,y))/8); debug("y" + xStroke); } // pointilize(x,y); drawCircle(x,y, circleSize * produceNormalDistributionNumber()); xStroke = yStroke = max(abs(int(distance/16)),minRadius); if(yTop > yBottom){ noLoop(); } //strokeSpace = min(abs(int(distance/8)); // for (int x = 0; x < width; x += strokeSpace){ // for(int y = 0; y < height; y += strokeSpace){ // pointilize(x,y); // strokeSpace = int(distance/8); // } //} // noLoop(); // for( int i = 0; i< 60; i++){ // pointilize() ; //} } } else{ //background(source); renderOriginPoints(); } } void pointilize(int x, int y) { //generate a raondom point that we are going to pointillize //int x = int(random(source.width)); //int y = int(random(source.height)); //what is the smallest distance we are from an origin point distance = minDist(new oPoint(x,y)); //let's generate a size based on that distance //we want that size to tend to be proportional to the distance //but allow for some random variation in size float circleSize = (distance/6);// * produceNormalDistributionNumber(); drawCircle(x, y, max(circleSize, minStart)); } //find the minimum distance from an origin point to this point p float minDist(oPoint p){ float smallestDistance = dist(p.x, p.y, points.points[0].x, points.points[0].y); for( int i = 1; i < points.counter; i++){ oPoint current = points.points[i]; smallestDistance = min(smallestDistance, dist(p.x, p.y, current.x, current.y)); } return smallestDistance; } //draw a circle and draw circles inside of it. void drawCircle(int x, int y, float radius) { radius = max(ceil(radius), minRadius); fill(getColorFromCircle(x,y,radius), 126); ellipse(x,y,radius,radius); if(radius > minRadius){ drawCircle(x, y, radius -1); } } color getColorFromCircle(int x, int y, float radius){ //we want to get a point that is radius away from x,y //lets pic a point along the radius that we are intersted in //one before the next circle will get drawn. radius = random(floor(radius-1), radius) + radius; //let's pic a random angle around the circle. int angle = floor(random(0,360)); //do a little trig int newX = floor((cos(angle) * radius)) + x; int newY = floor((sin(angle) * radius)) + y; return source.get(newX, newY); } //just seems weird that processing doesn't have points class oPoint{ int x; int y; oPoint(int xIn, int yIn){ x = xIn; y = yIn; } } class pointsArray { oPoint[] points; int counter; pointsArray(){ points = new oPoint[5]; counter = 0; } void addPoint(oPoint in){ if( counter == points.length){ oPoint[] temp = points; points = new oPoint[points.length+ 5]; for (int i = 0; i < counter; i++){ points[i] = temp[i]; } } points[counter++] = in; } void reset(){ counter = 0; points = new oPoint[5]; } } float produceNormalDistributionNumber(){ float a = random(0,2); float b = random(0,2); float c = random(0,2); float d = random(0,2); return (a + b + c + d)/4; }