Project 10: Sonic Story

One Night on the Farm
One night on the farm, the farmer left the animals out. The crickets were chirping and the chickens were clucking. A whirring hum was heard and an alien space ship appeared. The alien first abducted the sheep who let out a surprised “baa” as he rose into the air and shrunk. The pig was next. He let out a startled “oink” as he was lifted away from his mud. Then it was the cows turn. He let out a shocked “moo” before being whisked away. The space ship left with its new specimens, and the crickets chirped and the chickens clucked some more.

The farm images are licensed from Adobe stock images. The sounds used are from freesound.org and edited with Audacity. The sounds are used under the Creative Commons license. The owners did not want attribution. The sounds are: crickets.wav – crickets chirping, cluckcluck.wav – chickens clucking, spaceShip.wav – space ship sounds, moo.wav – a cow, baa.wav – a sheep, oink.wav – a pig.

sketch
/* Evan Stuhlfire
 * estuhlfi@andrew.cmu.edu Section B
 * Project-10:  Sonic Story - One Night on the Farm 
Assignment-10:  Sonic Story 
One Night on the Farm 
One night on the farm, the farmer left the animals 
out. The crickets were chirping and the chickens were
clucking. A whiring hum was heard and an alien space ship appeared.
The alien first abducted the sheep who let out a surprised "baa" as he
rose into the air and shrunk. The pig was next. He let out a startled
"oink" as he was lifted away from his mud. Then it was the cows turn. 
He let out a shocked "moo" before being whisked away. The 
space ship left with its new specimens, and the crickets chirped
and the chickens clucked some more.

The farm images are liscensed from Adobe stock images. The sounds used are from freesound.org and edited with Audacity.
The sounds are used under the Creative Commons liscense. The owners did not 
want attribution. The sounds are:
crickets.wav - crickets chirping, cluckcluck.wav - chickens clucking,
spaceShip.wav - space ship sounds, moo.wav - a cow, baa.wav - a sheep,
oink.wav - a pig.
 */

var farmImg = [];   // an array to store the images
var farmObjArray = []; // array to store images

// sound variables
var crickets;
var cluck;
var baa;
var moo;
var oink;
var spaceShip;

// starting sky and foreground colors
var rNight = 50;
var gNight = 100;
var bNight = 150;
var rFore = 50;
var gFore = 160;
var bFore = 80;
var moon = 100;
// position of the moon
var xMoon;
var yMoon;

// map to array indexes
var fence = 0;
var barn = 1;
var hay = 2;
var cow = 3;
var pig = 4;
var sheep = 5;
var chicken = 6; 
var rooster = 7;
var ship = 8;

function preload(){
    // These URLs are images stored on imgur 
    // images liscensed from Adobe Stock images
    // preload farm images
    var filenames = [];
    filenames[fence] = "https://i.imgur.com/bbBOrZ7.png"; 
    filenames[barn] = "https://i.imgur.com/inS5Xdt.png"; 
    filenames[hay] = "https://i.imgur.com/IXPEVak.png"; 
    filenames[cow] = "https://i.imgur.com/8XjQyMt.png"; 
    filenames[pig] = "https://i.imgur.com/7VPvVRB.png"; 
    filenames[sheep] = "https://i.imgur.com/vIFlqDY.png"; 
    filenames[chicken] = "https://i.imgur.com/vdTxUKf.png"; 
    filenames[rooster] = "https://i.imgur.com/SCYoQoX.png"; 
    filenames[ship] = "https://i.imgur.com/lAHddxj.png"
    // load farm images
    for (var i = 0; i < filenames.length; i++) {
        farmImg[i] = loadImage(filenames[i]);
    }

    // load sounds
    crickets = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/crickets2.wav");
    cluck = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/cluckcluck.wav");
    baa = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/baa.wav");
    moo = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/moo.wav");
    oink = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/oink.wav");
    spaceShip = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/spaceShip.wav");

}

