Data, Ecology, Art

Code Blog

Animated Logo

Malaga, Spain is a beautiful Mediterranean coast town that invested some of its income from tourism into education. That’s why the University of Malaga is thriving. The university hosts an annual Digital Art History Summer Seminar (DAHSS) which I am proud to participate in. For 2020, the theme is EPHEMERA, which requires an ephemeral logo, so I got busy designing an animated one.

ephemera_frame_1.gif

Of course, it’s made in processing with a simple graphic input, an image file. The code parses the image and creates a vector array list for all dark pixels. The array list becomes the basis for an animation, with nice ease functions by Roger Antonsen. Here is that code, and of course you can substitute the image for any other image.

PImage textpic; 
ArrayList<PVector> v = new ArrayList<PVector>();
float radiusRange = 3; 
int currFrame = 0;
int endFrame = 100; 
Boolean render = false; 
String filename = "ephemera"; 
int range = 25;

void setup() {
  
  size(1920, 540, P3D); 
  textpic = loadImage("ephemera.png");
  image(textpic, 0, 0, width/2, height/2);
  int imgXwidth=textpic.width;
  int imgYHeight=textpic.height;
  textpic.loadPixels();
  for (int i = 0; i < (imgXwidth*imgYHeight); i++) {
    int redvalue = int(red(textpic.pixels[i]));
    int greenvalue = int(green(textpic.pixels[i])); 
    int bluevalue = int(blue(textpic.pixels[i]));
    int sum = redvalue+greenvalue+bluevalue;
    //println(sum); 
    if (sum < 200) {
      for (int s = 0; s < 10; s++) {
        int x = width/6+int((i%imgXwidth)*5+random(0, range*1.26  )); 
        int y = height/4+int((i/imgXwidth)*5+random(0, range));
        int z = int (random(0, range));
        v.add(new PVector(x, y, z));
      }      
    }
  }
  println("v is "+v.size());
}
void draw() {
  clear(); 
  background(255); 
  float cycle = (currFrame%endFrame)/float(endFrame); 
  println(cycle); 
  radiusRange = easeback(cycle)*10.0;
  float breathing = easeback(cycle)*1.0+1.0; 
  for (int i = 0; i< v.size(); i++) {
    PVector here = v.get(i); 
    pushMatrix();
    //translate(here.x*breathing-width/5*breathing+width/10, here.y*breathing-height/6*breathing, here.z*breathing);
        translate(here.x, here.y, here.z*breathing);
    sphereDetail(6);
    noStroke();
    ambient(0);
    emissive(0);
    fill(0);
    float radius = random(0, radiusRange); 
    sphere(radius);
    popMatrix();
  }
  
  if (render == true && currFrame < endFrame) {
    saveFrame(filename+"_frame_"+currFrame+".png"); 
    currFrame++; 
    println ("saved " + filename+"_frame_"+currFrame+".png");
  }
}

void keyPressed() {

  if (key == 'a') {
    //render out the whole thing, the GO button
    currFrame = 0; 
    render = true;
  }
  
    if (key == 's') {
    //render out the whole thing, the GO button
    currFrame = 0; 
    render = false;

}
}

float easeback(float p) {
  p = constrain(p, 0, 1);
  if (p < 0.5) return ease(2 * p, 1.0);
  else return ease(2 - 2 * p, 1.0);
}

float ease(float p, float g) {
  p = constrain(p, 0, 1);
  if (p < 0.5) 
    return 0.5 * pow(2*p, g);
  else
    return 1 - 0.5 * pow(2*(1 - p), g);
}

Greg Niemeyer