Hi, I’ve found a beautiful starting point for what I am intending to achieve: drawing a portrait of a face with curved lines and exporting it to SVG.
However, it’s written in p5.js and the p5.js version doesn’t support exporting it to an SVG as well. I’ve tried for a few days to get the SVG export working but it doesn’t want to fly.
Now I’ve set out to convert the script to a processing sketch, luckily it isn’t too heavy of a script:
tab 1 has 71 lines
tab 2 has 152 lines
Anyway, I’ve gotten somewhere, but my knowledge just isn’t developed well enough to try it on my own. I’m getting stuck at where the ‘fget’ function is called in tab 1. Fget does appear in tab #2 called paint, but it’s not created as a function. I believe this is where it gets over my head. I have tried converting the createVector commands to PVector, I hope I did that well.
I’m hoping that someone with knowledge in both languages can help me out. I understand what the script does, I have an understanding of the functions and how the data is handled, but I cannot make it my own enough so that I can rewrite it yet.
The original P5 script can be found here:
I need the end result to be saved as an SVG so the animation part isn’t important to me. I am probably able to do the SVG part by myself (I’ve done this countless of times in Processing). My main goal was to learn from this project, but I think the difficulty is too high. So at first I think it would be great to get some pointers and tips to get me on my way, I am not expecting anyone to rewrite the entire script for me. The eventual purpose is that I want to generate images for the pen plotter I’m working on at the same time.
As you will see I also gave up on renaming all the variables as I didn’t understand how I should call some variables in Processing. In p5.js it’s all just ‘var’ which makes it easy in p5.js but hard in Processing.
I hope to learn how to make this sketch work, have SVG export and maybe also a function that imports files. I tried copying parts from another script I had laying around but importing was also a bit complicated to me so I stuck with simply importing it in the script itself with ‘imgs[0] = loadImage(“test3.png”);’.
If you have advice or know anything to get me further, thanks for your time and effort.
My attempt so far;
Tab 1:
PImage imgs[];
int imgIndex = -1;
String img;
PVector paint;
float subStep = 1600;
float z = 0;
boolean isStop = false;
float count = 0;
void preload() {
imgs[0] = loadImage("test3.png");
}
void setup() {
size(600, 600);
frameRate(60);
PImage img = createImage(width, height, RGB);
nextImage();
//paint = new Paint(new PVector(width/2, height/2)); <<<-- Old p5.js approach
PVector paint = new PVector(width/2, height/2); // <<<-- My failing Processing approach
background(255);
colorMode(RGB, 255);
}
void draw() {
if (!isStop) {
for (int i = 0; i < subStep; i++) {
paint();
//paint.show();
//z+= 0.01;
}
}
count++;
if (count > width) {
isStop = true;
}
}
void fget(i, j) {
var index = j * img.width + i;
index *= 4;
return color(img.pixels[index], img.pixels[index+1], img.pixels[index+2], img.pixels[index+3]);
}
void fset(i, j, c) {
var index = j * img.width + i;
index *= 4;
img.pixels[index] = red(c);
img.pixels[index+1] = green(c);
img.pixels[index+2] = blue(c);
img.pixels[index+3] = alpha(c);
}
void keyPressed() {
console.log(key);
if (key === 's' || key === 'S') {
isStop = !isStop;
}
}
void nextImage() {
if (!img) {
return;
}
imgIndex = (++imgIndex) % imgs.length;
var targetImg = imgs[imgIndex];
img.copy(targetImg, 0, 0, targetImg.width, targetImg.height, 0, 0, img.width, img.height);
//img.resize(width, height);
img.loadPixels();
clear();
}
Tab 2 called ‘paint’:
void Paint(p) {
var ppos = p.copy();
var pos = p.copy();
PVector vel = new PVector(0, 0);
PVector force = new PVector(0, 0);;
float maxSpeed = 3.0;
int perception = 5;
int bound = 60;
float boundForceFactor = 0.16;
float noiseScale = 100.0;
float noiseInfluence = 1 / 20.0;
int dropRate = 0;
int dropRange = 0;
int dropAlpha = 150;
int drawAlpha = 50;
color drawColor = color(0, 0, 0, drawAlpha);
int drawWeight = 1;
int count = 0;
int maxCount = 100;
this.update = function() {
ppos = pos.copy();
force.mult(0);
// Add pixels force
PVector target = new PVector(0, 0);
var count = 0;
for (var i = -floor(perception/2) ; i < perception/2 ; i++ ) {
for (var j = -floor(perception/2) ; j < perception/2 ; j++ ) {
if (i == 0 && j == 0)
continue;
var x = floor(pos.x+i);
var y = floor(pos.y+j);
if (x <= img.width - 1 && x >= 0 && y < img.height-1 && y >= 0) {
var c = fget(x, y);
var b = brightness(c);
b = 1 - b/100.0;
PVector p = new PVector(i, j);
target.add(p.normalize().copy().mult(b).div(p.mag()));
count++;
}
}
}
if (count != 0) {
force.add(target.div(count));
}
// Add noise force
var n = noise(pos.x/noiseScale, pos.y/noiseScale, z);
n = map(n, 0, 1, 0, 5*TWO_PI);
var p = p5.Vector.fromAngle(n);
if(force.mag() < 0.01)
force.add(p.mult(noiseInfluence * 5));
else
force.add(p.mult(noiseInfluence));
// Add bound force
PVector boundForce = new PVector(0, 0);
if (pos.x < bound) {
boundForce.x = (bound-pos.x)/bound;
}
if (pos.x > width - bound) {
boundForce.x = (pos.x - width)/bound;
}
if (pos.y < bound) {
boundForce.y = (bound-pos.y)/bound;
}
if (pos.y > height - bound) {
boundForce.y = (pos.y - height)/bound;
}
force.add(boundForce.mult(boundForceFactor));
vel.add(force);
vel.mult(0.9999);
if (vel.mag() > maxSpeed) {
vel.mult(maxSpeed/vel.mag());
}
pos.add(vel);
if (pos.x > width || pos.x < 0 || pos.y > height || pos.y < 0) {
this.reset();
}
}
this.reset = function() {
img.updatePixels();
img.loadPixels();
count = 0;
//maxCount = 200;
var hasFound = false;
while (!hasFound) {
pos.x = random(1)*width;
pos.y = random(1)*height;
var c = fget(floor(pos.x), floor(pos.y));
var b = brightness(c);
if(b < 35)
hasFound = true;
}
drawColor = fget(floor(pos.x), floor(pos.y));
drawColor.setAlpha(drawAlpha);
ppos = pos.copy();
vel.mult(0);
}
this.show = function() {
count++;
if (count > maxCount)
this.reset();
stroke(drawColor);
strokeWeight(drawWeight);
if (force.mag() > 0.1 && random(1) < dropRate) {
drawColor.setAlpha(dropAlpha);
stroke(drawColor);
var boldWeight = drawWeight+random(5);
strokeWeight(boldWeight);
drawColor.setAlpha(drawAlpha);
}
line(ppos.x, ppos.y, pos.x, pos.y);
this.fadeLineFromImg(ppos.x, ppos.y, pos.x, pos.y);
}
/* Fade the pixels of the line */
this.fadeLineFromImg = function(x1, y1, x2, y2) {
var xOffset = floor(abs(x1 - x2));
var yOffset = floor(abs(y1 - y2));
var step = xOffset < yOffset ? yOffset : xOffset;
for (var i = 0 ; i < step ; i++) {
var x = floor(x1 + (x2 - x1) * i / step);
var y = floor(y1 + (y2 - y1) * i / step);
var originColor = fget(x, y);
var r = red(originColor);
var g = green(originColor);
var b = blue(originColor);
originColor.setRed(r+50 > 255 ? 255 : r+50);
originColor.setGreen(g+50 > 255 ? 255 : g+50);
originColor.setBlue(b+50 > 255 ? 255 : b+50);
fset(x, y, originColor);
}
}
}
The image I’m using can be found here:
Have a great day, I hope you are all doing well in these difficult times,
- Marinus