Project 5: Text Design, Op Art and Word Image Tool

Op Art is one of the works of past art work from 1870 – 1970, and I believe if these artists from the past had programming skills they would most likely create some kind of a tool that would computationally generate these arts for them. With this motivation, I created a tool in Processing that has three features: 1. Text Design, 2. Op Art and 3. Word Image. The Text Design feature provides user the ability to design a short phrase (e.g., company's name, signature on an art etc.,) by allowing user to select fonts installed in a user's computer, choose size of the font and the color. The Text Design feature is made interactive where user can design a text with several combinations of fonts, sizes and colors. The Op Art provides user with several Op Art images based on user pressed keys. The Word Image takes the user-created final design of the text as an input and draws a word image from a text file saved in the data folder of the Processing sketch folder. The content of the text file can be changed based on user needs.

Below is snippet of code that explains the key concept behind the Text Design Tool:


String[] fontList = Pfont.list();

void displayText(){
font = createFont(fontList[fontIndex], fontSize);
textFont(font); //makes it the current font
textSize(fontSize);
textAlign(CENTER, CENTER);
background(255);
fill(pigmentRed,pigmentGreen,pigmentBlue);
text(myText, textPosX, textPosY);
}

The list method of the Pfont class in Processing is used to create an array of fonts of type String and is stored in a global variable called fontList. A function named displayText() is called that uses the global variables like fontIndex, fontSize, pigmentRed, pigmentGreen and pigmentBlue. The user-defined text which is also defined in the program as a global variable can be designed interactively by changing these global variables in the function displayText().

Below is a snippet of code the explains the Op Art image displayed at the top of the page (collapsing grid of rectangles):


void drawOpArt(){
float rectWidth = 90;
int rectHeight = 30;
int rectWidthAdjust = 0;
float x = 0;
Integer[] colorBits = new Integer[30];

...

for (int i = 0; i < yCount; i++){ //row yCount = 10; for (int j = 0; j < xCount; j++){ //col xCount = 30 //noFill(); if (colorBits[j] == 0) { fill(0); }else{ fill(255); } if (j < xCount/2){ rectWidth = map(j, 0 , 14 , 70, 0); }else{ rectWidth = map (j, 15, 30, 0, 70); } rect(x, i * rectHeight, rectWidth, rectHeight); x = x + rectWidth; } //reset x x = 0; ... } }

As always in a grid based problem, we implement a doubly nested for loop to draw a grid of rectangles. But a few things that need to be considered here is the two map functions used. The first function maps the lower half of the incoming variable j to a target range of rectangle widths that ranges from a higher value to a lower value. The second function maps the upper half of the incoming variable j to a target range of rectangle widths that ranges from a lower to a higher value. The position of x – axis at which the adjusted rectangle is to be drawn is tracked by the variable x which is incremented by the new rectangle width calculated from the above map functions. The color of each rectangle is determined by an array of bits called colorBits which is initialized with alternating 1 and 0 representing white and black respectively. The bits in the array are flipped when all rectangles in a particular row are drawn.

Below is a snippet of code that explains the Word Image feature of the tool:


void drawWordImage(){
int counter = 0;
int myTextSize = 10;

for (int j = 0; j < height; j++){ for (int i = 0; i < width; i++){ color c = im1.get(i,j); //check if this color is from myText boolean fromMyText = ((red(c) == pigmentRed) && (green(c) == pigmentGreen) && (blue(c) == pigmentBlue)); if (fromMyText) { textSize(myTextSize + 3); strokeWeight(2); fill(c); text(joinedText.charAt(counter), i, j); }else{ textSize(myTextSize); fill(100, 70); text(joinedText.charAt(counter), i, j); } //increment i based on the above width of the character i = i + (int) textWidth(joinedText.charAt(counter)); counter++; if (counter > joinedText.length()-1) {
counter = 0 ;
}
}
//increment j based on the size of the text determined by the above statement - textSize()
j = j + myTextSize;
}
}

Here, we compare every pixel of the Processing window with the color of the text designed by a user. If it matches, we draw the character contained in the String joinedText (which is a whole text file in a single string) of a slightly bigger size and stroke weight. A key point to note in the above code is the resetting of the counter to zero after completion of a row. If the length of joinedText is not larger than (width * height) of the window then the statement joinedText.charAt(counter) will go out of bound. To prevent this, we reset the counter to 0 and the joinedText will start repeating until the code is out of the loop.

Below is a set of few images generated from this tool:

The top two images show examples of Op Art images computationally generated using this tool. The top left image shows a Word Image and the top right image shows a sample user-generated text design.

The source code of this project can be downloaded from here:
.zip file(242KB)

Project 4: Oscillation and Random Walk with Perlin Noise

Project 4 of the 2D Generative Design is about generating two images computationally – one using perlin noise and the other using oscillation.

Below is a snippet of code that explains the key concept behind generating the above image on the left using perlin noise:


void perlinMove(PVector inLocation, float inSize, int inRed){
float angle = noise (inLocation.x / noiseScale, inLocation.y / noiseScale) * TWO_PI * noiseStength;
fill(c, 0,0);
ellipse(inLocation.x,inLocation.y, size,size);

The above perlinMove function takes four arguments that determines the location, the size and the amount of red to fill in the circle randomly drawn by the function. Notice how the size and the color of the circles gradually increase until they reach their maximum limit.

Below is a snippet of code that explains the key concept behind generating the above image on the right using oscillation:


void oscillate(){
float cycleCount = (float)frameCount/oscPointCount;
float t = cycleCount % 1;
oscAngle = map(t, 0, 1, 0, TWO_PI);
line(t*oscPointCount, oscPointY, t*oscPointCount, height/2);
}

The oscillate function counts the number of the current frames of the window and divides it by the number of oscillation points used to get a value between 0 and 1. This makes the oscillation dynamic. The sine and cosine function determine the x and y coordinates of the line that is drawn by the function.

Below is a set of few images that show some aspect of how the code was used to generate them:

The top left image shows the trails of random walks generated by the program after running for about a minute. The top right image shows a complete cycle of oscillation. The image on the bottom shows a half cycle highlighting the trailing sequence of blue lines above it.

The source code of this project can be downloaded from here:
.zip file(2KB)