function stepImage() {
    // // move and grow the space ship to get the sheep
    if(this.imageNum == ship & this.moving) {
        if(this.target == sheep) {
            if(this.x < width/4) {
                this.x += this.speed;
            }
            if(this.y < height/2.5) {
                this.y += this.speed;
            }
            if(this.ySize <= 100) {
                this.ySize += this.speed;
            }
            if(this.xSize <= 200) {
                this.xSize += this.speed;
            } else {
                if(this.drawBeam) {
                    drawBeam(this.x, this.y, this.target); 
                }
            }
        } else if(this.target == pig) {
            // move the space ship to get the pig
            this.drawBeam = true; // turn the beam back on

            if(this.ySize >= 80) {
                this.ySize -= this.speed;
            }
            if(this.xSize >= 180) {
                this.xSize -= this.speed;
            }

            if(this.y > height/3) {
                this.y -= this.speed;
            }
            if(this.x <= width/2) {
                this.x += this.speed;
            } else {
                if(this.drawBeam) {
                    drawBeam(this.x, this.y, this.target); 
                }
            }
        } else if(this.target == cow) {
            // move the space ship to get the cow
            this.drawBeam = true; // turn the beam back on

            if(this.ySize <= 120) {
                this.ySize += this.speed;
            }
            if(this.xSize <= 240) {
                this.xSize += this.speed;
            }

            if(this.y < height/1.8) {
                this.y += this.speed;
            }
            if(this.x >= width/4) {
                this.x -= this.speed;
            } else {
                // the ship is in the correct location for the beam
                if(this.drawBeam) {
                    drawBeam(this.x, this.y, this.target); 
                }
            }
        } else if(this.target < cow) {
            // fly away
            if(this.ySize >= 0) {
                this.ySize -= this.speed;
            }
            if(this.xSize >= 0) {
                this.xSize -= this.speed;
            }
            if(this.y > 0) {
                this.y -= this.speed;
            }
            if(this.x <= width) {
                this.x += this.speed;
            }
        }
    } 

    // when an animal is being abducted it shrinks and rises into the ship
    if(this.imageNum == farmObjArray[ship].target & this.moving) {
        // decrease y to rise into the ship
        if(this.y >= farmObjArray[ship].y) {
            this.y -= this.speed;
        } else {
            // turn the beam off and set target to pig
            farmObjArray[ship].drawBeam = false;

            // don't decrease the target below the cow index
            if(farmObjArray[ship].target >= cow) {
                farmObjArray[ship].target--;
            }
            
            // stop drawing this image
            this.moving = false;
            this.drawOn = false;
        }
        
        // shrink
        if(this.xSize > 0) {
            this.xSize *= .95;
        }
        if (this.ySize > 0) {
            this.ySize *= .95;
        } 
        if(this.imageNum == sheep & frameCount % 15 == 0) {
            baa.play();
        } else if(this.imageNum == pig & frameCount % 15 == 0) {
            oink.play();
        } else if(this.imageNum == cow & frameCount % 12 == 0) {
            moo.play();
        }

    }
}

function drawImage() {
    // draw image
    if(this.drawOn){
       image(farmImg[this.imageNum], this.x, this.y, this.xSize, this.ySize);
    } 
}

// Constructor for each farm image
function makeObj(cx, cy, imNum, xs, ys) {
    var c = {x: cx, y: cy, xSize: xs, ySize: ys, 
             imageNum: imNum,
             moving: false,
             drawBeam: true,
             target: sheep,
             speed: 5,
             drawOn: true,
             stepFunction: stepImage,
             drawFunction: drawImage
         }
    return c;
}

function setup() {
    createCanvas(480, 480);
    // set farm colors
    background(rNight, gNight, bNight);
    foreground(rFore, gFore, bFore);
    // set initial moon position
    xMoon = width + 25;
    yMoon = height/2.25;
    xShip = width/4;
    yShip = height/2 + 50;

    imageMode(CENTER);
    // create array of farm objects
    createFarmObjs(); 

    frameRate(10);
    useSound();
}

function soundSetup() { // setup for audio generation
    crickets.setVolume(0.1);
    cluck.setVolume(0.3);
    baa.setVolume(0.3);
    moo.setVolume(0.5);
    oink.setVolume(0.3);
    spaceShip.setVolume(0.5);
}

function draw() {
    noStroke();
    background(rNight, gNight, bNight);
    foreground(rFore, gFore, bFore);
    makeSounds();

    var currentImage;
    // loop over farm images and draw them
    for(var i = 0; i < farmObjArray.length; i++) {
        currentImage = farmObjArray[i];
        // draw the farm
        currentImage.stepFunction();
        currentImage.drawFunction();
    }

    // darken to night sky
    fadeNightSky();        

}

