Created
July 16, 2015 16:12
-
-
Save n1ckfg/86a629e58a1f54477736 to your computer and use it in GitHub Desktop.
Simplified version of https://github.com/n1ckfg/AutoTrace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// get sample brushes from | |
// http://fox-gieg.com/stuff/for/recurse/brush_examples.zip | |
// brush path code by Amnon Owed | |
// http://forum.processing.org/one/topic/help-starting-bitmap-trace.html | |
PImage img; | |
int numDrawers = 1000; //points drawn per frame--use lots | |
int numDrawerReps = 1;//scatter points per point--use sparingly | |
int numStrokes = 10; | |
int numRepsMax = 200; // draw loops--to taste | |
int numReps = 0; | |
boolean ready = false; | |
String brushFile = "brush5"; | |
PImage brush; | |
PVector p = new PVector(0, 0); | |
int alphaDecrease = 50; | |
float brushSizeOrig = 20; | |
float brushSize = brushSizeOrig; | |
float brushSizeMin = 5; | |
float brushSizeMax = 40; | |
float leakRandom = 0.2; //0-1 | |
float scatter = 4; | |
PGraphics alphaImg; | |
PGraphics alphaImgOrig; | |
boolean firstRun = true; | |
boolean cleanOutlines = true; | |
boolean useBase = true; | |
float shrinkAmount = 0.99; | |
int counter = 0; | |
void setup() { | |
//Settings settings = new Settings("settings.txt"); | |
loadFiles(); | |
nextImage(counter); | |
size(img.width, img.height); | |
brush = loadImage(brushFile+".png"); | |
brush.filter(INVERT); | |
} | |
void draw() { | |
//prep graphics | |
if (firstRun) { | |
prepGraphics(); | |
println("RENDERING frame " + (counter+1) + " of " + imgNames.size()); | |
firstRun = false; | |
} | |
if (numReps < numRepsMax) { | |
alphaImg.beginDraw(); | |
for (int j=0; j<numDrawerReps; j++) { | |
for (int i=0; i<numDrawers; i++) { | |
float x = noise(0.01*frameCount+i)*width*2-width/2; | |
float y = noise(0.01*frameCount+30*i)*height*2-height/2; | |
int index = constrain(int(x) + int(y) * img.width, 0, img.pixels.length-1); | |
//important--first check if there's anything there | |
//color c = color(img.pixels[index], 127); | |
color c = img.pixels[index]; | |
if (alpha(c) != 0) { | |
//c = color(c,127); | |
float theta = map(brightness(c), 0, 255, 0, TWO_PI); | |
alphaImg.pushMatrix(); | |
alphaImg.translate(x, y); | |
alphaImg.rotate(theta); | |
float bs; | |
if (random(1)<leakRandom) { | |
bs = random(brushSize, brushSizeMax); | |
} else { | |
bs = brushSize; | |
} | |
if (j==0) { | |
//centered on first pass | |
p.x=0; | |
p.y=0; | |
} else { | |
//pick a direction on second pass; | |
p.x = random(-scatter, scatter)*j; | |
p.y = random(-scatter, scatter)*j; | |
} | |
PVector strokeDir; | |
float r = random(1); | |
if (r <= 0.25) { | |
strokeDir = new PVector(-1, -1); | |
} else if (r > 0.25 && r <= 0.5) { | |
strokeDir = new PVector(-1, 1); | |
} else if (r > 0.5 && r <= 0.75) { | |
strokeDir = new PVector(1, -1); | |
} else { | |
strokeDir = new PVector(1, 1); | |
} | |
for (int l=0; l<numStrokes; l++) { | |
doBrushSimple(new PVector(p.x + (strokeDir.x * l), p.y + (strokeDir.y * l)), c, bs);//line(0, 0, 0, random(5, 15)); | |
} | |
alphaImg.popMatrix(); | |
} | |
} | |
} | |
alphaImg.endDraw(); | |
image(alphaImg, 0, 0); | |
if (numReps > (numRepsMax/2) && brushSize > brushSizeMin) brushSize *= shrinkAmount; | |
numReps++; | |
} else { | |
if (cleanOutlines) { | |
//uses the alpha of the original image | |
color c1, c2; | |
alphaImg.loadPixels(); | |
alphaImgOrig.loadPixels(); | |
for (int i=0; i<alphaImg.pixels.length; i++) { | |
c1 = alphaImg.pixels[i]; | |
c2 = alphaImgOrig.pixels[i]; | |
float r = red(c1); | |
float g = green(c1); | |
float b = blue(c1); | |
float a = alpha(c2); | |
alphaImg.pixels[i] = color(r, g, b, a); | |
} | |
alphaImg.updatePixels(); | |
} | |
if (counter<imgNames.size()-1) { | |
saveGraphics(alphaImg, false); //don't exit | |
counter++; | |
numReps = 0; | |
brushSize = brushSizeOrig; | |
nextImage(counter); | |
prepGraphics(); | |
} else { | |
saveGraphics(alphaImg, true); //exit | |
} | |
} | |
} | |
void prepGraphics() { | |
background(0); | |
alphaImg = createGraphics(width, height, JAVA2D); | |
alphaImg.beginDraw(); | |
// make sure alpha is set to 0--may no longer be needed in Processing 2 | |
alphaImg.loadPixels(); | |
for (int i=0; i<alphaImg.pixels.length; i++) { | |
alphaImg.pixels[i] = color(0, 0); | |
} | |
alphaImg.updatePixels(); | |
if (useBase) alphaImg.image(img, 0, 0); //build on original image | |
alphaImg.endDraw(); | |
alphaImgOrig = createGraphics(width, height, JAVA2D); | |
alphaImgOrig.beginDraw(); | |
alphaImgOrig.loadPixels(); | |
for (int i=0; i<alphaImgOrig.pixels.length; i++) { | |
alphaImgOrig.pixels[i] = color(0, 0); | |
} | |
alphaImgOrig.updatePixels(); | |
alphaImgOrig.image(img, 0, 0); | |
alphaImgOrig.endDraw(); | |
} | |
void doBrushSimple(PVector p, color c, float _bs) { | |
float r = red(c); | |
float g = green(c); | |
float b = blue(c); | |
float a = alpha(c) - alphaDecrease; | |
if (a<0) a=0; | |
alphaImg.tint(color(r, g, b, a)); | |
alphaImg.imageMode(CENTER); | |
alphaImg.image(brush, p.x, p.y, _bs, _bs); | |
} | |
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |
// file handling | |
import java.awt.Desktop; | |
String openFilePath = "render"; | |
String folderPath; | |
File dataFolder; | |
ArrayList imgNames; | |
String fileName = "frame"; | |
boolean filesLoaded = false; | |
//~~~~~~~~~~~~~~~~~~~~~~~~ | |
//choose folder dialog, Processing 2 version | |
void loadFiles() { | |
chooseFolderDialog(); | |
filesLoadedChecker(); | |
} | |
void chooseFolderDialog(){ | |
selectFolder("Choose a PNG, JPG, GIF, or TGA sequence.","chooseFolderCallback"); // Opens file chooser | |
} | |
void chooseFolderCallback(File selection){ | |
if (selection == null) { | |
println("No folder was selected."); | |
exit(); | |
} else { | |
folderPath = selection.getAbsolutePath(); | |
println(folderPath); | |
countFrames(folderPath); | |
} | |
} | |
void countFrames(String usePath) { | |
imgNames = new ArrayList(); | |
//loads a sequence of frames from a folder | |
dataFolder = new File(usePath); | |
String[] allFiles = dataFolder.list(); | |
for (int j=0;j<allFiles.length;j++) { | |
if ( | |
allFiles[j].toLowerCase().endsWith("png") || | |
allFiles[j].toLowerCase().endsWith("jpg") || | |
allFiles[j].toLowerCase().endsWith("jpeg") || | |
allFiles[j].toLowerCase().endsWith("gif") || | |
allFiles[j].toLowerCase().endsWith("tga")){ | |
imgNames.add(usePath+"/"+allFiles[j]); | |
} | |
} | |
if(imgNames.size()<=0){ | |
exit(); | |
}else{ | |
// We need this because Processing 2, unlike Processing 1, will not automatically wait to let you pick a folder! | |
String s; | |
if (imgNames.size() == 1) { | |
s = "image"; | |
} else { | |
s = "images"; | |
} | |
println("FOUND " + imgNames.size() + " " + s); | |
filesLoaded = true; | |
} | |
} | |
void filesLoadedChecker() { | |
// We need this because Processing 2, unlike Processing 1, will not automatically wait to let you pick a folder! | |
while(!filesLoaded){ | |
try{ | |
if(imgNames.size() > 0) img = loadImage((String) imgNames.get(0)); | |
}catch(Exception e){ | |
filesLoaded = false; | |
} | |
} | |
} | |
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
//reveal folder, processing 2 version | |
void openAppFolderHandler(){ | |
if(System.getProperty("os.name").equals("Mac OS X")){ | |
try{ | |
print("Trying OS X Finder method."); | |
open(sketchPath(openFilePath)); | |
//open(sketchPath("ManosOsc.app/Contents/Resources/Java/" + openFilePath)); | |
}catch(Exception e){ } | |
}else{ | |
try{ | |
print("Trying Windows Explorer method."); | |
Desktop.getDesktop().open(new File(sketchPath("") + "/" + openFilePath)); | |
}catch(Exception e){ } | |
} | |
} | |
//run at startup if you want to use app data folder--not another folder. | |
//This accounts for different locations and OS conventions | |
void scriptsFolderHandler(){ | |
String s = openFilePath; | |
if(System.getProperty("os.name").equals("Mac OS X")){ | |
try{ | |
print("Trying OS X Finder method."); | |
openFilePath = dataPath("") + "/" + s; | |
}catch(Exception e){ } | |
}else{ | |
try{ | |
print("Trying Windows Explorer method."); | |
openFilePath = sketchPath("") + "/data/" + s; | |
}catch(Exception e){ } | |
} | |
} | |
void saveGraphics(PGraphics pg,boolean last){ | |
try{ | |
String savePath = openFilePath + "/" + fileName + "_" + zeroPadding(counter+1,imgNames.size()) + ".png"; | |
pg.save(savePath); | |
println("SAVED " + savePath); | |
}catch(Exception e){ | |
println("Failed to save file."); | |
} | |
if(last) { | |
openAppFolderHandler(); | |
exit(); | |
} | |
} | |
void nextImage(int _n){ | |
String imgFile = (String) imgNames.get(_n); | |
img = loadImage(imgFile); | |
println("LOADED " + imgFile); | |
} | |
String zeroPadding(int _val, int _maxVal){ | |
String q = ""+_maxVal; | |
return nf(_val,q.length()); | |
} | |
float tween(float v1, float v2, float e) { | |
v1 += (v2-v1)/e; | |
return v1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment