Algorithmic Ballyhoo: Using Processing to Make Hundreds of Unique Posters

MFBlogPost

This post describes a process I like to call algorithmic ballyhoo; using a Processing program to generate many different unique poster designs. We needed a poster for the Rhode Island Mini Maker Faire this year, so I decided to use a Processing sketch to do the work for me. Modern Device will be at the Mini Maker Faire, and will have a new Bytebeat-based kit for the soldering workshop.

poster-final-600p

Algorithmic ballyhoo is nothing but sheer randomness without some sort of seed or design constraint. The Mini Maker Faire is embedded in AS220’s Foo Fest, and Xander Marro is this year’s Foo Fest artist-in-residence. Xander designed the Foo Fest posters (pictured to the right) and I decided to use the same elements in the Mini Maker Faire poster.

Read on for the Processing code. It’s pretty straightforward; the key is to use the processing.pdf library to record a printable version of everything you’re drawing on the screen. Then, just bring it to your local copy shop (or fine art large format printer). Remember that your drawing grid is at 72dpi. In the final PDF all graphics will be drawn as scalable vector art, but any included bitmap images will be drawn at screen resolution, so make sure any included PNGs are at least 4 or 5 times the final size, then shrunk down.


[ngg-nivoslider gallery=”1″ html_id=”about-slider” center=”1″ effect=”slideInLeft” resizewidth=”388″ resizeheight=”600″ width=”388″ controlnav=”true” pauseonhover=”true”]

The great thing about Processing is that it is relatively easy to get started drawing things on the screen, which facilitates a quick iterative sketching process. This sketch started from another similar sketch (below left) that generated a colorful mountainous landscape.

MFPosterBlog1

By building on code that was already in my Sketchbook, I had a workable idea (middle, above) in a few minutes. Then it was just a matter of adding more detail, like the round Bezier bulbs. It would be worth taking one more pass and replacing some of the code for repeated and rotated curves with something using the transform() function, which would make it more flexible to reuse.

Here’s the code, which you can also grab as a zip file which has the extra image and font files needed by the sketch:

import processing.pdf.*;

int w = 72*11;
int h = 72*17;
int r;
int x=0;
int y=100;
boolean logoInserted = false;
boolean logoJustInserted = false;
PImage banner;
PImage blurb;
PImage logo;
PFont benton24;
PFont benton10;

void setup() {
  banner = loadImage("MFbanner.png");
  blurb = loadImage("MFblurb.png");
  logo = loadImage("makeLogo.png");
  size(w, h);
  smooth();
  noLoop();
  noStroke();
  benton24 = createFont("BentonSans-Bold", 24);
  benton10 = createFont("BentonSans-Bold", 10);
} 

void drawStructure(float x1, float y1, float dx, float dy) {
  int grey = (int)random((h-y)/5);
  float a = 255;
  fill(grey, grey, grey, a);
  stroke(grey, grey, grey, a);
  strokeWeight(1);

  // Outline
  beginShape();
  vertex(x1, h);
  vertex(x1, y1);
  bezierVertex(x1+dx, y1, x1, y1-dy, x1+dx, y1-dy);
  bezierVertex(x1+dx, y1-2*dy, x1+2*dx, y1-dy, x1+2*dx, y1-2*dy);
  bezierVertex(x1+2*dx, y1-dy, x1+3*dx, y1-2*dy, x1+3*dx, y1-dy);
  bezierVertex(x1+4*dx, y1-dy, x1+3*dx, y1, x1+4*dx, y1);
  vertex(x1+4*dx, h);
  endShape();
  
  //Line
  float bulbY = y1-2*dy-random(100)-20;
  float radius = random(2*dx)+dx; 
  strokeWeight(random(4)+1);
  line(x1+2*dx, bulbY-radius/2-5-radius/4-5-radius/8-5, x1+2*dx, y1);
  
  //Bulb
  strokeWeight(1);
  drawBulb(x1+2*dx, bulbY,radius); 
  
  //Circles down
  fill(255, 255, 255, 50);
  noStroke();
  for (int i=(int)y1; i<h; i+=dy) {
    float r3 = random(8)+1;
    ellipse(x1+2*dx, i, dy/r3, dy/r3);
  }
}

void drawBulb(float x1, float y1, float r) {
  float dx = r/4;
  float dy = r/4;

  //The big bulb  
  translate(-2*(int)dx-2, 0);
  beginShape();
  vertex(x1, y1);
  bezierVertex(x1+dx, y1, x1, y1-dy, x1+dx, y1-dy);
  bezierVertex(x1+dx, y1-2*dy, x1+2*dx, y1-dy, x1+2*dx, y1-2*dy);
  bezierVertex(x1+2*dx, y1-dy, x1+3*dx, y1-2*dy, x1+3*dx, y1-dy);
  bezierVertex(x1+4*dx, y1-dy, x1+3*dx, y1, x1+4*dx, y1);
  bezierVertex(x1+3*dx, y1, x1+4*dx, y1+dy, x1+3*dx, y1+dy);
  bezierVertex(x1+3*dx, y1+2*dy, x1+2*dx, y1+dy, x1+2*dx, y1+2*dy);
  bezierVertex(x1+2*dx, y1+dy, x1+dx, y1+2*dy, x1+dx, y1+dy);
  bezierVertex(x1, y1+dy, x1+dx, y1, x1, y1);
  endShape();
  resetMatrix();
  
  //Circles up and down
  ellipse(x1, y1-r/2-5, r/4, r/4);
  ellipse(x1, y1-r/2-5-r/4-5, r/8, r/8);
  ellipse(x1, y1-r/2-5-r/4-5-r/8-5, r/16, r/16);
  ellipse(x1, y1+r/2+5, r/4, r/4);
  ellipse(x1, y1+r/2+5+r/4+5, r/8, r/8);
  ellipse(x1, y1+r/2+5+r/4+5+r/8+5, r/16, r/16);
  float dh=random(r)+10;
  float dw=random(r)+10;
  beginShape();
  fill(255, 255, 255, 30);
  noStroke();
  vertex(x1, y1);
  vertex(x1+random(w), y1-random(h));
  vertex(x1+random(w), y1+random(h));
  vertex(x1, y1);
  endShape();
}

void draw() {
  for (int version=1; version<100; version++) {
    beginRecord(PDF, "MakerFairePoster2013v"+version+".pdf");
    x = 0;
    y = 100;
    logoInserted=false;
    logoJustInserted = false;
    while (y<(h-50)) {
      while (x < w) {
        float r1 = (int)random(30)+20;
        float r2 = (int)random(30)+20;
        drawStructure(x, y+random(200)-100, r1, r2);
        x += 4*r1+random(50);
      }
      if ((y>150) && !logoInserted) {
          stroke(0, 0, 255);
          fill(255,255,255);
          strokeWeight(10);
          image(banner, 100, y, 592, 182);
          logoInserted=true;
          logoJustInserted = true;
      }
      if (logoJustInserted) {
        y+=random(150)+200;
        logoJustInserted = false;
      } else {
        y+=random(150)+50;
      }
      x = 0;
      println(".");
    }
    image(blurb, 100, h-280, 592, 260);
   // image(logo, 20, h-20, 120, 58);
   fill(255, 0, 0);
   textFont(benton24);
   text("Make:", 15, h-35);
   fill(0, 167, 238);
   textFont(benton10);
   text("makezine.com", 15, h-25);
   endRecord();
  }
}
By Shawn Wallace on July 23, 2013.