function makeSounds() {
    // make sounds at frameCount intervals
    // play crickets
    if(frameCount >5 & frameCount < 350 && frameCount % 25 == 0) {
        crickets.play();
    } 
    // play cluck cluck
    if ((frameCount > 24 & frameCount < 350 && frameCount % 50 == 0)) {
        cluck.play();
    }
    if(frameCount > 24 & frameCount < 200 && frameCount % 25 == 0) {
        spaceShip.play();
    }

    if(frameCount > 400){
        // stop all sounds
        crickets.stop();
        cluck.stop();
        spaceShip.stop();
        baa.stop();
        moo.stop();
        oink.stop();

        // stop looping
        noLoop();
    }
}

function createFarmObjs() {
    // create objects for farm: fence, barn, hay
    // set initial positions xPos and yPos
    var xPos = width/1.25;
    var yPos = height/2;

    // set initial size
    var xs = 125;
    var ys = 125;

    // create farm objects
    farmObjArray[fence] = makeObj(width/2, yPos + 20, fence, xs * 5, 
        ys * .25);
    farmObjArray[barn] = makeObj(xPos, yPos, barn, xs, ys);
    farmObjArray[hay] = makeObj(xPos + 50, yPos + 50, hay, xs/2, ys/2);
    farmObjArray[cow] = makeObj(width/4, height/1.2, cow, 100, 70);
    farmObjArray[pig] = makeObj(width/2, height/1.68, pig, 55, 45);
    farmObjArray[sheep] = makeObj(width/4, height/1.65, sheep, 30, 50);
    farmObjArray[chicken] = makeObj(width/1.2, height/1.35, 
        chicken, 25, 35);
    farmObjArray[rooster] = makeObj(width/1.3, height/1.45, 
        rooster, 30, 40);
    farmObjArray[ship] = makeObj(0, height/8, ship, 20, 1);
}

function drawBeam(x, y, target) {
    // draw beam
    fill(240, 250, 240, 80);
    triangle(x, y, x + 65,
        farmObjArray[target].y + 40, 
        x - 65,
        farmObjArray[target].y + 40);

    // set target to moving
    farmObjArray[target].moving = true;
}

function fadeNightSky() {
    // decrease the background colors to darken the sky to night
    var offset = 5;
    rNight -= offset;
    gNight -= offset;
    bNight -= offset;
    rNight = max(0, rNight);
    gNight = max(0, gNight);
    bNight = max(0, bNight);

    // draw moon
    if(rNight == 0) {
        fill(moon);
        ellipse(xMoon, yMoon, 50);
        moon++;
        moon = min(moon, 245);  
        xMoon -= offset;
        yMoon -= offset;
        xMoon = max(width/1.35, xMoon);
        yMoon = max(height/7.75, yMoon);
    }

    // when it is dark start moving space ship
    if(bNight == 0) {
          farmObjArray[ship].moving = true;
    }
}

function foreground(r, g, b) {
    // create lawn and mud puddle for pig
    fill(r, g, b);
    rect(0, height/2, width, height/2);

    fill(90, 80, 15);
    ellipse(width/2 - 10, height/1.6, 150, 25);
}

Project – 09: Portrait

Using pointillism for different shapes. Before, I was trying to use different lines, but I wasn’t able to get it to work sadly.

sketch
After 1 minute
After 2 minutes
After 5 minutes
var sonia;
var smallPoint, largePoint;

function preload() {
    sonia = loadImage("https://i.imgur.com/3h0u1wQ.jpeg");
}
function setup() {
    createCanvas(480, 480);
    //creating variables for the smallPoint size and the largePoint size
    smallPoint = 4;
    largePoint = 20;
    noStroke();
    background(220);
    rectMode(CENTER)
}

function draw() {
    //created 6 x and y variables to hold different sizes of widths and heights based on the corresponding variable
    var x1 = floor(random(sonia.width));
    var y1 = floor(random(sonia.height));
    //-10 and +10 so that it would always draw a shorter line, so when I used get, it would get a color closer to the point.
    var x2 = floor(random(x1 - 10, x1 + 10));
    var y2 = floor(random(y1 -10, y1 + 10));
    var x = floor(random(sonia.width));
    var y = floor(random(sonia.height));
    var lineLength = ((y2 - y1) / (x2 - x1)) / 10;
    createMultipleLines(x1,y1, x2,y2);
    createMultipleRectangles(x,y);
    createMultiplePoints(x,y);
}

function createMultipleLines(x1, y1, x2, y2) {
    var pointillize = map(mouseX, 0, width, smallPoint, largePoint);
    //gets color
    var pix = sonia.get(x1,y1);
    var pix1 = sonia.get(x2,y2);
    stroke(pix);
    //random strokeWeight
    strokeWeight(random(0.1, pointillize));
    line(x1,y1,x2,y2);
}

