Banner Image

The banner image in the header for this site was made with Processing, a Java-based “open-source programming language and environment for people who want to create images, animations, and interactions.”

It is conceptually very straightforward, very easy to use, and enormously satisfying since it is so simple and fast to try out many ideas. I intend to use it in computer science courses at Roosevelt HS in the near future.

Soon, I will set up a system to let people contribute their own banner art for this Roosevelt CS site, and we can feature lots of artists’ works here.

For this image, I wrote a Processing program to generate the image in the right size and shape and put the text on it. My friend Andrew Duncan, mathematician straordinario, wrote the algorithm to generate the moiré patterns. Here are some notes from him about that:

Moiré Pattern

The moiré pattern, an example of “visual aliasing,” forms when the progressively narrower bands become too fine for the computer screen’s resolution. The pixels “undersample” the rapid alternation of colors. Another example of this is when the radial spokes of a wheel seem, in a video, to rotate opposite the wheel’s spin. Similarly in digital audio, pitches higher than the system’s resolution can sound low if they are not filtered out before recording. A hand that waves back and forth will appear slower or even stationary when viewed with a strobe light.

(Image from Wikipedia.)

Many things we take for solid only seem this way because of our limited perceptions. A solid tabletop is composed of many particles moving at high speeds. Our thought processes come about from the frequency-modulated rapid firing of neurons. Reality itself is filled with highly energetic phenomena which we barely perceive or understand. Yet.

Drawing Algorithm

We mark the pixels with one of two colors based on just one criterion: whether a certain number comes out even or odd. That number is proportional to the distance-squared from a center point. So as you move further from that point the alternation of odd and even gets faster and faster. Without the exponent, you just get regular rings. You can put a brake on this with a denominator, which becomes a “knob,” (what we call a parameter) that you can turn and watch the effect.

Based on Andrew’s “knob” idea, I would like to add something to the program to let you twist the knob in real time and see the effect of varying the denominator on the resulting image.

Below is the code that generated the current banner image. If you would like to experiment with making your own banner image for this site, or just to experiment with Processing, you can download Processing from their website (it’s free and runs on Mac OS X, Windows, and Linux), here: http://processing.org/download/. Then you can download the code we wrote from here.

/* RHS banner generator
 *
 * Processing 1.2
 *
 * Andrew Davidson
 * Andrew Duncan
 *
 */

int winWidth     = 990;  // size of banner image
int winHeight    = 180;

int rightTab     = 900;  // coordinate for right-justified text
int line1Loc     = 100;  // position of first line of text
int line2Loc     = line1Loc + 30;  // position of second line of text

int magicNumber  = 1157;  // the magic number used in the denominator of the drawing algorithm

color winColor   = color (224, 229, 218);  // backgrouynd color of window
color dotColor   = color (240, 180,  60);  // foreground color of image
color textColor  = color ( 36,  83,   0);  // text color
color bordColor  = color (  0,   0,   0);  // border color

//  Unicode 201C = left curly quote
//  Unicode 201D = right curly quote
//  Unicode 2013 = N dash
//  Unicode 2014 = M dash

String line1     = "\u201CAny sufficiently advanced technology is indistinguishable from magic.\u201D";
String font1Name = "MyriadPro-Regular-24.vlw";  // made with Procesing/Tools/Create Font... 

String line2     = "\u2014 Arthur C. Clarke  ";  // needs the trailing spaces for alignment with line above
String font2Name = "MyriadPro-Regular-18.vlw";  // made with Procesing/Tools/Create Font... 

String fileName  = "magic.gif";  // image is saved in this file, format automatic from extension

boolean isOdd(int i) {
  return ((i % 2) == 1);
}

void drawBanner (int magicNum) {

  // Moire patterns

  stroke(dotColor);

  for (int x = 0; x < winWidth; x++) {
    for (int y = 0; y < winHeight; y++) {

      int hypotenuseSquared = x*x + y*y;
      if (isOdd(floor(hypotenuseSquared / magicNum))) {  // adjust the denominator for varying patterns
        point(x,y);
      }
    }
  }
}

void setup () {

  // draw window and fill it with background color

  size (winWidth, winHeight);
  background (winColor);

  // do the actual image drawing

  drawBanner(magicNumber);

  // write the text lines, right aligned

  // set text drawing parameters

  fill (textColor);
  textAlign (RIGHT);
  textMode (SCREEN);
  PFont font1 = loadFont (font1Name);
  PFont font2 = loadFont (font2Name);

  // and draw the actual text

  textFont (font1);
  text (line1, rightTab, line1Loc); 

  textFont (font2);
  text (line2, rightTab, line2Loc);

  // draw a border around the image

  stroke (bordColor);

  // top line needs to be thinner to match the banner template
  // otherwise could have used a simple rect() to draw the box

  strokeWeight (1);
  line (0, 0, winWidth-1, 0);

  // the other sides of the border are carefully plotted to get even thickness
  // the offsets were done painstakingly empirically, without careful study of the Processing coordinate space

  strokeWeight (4);
  line (winWidth-2, 0, winWidth-2, winHeight);
  line (winWidth, winHeight-1, 0, winHeight-1);
  line (1, winHeight, 1, 0);

  // save image in a file for uploading

  save (fileName);
}

void draw () {
  // not needed
}