• fullscreen
  • HScrollbar.pde
  • Store.pde
  • vor_screen_v15.pde
  • class HScrollbar {
      int swidth, sheight;    // width and height of bar
      float xpos, ypos;       // x and y position of bar
      float spos, newspos;    // x position of slider
      float sposMin, sposMax; // max and min values of slider
      int loose;              // how loose/heavy
      boolean over;           // is the mouse over the slider?
      boolean locked;
      float ratio;
    
      HScrollbar (float xp, float yp, int sw, int sh, int l) {
        swidth = sw;
        sheight = sh;
        int widthtoheight = sw - sh;
        ratio = (float)sw / (float)widthtoheight;
        xpos = xp;
        ypos = yp-sheight/2;
        spos = xpos + swidth/2 - sheight/2;
        newspos = spos;
        sposMin = xpos;
        sposMax = xpos + swidth - sheight;
        loose = l;
      }
    
      void update() {
        if (overEvent()) {
          over = true;
        } else {
          over = false;
        }
        if (mousePressed && over) {
          locked = true;
        }
        if (!mousePressed) {
          locked = false;
        }
        if (locked) {
          newspos = constrain(mouseX-sheight/2, sposMin, sposMax);
        }
        if (abs(newspos - spos) > 1) {
          spos = spos + (newspos-spos)/loose;
        }
      }
    
      float constrain(float val, float minv, float maxv) {
        return min(max(val, minv), maxv);
      }
    
      boolean overEvent() {
        if (mouseX > xpos && mouseX < xpos+swidth &&
           mouseY > ypos && mouseY < ypos+sheight) {
          return true;
        } else {
          return false;
        }
      }
    
      void display() {
        noStroke();
        fill(204);
        rect(xpos, ypos, swidth, sheight);
        if (over || locked) {
          fill(0, 0, 0);
        } else {
          fill(120);
        }
        rect(spos, ypos, sheight, sheight);
      }
    
      float getPos() {
        // Convert spos to be values between
        // 0 and the total width of the scrollbar
        return spos * ratio;
      }
    }
    
    
    class Store {
    
      int x=10;
      int y=10;
      int brightness=55;
    
    
      Store() {
        println("constructed a store");
      } 
    
      Store(int x, int y, int brightness) {
        this.x=x;
        this.y=y;
        this.brightness=brightness;
      } 
    
    int get_x() {
     return x; 
    }
    
    int get_y() {
     return y; 
    }
    
    int getBrightness() {
     return brightness; 
    }
    
    }
    
    
    // import libraries
    import toxi.geom.*;
    import toxi.geom.mesh2d.*;
    import toxi.util.*;
    import toxi.util.datatypes.*;
    import toxi.processing.*;
    
    // voronoi triangles
    float DSIZE = 10000; // radius of the root triangle which encompasses (MUST) all other points
    Voronoi voronoi;
    Voronoi voronoi_copy;
    ToxiclibsSupport gfx;
    FloatRange xpos, ypos; // ranges for x/y positions of random points
    
    // switches
    boolean loadSave = true;
    boolean doSave;
    boolean doIgnoreRoot=true;
    boolean clean = true;
    int show = 1;
    
    // images
    PImage myImage;  
    PImage compImage;
    PImage pixImage;
    PImage binaryImage;
    PImage whiteImage;
    PImage maskImg;
    PImage maskHalfImg;
    PImage topLeft;
    PImage bottomLeft;
    
    PFont font;
    
    // arraylists
    ArrayList<Store> brightArrayList = new ArrayList<Store>();
    ArrayList<Vec2D> vectorArrayList = new ArrayList<Vec2D>();
    ArrayList<Vec2D> vectorArrayListCopy = new ArrayList<Vec2D>();
    
    // scrollbar
    HScrollbar hs1;
    int mapped;
    
    int w = 841;
    int h = 595;
    
    void setup() {
      size(841, 595);
    
      // load your own image here (make sure it's 841x595)
      myImage = loadImage("john1.jpg");
      myImage.filter(GRAY);
      topLeft = myImage.get(0, 0, w/4, h/2);
      font = loadFont("Courier-32.vlw");
    
      background(255);
      smooth();
      noStroke();
      colorMode(HSB, 255);
      rectMode(CORNER);
    
      // draw images to save
      saveFrame("data/white.jpg");
      // draw binary image
      loadPixels(); 
      fill(0);
      float pxSize = (width/4)/1.1; ///change pxSize parameter to position digits horizontally
      int pxH = 12;
      for (int x=0; x<myImage.width; x+=pxSize) {
        for (int y=0; y<myImage.height; y+=pxH) {
          int loc = x + y*myImage.width;
          color pc = myImage.pixels[loc];
          textFont(font, 12);
          text(binary(pc), x, y+pxH);
        }
      }
      fill(255); 
      noStroke();
      rect(w/2, 0, w/2, h);
      saveFrame("data/binary.jpg"); // save binary image
    
        image(myImage, 0, 0);
      saveFrame("data/original.jpg"); // save original image
    
        textFont(font, 10);
      // pixelateImage function creates a pixelated image
      pixelateImage(25);
      fill(255); 
      noStroke();
      rect(w/2, 0, w/2, h);
      saveFrame("data/pixelated.jpg"); // save pixelated image
    
        // create a composite image
      fill(255);
      noStroke();
      image(topLeft, 0, 0, w/4, (h/2));
      rect(w/2, 0, w/2, h);
      rect(w/4, h/2, w/4, h/2);
      rect(0, h/2, w/2, h/2);
      binaryImage = loadImage("binary.jpg"); 
      bottomLeft = binaryImage.get(0, h/2, w/4, h/2);
      image(bottomLeft, 0, h/2, w/4, (h/2));
      saveFrame("data/composite.jpg"); // save composite image
    
        // scrollbar
      hs1 = new HScrollbar(width/2, 15, width/2, 30, 1);
    
      noStroke();       
    
      //// voronoi triangle ////
      // focus x positions around horizontal center (w/ 33% standard deviation)
      xpos=new BiasedFloatRange(width/2, width, width/2+width/4, 0.333f);
      // focus y positions around bottom (w/ 50% standard deviation)
      ypos=new BiasedFloatRange(0, height, height, 0.5f);
      voronoi = new Voronoi(DSIZE);
      voronoi_copy = new Voronoi(DSIZE);
      gfx = new ToxiclibsSupport(this);
    }
    
    void threshSelect() {
      image(myImage, 0, 0);
      loadPixels();
    
      // clear arraylists
      brightArrayList.clear();
      vectorArrayList.clear();
      vectorArrayListCopy.clear();
    
      // go though all the pixels in myImage
      for (int x=0; x<myImage.width; x++) {
        for (int y=0; y<myImage.height; y++) {
          int loc = x + y*width;
          int bright = int(brightness(pixels[loc]));
          // select the pixels whose intensity values are in the range of 1 below and 1 above current scrollbar value
          if (bright > mapped-1 && bright < mapped+1) {
            pixels[loc] = color(bright);
            // take the first 100 values and create an ArrayList with Store objects
            if (brightArrayList.size() < 100) {
              brightArrayList.add(new Store(x, y, bright));
            }
          }
        }
      }
      // use the contents of the brightArrayList to create arrays of Vec2D objects (with x,y coordinate information)
      for (int i = 0; i < brightArrayList.size(); i ++) {
        Store store = brightArrayList.get(i);
        vectorArrayList.add(new Vec2D(store.get_x(), store.get_y()));
        vectorArrayListCopy.add(new Vec2D(store.get_x()+width/2, store.get_y()));
      }
      updatePixels();
    }
    
    
    /////////////////////////////
    
    void draw() {
    
      textSize(9);
    
      // load images once
      if (loadSave) {
        compImage = loadImage("composite.jpg");
        maskImg = loadImage("mask_invert.jpg");
        compImage.mask(maskImg);
        maskHalfImg = loadImage("mask_half.jpg");
        pixImage = loadImage("pixelated.jpg");
        whiteImage = loadImage("white.jpg");
        pixImage.mask(maskHalfImg);
        binaryImage.mask(maskHalfImg);
        whiteImage.mask(maskHalfImg);
        loadSave = false;
      }
    
      // if key 4 is pressed
      if (show == 4) {
        image(whiteImage, 0, 0);
      }  
    
      // if key c is pressed
      if (clean == true) {
        image(myImage, w/2+1, 0);
      } 
      else {
        noStroke();
        fill(255);
        rect(w/2, 0, w/2, h);
      }
    
      // draw lines 
      noFill();
      beginShape(TRIANGLES);
      stroke(240);
      // get the delaunay triangles
      for (Triangle2D t : voronoi.getTriangles()) {
        // ignore any triangles which share a vertex with the initial root triangle
        if (!doIgnoreRoot || (abs(t.a.x)!=DSIZE && abs(t.a.y)!=DSIZE)) {
          gfx.triangle(t, false);
        }
      }
    
      stroke(0);
      for (Triangle2D t : voronoi_copy.getTriangles()) {
        // ignore any triangles which share a vertex with the initial root triangle
        if (!doIgnoreRoot || (abs(t.a.x)!=DSIZE && abs(t.a.y)!=DSIZE)) {
          gfx.triangle(t, false);
        }
      }
      endShape();
    
      // draw points between lines
      fill(5);
      for (Vec2D c : voronoi.getSites()) {
        ellipse(c.x, c.y, 2, 2);
      }
    
      ////////////////////////
      // draw digits
      for (int i = 0; i < brightArrayList.size(); i ++) {
        Store store = brightArrayList.get(i);
        int x = store.get_x();
        int y = store.get_y();
    
        String sp = str(' ');
        String sa = str(x);
        String sb = str(',');
        String sc = str(y);
        //println(sp+sa+sb+sc);
        fill(40);
        text(sp+sa+sb+sc, x, y);
      }
    
      // if key 1 is pressed
      if (show == 1) {
        image(compImage, 0, 0);
      } 
      // if key 2 is pressed
      else if (show == 2) {
        image(pixImage, 0, 0);
      } 
      // if key 3 is pressed
      else if (show == 3) {
        image(binaryImage, 0, 0);
      } 
    
      /////////////////////////////////
    
      // labels
    
      noStroke();
    
    if (show == 1){
      // <scanned drawing>
      fill(80);
      rect(width/140, height/100, width/9, height/50);
      fill(255);
      text("<scanned drawing>", width/140+(width/175), height/100+(height/70));
      
      // <pixel intensity (bitmap)>
      fill(80);
      rect((width/2)-(width/5.85), height/100, width/6.05, height/50);
      fill(255);
      text("<pixel intensity (bitmap)>", (width/2)-(width/5.8)+(width/140), height/100+(height/70));
      
      // <binary code>
      fill(80);
      rect(width/140, height-((height/100)+(height/50)), width/11.5, height/50);
      fill(255);
      text("<binary code>", width/140+(width/175), height-((height/100)+(height/180)));
      
      // <x,y coordinates (vector)>
      fill(80);
      rect((width/2)-(width/5.85), height-((height/100)+(height/50)), width/6.05, height/50);
      fill(255);
      text("<x,y coordinates (vector)>", (width/2)-(width/5.8)+(width/140), height-((height/100)+(height/180)));
      
    } else if (show == 2){
      // <pixel intensity (bitmap)>
      fill(80);
      rect((width/2)-(width/5.85), height/100, width/6.05, height/50);
      fill(255);
      text("<pixel intensity (bitmap)>", (width/2)-(width/5.8)+(width/140), height/100+(height/70));
      
    } else if (show == 3){
        // <binary code>
      fill(80);
      rect(width/140, height-((height/100)+(height/50)), width/11.5, height/50);
      fill(255);
      text("<binary code>", width/140+(width/175), height-((height/100)+(height/180)));
      
    } else if (show == 4){
     
      // <x,y coordinates (vector)>
      fill(80);
      rect((width/2)-(width/5.85), height-((height/100)+(height/50)), width/6.05, height/50);
      fill(255);
      text("<x,y coordinates (vector)>", (width/2)-(width/5.8)+(width/140), height-((height/100)+(height/180))); 
    }
    
    // <drawing by numbers and me>
      fill(80);
      rect(width-((width/140)+(width/5.9)), height-((height/100)+(height/50)), width/5.9, height/50);
      fill(255);
      text("<drawing by numbers and me>", width-((width/140)+(width/6.05)), height-((height/100)+(height/180)));
    
      //////////////////////////
    
      // draw scrollbar
      // Get the position of the scrollbar
      // and convert to a value to display it
      float hs1_val = hs1.getPos()-(w/2);
      mapped = int(map(hs1_val, 43, 638, 0, 256));
    
      hs1.update();
      hs1.display();
    
      // scroll number display
      fill(40);
      textSize(30);
      text(mapped, w/2+2, height/24);
    
    
      /////////////////////
    
      // save image
      if (doSave) {
        saveFrame("data/drawing_by_numbers-" + DateUtils.timeStamp() + ".jpg");
        doSave = false;
      }
      doIgnoreRoot=true;
    }
    
    // function to pixelate image
    void pixelateImage(int pxSize) {
    
      strokeWeight(0.6);
      stroke(0);
      for (int x=0; x<myImage.width; x+=pxSize) {
        for (int y=0; y<myImage.height; y+=pxSize) {
          // take the colour value for each pixel in the image
          color c = myImage.get(x, y);
          // take the greyscale value to fill the squares
          int tots = (int(red(c))+int(green(c))+int(blue(c)))/3;
          fill(tots);
          rect(x, y, pxSize, pxSize);
          // fill the text with the opposite values
          fill(abs(255-tots));
          text(tots, (x+(pxSize/6)), y+(pxSize/1.25));
        }
      }
    }
    
    void keyPressed() {
      switch(key) {
      case ' ':
        // save image
        doSave = true;
        break;
      case 's':
        // toggle image
        clean=!clean;
        break;
      case 'c':
        // refresh
        voronoi_copy = new Voronoi(DSIZE);
        break;
      case 'r':
        // randomise number of points
        for (int i = 0; i < 10; i++) {
          voronoi_copy.addPoint(new Vec2D(xpos.pickRandom(), ypos.pickRandom()));
        }
        break;
      case 't':
        // clear, take threshold & draw
        voronoi = new Voronoi(DSIZE);
        voronoi_copy = new Voronoi(DSIZE);
        threshSelect();
        for (int i = 0; i <= vectorArrayList.size()-1; i ++) {
          voronoi.addPoint(new Vec2D(vectorArrayList.get(i)));
          voronoi_copy.addPoint(new Vec2D(vectorArrayListCopy.get(i)));
        }
        break;
      case '1':
        // show composite image
        show = 1;
        break;
      case '2':
        // show pixelated image
        show = 2;
        break;
      case '3':
        // show binary image
        show = 3;
        break;
      case '4':
        // show clear image
        show = 4;
        break;
      }
    }
    
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement

    <drawing by numbers>

    <drawing_by_numbers>

    Add to Faves Me Likey@!
    You must login/register to add this sketch to your favorites.

    Created for the Drawing by Numbers workshop at the Media Space in the Science Museum, London

    - ACTIVE KEYS -
    -left side-
    1 – display composite image
    2 – display pixelated image
    3 – display binary image
    4 – display x, y coordinates image
    -right side-
    s - show or hide scanned image
    t – update and draw thresholded points
    r - draw random points
    c – clear image

    - NOTES -
    Tested with Safari, Firefox v22-25, Internet Explorer v10
    Not compatible with Chrome.

    - ACKNOWLEDGEMENTS -
    This software makes use of the Toxiclibs library for Processing

    - MORE -
    http://bit.ly/drawing-by-numbers

    You need to login/register to comment.