function createMultipleRectangles(x,y) {
    //creates multiple rectangles using same method
    var pointillize = map(mouseX, 0, width, smallPoint, largePoint);
    print(sonia.width);
    print(sonia.height)
    var pix = sonia.get(x,y);
    fill(pix);
    noStroke();
    rect(x,y, pointillize, pointillize);
}

function createMultiplePoints(x,y) {
    //creates multiple circular points using same method.
    var pointillize = map(mouseX, 0, width, smallPoint, largePoint);
    print(sonia.width);
    print(sonia.height)
    var pix = sonia.get(x,y);
    fill(pix);
    noStroke();
    ellipse(x,y, pointillize, pointillize);
}
    


// function createTinyLines(x1,y1,x2,y2, lineLength) {
//     var pointillize = map(mouseX, 0, width, smallPoint, largePoint);
//     for (var i = 0; i< lineLength; i ++) {
//         var pix = sonia.get(x1,y1);
//         var pix1 = sonia.get(x2,y2);
//         stroke(pix);
//         line(x1,y1,x2,y2);
//         var slopeY = y2 - y1;
//         var slopeX = x2 - x1;
//         x1 = x2;
//         y1 = y2;
//         x2 += slopeX;
//         y2 += slopeY;
//     }
// }

// function createOneLine(x1,y1,x2,y2, lineLength) {
//     //var pointillize = map(mouseX, 0, width, smallPoint, largePoint);
//     var pix = sonia.get(x1,y1);
//     var pix1 = sonia.get(x2,y2);
//     stroke(pix);
//     for (var i = 0; i< 20; i ++) {
//         line(x1,y1,x2,y2);
//         var slopeY = y2 - y1;
//         var slopeX = x2 - x1;
//         x1 == x2;
//         y1 == y2;
//         x2 += slopeX;
//         y2 += slopeY;
    
//     }
    
// }

Project 09: Computational Portrait (Custom Pixel)

i used my portrait as an each pixel to create a whole portrait. I used smaller images for face & background section, but bigger and rotated images for hair and eye section to separate the section of my feature.

sketchDownload
// Alicia Kim
// yoonbink
// Section B

function preload(){ //load the image
    alicia = loadImage("https://i.imgur.com/FPEjcyO.jpeg");
}


function setup() {
    createCanvas(480, 480);
    imageMode(CENTER);
    angleMode(DEGREES);
    background(220);
    alicia.resize(480,480); //resize alicia to canvas size
    alicia.loadPixels(); //load pixels
}

function draw() {
    var x = floor(random(alicia.width)); //random x-coordinate value
    var y = floor(random(alicia.height)); //random y-coordinate value
    var pixColor = alicia.get(x,y); //get random coordinate in the canvas
    tint(pixColor); //tint with the color of that coordinate 

// divide sections by hair and the rest

    if (pixColor[0]>130) { //face & background has smaller images
        image(alicia,x,y,9,9);
    }

    if (pixColor[0]<130) { //hair section has bigger & rotated images 
        push();
        translate(x,y);
        rotate(180);
        image(alicia,0,0,13,13);
        pop();   
    }
}

Looking Outwards 09: A Focus on Women and Non-binary Practitioners in Computational Art

Sinew Flex is a responsive installation by architect Jenny Sabin. Jenny Sabin is an architect using a computational techniques to create experimental form, bringing new perspectives to ways we see structures around us. She studied interdisciplinary visual art for bachelors and architecture for masters degree. Since she specializes in adaptive architecture, material computation, and biomimicry,  most of her works contain bioinspired design created through knitting of responsive fibres. Similarly, Sinew Flex, a 2 story double canopy structure connected with a central bifurcated tubular form, is mathematically generated and activated by digital knitting process and light.The responsive fibres used in the structure change color and glow in response to an integrated lighting system and changing programs. She employs artificial intelligence to translate the data from environment  into an immersive and interactive light and color. Also, the inhabitable structure provides various points of engagement; transformational views when audience descends the stairs, pause, productivity, and reflection at the base of the sculpture.  I admire how she breaks down the barriers of disciplines and create a integrated work of engineering, architecture, biology, and mathematics. Especially, how she branches “knitting” into structural and architectural applications is very creative and compelling as it’s not a common material used in architecture.

https://www.jennysabin.com/sinewflex

Sinew Flex

Looking Outwards 09: A Focus on Women and Non-binary Practitioners in Computational Art 

Caroline Record’s Falling OBJs was such a delightful treat to look at. With her use of random, oscillating lines that transform the perceived object into something else entirely, as well as the colors utilized to portray a clash of normality and chaos, she showcases her artistic and coding skills in an intersection of art and technology. Within each piece, she utilizes motion, as well, to create a sense of dissolving and forming. Record is a developer and artist that focuses primarily on writing the software to bring her installations to life. She has a background in fine arts, programming, and user-interaction design, having studied it at Carnegie Mellon University. She is currently focused on creating more digital, interactive works to be displayed in museums. She has also contributed to projects such as Popbox, which studied childhood obesity and the pressures and constraints that lead the children to their unhealthy weight gain. 

Falling OBJs (Caroline Record)


Her website here

Looking Outwords:09

The Horticultural Spa is a spa for plants and people. It is part greenhouse and part “pneumatic bubble”. The purpose it to create a place for people to breathe and connect. I chose Rachel Wingfield as she has experience with large-scale architecture which is something I am also interested in. In this space, she transforms this public garden in order to tell her story about water scarcity and how innovative technologies can start to be redeveloped to reduce consumption. Meditative practices are also used in the spa and certain soundtracks generate music as well. I like how she tries to merge biological and technological futures through her work especially at an urban scale.

Horticultural Spa

link

Project 09: Computational Portrait (Custom Pixel)

Click to switch between “circles” or “lines” mode.

“Circles” Mode: move the mouse left or right to change the circles’ size and stroke weight to make the portrait more blurry.

“Lines” Mode: move the mouse left or right to change the rotation angle of the lines to create the wind blowing effect.

sketch
Circles
Lines
//Xinyi Du 
//15104 Section B
//xinyidu@andrew.cmu.edu
//Assignment-09

//Click to switch between "circles" or "lines" mode.

//"Circles" Mode: 
//move the mouse left or right to change the circles' size and stroke weight 
//to make the portrait more blurry.

//"Lines" Mode: 
//move the mouse left or right to change the rotation angle of the lines 
//to create the wind blowing effect.

var click = 0; //number of clicks

function preload() {
  
  img = loadImage("https://i.imgur.com/ncc1zMh.jpg");
  //original url https://i.imgur.com/mOmrZEo.jpg
}

function setup() {
  createCanvas(547, 547);
  background(255);
  imageMode(CENTER);
  img.loadPixels(); //load pixels
}

function draw() { 
  //click to switch between "circles" or "lines" mode
  if (click % 2 == 0) {
    draw1(); //circles mode
  }
  else {
    draw2(); //lines mode
  }
}


function draw1() { //circles
  for (i=0; i<100; i++) {
    var x = floor(random(img.width)); //random x of the center of circles
    var y = floor(random(img.height)); //random y of the center of circles
    var dotcolor = img.get(x, y); //get the pixel color info
    var point = (dotcolor[0]+dotcolor[1]+dotcolor[2])/3; //get the average RGB value

    //map the mouseX position to circle sizes
    var mapsize = map(mouseX, 0, width, 5, 30);
    //map the mouseX position to circle stroke weights
    var mapWeight = map(mouseX, 0, width, 5, 0.5);;

    strokeWeight(mapWeight);
    stroke(dotcolor); //strokecolor is the pixel color
    noFill();
    ellipse(x, y, mapsize, mapsize);
    stroke(dotcolor[0]+35, dotcolor[1]+35, dotcolor[2]+35); //stroke color ligher
    ellipse(x, y, mapsize*1.5, mapsize*1.5); //circle size bigger
    stroke(dotcolor[0]-35, dotcolor[1]-35, dotcolor[2]-35); //stroke color darker
    ellipse(x, y, mapsize*0.5, mapsize*0.5); //circle size smaller
  }
}


