Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
golanlevin opened this issue Jun 22, 2020 · 3 comments
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@golanlevin
Copy link
Member

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

@golanlevin golanlevin self-assigned this Jun 22, 2020
@golanlevin golanlevin added the documentation Improvements or additions to documentation label Jun 22, 2020
@LingDong-
Copy link
Collaborator

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
Copy link
Member Author

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-
Copy link
Collaborator

LingDong- commented Jun 26, 2020

Thanks :)

I pushed the examples: eacbe76

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants