DigitalArtisanalPortraitMaker.pde

//Greyscale Pattern maker with a class of stitches
//by Brianne Benness for DigitalArtisanal.com

//to toggle display modes in the sketch, use x, b & y
//to export pattern to pdf, use r

import processing.pdf.*;

Stitch[] stitches = new Stitch[500*500];//this is where all the stitches are stored, the size is overkill for this version
int w=10;// this is the pixel width of each stitch
int h=w;// default square stitches
int e=15;//width of exported stitches
PImage myPic;
int l=70;// side length in pixels of the source image
int c=0; //color options
int p = 9; //number of colors in our palette, overkill in this version of the program
color[] palette=new color[p];
char symb[] = {'✖', '❄', '❤', '✦', '✖', '✫', '✿', ' ', 'i'}; //character array for symbol output, needs to be at least as long a the palette
int mode = 1; //stitch fill mode

PFont symbs;

void setup() {
  size(1050,1050); 
  background(240);

  myPic = loadImage("MyPic.jpg");
  
  symbs = createFont("ZapfDingbatsITC", 10);
  textFont(symbs);
  textAlign(CENTER,CENTER);

  palette[0]=color(0); //black DMC 310 NOT USING
  palette[1]=color(255); //white DMC B5200 NOT USING
  palette[2]=color(200,200,200); // lightest Color - customize palette here if you want
  palette[3]=color(150,150,150); // middle color - costomize palette here if you want
  palette[4]=color(100,100,100); // darker color - customize palette here if you want
  palette[5]=color(50,50,50); // darkest color - customize palette here if you want
  palette[6]=color(87,36,51); // not using
  palette[7]=color(255); // white fabric

  stroke(240); //grey lines
  textSize(10);
  
  for (int y=0; y < l; y++) { //fill stitch array & draw initial stitches
    for (int x=0; x < l; x++) { color b=myPic.pixels[x+y*myPic.width]; if (red(b)-green(b)>100) { //is it background? 
        c=7;  
        
       // this is how each pixel is converted to a thread color.
       // to adjust the color distribution, try bumping the threshold numbers up and down in increments of 5.
       
      } else if (red(b)<90){ //is it darkest?
        c=5;
      } else if (red(b)<135){//is it darker?
        c=4;
      } else if (red(b)<150) { //is it medium?
        c=3;
      } else if (red(b)<256){//is it lightest?
        c=2;
      } else { //lost pixels
        c=7;
      }
      stitches[x+y*l*w] = new Stitch(c); //populate the class with fill color
      stitches[x+y*l*w].adjust(x*w, y*h, w, h, mode); //draw the class as boxes
    }
  }
}

void draw() {
}

void keyPressed() {

  //stitch type options

  if (key=='x') {//cross stitch display
    mode=2;
  }

  if (key=='y') {//half stitch display
    mode=3;
  }

  if (key=='b') {//box display
    mode=1;
  }
  
  if (key=='r'){//export pdfs
    
    beginRecord(PDF, "BWPattern.pdf"); //export b&w pattern
textFont(symbs); for (int y=0; y < l; y++) { //fill stitch array and draw initial grid for (int x=0; x < l; x++) { stitches[x+y*(w*l)].adjust(x*e, y*e, e, e, 5); //draw the class as b&w symbols } } stroke(0); for (int z=0; z < (l+1); z++) {//draw grid above stitches if(z%10==0) { strokeWeight(2); }else{ strokeWeight(1); } line(z*e, 0, z*e, l*e); line(0, z*e, l*e, z*e); } endRecord(); beginRecord(PDF, "Stitches.pdf"); //export rendered stitches for (int y=0; y < l; y++) { //fill stitch array and draw initial grid for (int x=0; x < l; x++) { stitches[x+y*(w*l)].adjust(x*e, y*e, e, e, 3); //draw the class as b&w symbols } } endRecord(); strokeWeight(1); } background(255); for (int y=0; y < l; y++) { //fill stitch array and draw initial grid for (int x=0; x < l; x++) { stitches[x+y*(w*l)].adjust(x*w, y*h, w, h, mode); //draw the class as boxes } } } class Stitch { //this is a class to manage all the details of an individual stitch int x, y, w, h, mode; //width and height of the individual stitch, plus display mode int f; //fill color Stitch (int f_) { //each stitch will save it's fill color index for now f=f_; } void adjust(int x_, int y_, int w_, int h_, int mode_) {//toggle stitch appearance x=x_; y=y_; w=w_; h=h_; mode=mode_; if (mode==1) { //box stitch //noStroke(); stroke(255); fill(palette[f]); rect(x, y, w, h); } else if (mode==2) { //cross stitch display stroke(240); fill(255); rect(x, y, w, h); stroke(palette[f]); strokeWeight(2); line(x, y, x+w, y+h); line(x, y+h, x+w, y); strokeWeight(1); } else if (mode==3) { //cross stitch export stroke(240); fill(255); rect(x, y, w, h); stroke(palette[f]); strokeWeight(6); line(x, y, x+w, y+h); line(x, y+h, x+w, y); strokeWeight(1); } else if (mode==4) { //export stitch or symbol noStroke(); fill(palette[f]); text(symb[f],x+w/4,y+h*.75); //these ratios look wacky in processing but line up in pdf } else if (mode==5) { //just black symbols noStroke(); fill(0); text(symb[f],x+w/4,y+h*.75); //these ratios look wacky in processing but line up in pdf } } }