function draw2() { //lines
  for (i=0; i<10000; i++) {
    var initdegree = mouseX; //mouseX determines the initial degree
    //x, y of the starting point of the lines, random points within the canvas
    var x = floor(random(img.width)); 
    var y = floor(random(img.height));
    var dotcolor = img.get(x, y);
    var point = (dotcolor[0]+dotcolor[1]+dotcolor[2])/3;

    //map the average RGB value to degrees, the greater the value the greater the degrees
    var mapdegree = initdegree+map(point, 0, 255, 0, 180);
    //map the average RGB value to line lengths, the greater the value the shorter the lengths
    var maplength = map(point, 0, 255, 15, 2);
    //map the average RGB value to stroke weights, the greater the value the smaller the stroke weights
    var mapWeight = map(point, 0, 255, 5, 0.3);

    noFill();
    strokeWeight(mapWeight);

    push();
    translate(x,y); //translate the origin to (x,y)
    rotate(radians(mapdegree)); //rotate mapdegree
    stroke(dotcolor);
    line(0, 0, 0+maplength, 0+maplength);
    stroke(dotcolor[0]+35, dotcolor[1]+35, dotcolor[2]+35);
    line(10, 0, 10+maplength+5, 0+maplength+5);
    stroke(dotcolor[0]-35, dotcolor[1]-35, dotcolor[2]-35);
    line(-10, 0, -10+maplength-5, 0+maplength-5); 
    pop();
  }

}

function mousePressed() {
  click ++ ; //if mouse is pressed, increase number of clicks
}


Looking Outward 09 / Caitlin Morris

Caitlin Morris is a researcher with MIT and has been faculty at the School for Poetic Computation since its founding in 2013. She holds a BS in Cognitive Psychology and Architectural Sciences and an MFA in Design and Technology. Her career focus is on the complex relationship between humans and our collective environment, as well as the concept of perception in regard to the natural world.
I chose to look at Morris’ 2018 project Seed and Signal for this weeks blog. This particular work is a sculpture meant to simulate the reflection of a tree in the water. A large blue board serves the base of the work, onto which dozens of square and diamond shaped golden plates are mounted. As the plates fold in and open outward, taking up different degrees of reflection depending on where you stand, the piece creates random but coordinated movement across the board.
I enjoy the simplicity of this project, and the visual is calming. It is not based in realism yet still feels as natural as watching reflections on the water. The stated objective of this piece is to visually manifest Morris’ perspective that ‘scientific theories are reflections of the reality beneath’.

Seed and Signal, 2018

Looking Outwards 09: A Focus on Women and Non-binary Practitioners in Computational Art

https://www.adriensegal.com/

Work: Molalla River Meander

Artist: Adrien Segal

Adrien Segal is an artist and writer based in Oakland, California.

She mainly focuses on transforming statistical information and data into artworks (sculpture) that reflect aspects like “history, narrative, emotion, landscape, and perception”, through artistic explorations and experiments.

Molalla River Meander

“Molalla River Meander” is my favorite work of the artist.

This work transforms alluvial flow data of the Molalla River in Oregon into a sculpture art piece. Data were obtained from the USGS Oregon Water Science Center, LIDAR maps of the Molalla River in Clackamas County, Oregon, which recorded river path changes from 1995 to 2009.

What I admire a lot about the project is that the years recorded are reflected through the thickness of the art piece and the general variations of the flow are reflected through the vertical variations of the wooden curved “wall”. I think Adrien Segal combined and reflected the two aspects (years and path changes) perfectly through her artistic expression.

Molalla River Meander
Video

Project 09: Computational Portrait

My process: I chose a picture of me on my 3rd birthday. I wanted to incorporate the number 3 into my custom pixel portrait. So I started there. My first custom pixels are made of 3s. Then I started to play with the other ways I could deconstruct, rebuild, and recolor play with the other ways I could deconstruct, rebuild, and recolor my portrait. I have created a 5 Portrait Series.

Portrait 1 – Made of Threes, Portrait 2 – Made of Ovals – inspired by thumbprint art, Portrait 3 – Made of Squares, Portrait 4 – Made of Legos – inspired by Legos, Portrait 5 – Made of Warhol – inspired by Andy Warhol

Press the space bar to see the various portraits I created. Click the mouse to freeze the creation of a portrait. Click again to resume.

sketch
/* Evan Stuhlfire
 * estuhlfi@andrew.cmu.edu section B
 * Project-09: Computational Portrait */

/* My process: I chose a picture of me on my 3rd 
 * birthday. I wanted to incorporate the number 3 into
 * my custom pixel portrait. So I started there. My first custom pixels
 * are made of 3s. Then I started to 
 * play with the other ways I could deconstruct, rebuild, and recolor
 * my portrait. I have created a 5 Portrait Series. */

 /* Portrait 1 - Made of Threes
  * Portrait 2 - Made of Ovals - inspired by thumbprint art
  * Portrait 3 - Made of Squares
  * Portrait 4 - Made of Legos - inspired by Legos
  * Portrait 5 - Made of Warhol - inspired by Andy Warhol */

