Open golanlevin opened 4 years ago
Hi @golanlevin ,
That sounds really cool so I wanted to give it a quick try ;)
Turned out I can abuse my TSP solver to make dithers. I actually didn't know my particular implementation was good enough to do so until I tried.
For the color one, I simply split the image into 4 channels (CMYK) and run dither and TSP on each. Each "pixel" is divided into 4 (2x2) for each thread so the stitches don't stack at the exact same point.
The code is super simple:
import processing.embroider.*;
PEmbroiderGraphics E;
void dot(float x, float y){
E.beginRawStitches();
E.rawStitch(x,y);
E.rawStitch(x+1,y+1);
E.endRawStitches();
}
void dot(PVector p){
dot(p.x,p.y);
}
// Floyd Steinberg dither
ArrayList<PVector> dither(PImage im){
ArrayList<PVector> pts = new ArrayList<PVector>();
float[] tmp = new float[im.width*im.height];
im.loadPixels();
for (int i= 0; i < im.height; i++) {
for (int j= 0; j < im.width; j++) {
float o = (im.pixels[i*im.width+j]&255) + tmp[i*im.width+j];
int n = o > 128 ? 255 : 0;
float qe = o - n;
if(j<im.width -1){ tmp[ i *im.width+ j+1] += qe * 7.0/16.0; }
if(i<im.height-1){if(j!=0){tmp[(i+1)*im.width+ j-1] += qe * 3.0/16.0; }
tmp[(i+1)*im.width+ j ] += qe * 5.0/16.0;
if(j<im.width -1){ tmp[(i+1)*im.width+ j+1] += qe * 1.0/16.0; }}
if (n == 0){
pts.add(new PVector(j,i));
}
}
}
return pts;
}
void setup(){
size(1024,1024);
smooth();
E = new PEmbroiderGraphics(this);
E.setPath(sketchPath("tsp-painting.vp3"));
PImage im = loadImage("cameraman.bmp");
ArrayList<PVector> pts = dither(im);
for (int i = 0; i < pts.size(); i++){
dot(pts.get(i).copy().mult(4));
}
E.optimize();
E.visualize(true,true,true);
E.endDraw();
}
void draw(){
}
OMG I am slain @LingDong- . Well this is great, because I was taking too long to get around to this anyway. Please push an Example into the examples/
directory and I'll clean it up.
Thanks :)
I pushed the examples: eacbe76967c706dca980abe46f5ad82339afa77b
Saving this one for me, just wanted to put it up so I could cross it off.