CreativeInquiry / PEmbroider

Embroidery Library for Processing
Other
442 stars 28 forks source link

Demo example that renders a color photo portrait with Red/Yellow/Blue thread #47

Open golanlevin opened 4 years ago

golanlevin commented 4 years ago

Saving this one for me, just wanted to put it up so I could cross it off.

LingDong- commented 4 years ago
Screen Shot 2020-06-25 at 8 28 01 PM Screen Shot 2020-06-25 at 8 26 42 PM Screen Shot 2020-06-25 at 8 43 02 PM

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(){
}
Screen Shot 2020-06-25 at 8 44 10 PM
golanlevin commented 4 years ago

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.

LingDong- commented 4 years ago

Thanks :)

I pushed the examples: eacbe76967c706dca980abe46f5ad82339afa77b