/* Press the space bar to see the various portraits I created.
 * Click the mouse to freeze the creation of a portrait. Click again
 * to resume. This way portraits can be saved in different states. */

var img; // image variable
var scaleCanvas = 1.4; // factor to make canvas bigger than image

// booleans to determin which portrait to draw
var dThrees = true;
var dEllipses = false;
var dSquares = false;
var dLines = false;
var dOutline = false;

// used with a mouse click to freeze and resume dynamic portraits
var freeze = false; 

function preload() {
    img = loadImage("https://i.imgur.com/FRtQdiE.jpg");
}

function setup() {
    // create canvas 1.4 times the size of the original image
    createCanvas(img.width * scaleCanvas, img.height * scaleCanvas);
    background(230);

    textAlign(CENTER);
}
    
function draw() {
    // randomly generate x and y to get color from

    // use randomGaussian so image appears in center first
    var xPos = Math.floor(randomGaussian(img.width/2, 100));
    var yPos = Math.floor(randomGaussian(img.height/2, 100));

    // remap coordinates of image to the canvas size
    var xMap = map(xPos, 0, img.width, 0, width);
    var yMap = map(yPos, 0, img.height, 0, height);

    // get pixel color
    var pixCol = img.get(xPos, yPos);

    // test which syle to draw
    if(dThrees & !freeze) {
        drawThrees(xMap, yMap, pixCol);
    } else if(dEllipses & !freeze) {
        drawEllipses(xMap, yMap, pixCol);
    } else if(dSquares & !freeze) {
        rectMode(CENTER);
        drawSquares(xMap, yMap, pixCol);
    } else if(dLines & !freeze) {
        drawLines();
    } else if(dOutline & !freeze) {
        rectMode(CORNER);
        drawOutline();
    }
}

function keyPressed() {
    // switch between portait drawings when
    // the space bar is pressed
    if(key != " ") {
        // key was not space bar, return
        return;
    }

    if(dThrees){
        dThrees = false;
        dEllipses = true;
        dSquares = false;
        dLines = false;
        dOutline = false;
    } else if(dEllipses) {
        dThrees = false;
        dEllipses = false;
        dSquares = true;
        dLines = false;
        dOutline = false;
    } else if(dSquares) {
        dThrees = false;
        dEllipses = false;
        dSquares = false;
        dLines = true;
        dOutline = false;
    } else if(dLines) {
        dThrees = false;
        dEllipses = false;
        dSquares = false;
        dLines = false;
        dOutline = true;
    } else if(dOutline) {
        dThrees = true;
        dEllipses = false;
        dSquares = false;
        dLines = false; 
        dOutline = false; 
    }
    // reset background, unfreeze if frozen
    background(230);
    freeze = false;
}

function mousePressed() {
    // toggle the freeze boolean to freeze drawing
    freeze = !freeze;
}

function colorShift(pc, shiftType) {
    // read the pixel color variable and shift the color
    // based on shiftType specified
    var r, g, b, t;

    // read colors
    r = pc[0];
    g = pc[1];
    b = pc[2];
    t = pc[3];

    if(shiftType == "green") {
        // shift colors towards green
        r = constrain(r - 10, 5, 200);
        g = constrain(g + 50, 50, 230);
        b = constrain(b + 10, 10, 200);  
    } else if(shiftType == "blue") {
        // shift colors towards blue
        r = constrain(r - 10, 5, 200);
        g = constrain(g + 10, 10, 200);
        b = constrain(b + 50, 50, 230);        
    }

    // map mouse to change trasparancy as it moves vertical
    var my = map(mouseY, 0, height, 50, 180);
    t = my;

    return color(r, g, b, t);
}

function drawThrees(xMap, yMap, pixCol) {
    // draw portrait out of 3s
    var maxSize = 40;

    // green shift colors from original image
    pixCol = colorShift(pixCol, "green");
    stroke(pixCol);
    strokeWeight(1);
    fill(pixCol);
    // map mouse x to new range to control text size
    var mx = map(mouseX, 0, width, 10, maxSize);
    textSize(min(mx, maxSize));

    // draw 3s on canvas
    text("3", xMap, yMap);
}

function drawEllipses(xMap, yMap, pixCol) {
    // draw portrait out of random ellipses

    // blue shift colors from original image
    pixCol = colorShift(pixCol, "blue");
    // use color for fill
    fill(pixCol);
    stroke(pixCol);
    strokeWeight(1);
    ellipse(xMap, yMap, random(5, 35), random(5, 15));
}

function drawSquares(xMap, yMap, pixCol) {
    // create portrait from squares
    // square size is based on the darkness of the pixel color
    var maxColor = 140;
    var midColor = 100;
    var midColor2 = 70;

    // make color more or less transparent with movement of mouseY
    var transColor = colorShift(pixCol, "");
    // set colors
    stroke(transColor);
    fill(transColor);

    // Check pixel color and adjust square size based on how dark color is
    if(pixCol[0] > maxColor & pixCol[1] > maxColor && pixCol[3] > maxColor) {
        square(xMap, yMap, 30);
        fill(pixCol);
        circle(xMap, yMap, 5);
    } else if(pixCol[0] > midColor & pixCol[1] > midColor && pixCol[3] >
        midColor) {
        square(xMap, yMap, 20);
        fill(pixCol);
        circle(xMap, yMap, 5);
    } else if(pixCol[0] > midColor2 & pixCol[1] > midColor2 && pixCol[3] >
        midColor2) {
        square(xMap, yMap, 15);
        fill(pixCol);
        circle(xMap, yMap, 5);
    }else {
        square(xMap, yMap, 20);
        fill(pixCol);
        circle(xMap, yMap, 5);
    }
}

function drawLines() {
    // lego like circles and square in rows and columns
    for(var y = 5; y < img.height; y += 5) {

        for(var x = 5; x < img.width; x += 5) {
            var c = img.get(x, y);

            // map x from img to x from canvas
            var mx = map(x, 0, img.width, 0, width);
            // map y from img to y from canvas
            var my = map(y, 0, img.height, 0, height);

            // fill and draw 
            // shift to lego colors   
            if(c[0] > 180) {
                c = color(255, 255, 0);
            } else if(c[0] > 80) {
                c = color(0, 255, 0);
            } else if(c[0] > 50) {
                c = color(255, 0, 0);
            } else {
                c = color(0, 0, 255);
            }
            fill(c);
            noStroke();
            rect(mx, my, 10, 10);
            stroke(50);
            circle(mx, my, 5);
        }
    }
}

function drawOutline() {
    // draw an Andy Warhol style grid of pixel faces
    // draw four color quadrants
    fill(0, 255, 0); // green
    rect(0, 0, width/2, height/2);
    fill(255, 255, 77); // yellow
    rect(width/2, 0, width, height/2);
    fill(77, 255, 255); // blue
    rect(0, height/2, width/2, height);
    fill(255, 148, 77); // orange
    rect(width/2, height/2, width, height);

    // draw monochrome points at points of color change
    for(var y = 0; y < img.height; y += 3) {
        // get color from image
        var c = img.get(0, y);

        // look ahead to see when to change line color
        for(var x = 0; x < img.width; x += 2) {
            var dc = img.get(x, y);

            // color is different, draw this point
            if(dc[0] - c[0] > 10 || c[0] - dc[0] > 10 || 
                x == img.width - 1) {
                // map x from img to x from canvas
                var mx = map(x, 0, img.width, 0, width);
                // map y from img to y from canvas
                var my = map(y, 0, img.height, 0, height);

                if(c[0] > 60) {
                    drawPointImg(mx, my, color(0, 0, 230), 1);
                    drawPointImg(mx, my, color(230, 0, 230), 2);
                    drawPointImg(mx, my, color(255, 0, 0), 3);
                    drawPointImg(mx, my, color(255, 216, 204), 4);
                }

                // set color variable to new color
                c = dc;
            }
        }
    }
}

function drawPointImg(mx, my, pc, quad) {
    // draw set of points for specified quadrant 
    // map to specified quad
    if(quad == 1) {
        // map points to first quadrant
        qmx = map(mx, 0, width, 0, width/2);
        qmy = map(my, 0, height, 0, height/2);
    } else if (quad == 2) {
        // map points to second quadrant
        qmx = map(mx, 0, width, width/2, width);
        qmy = map(my, 0, height, 0, height/2);
    } else if (quad == 3) {
        // map points to third quadrant
        qmx = map(mx, 0, width, 0, width/2);
        qmy = map(my, 0, height, height/2, height);
    } else if (quad == 4) {
        // map points to fourth quadrant
        qmx = map(mx, 0, width, width/2, width);
        qmy = map(my, 0, height, height/2, height);
    }

    // set color of point
    stroke(pc);
    strokeWeight(.25);

    // draw point
    point(qmx, qmy);
}


Project Notes