Week 1: Self Portrait Assignment

Description:

This project consisted of creating a self-portrait based on basic shapes we learned in class. We tried basic shapes such as line, ellipse, rectangle, and circle to create a basic face. 

Challenges:

Throughout this project, I faced numerous challenges that I had to overcome. When working with processing one of the greatest challenges for me is thinking about the plane and space to work. Generally, people are used to working with the first quadrant in a Cartesian plane. However, Processing uses the fourth quadrant as space. At first, it was difficult to locate and determine when to write a minus or plus sign. However, after practicing, I could think faster about the space we are using. Another challenge I faced was the location itself. I mostly hardcoded my code as I added specific numbers for each line. I tried to avoid Hardcoding in some parts such as when I use faceCenterX and faceCenterY and I think I was able to work well with this. In the future, I hope I will be able to avoid hardcoding in every part of my code. 

Process: 

For this project, I learned several new features for processing such as the use of triangles and the arc. The use of arc was challenging as it required me to think about angles. The use of triangles was much simpler once I got used to thinking about space and location. While doing this project I made several sketches to see how I wanted the drawing to look. After several attempts, I realized it was challenging to make the hair for my portrait. I realized that I like wearing caps and I thought it would be a good idea to include this in my portrait. After drawing the character in processing, I felt the portrait lacked vividness. Therefore in the end I decided to use the fill() function to add color. 

Conclusion:

Overall I think I learned a lot through this project; however, I still think there is much more to learn. This project helped me plan something before actually doing it and it made me realize that most of the time the project does not come out to be as I expected. Still, the project also helped me get experience in calculating space and determining location. 

Final Work: 

Code: 

void setup(){
  size(640, 480);
}

void draw() {
  background(153,238,255);
  
  int faceCenterX = width/2;
  int faceCenterY = height/2;
  
  fill(255);

  //CAP
  fill(155);
  
  arc(faceCenterX, faceCenterY - 28, 200, 220, PI, 2*PI);
  
  line(faceCenterX - 100, faceCenterY-28, faceCenterX + 100, faceCenterY-28);
  
  fill(0,128,255);
  
  rect(faceCenterX-40, faceCenterY-49, 80, 20);
  
  fill(0);
  
  arc(faceCenterX, faceCenterY - 45, 80, 60, PI, 2*PI);
  
  fill(0,128,255);
  
  triangle(faceCenterX - 100, faceCenterY-28, faceCenterX - 130, faceCenterY, faceCenterX - 90, faceCenterY);
  
  
  //Neck
  fill(255,230,204);
  rect(faceCenterX - 35, faceCenterY + 100, 70, 30);
  
  //Face
  fill(255,230,204);
  
  arc(faceCenterX, faceCenterY - 27, 200, 270, 0, PI);
  
  //EYES
  
  arc(faceCenterX - 45, faceCenterY - 25, 65, 75, QUARTER_PI, HALF_PI+QUARTER_PI);
 
  arc(faceCenterX - 45, faceCenterY + 30, 65, 75, PI+QUARTER_PI, PI+HALF_PI+QUARTER_PI);
  
  arc(faceCenterX + 45, faceCenterY - 25, 65, 75, QUARTER_PI, HALF_PI+QUARTER_PI);
 
  arc(faceCenterX + 45, faceCenterY + 30, 65, 75, PI+QUARTER_PI, PI+HALF_PI+QUARTER_PI);
  
  fill(26, 13, 0);
  
  circle(faceCenterX - 45, faceCenterY + 2, 20);
  
  circle(faceCenterX + 45, faceCenterY + 2, 20);
  
  fill(0);
  
  circle(faceCenterX - 45, faceCenterY + 2, 10);
  
  circle(faceCenterX + 45, faceCenterY + 2, 10);
  
  fill(255);
  
  circle(faceCenterX - 40, faceCenterY + 2, 5);
  
  circle(faceCenterX + 50, faceCenterY + 2, 5);
  
  //NOSE
  
  line(faceCenterX + 5, faceCenterY, faceCenterX + 5, faceCenterY+ 40);
  
  line(faceCenterX + 5, faceCenterY + 40, faceCenterX + 13, faceCenterY + 47);
  
  line(faceCenterX + 13, faceCenterY + 47, faceCenterX + 5, faceCenterY + 54);
  
  line(faceCenterX + 5, faceCenterY + 40, faceCenterX + 13, faceCenterY + 47);
  
  line(faceCenterX + 3, faceCenterY + 50, faceCenterX - 2, faceCenterY + 54);
  
  line(faceCenterX - 2, faceCenterY + 54, faceCenterX - 7, faceCenterY + 50);
   
  line(faceCenterX - 18, faceCenterY + 47, faceCenterX - 10, faceCenterY + 54);
  
  line(faceCenterX - 10, faceCenterY + 40, faceCenterX - 18, faceCenterY + 47);
  
  //Mouth 
  
  line(faceCenterX - 15, faceCenterY + 75, faceCenterX + 5, faceCenterY + 75);
  
  //Shirt
  fill(0,115,230);
  rect(faceCenterX - 95, faceCenterY + 130, 200, 200);
  
  triangle(faceCenterX - 95, faceCenterY + 130, faceCenterX - 95, faceCenterY + 180, faceCenterX - 140, faceCenterY + 180);
  
  triangle(faceCenterX + 105, faceCenterY + 130, faceCenterX + 105, faceCenterY + 180, faceCenterX + 150, faceCenterY + 180);
  
  //Arms
  fill(255,230,204);
  
  rect(faceCenterX - 127, faceCenterY + 180, 32, 60);
  
  rect(faceCenterX + 105, faceCenterY + 180, 32, 60);
  
  
}

 

Week 1 – Self Portrait

The first assignment was about experimenting with shapes and Processing functions in order to create a self-portrait. I decided to add some flavour to it through a representation of my tongue touching my nose, something I am extremely proud of. And yes, this is exactly how the rest of my face looks like when I try showcasing my talents.

I have learnt a lot about the use of shapes during this process of making the self-portrait. Some of the shapes I used were triangle(), rect(), arc(), ellipse(), circle() and line(). I used functions for different parts of the face which made it easier for me to work with them individually.

The most challenging part for me was experimenting with the coordinates so that everything could appear in the right place. Some of the features of coding using Processing really helped me here, such as using a circle to represent the ears. Although I have used full circles to represent the ears, they do not appear as full circles because the colour used was the same as that of the rest of the face, leading to an overlap.

Also, I used two different hairstyles (one of them is commented). Once again, allowing the hair to appear over the face (because code is executed line by line) helped me avoid dealing with awkward shapes.

int centerX;
int centerY;
int faceCenter;
float faceWidth = 140;
float faceHeight = 175;

void setup() {
  size(640, 480);
  background(255, 255, 0);
  centerX = width / 2;
  centerY = height / 2;
}


void draw() {
  face();
  nose();
  hair();
  eyes();
  lips();
  body();
}

void face() {
  fill(247, 194, 168);
  noStroke();
  //ellipse(centerX, centerY - 45, faceWidth, faceHeight);
  rect(260, 140, 120, 90);
  arc(320, 230, 120, 70, 0, PI);
  ellipse(385, 180, 20, 25);
  ellipse(255, 180, 20, 25);
  noFill();
  stroke(255, 160, 180);
  ellipse(253, 180, 10, 15);
  ellipse(386, 180, 10, 15);
}

void nose() {
  stroke(0);
  strokeWeight(1);
  line(centerX, centerY - 55, centerX - 7, centerY - 35);
  line(centerX, centerY - 55, centerX + 7, centerY - 35);
  line(centerX - 7, centerY - 35, centerX, centerY - 33);
  line(centerX + 7, centerY - 35, centerX, centerY - 33);
}

void hair() {
  fill(0);
  arc(320, 140, 118, 50, PI, PI*2);
  triangle(260, 140, 360, 150, 379, 140);
  //the two lines below can be used to present another version of the hair
  //arc(290, 140, 60, 25, 0, PI);
  //arc(350, 140, 60, 25, 0, PI);
}

void eyes() {
  stroke(0);
  noFill();
  strokeWeight(2);
  arc(290, 170, 25, 10, PI, PI*2);
  arc(350, 170, 25, 10, PI, PI*2);
  strokeWeight(1);
  ellipse(290, 178, 25, 10);
  ellipse(350, 178, 25, 10);
  fill(0);
  circle(290, 178, 5);
  circle(350, 178, 5);
}

void lips() {
  noFill();
  arc(320, 230, 32, 15, 0, PI);
  //line(300, 230, 340, 230);
  //arc(320, 230, 32, 10, PI, 2*PI);
  fill(220, 133, 146);
  arc(320, 230, 32, 48, PI, 2*PI);
  fill(247, 194, 168);
  arc(320, 230, 32, 10, PI, 2*PI);
}

void body() {
  noStroke();
  fill(247, 194, 168);
  rect(300, 262, 40, 40);
  fill(0, 255, 255);
}

 

 

[Week 1] Self-portrait with Processing

For the first assignment, I want to explore the various drawing functions in the Processing library for Java. Here’s a glimpse at my product:

 

Processes

I found out that the function createShape() can be used to define a new shapes on the basis of other primitive shape functions like ellipse(), rect(), arc(), etc. Each of the shape created this way can be stored in a PShape object and will later be drawn with the function shape(). I find this to be a particularly neat way of organizing different components of the sketch without having to construct new classes.

So, utilizing createShape(), I organize my drawing into different components: face, hair, mouth, and eyes. Each of these component is constructed from one or more PShape objects which are all included in one big object called portrait.

The face is a simple, classic ellipse. Nothing much to see here.

The hair is a bit more complex. I divide it into four objects: upperHair, lowerHair, leftFringe, and rightFringe.

The upper part of the hair is also a simple ellipse like the face, just slightly bigger. For the lower hair, I use a rectangle with a specified radius value to make the corners round. The top of the rectangle overlaps with the lower half of the upper hair ellipse to create a view of consistency.

The fringe, even though I have chosen to stick to primitive shapes, proves to be quite tricky. I first try to construct a curve using the edge of an ellipse.

 

The problem is that with this, I expected to be able to use the contour function to remove the unwanted part of the ellipse, keeping only the part that overlaps with the back hair. It turns out that beginContour() and endContour() cannot be used on an ellipse. There might be a way to get around this so I hope I can return to this problem later.

So instead of drawing a big ellipse hoping to cut out unwanted part, I try to draw a smaller ellipse with approximately the same fringe curve that fits right into the head. For this, I find rotate() really useful. One thing to note is that the coordinates are always rotated around their relative positive to the origin (from Processing reference page), so it will be best to create the shape at the origin (0, 0), move it to the desired position using translate(), then rotate().

arc() is very handy for drawing half an ellipse for the mouth.

For the eyes, I want something a little different from ellipses, so I turn to rect() instead with high radius value so that the eyes (and the eyeballs) will look rounded instead of sharp.

Development

First, as I mentioned above, I want to explore contour a bit more to see if there is a way to resolve the fringe problem without compromising the shapes.

Second, I would want to add some animations to the drawing. I was working on a blinkEyes() function (code at the end) but it is not finished. Right now the blinking motion looks very un-blinking-like, so I want to improve the piece of code too.

Code

PShape portrait, face, upperHair, lowerHair, leftFringe, rightFringe, mouth, leftEye, rightEye, leftEyeball, rightEyeball;

int faceWidth = 180;
int faceHeight = 230;
int leftXOfFace;
int rightXOfFace;
color skinColor = color(255, 181, 159);

int hairWidth = faceWidth + 20;
int hairHeight = faceHeight + 20;
color hairColor = color(102, 58, 37);
int roundFactor = 30;

color mouthColor = color(165, 69, 68);

float eyeWidth;
float eyeHeight;

PShape drawEye(int x, int y) {
  /*
  * @param x,y coordinates of the upper left corner of the eye
  * @return PShape object of the eye
  */
  PShape eye = createShape(RECT, x, y, eyeWidth, eyeHeight, roundFactor);
  return eye;
}

PShape drawEyeball(int x, int y) {
  /*
  * @param x,y coordinates of the upper left corner of the eyeball
  * @return PShape object of the eyeball
  */
  PShape eyeball = createShape(RECT, x, y, eyeWidth*.5, eyeHeight*.5, roundFactor);
  return eyeball;
}

void setup() {
  size(640, 480);
  frameRate(30);
  
  leftXOfFace = width/2 - faceWidth/2;
  rightXOfFace = width/2 + faceWidth/2;
  eyeWidth = faceWidth*.2;
  eyeHeight = faceHeight*.2;
  
  portrait = createShape(GROUP);

  face = createShape(ELLIPSE, width/2, height/2, faceWidth, faceHeight);
  face.setFill(skinColor);
  face.setStroke(false);

  upperHair = createShape(ELLIPSE, width/2, height/2, hairWidth, hairHeight);
  upperHair.setFill(hairColor);
  upperHair.setStroke(false);

  lowerHair = createShape(RECT, leftXOfFace-10, height/2, hairWidth, faceHeight, 0, 0, roundFactor, roundFactor);
  lowerHair.setFill(hairColor);
  lowerHair.setStroke(false);
  
  leftFringe =  createShape(ELLIPSE, 0, 0, hairWidth*.75, hairHeight*.3);
  leftFringe.translate(width/2-faceWidth*.2, height/2-faceHeight*.28);
  leftFringe.rotate(-PI*.23);
  leftFringe.setFill(hairColor);
  leftFringe.setStroke(false);
  
  rightFringe = createShape(ELLIPSE, 0, 0, hairWidth*.6, hairHeight*.2);
  rightFringe.translate(width/2+faceWidth*.27, height/2-faceHeight*.28);
  rightFringe.rotate(PI*.28);
  rightFringe.setFill(hairColor);
  rightFringe.setStroke(false);

  mouth = createShape(ARC, width/2, height/2+faceWidth*.25, faceWidth*.5, faceHeight*.3, 0, PI, CHORD);
  mouth.setFill(mouthColor);
  mouth.setStroke(false);
  
  leftEye = drawEye(0, 0);
  leftEye.translate(width/2-faceWidth*.25-eyeWidth/2, height/2-faceHeight*.15);
  leftEye.setStroke(false);
  
  leftEyeball = drawEyeball(0, 0);
  leftEyeball.setFill(color(0, 0, 0));
  leftEyeball.translate(width/2-faceWidth*.25, height/2-faceHeight*.15+eyeHeight*.3);
  leftEyeball.setStroke(false);
  
  rightEye = drawEye(0, 0);
  rightEye.translate(width/2+faceWidth*.25-eyeWidth/2, height/2-faceHeight*.15);
  rightEye.setStroke(false);
  
  rightEyeball = drawEyeball(0, 0);
  rightEyeball.setFill(color(0, 0, 0));
  rightEyeball.translate(width/2+faceWidth*.25-eyeWidth/2, height/2-faceHeight*.15+eyeHeight*.3);
  rightEyeball.setStroke(false);
  
  // .addChild(): object added later will be placed on top
  portrait.addChild(upperHair);
  portrait.addChild(lowerHair);
  portrait.addChild(face);
  portrait.addChild(leftEye);
  portrait.addChild(rightEye);
  portrait.addChild(leftEyeball);
  portrait.addChild(rightEyeball);
  portrait.addChild(leftFringe);
  portrait.addChild(rightFringe);
  portrait.addChild(mouth);
}

void draw() {
  background(255);
  shape(portrait);
}
void blinkEyes() {
  /* Create animation of eyes blinking
  * @param None
  * @return None
  */
  if (eyeHeight > 1) {
    eyeHeight -= 1;
  } else {
    eyeHeight = faceHeight*.2;
  }
  eyes = createShape(GROUP);
  leftEye = drawEye(0, 0);
  leftEye.translate(width/2-faceWidth*.25-eyeWidth/2, height/2-faceHeight*.15);
  leftEye.setStroke(false);
  
  leftEyeball = drawEyeball(0, 0);
  leftEyeball.setFill(color(0, 0, 0));
  leftEyeball.translate(width/2-faceWidth*.25, height/2-faceHeight*.15+eyeHeight*.3);
  leftEyeball.setStroke(false);
  
  rightEye = drawEye(0, 0);
  rightEye.translate(width/2+faceWidth*.25-eyeWidth/2, height/2-faceHeight*.15);
  rightEye.setStroke(false);
  
  rightEyeball = drawEyeball(0, 0);
  rightEyeball.setFill(color(0, 0, 0));
  rightEyeball.translate(width/2+faceWidth*.25-eyeWidth/2, height/2-faceHeight*.15+eyeHeight*.3);
  rightEyeball.setStroke(false);
  
  eyes.addChild(leftEye);
  eyes.addChild(rightEye);
  eyes.addChild(leftEyeball);
  eyes.addChild(rightEyeball);
  shape(eyes);
}

 

Sketch a Self-Portrait

PROJECT DESCRIPTION

My task was to sketch a self-portrait using basic 2-D shapes available to me in Processing. Building upon the short exercise we did in class, I played more with the different shapes and colors to try and make my portrait as close as possible to a real person than the stick figure it was looking like initially. I focused on the smallest of the details, from lines in the bangs to reflection in the eyes; each and every element in the portrait contributing towards the overall look of the sketch. My sketch mostly uses the following drawing features:

      • line
      • ellipse
      • circle
      • rectangle
      • arc

PROCESS

I first started out with sketching a basic idea of what I wanted my sketch to look like (see below).

I chose the second look as I wear my hair more often like that.

The next step was to start coding it using Processing. I started with the basic things or the ones that were most important first and then kept on building upon it, adding more features as and when required. The poster below outlines my step-by-step process:


collageAs per my vision, I first created an outline for my sketch, which included adding a face and hair. I wanted to make the layout first and then focus on details, so I coded the clothes, hands, and gave the round neck effect. Then came the detailing on the face which was quite difficult initially, keeping the proportions in mind. It really challenged the mathematician in me but was very fun to accomplish. Using the arc function was particularly hard as its parameters were confusing to understand and implement initially. Next came adding accessories like ears, earrings, blush lines, and design on clothes.

I then fine-tuned a few things here and there (like increasing the hand width, rounding the shoulders more, adjusting the lines in the bangs, adding eyebrows, etc.) to make the drawing more proportionate. I decided against adding the specs as my drawing was looking crowded and was taking away from the aesthetics.

After I was happy with how my portrait was looking, I added a little pattern in the background to make it more appealing. This is the final version of my sketch:

 

CODE

//decleration of variables
float x0, y0; //center coordinates of face i.e. point of reference
float h, w; //stores width and height of canvas
float faceL, faceW; //stores dimensions of the face so that it is easier to position other elements

void setup() {
  size(640, 480);

  //initialization of the variable
  h = height;
  w = width;
  x0 = w/2; //sketch to be positioned at the center
  y0 = h/2;
  faceL = h*0.5;
  faceW = faceL*0.8; //so that face dimensions are preserved irrespective of canvas size
}

void draw() {

  background(254, 249, 131);
  
  //pattern
  strokeWeight(5);
  //stroke(252, 247, 79);
  //stroke(255, 224, 102);
  stroke(252, 245, 54);
  //stroke(255, 255, 179);
  line(0,h,w,0);
  line(0,0,w,h);
  line(0,2*h/10,2*w/10,0);
  line(2*w/10,0,w,8*h/10);
  line(0,4*h/10,4*w/10,0);
  line(4*w/10,0,w,6*h/10);
  line(0,6*h/10,6*w/10,0);
  line(6*w/10,0,w,4*h/10);
  line(0,8*h/10,8*w/10,0);
  line(8*w/10,0,w,2*h/10);
  //second half
  line(0,2*h/10,8*w/10,h);
  line(2*w/10,h,w,2*h/10);
  line(0,4*h/10,6*w/10,h);
  line(4*w/10,h,w,4*h/10);
  line(0,6*h/10,4*w/10,h);
  line(6*w/10,h,w,6*h/10);
  line(0,8*h/10,2*w/10,h);
  line(8*w/10,h,w,8*h/10);
  //line(0,2*h/10,8*w/10,h);
  
  stroke(0);
  strokeWeight(1);

  //background hair
  fill(53, 40, 30);
  rect(x0-faceW*1.15/2, y0-faceL*0.1, faceW*1.15, faceL*0.7);

  //neck
  fill(246, 211, 189);
  rect(x0-faceW*0.2, y0-faceL*0.1, faceW*0.4, faceL*0.7);

  //ears
  ellipse(x0-faceW*0.5, y0+faceL*0.05, faceW*0.15, faceL*0.2);
  ellipse(x0+faceW*0.5, y0+faceL*0.05, faceW*0.15, faceL*0.2);
  //earrings
  fill(78, 102, 238);
  noStroke();
  circle(x0-faceW*0.51, y0+faceL*0.15, faceW*0.1);
  circle(x0+faceW*0.51, y0+faceL*0.15, faceW*0.1);
  stroke(0);

  //face
  fill(246, 211, 189);
  ellipse(x0, y0, faceW, faceL);

  //hair
  fill(53, 40, 30);
  arc(x0, y0-faceL*0.1, faceW*1.15, faceL*0.9, PI, 2*PI, PIE);
  //lines on the bangs
  strokeWeight(1.3);
  line(x0, y0-faceL*0.1, x0, y0-faceL*0.32);
  line(x0-faceW*0.1, y0-faceL*0.1, x0-faceW*0.1, y0-faceL*0.32);
  line(x0+faceW*0.1, y0-faceL*0.1, x0+faceW*0.1, y0-faceL*0.32);
  line(x0-faceW*0.2, y0-faceL*0.1, x0-faceW*0.19, y0-faceL*0.3);
  line(x0+faceW*0.2, y0-faceL*0.1, x0+faceW*0.19, y0-faceL*0.3);
  line(x0-faceW*0.3, y0-faceL*0.1, x0-faceW*0.28, y0-faceL*0.28);
  line(x0+faceW*0.3, y0-faceL*0.1, x0+faceW*0.28, y0-faceL*0.28);
  line(x0-faceW*0.4, y0-faceL*0.1, x0-faceW*0.37, y0-faceL*0.27);
  line(x0+faceW*0.4, y0-faceL*0.1, x0+faceW*0.37, y0-faceL*0.27);
  strokeWeight(1);

  //hands
  fill(246, 211, 189);
  rect(x0-faceW*1.63/2, y0+faceL*0.62, faceW*1.63, faceL*0.48, 48, 48, 0, 0);

  //clothes
  fill(87, 190, 241);
  rect(x0-faceW*1.2/2, y0+faceL*0.6, faceW*1.2, faceL*0.5, 5, 5, 0, 0);
  //round neck
  fill(246, 211, 189);
  arc(x0, y0+faceL*0.6, faceW*0.6, faceW*0.35, 0, PI);
  //design
  fill(78, 102, 238);
  noStroke();
  rect(x0+faceW*0.1, y0+faceL*0.83, faceW*0.5, faceL*0.27);
  rect(x0-faceW*0.6, y0+faceL*0.83, faceW*0.5, faceL*0.27);
  //rect(x0-faceW*0.4, y0+faceL*0.8, faceW*0.1, faceL*0.5);
  stroke(0);

  //eyes
  fill(255); 
  ellipse(x0-faceW*0.22, y0+faceL*0.05, faceW*0.18, faceW*0.12);
  ellipse(x0+faceW*0.22, y0+faceL*0.05, faceW*0.18, faceW*0.12);
  noStroke();
  fill(69, 46, 44);
  circle(x0-faceW*0.22, y0+faceL*0.05, faceW*0.12);
  circle(x0+faceW*0.22, y0+faceL*0.05, faceW*0.12);
  fill(0);
  circle(x0-faceW*0.22, y0+faceL*0.05, faceW*0.05);
  circle(x0+faceW*0.22, y0+faceL*0.05, faceW*0.05);
  fill(255);
  circle(x0-faceW*0.22+faceW*0.03, y0+faceL*0.05-faceL*0.02, faceW*0.025);
  circle(x0+faceW*0.22+faceW*0.03, y0+faceL*0.05-faceL*0.02, faceW*0.025);
  stroke(0);

  //eyebrows
  noFill();
  stroke(53, 40, 30);
  strokeWeight(2);
  //fill(246, 211, 189);
  arc(x0-faceW*0.22, y0+faceL*0.01, faceW*0.25, faceW*0.1, 1.2*PI, 1.8*PI);
  arc(x0+faceW*0.22, y0+faceL*0.01, faceW*0.25, faceW*0.1, 1.2*PI, 1.8*PI);
  strokeWeight(1);
  stroke(0);

  //specs
  //noFill(); 
  //stroke(170,169,173);
  //strokeWeight(2);
  //ellipse(x0-faceW*0.22, y0+faceL*0.05, faceW*0.3, faceW*0.25);
  //ellipse(x0+faceW*0.22, y0+faceL*0.05, faceW*0.3, faceW*0.25);
  //strokeWeight(1);

  //nose
  line(x0, y0+faceL*0.1, x0, y0+faceL*0.23);
  line(x0, y0+faceL*0.26, x0+faceW*0.06, y0+faceL*0.24);
  line(x0, y0+faceL*0.26, x0-faceW*0.06, y0+faceL*0.24);

  //mouth
  stroke(220, 55, 83);
  strokeWeight(2);
  fill(229, 109, 126);
  arc(x0, y0+faceL*0.33, faceW*0.2, faceW*0.17, 0, PI, CHORD);
  stroke(0);
  strokeWeight(1);

  //blush
  strokeWeight(2);
  stroke(242, 193, 162);
  line(x0+faceW*0.3, y0+faceL*0.26-faceL*0.1, x0+faceW*0.08+faceW*0.3, y0+faceL*0.24-faceL*0.1);
  line(x0+faceW*0.32, y0+faceL*0.26-faceL*0.08, x0+faceW*0.08+faceW*0.32, y0+faceL*0.24-faceL*0.08);
  line(x0-faceW*0.3, y0+faceL*0.26-faceL*0.1, x0-faceW*0.08-faceW*0.3, y0+faceL*0.24-faceL*0.1);
  line(x0-faceW*0.32, y0+faceL*0.26-faceL*0.08, x0-faceW*0.08-faceW*0.32, y0+faceL*0.24-faceL*0.08);
  stroke(0);
  strokeWeight(1);
}

 

The key element of my code is that my portrait is dynamic with respect to the canvas. I have not hardcoded any of the values required to build my sketch. Every position, length, width mentioned in the code is in reference to the canvas size chosen. The reference point for the portrait (x0, y0 in the code) is the middle of the canvas and the portrait remains in the center irrespective of the canvas size. In fact, one can change the coordinates of x0 and y0 to make the reference point of the figure higher up/ down, a little left/right, and the entire portrait shifts (video attached later). It does not get disproportionate at all. For sketching the girl, I used face length (faceL) and face width (faceW) which are in proportion to the canvas size as standard measures to draw the other elements. This ensures my portrait does not disfigure.

Softcoding my program also made it easier for me to fine-tune, edit, and change aspects in my code as I did not have to calculate a number and put it, calculate again, and put it. I was just using variables which values and I had to adjust those values.

Commenting out the code and breaking it into blocks made it easier for me to go back and edit it.

Below you can see a short video of how my portrait behaves when a few reference points are changed:

Alima’s self-portrait

This week I finished my first assignment of this class – making a self-portrait using Processing. During the class, we played with shapes and even tried to draw the simplest version of the face using geometrical figures such as circles, rectangles, and ellipses. For this assignment, I’ve decided to take it to the next level and attempted to make a cartoon version of myself.

I started by researching the proportions of a human’s face so the drawing would look like me.

Then, I made few sketches of the portrait and decided on the color scheme. [I won’t put them here because they are messy]

The final version is here. I added blush to my cheeks, and the color changes to more intense when the mouse points to it. Also, the hairstyle and eye shape resemble me. For the background, I asked my friends to choose the color they associate with me, and they chose this shade of purple.

 

Most of the time I used beginShape() and endShape() to draw any shape I needed and to be able to color it with fill(). bezierVertex() and bezier() helped to draw curves with appropriate parameters. I used strokeWeight() to change the width of some lines and emphasize my eyes.

Code:

void setup() {

  size(640, 460); //width, height

}

void draw() {  //looping 
  int faceCenterX=width/2;
  int faceCenterY=height/2-50;
  background(204, 153, 255);

  stroke(51, 25, 0);
  //line(width/2, 0, width/2, height); //main axis
  //line(0, faceCenterY, width, faceCenterY);

  //hair
  fill(51, 25, 0); //hair color
  beginShape();
  vertex(faceCenterX-140, faceCenterY+150);
  bezierVertex(faceCenterX-170, faceCenterY-270, faceCenterX+170, faceCenterY-270, faceCenterX+140, faceCenterY+150);
  endShape();

 //neck
  fill(255, 229, 204);
  beginShape();
  vertex(faceCenterX-60, faceCenterY+40);
  bezierVertex(faceCenterX-50, faceCenterY+140, faceCenterX-50, faceCenterY+180, faceCenterX-120, faceCenterY+180);
  bezierVertex(faceCenterX-100, faceCenterY+200, faceCenterX+80, faceCenterY+200, faceCenterX+120, faceCenterY+180);
  bezierVertex(faceCenterX+50, faceCenterY+180, faceCenterX+50, faceCenterY+140, faceCenterX+60, faceCenterY+40);
  endShape(); 
  
  //longsleeve
  fill(153, 255, 229);
  beginShape();
  vertex(80, height);
  bezierVertex(100, height-50,100, height-50,faceCenterX-120, faceCenterY+180);
  bezierVertex(faceCenterX-100, faceCenterY+200,faceCenterX+80, faceCenterY+200, faceCenterX+120, faceCenterY+180);
  bezierVertex(width-100, height-50, width-100, height-50, width-80, height);
  endShape();

  //face
  fill(255, 229, 204); //skin tone
  beginShape();
  vertex(faceCenterX-100, faceCenterY-10);
  bezierVertex(faceCenterX-100, faceCenterY-200, faceCenterX+100, faceCenterY-200, faceCenterX+100, faceCenterY-10);
  bezierVertex(faceCenterX+140, faceCenterY-50, faceCenterX+140, faceCenterY+30, faceCenterX+100, faceCenterY+40);
  bezierVertex( faceCenterX+30, faceCenterY+170, faceCenterX-30, faceCenterY+170, faceCenterX-100, faceCenterY+40);
  bezierVertex(faceCenterX-140, faceCenterY+30, faceCenterX-140, faceCenterY-50, faceCenterX-100, faceCenterY-10);
  endShape();

  //bangs
  fill(51, 25, 0); //hair color
  beginShape();
  vertex(faceCenterX-100, faceCenterY-10);
  bezierVertex(faceCenterX-40, faceCenterY-30, faceCenterX, faceCenterY-70, faceCenterX, 40);
  bezierVertex(faceCenterX, faceCenterY-70, faceCenterX+40, faceCenterY-30, faceCenterX+100, faceCenterY-10);
  bezierVertex(faceCenterX+100, faceCenterY-200, faceCenterX-100, faceCenterY-200, faceCenterX-100, faceCenterY-10);
  endShape();

  //eyes
  //left eye 
  beginShape();
  fill(255);
  vertex(faceCenterX-30, faceCenterY);
  bezierVertex(faceCenterX-40, faceCenterY+12, faceCenterX-60, faceCenterY+12, faceCenterX-75, faceCenterY);
  bezierVertex(faceCenterX-50, faceCenterY-12, faceCenterX-40, faceCenterY-12, faceCenterX-30, faceCenterY);
  endShape();


  fill(128, 94, 94);
  strokeWeight(1);
  circle(faceCenterX-50, faceCenterY, 16);
  fill(1, 1, 0);
  circle(faceCenterX-50, faceCenterY, 9);

  //eye makeup
  noFill();
  strokeWeight(3);
  bezier(faceCenterX-30, faceCenterY, faceCenterX-40, faceCenterY-12, faceCenterX-50, faceCenterY-12, faceCenterX-75, faceCenterY); 


  strokeWeight(1);
  //right eye
  beginShape();
  fill(255);
  vertex(faceCenterX+30, faceCenterY);
  bezierVertex(faceCenterX+40, faceCenterY+12, faceCenterX+60, faceCenterY+12, faceCenterX+75, faceCenterY);
  bezierVertex(faceCenterX+50, faceCenterY-12, faceCenterX+40, faceCenterY-12, faceCenterX+30, faceCenterY);
  endShape();

  fill(128, 94, 94);
  circle(faceCenterX+50, faceCenterY, 16);
  fill(1, 1, 0);
  circle(faceCenterX+50, faceCenterY, 9);


  //eye makeup
  noFill();
  strokeWeight(3);
  bezier(faceCenterX+30, faceCenterY, faceCenterX+40, faceCenterY-12, faceCenterX+50, faceCenterY-12, faceCenterX+75, faceCenterY);


  strokeWeight(1);
  //eye brows
  beginShape();
  fill(51, 25, 0);
  vertex(faceCenterX-30, faceCenterY-20);
  bezierVertex(faceCenterX-35, faceCenterY-30, faceCenterX-60, faceCenterY-35, faceCenterX-80, faceCenterY-20);
  endShape();

  beginShape();
  fill(51, 25, 0);
  vertex(faceCenterX+30, faceCenterY-20);
  bezierVertex(faceCenterX+35, faceCenterY-30, faceCenterX+60, faceCenterY-35, faceCenterX+80, faceCenterY-20);
  endShape();

  //nose
  noFill();
  stroke(51, 25, 0);
  bezier(faceCenterX-15, faceCenterY+40, faceCenterX-5, faceCenterY+50, faceCenterX+5, faceCenterY+50, faceCenterX+15, faceCenterY+40);

  //mouth
  fill(255, 153, 153);
  stroke(255, 102, 102);
  beginShape();
  vertex(faceCenterX-30, faceCenterY+80);
  bezierVertex(faceCenterX-15, faceCenterY+70, faceCenterX-10, faceCenterY+70, faceCenterX, faceCenterY+75);
  bezierVertex(faceCenterX+10, faceCenterY+70, faceCenterX+15, faceCenterY+70, faceCenterX+30, faceCenterY+80);
  endShape();

  beginShape();
  vertex(faceCenterX+30, faceCenterY+80);
  bezierVertex(faceCenterX+20, faceCenterY+90, faceCenterX-20, faceCenterY+90, faceCenterX-30, faceCenterY+80);
  endShape();

  //blush
  noStroke();
  fill(255, 185, 185);
  circle(faceCenterX-70, faceCenterY+50, 40);
  circle(faceCenterX+70, faceCenterY+50, 40);
  
  
  //extra blush
  if (mouseX > faceCenterX-110 && mouseX < faceCenterX-30){
    if (mouseY > faceCenterY+10 && mouseY < faceCenterY+90){
      fill(255, 102, 102);
      circle(faceCenterX-70, faceCenterY+50, 40);
      circle(faceCenterX+70, faceCenterY+50, 40);
    }
  }
    
  if (mouseX > faceCenterX+30 && mouseX < faceCenterX+110){
    if (mouseY > faceCenterY+10 && mouseY < faceCenterY+90){
      fill(255, 102, 102);
      circle(faceCenterX-70, faceCenterY+50, 40);
      circle(faceCenterX+70, faceCenterY+50, 40);
    }
  }

   
}

Even though I hard-coded numbers, I did it based on my faceCenter X and Y coordinates. In future work, I will avoid hard-coding. This assignment has shown me how useful https://processing.org/ site is and that there are many interesting things available in processing. Now I’m inspired to know how to use them!

A Self-Portrait Using Processing

Overview:

For this first assignment, I tried to utilize the principles learned in class to best create a portrait of myself using Processing. This involved the use of  Processing’s 2D Primitive shapes, including quads, triangles, arcs, lines and ellipses. I tried to stay within the bounds of what we have done thus far, but made extensive use of the basic coding principles we have covered including the use of variables to accomplish scaling and parameter specification.

Process:

For this assignment I took the warm up exercise we finished in class and continued on to make it an entire portrait. I first chose which shapes I wanted to utilize to compose a feature such as a nose or a mouth, and placed them in a 640×480 canvas. Once I was happy with how the face looked at this point I replaced everything with variables that could be easily adjusted to tweak certain features such as size or placement, as well as make it easily scalable to any 4×3 resolution just by changing the canvas size.

Code: 

In my code I made sure to divide everything out into clear sections with comments so that I could easily find and tweak features as needed. This allowed me to easily manipulate what I had already done. You will note that I initialize all my variables before running anything. These parameters define the face and could easily be tweaked to make any sort of face, not just one that looks like me! This gives futures possibilities for a UI that would allow a simple character creature.

Once all my parameters were defined I went ahead and created a larger 4×3 canvas, set certain position variables, and then continued on to draw my face with the parameters defined initially. I took advantage of how Processing layers shapes to create features such as the shirt, neck line, and ears with far less math by letting other features simple draw over the top as necessary instead of needing more complex shapes.

//Position variables
int centerX;
int centerY;
float faceScale = 1;

//Face Parameters
float faceWidth = 200;
float faceHeight = 250;

float neckHeight = 330; //arc from center
float neckWidth = 100; //arc from center

float pocketHeight = 80;
float pocketWidth = 40;
float pocketPosX = 60;  //relative to center of face
float pocketPosY = 180;  //relative to center of face

float earHeight = 0;  //0 is center of face
float earLength = 20;
float earWidth = 10;

float eyeScale = 1;
float eyeHeight = 20;  //0 is center of face
float eyeDistance = 30; //0 is pupil aligned with center

float mouthHeight = 30;  //0 is not center, center or curve
float mouthWidth = 100;
float mouthThickness = 110;

float hairLine = 70; // 0 is center
float hairHeight = 60;
float hairSweep = -30;
float sideBurnDepth = 20;
float sideBurnHeight = 60;

void setup() {
  size(640, 480); //!!Maintain 4x3 for right aspect ratio!! (640, 480), (1280, 960) etc..
  //size(1280, 960); //!!Maintain 4x3 for right aspect ratio!! (640, 480), (1280, 960) etc..
  centerX = width/2;
  centerY = height/2;
  faceScale = width/640;
}

void draw() {

  background(255);  //white
  //RGB
  stroke(0);

  //line(centerX, centerY, width, height); //draw line from center to bottom right corner

  //Shirt
  fill(#006994);  //Shirt Color
  triangle(centerX, centerY, centerX - faceScale*160, height, centerX + faceScale*160, height);
  fill(255, 233, 208);
  arc(centerX, centerY, faceScale*neckWidth, faceScale*neckHeight, 0, PIE, CHORD);//neckline
  fill(159,226,191);
  arc(centerX + faceScale*pocketPosX, centerY + faceScale*pocketPosY, faceScale*pocketWidth, faceScale*pocketHeight, 0, PIE, CHORD);//Pocket

  //Ears
  fill(255, 233, 208);
  ellipse(centerX - faceScale*faceWidth/2, centerY + faceScale*earHeight, faceScale*earWidth, faceScale*earLength);
  ellipse(centerX + faceScale*faceWidth/2, centerY + faceScale*earHeight, faceScale*earWidth, faceScale*earLength);
  

  //Face
  fill(255, 233, 208);
  ellipse(centerX, centerY, faceScale*faceWidth, faceScale*faceHeight); //(width, height, diameter)

  //EYES
  //Eyelash
  noFill();
  arc(centerX + faceScale*eyeDistance, centerY - faceScale*eyeHeight - 8, eyeScale*faceScale*30, eyeScale*faceScale*15, PI+QUARTER_PI, TWO_PI-QUARTER_PI);
  arc(centerX - faceScale*eyeDistance, centerY - faceScale*eyeHeight - 8, eyeScale*faceScale*30, eyeScale*faceScale*15, PI+QUARTER_PI, TWO_PI-QUARTER_PI);
  noStroke();
  //White Part
  fill(255);
  ellipse(centerX + faceScale*eyeDistance, (centerY - faceScale*eyeHeight), eyeScale*faceScale*30, eyeScale*faceScale*15); //(width, height, diameter)
  ellipse(centerX - faceScale*eyeDistance, (centerY - faceScale*eyeHeight), eyeScale*faceScale*30, eyeScale*faceScale*15); //(width, height, diameter)
  // Blue eyes
  fill(0, 0, 255);
  ellipse(centerX + faceScale*eyeDistance, (centerY - faceScale*eyeHeight), eyeScale*faceScale*15, eyeScale*faceScale*15); //(width, height, diameter)
  ellipse(centerX - faceScale*eyeDistance, (centerY - faceScale*eyeHeight), eyeScale*faceScale*15, eyeScale*faceScale*15); //(width, height, diameter)
  //Outline to see pupil
  fill(255);
  ellipse(centerX + faceScale*eyeDistance, (centerY - faceScale*eyeHeight), eyeScale*faceScale*6, eyeScale*faceScale*6); //(width, height, diameter)
  ellipse(centerX - faceScale*eyeDistance, (centerY - faceScale*eyeHeight), eyeScale*faceScale*6, eyeScale*faceScale*6); //(width, height, diameter)
  //Pupil
  fill(0);
  ellipse(centerX + faceScale*eyeDistance, (centerY - faceScale*eyeHeight), eyeScale*faceScale*5, eyeScale*faceScale*5); //(width, height, diameter)
  ellipse(centerX - faceScale*eyeDistance, (centerY - faceScale*eyeHeight), eyeScale*faceScale*5, eyeScale*faceScale*5); //(width, height, diameter)
  
  
  //Nose
  stroke(0);
  line(centerX, centerY, centerX + faceScale*20, centerY + faceScale*30);
  line(centerX, centerY + faceScale*30, centerX + faceScale*20, centerY + faceScale*30);
  
  //Mouth
  stroke(191, 112, 104);
  fill(255);
  strokeWeight(faceScale*8);
  arc(centerX, centerY + faceScale*mouthHeight, faceScale*mouthWidth, faceScale*mouthThickness, QUARTER_PI, PI-QUARTER_PI, CHORD);
  strokeWeight(faceScale*1);
  
  //Hair
  noStroke();
  fill(227,204,136);
  quad(centerX + faceScale*faceWidth/2, centerY - faceScale*hairLine, centerX - faceScale*faceWidth/2, centerY - faceScale*hairLine, centerX - faceScale*faceWidth/2 + faceScale*hairSweep, centerY - faceScale*hairLine - faceScale*hairHeight, centerX + faceScale*faceWidth/2 + faceScale*hairSweep, centerY - faceScale*hairLine - faceScale*hairHeight);
  triangle(centerX + faceScale*faceWidth/2, centerY - faceScale*hairLine, centerX + faceScale*faceWidth/2 - faceScale*sideBurnDepth, centerY - faceScale*hairLine, centerX + faceScale*faceWidth/2, centerY - faceScale*hairLine + faceScale*sideBurnHeight);
  triangle(centerX - faceScale*faceWidth/2, centerY - faceScale*hairLine, centerX - faceScale*faceWidth/2 + faceScale*sideBurnDepth, centerY - faceScale*hairLine, centerX - faceScale*faceWidth/2, centerY - faceScale*hairLine + faceScale*sideBurnHeight);
}

 

Going Forward:

As mentioned previously, there is a lot more that could be done with this project. The goal was to use simplistic shapes and drawing techniques to make the best portrait we could. Using future techniques such as loops I would create more complex shapes such as eye lashes, or control statements to create a UI. This would all allow greater customizability overall.

An Interactive Game and a Self Portrait

For our first week of classes, we were given the task of making a self portrait using processing. In order to tackle this problem, I had to first understand the resources at my disposal and then figure out a way to use them in the best way possible in order to render my vision of the self portrait.

Apart from the functions we learnt in class, the circle( ), arc( ) and ellipse( ), I found the beginShape( ) – endShape( ) and curve( ) functions to be extremely helpful. However during my use of them I had run into some difficulties and then had resolved them thanks to the suggestion given by Professor Aaron. The following is a list of some of those difficulties followed by their resolution.

Difficulties:

  • The curve functions work on the principle of a bezeir curve which involves the use of control points and anchor points. The curve function comprises of the coordinates of four points in which the second and third points depict the beginning and end points of the curve and the first and fourth refer the control points. It was thus difficult to predict the location of the curve point in order to get the right curve and this was highly tiresome since the structure of the portrait involved the use of a lot of curves.
  • Even after getting the curves done, figuring out how to fill them was a task in itself. Since I had initially made shapes using a combination of curves and lines, using the fill function simply did not solve the task. An example of this is if i would make a shape like → )__| then the fill function would fill up the curve and the line joining its beginning and end points, instead of filling up the shape.

Resolution:

  • The resolution to the first problem was actually suggested by Professor Aaron, in which I used mouseX and mouseY as arguments in the curve function. This allowed me to see how the curve would change according to the mouse coordinates. I would then keep a track of the mouse coordinates using the following line of code.
      text("x: "+(mouseX-faceCenterX)+" y: "+(mouseY-faceCenterY), mouseX, mouseY);
    

    After finding the appropriate coordinate, I would then write it in the curve function.

  • In order to tackle the fill problem, I learnt to implement the beginShape() and endShape() functions. Using my preliminary figures of curves and lines, I would get an estimate of the vertices needed to create the shape and then I would jot them down and put it in between the beginShape() and endShape() functions. This way I would generate a shape of my own and then the fill process would be easier.

Workflow:

  • My workflow for this task primarily involved the following:
    • Ideation
    • Creation
    • Addition

Ideation:

  • For the Ideation, process., I had actually started browsing through some of my portraits in order to find a picture that does not emphasis a lot on the details and would be simple to represent through arcs and lines.
  • After finding a picture like that, I drew a simple sketch of it on my iPad. During sketching my portrait, I made sure to identify components that could be made by curves and lines so that I could recreate them in processing.

    Portrait and Sketch

Creation:

  • After reviewing the sections of the portrait, I started implementing them in processing. The first step was to get a basic structure done which comprised of the hair, face, eyes, ear and smile. After that details such as the eyebrows, nostrils, neck and shirt were added. These were then filled with the appropriate colors
    Basic Structure

    Portrait Skeleton
Final

Addition:

  • After the portrait was done, I felt the project required some amount of interactivity and I added three interactive features.
    • An emoticon option which provides you with three ways to change your characters smile – he can grin, he can be sad, he can smile with his teeth. I implemented this by assigning an if function which would display the correct emoticon when clicked.
    • Size change buttons which could alter the size of the portrait among small, medium and large. This was easy to implement as I had kept the faceSize a variable and had not hard coded the project.
    • A hair color palette which could toggle the portrait’s hair color from blond to light brown to dark brown and to black. In order to do this I had kept the rgb values of the fill function as variables.
    • A dynamic background of expanding circles. I actually got this idea from a previous post in the IM Website (Sarah Al-Yahya, 13 September 2020) and found it really cool. Hence, I implemented this in my own project.

Concepts Learned:

  • This project taught me how to play with shapes and how one can use the crazy amount of possibilities to experiment with them.
  • It taught me to think out of the box in order to find creative solutions to problems.

Project Video:

Thought of doing something that would connect IM to another passion of mine, Film!

So, this is the first episode of 3 minutes or less! A short vlog series in which I describe my experiences with IM Projects in 3 minutes or less.

I really hope I can carry this throughout the semester, although midterm and final weeks can be a bit scary 🙁

PS: Will try fixing the background audio next time!

Project Code:

int faceCenterX;
int faceCenterY;
float faceSize; //face variables 

int hair_color_r = 63; //initializing hair color
int hair_color_g = 42; 
int hair_color_b = 20;

int smileValue = 1; // initializing smile 

color first_Ringcolor = color(255, 153, 51);//255,179,102);
color second_Ringcolor = color(255, 166, 77);//255,191,128);
color third_Ringcolor = color(255, 179, 102);//255,204,153);
color fourth_Ringcolor = color(255, 191, 128);
color fifth_Ringcolor = color(255, 204, 153);
int x;
int y;
int circle_width_1;
int circle_width_2;
int circle_width_3;
int circle_width_4;
int circle_width_5;
int expand = 1; //for dynamic background



void eyebrow() {
  strokeWeight(1);
  fill(63, 42, 20);
  beginShape();
  vertex(faceCenterX-int(faceSize*0.425), faceCenterY-int(faceSize*0.250));
  vertex(faceCenterX-int(faceSize*0.415), faceCenterY-int(faceSize*0.300));
  vertex(faceCenterX-int(faceSize*0.400), faceCenterY-int(faceSize*0.315));
  vertex(faceCenterX-int(faceSize*0.300), faceCenterY-int(faceSize*0.340));
  vertex(faceCenterX-int(faceSize*0.250), faceCenterY-int(faceSize*0.345));
  vertex(faceCenterX-int(faceSize*0.175), faceCenterY-int(faceSize*0.345));
  vertex(faceCenterX-int(faceSize*0.125), faceCenterY-int(faceSize*0.340));
  vertex(faceCenterX-int(faceSize*0.100), faceCenterY-int(faceSize*0.315));
  vertex(faceCenterX-int(faceSize*0.125), faceCenterY-int(faceSize*0.275));
  vertex(faceCenterX-int(faceSize*0.175), faceCenterY-int(faceSize*0.280));
  vertex(faceCenterX-int(faceSize*0.250), faceCenterY-int(faceSize*0.275));
  vertex(faceCenterX-int(faceSize*0.325), faceCenterY-int(faceSize*0.270));   
  endShape(CLOSE);                        //left eyebrow


  beginShape();
  vertex(faceCenterX+int(faceSize*0.425), faceCenterY-int(faceSize*0.250));
  vertex(faceCenterX+int(faceSize*0.415), faceCenterY-int(faceSize*0.300));
  vertex(faceCenterX+int(faceSize*0.400), faceCenterY-int(faceSize*0.315));
  vertex(faceCenterX+int(faceSize*0.300), faceCenterY-int(faceSize*0.340));
  vertex(faceCenterX+int(faceSize*0.250), faceCenterY-int(faceSize*0.345));
  vertex(faceCenterX+int(faceSize*0.175), faceCenterY-int(faceSize*0.345));
  vertex(faceCenterX+int(faceSize*0.125), faceCenterY-int(faceSize*0.340));
  vertex(faceCenterX+int(faceSize*0.100), faceCenterY-int(faceSize*0.315));
  vertex(faceCenterX+int(faceSize*0.125), faceCenterY-int(faceSize*0.275));
  vertex(faceCenterX+int(faceSize*0.175), faceCenterY-int(faceSize*0.280));
  vertex(faceCenterX+int(faceSize*0.250), faceCenterY-int(faceSize*0.275));
  vertex(faceCenterX+int(faceSize*0.325), faceCenterY-int(faceSize*0.270));   
  endShape(CLOSE);                        //right eyebrow
}

void face() {
  fill(255, 206, 180);
  stroke(0);
  beginShape();
  vertex(faceCenterX-int(faceSize*0.500), faceCenterY-int(faceSize*0.350));
  vertex(faceCenterX-int(faceSize*0.500), faceCenterY+int(faceSize*0.350));
  vertex(faceCenterX-int(faceSize*0.475), faceCenterY+int(faceSize*0.425));
  vertex(faceCenterX-int(faceSize*0.450), faceCenterY+int(faceSize*0.450));
  vertex(faceCenterX-int(faceSize*0.025), faceCenterY+int(faceSize*0.700));
  vertex(faceCenterX+int(faceSize*0.025), faceCenterY+int(faceSize*0.700));
  vertex(faceCenterX+int(faceSize*0.450), faceCenterY+int(faceSize*0.450));
  vertex(faceCenterX+int(faceSize*0.475), faceCenterY+int(faceSize*0.425));
  vertex(faceCenterX+int(faceSize*0.500), faceCenterY+int(faceSize*0.350));
  vertex(faceCenterX+int(faceSize*0.500), faceCenterY-int(faceSize*0.350));
  vertex(faceCenterX+int(faceSize*0.300), faceCenterY-int(faceSize*0.475));
  vertex(faceCenterX-int(faceSize*0.125), faceCenterY-int(faceSize*0.500));
  vertex(faceCenterX-int(faceSize*0.425), faceCenterY-int(faceSize*0.425));
  endShape(CLOSE); //a face structure involving two lines and two slant lines along with a chin and a big face arch
}

void ear() {
  fill(255, 206, 180);
  beginShape(); //left ear
  curveVertex(faceCenterX-int(faceSize*0.500), faceCenterY-int(faceSize*0.100));
  curveVertex(faceCenterX-int(faceSize*0.500), faceCenterY-int(faceSize*0.250));
  curveVertex(faceCenterX-int(faceSize*0.600), faceCenterY-int(faceSize*0.225));
  curveVertex(faceCenterX-int(faceSize*0.500), faceCenterY-int(faceSize*0.025));
  curveVertex(faceCenterX-int(faceSize*0.500), faceCenterY-int(faceSize*0.350));
  endShape();

  fill(255, 206, 180);
  beginShape(); //right ear
  curveVertex(faceCenterX+int(faceSize*0.500), faceCenterY-int(faceSize*0.100));
  curveVertex(faceCenterX+int(faceSize*0.505), faceCenterY-int(faceSize*0.250));
  curveVertex(faceCenterX+int(faceSize*0.600), faceCenterY-int(faceSize*0.225));
  curveVertex(faceCenterX+int(faceSize*0.505), faceCenterY-int(faceSize*0.025));
  curveVertex(faceCenterX+int(faceSize*0.500), faceCenterY-int(faceSize*0.350));
  endShape();
}

void hair() {
  stroke(0);
  fill(hair_color_r, hair_color_g, hair_color_b); //variable hair color values
  beginShape(); //left hair
  vertex(faceCenterX-int(faceSize*0.500), faceCenterY-int(faceSize*0.350));
  vertex(faceCenterX-int(faceSize*0.600), faceCenterY-int(faceSize*0.500));
  vertex(faceCenterX-int(faceSize*0.625), faceCenterY-int(faceSize*0.650));
  vertex(faceCenterX-int(faceSize*0.550), faceCenterY-int(faceSize*0.750));
  vertex(faceCenterX-int(faceSize*0.375), faceCenterY-int(faceSize*0.800));
  vertex(faceCenterX-int(faceSize*0.150), faceCenterY-int(faceSize*0.750));
  vertex(faceCenterX-int(faceSize*0.150), faceCenterY-int(faceSize*0.700));
  endShape();

  stroke(hair_color_r, hair_color_g, hair_color_b); ////variable hair color values so that the middle stroke is not seen
  fill(hair_color_r, hair_color_g, hair_color_b); //variable color values
  beginShape(); //middle hair
  vertex(faceCenterX-int(faceSize*0.075), faceCenterY-int(faceSize*0.750));
  vertex(faceCenterX-int(faceSize*0.150), faceCenterY-int(faceSize*0.750));
  vertex(faceCenterX-int(faceSize*0.450), faceCenterY-int(faceSize*0.425));
  vertex(faceCenterX-int(faceSize*0.125), faceCenterY-int(faceSize*0.500));
  vertex(faceCenterX+int(faceSize*0.325), faceCenterY-int(faceSize*0.475)); 
  endShape();

  stroke(0);
  fill(hair_color_r, hair_color_g, hair_color_b); //variable hair color values
  beginShape(); //right hair
  curveVertex(faceCenterX+int(faceSize*0.500), faceCenterY);
  curveVertex(faceCenterX-int(faceSize*0.150), faceCenterY-int(faceSize*0.750));
  curveVertex(faceCenterX+int(faceSize*0.450), faceCenterY-int(faceSize*0.800));
  curveVertex(faceCenterX+int(faceSize*0.500), faceCenterY-int(faceSize*0.350));
  curveVertex(faceCenterX-int(faceSize*1.500), faceCenterY+int(faceSize*0.500));
  endShape();
}

void eye() {
  stroke(0);
  fill(255);
  ellipse(faceCenterX-int(faceSize*0.250), faceCenterY-int(faceSize*0.150), int(faceSize)*0.250, int(faceSize*0.700)*0.25); //left eye
  ellipse(faceCenterX+int(faceSize*0.250), faceCenterY-int(faceSize*0.150), int(faceSize)*0.250, int(faceSize*0.700)*0.25); //right eye

  fill(153, 77, 0);
  circle(faceCenterX-int(faceSize*0.225), faceCenterY-int(faceSize*0.175), int(faceSize)*0.12); //left iris
  circle(faceCenterX+int(faceSize*0.225), faceCenterY-int(faceSize*0.175), int(faceSize)*0.12); //rught iris

  fill(0);
  circle(faceCenterX-int(faceSize*0.225), faceCenterY-int(faceSize*0.175), int(faceSize)*0.07); //left pupil
  circle(faceCenterX+int(faceSize*0.225), faceCenterY-int(faceSize*0.175), int(faceSize)*0.07); //right pupil

  fill(255);
  circle(faceCenterX-int(faceSize*0.240), faceCenterY-int(faceSize*0.200), int(faceSize)*0.045); //left white spot
  circle(faceCenterX+int(faceSize*0.240), faceCenterY-int(faceSize*0.200), int(faceSize)*0.045); //right whote spot
}

void smile() {

  if (smileValue == 1)
  {
    noFill();
    curve(faceCenterX, faceCenterY-int(faceSize*0.850), 
      faceCenterX-int(faceSize*0.250), faceCenterY+int(faceSize*0.275), 
      faceCenterX+int(faceSize*0.250), faceCenterY+int(faceSize*0.275), 
      faceCenterX, faceCenterY-int(faceSize*0.850)); // happy smile

    line(faceCenterX-int(faceSize*0.225), faceCenterY+int(faceSize*0.250), 
      faceCenterX-int(faceSize*0.275), faceCenterY+int(faceSize*0.300)); //small face line left

    line(faceCenterX+int(faceSize*0.225), faceCenterY+int(faceSize*0.250), 
      faceCenterX+int(faceSize*0.275), faceCenterY+int(faceSize*0.300)); //small face line right
  }

  if (smileValue == 2)
  {
    noFill();
    curve(faceCenterX, faceCenterY+int(faceSize), 
      faceCenterX-int(faceSize*0.250), faceCenterY+int(faceSize*0.375), 
      faceCenterX+int(faceSize*0.250), faceCenterY+int(faceSize*0.375), 
      faceCenterX, faceCenterY+int(faceSize)); // sad face
  }

  if (smileValue == 3)
  {
    noFill();
    beginShape();
    curveVertex(faceCenterX, faceCenterY-int(faceSize*0.725)); 
    curveVertex(faceCenterX-int(faceSize*0.300), faceCenterY+int(faceSize*0.200)); 
    curveVertex(faceCenterX, faceCenterY+int(faceSize*0.500));
    curveVertex(faceCenterX+int(faceSize*0.300), faceCenterY+int(faceSize*0.200)); 
    curveVertex(faceCenterX, faceCenterY-int(faceSize*0.725));
    endShape(); //big smile curve


    beginShape(); 
    curve(faceCenterX, faceCenterY-int(faceSize*0.300), 
      faceCenterX-int(faceSize*0.300), faceCenterY+int(faceSize*0.200), 
      faceCenterX+int(faceSize*0.300), faceCenterY+int(faceSize*0.200), 
      faceCenterX, faceCenterY-int(faceSize*0.300)); // small smile curve

    fill(255); 
    curve(faceCenterX, faceCenterY-int(faceSize*0.325), 
      faceCenterX-int(faceSize*0.285), faceCenterY+int(faceSize*0.275), 
      faceCenterX+int(faceSize*0.285), faceCenterY+int(faceSize*0.275), 
      faceCenterX, faceCenterY-int(faceSize*0.325)); // teeth
    endShape();

    fill(255);
    noStroke();
    beginShape();
    vertex(faceCenterX-int(faceSize*0.300), faceCenterY+int(faceSize*0.200));
    vertex(faceCenterX-int(faceSize*0.295), faceCenterY+int(faceSize*0.260));
    vertex(faceCenterX-int(faceSize*0.285), faceCenterY+int(faceSize*0.275));
    vertex(faceCenterX, faceCenterY+int(faceSize*0.275));
    vertex(faceCenterX-int(faceSize*0.125), faceCenterY+int(faceSize*0.270));
    vertex(faceCenterX-int(faceSize*0.250), faceCenterY+int(faceSize*0.250));
    endShape(CLOSE); //teeth filler


    fill(255);
    noStroke();
    beginShape();
    vertex(faceCenterX+int(faceSize*0.300), faceCenterY+int(faceSize*0.200));
    vertex(faceCenterX+int(faceSize*0.295), faceCenterY+int(faceSize*0.260));
    vertex(faceCenterX+int(faceSize*0.285), faceCenterY+int(faceSize*0.275));
    vertex(faceCenterX, faceCenterY+int(faceSize*0.275));
    vertex(faceCenterX+int(faceSize*0.125), faceCenterY+int(faceSize*0.270));
    vertex(faceCenterX+int(faceSize*0.250), faceCenterY+int(faceSize*0.250));
    endShape(CLOSE); //teeth filler
  }
}

void nose() {
  noFill();
  strokeWeight(2);
  stroke(205, 133, 63);
  beginShape();
  vertex(faceCenterX, faceCenterY+int(faceSize*0.175));
  vertex(faceCenterX-int(faceSize*0.025), faceCenterY+int(faceSize*0.175));
  vertex(faceCenterX-int(faceSize*0.040), faceCenterY+int(faceSize*0.150));
  vertex(faceCenterX-int(faceSize*0.050), faceCenterY+int(faceSize*0.125));
  vertex(faceCenterX-int(faceSize*0.075), faceCenterY+int(faceSize*0.120));
  vertex(faceCenterX-int(faceSize*0.088), faceCenterY+int(faceSize*0.100));
  vertex(faceCenterX-int(faceSize*0.075), faceCenterY+int(faceSize*0.075));
  endShape(); // left nose

  noFill();
  strokeWeight(2);
  stroke(205, 133, 63);
  beginShape();
  vertex(faceCenterX, faceCenterY+int(faceSize*0.175));
  vertex(faceCenterX+int(faceSize*0.025), faceCenterY+int(faceSize*0.175));
  vertex(faceCenterX+int(faceSize*0.040), faceCenterY+int(faceSize*0.150));
  vertex(faceCenterX+int(faceSize*0.050), faceCenterY+int(faceSize*0.125));
  vertex(faceCenterX+int(faceSize*0.075), faceCenterY+int(faceSize*0.120));
  vertex(faceCenterX+int(faceSize*0.088), faceCenterY+int(faceSize*0.100));
  vertex(faceCenterX+int(faceSize*0.075), faceCenterY+int(faceSize*0.075));
  endShape(); // right nose

  noFill();
  strokeWeight(2);
  stroke(205, 133, 63);
  beginShape();
  vertex(faceCenterX-int(faceSize*0.070), faceCenterY+int(faceSize*0.075));
  vertex(faceCenterX-int(faceSize*0.060), faceCenterY-int(faceSize*0.010));
  vertex(faceCenterX-int(faceSize*0.050), faceCenterY-int(faceSize*0.060));
  endShape(); // nose line
}

void body_shoulder() {
  strokeWeight(1);
  stroke(0);
  fill(201, 255, 229);
  beginShape();
  vertex(faceCenterX-int(faceSize*0.300), faceCenterY+int(faceSize*0.775));
  vertex(faceCenterX-int(faceSize*0.450), faceCenterY+int(faceSize*0.860));
  vertex(faceCenterX-int(faceSize*0.575), faceCenterY+int(faceSize*0.875));
  vertex(faceCenterX-int(faceSize*0.625), faceCenterY+int(faceSize*0.950));
  vertex(faceCenterX-int(faceSize*0.625), faceCenterY+int(faceSize*1.025));
  vertex(faceCenterX-int(faceSize*0.625), faceCenterY+int(faceSize*1.100));
  vertex(faceCenterX-int(faceSize*0.600), faceCenterY+int(faceSize*1.200)); //left shoulder and body

  vertex(faceCenterX+int(faceSize*0.600), faceCenterY+int(faceSize*1.200));
  vertex(faceCenterX+int(faceSize*0.625), faceCenterY+int(faceSize*1.100));
  vertex(faceCenterX+int(faceSize*0.625), faceCenterY+int(faceSize*1.025));
  vertex(faceCenterX+int(faceSize*0.625), faceCenterY+int(faceSize*0.950));
  vertex(faceCenterX+int(faceSize*0.575), faceCenterY+int(faceSize*0.875));
  vertex(faceCenterX+int(faceSize*0.450), faceCenterY+int(faceSize*0.860));
  vertex(faceCenterX+int(faceSize*0.300), faceCenterY+int(faceSize*0.775)); //right shoulder and body
  endShape();
}

void neck() {
  strokeWeight(1);
  stroke(0);
  fill(255, 206, 180);
  beginShape();
  vertex(faceCenterX-int(faceSize*0.025), faceCenterY+int(faceSize*0.700));
  vertex(faceCenterX-int(faceSize*0.250), faceCenterY+int(faceSize*0.575));
  vertex(faceCenterX-int(faceSize*0.225), faceCenterY+int(faceSize*0.600));
  vertex(faceCenterX-int(faceSize*0.215), faceCenterY+int(faceSize*0.650));
  vertex(faceCenterX-int(faceSize*0.300), faceCenterY+int(faceSize*0.775));
  vertex(faceCenterX+int(faceSize*0.300), faceCenterY+int(faceSize*0.775));
  vertex(faceCenterX+int(faceSize*0.215), faceCenterY+int(faceSize*0.650));
  vertex(faceCenterX+int(faceSize*0.225), faceCenterY+int(faceSize*0.600));
  vertex(faceCenterX+int(faceSize*0.250), faceCenterY+int(faceSize*0.575));
  vertex(faceCenterX+int(faceSize*0.025), faceCenterY+int(faceSize*0.700));
  endShape(); //neck outline


  fill(255, 206, 180);
  curve(faceCenterX, faceCenterY-int(faceSize*1.200), 
    faceCenterX-int(faceSize*0.300), faceCenterY+int(faceSize*0.775), 
    faceCenterX+int(faceSize*0.300), faceCenterY+int(faceSize*0.775), 
    faceCenterX, faceCenterY-int(faceSize*1.200)); //neck curve
}

void sizeControl() {
  fill(114, 160, 193);
  rect(width/2 - 300, height/2 + 105, 25, 15);  //small size portrait

  fill(114, 160, 193);
  rect(width/2 - 300, height/2 + 135, 50, 20);  //medium size portrait

  fill(114, 160, 193);
  rect(width/2 - 300, height/2 + 170, 90, 25);  //dark size portrait
}

void hairControl() {

  fill(250, 240, 190);
  circle(width/2+215, height/2-175, 50); //blond hair

  fill(181, 101, 29);
  circle(width/2+215, height/2-105, 50); //light brown hair

  fill(63, 42, 20);
  circle(width/2+215, height/2-35, 50);  //dark brown hair

  fill(0);
  circle(width/2+215, height/2+35, 50);  //black hair
}  

void moodCheck() {

  fill(255, 191, 0);
  circle(width/2-280, height/2-25, 30);
  fill(0);
  circle(width/2-285, height/2-30, 5);
  circle(width/2-275, height/2-30, 5);
  fill(255, 191, 0);
  arc(width/2-280, height/2-25, 20, 15, 0, PI); //happy mood emoticon
  //////////////////
  fill(255, 191, 0);
  circle(width/2-240, height/2-25, 30);
  fill(0);
  circle(width/2-245, height/2-30, 5);
  circle(width/2-235, height/2-30, 5);
  fill(255, 191, 0);
  curve(width/2-240, height/2, 
    width/2-250, height/2-20, 
    width/2-230, height/2-20, 
    width/2-240, height/2);  //sad mood emoticon
  ///////////////////
  fill(255, 191, 0);
  circle(width/2-200, height/2-25, 30);
  fill(0);
  circle(width/2-205, height/2-30, 5);
  circle(width/2-195, height/2-30, 5);
  fill(255);
  arc(width/2-200, height/2-22.5, 20, 15, 0, PI);
  line(width/2-210, height/2-22.5, width/2-190, height/2-22.5); //very happy mood emoticon
}


void sizeActionBox() 
{
  if ((mouseX >= width/2-300)  && (mouseX <= width/2-275))
  {
    if (mouseY >= height/2+105 && mouseY <= height/2+120)
    {
      faceSize = 100.0;
    }
  }

  if ((mouseX >= width/2-300)  && (mouseX <= width/2-250))
  {
    if (mouseY >= height/2+135 && mouseY <= height/2+155)
    {
      faceSize = 150.0;
    }
  }


  if ((mouseX >= width/2-300)  && (mouseX <= width/2-210))
  {
    if (mouseY >= height/2+175  && mouseY <= height/2+200)
    {
      faceSize = 200.0;
    }
  }
}

void hairActionBox() //for changing hair color depending on where the mouse is pressed
{
  if ((dist(mouseX, mouseY, width/2+215, height/2-175) <= 25))
  {
    hair_color_r = 250;
    hair_color_g = 240;
    hair_color_b = 190;
  }

  if ((dist(mouseX, mouseY, width/2+215, height/2-105) <= 25))
  {
    hair_color_r = 181; 
    hair_color_g = 101;
    hair_color_b = 29;
  }

  if ((dist(mouseX, mouseY, width/2+215, height/2-35) <= 25))
  {
    hair_color_r = 63; 
    hair_color_g = 42;
    hair_color_b = 20;
  }

  if ((dist(width/2+215, height/2+35, mouseX, mouseY) <= 25))
  {
    hair_color_r = 0;
    hair_color_g = 0;
    hair_color_b = 0;
  }
}


void smileActionBox()  //for changing smile depending on where the mouse is pressed
{
  if ((dist(mouseX, mouseY, width/2-280, height/2-25) <= 25))
  {
    smileValue = 1;
  }

  if ((dist(mouseX, mouseY, width/2-240, height/2-25) <= 25))
  {
    smileValue = 2;
  }

  if ((dist(mouseX, mouseY, width/2-200, height/2-25) <= 25))
  {
    smileValue = 3;
  }
}

void setup()
{
  size(640, 480);
  faceCenterX = width/2;
  faceCenterY = height/2;
  float a = 200.0;
  faceSize =a;
  circle_width_1 = 480;
  circle_width_2 = 360;
  circle_width_3 = 240;
  circle_width_4 = 120;
  circle_width_5 = 40;
}

void draw()
{

  background(255,140,25);


  //dynamic background
  x = width/ 2;
  y = height / 2;

  stroke(first_Ringcolor);
  strokeWeight(60);
  noFill();
  circle(x, y, circle_width_1);  //concentric circles
  stroke(second_Ringcolor);
  circle(x, y, circle_width_2);
  stroke(third_Ringcolor);
  circle(x, y, circle_width_3);
  stroke(fourth_Ringcolor);
  circle(x, y, circle_width_4);
  stroke(fifth_Ringcolor);
  strokeWeight(40);
  circle(x, y, circle_width_5);


  circle_width_1 = circle_width_1 + expand; //circles expanding for dynamic effect
  circle_width_2 = circle_width_2 + expand;
  circle_width_3 = circle_width_3 + expand;
  circle_width_4 = circle_width_4 + expand;
  circle_width_5 = circle_width_5 + expand;

  //upper limit
  if (circle_width_1 > 640 ) {
    circle_width_1 = 480;
  }

  if (circle_width_2 > 520 ) {
    circle_width_2 = 360;
  }
  if (circle_width_3 > 400 ) {
    circle_width_3 = 240;
  }
  if (circle_width_4 > 280 ) {
    circle_width_4 = 120;
  }
  if (circle_width_5 > 160 ) {
    circle_width_5 = 80;
  }

  stroke(0);
  strokeWeight(1);
  face();
  ear();
  nose();
  eye();
  eyebrow();
  smile();
  hair();
  body_shoulder();
  neck();
  sizeControl();
  hairControl();
  moodCheck();
}

void mousePressed()
{

  sizeActionBox();
  /////////////////////////////////////////////
  hairActionBox();
  ////////////////////////////////
  smileActionBox();
}

 

Week 1: Self-Portrait

In class this week, we played around with the coordinate system and making shapes in Processing.

Processing sketch of three ellipses and arc creating face structure with purple background
Processing sketch from Wednesday’s class.

For our practice this week, I wanted to experiment with pixel art but the prospect of measuring and coloring every little rectangle filled me with dread. I remember watching a Coding Train video a while ago where Dan Shiffman used a .get() method to get the color from an image, so I decided to create the rectangles based on an image.

In terms of the pseudocode:

  1. Load an image (keep in same sketch folder)
  2. Define the canvas size.
  3. Pick a random x and y coordinate from the photo.
  4. Get the color of the photo at that x,y point.
  5. Create a rectangle at that x,y point with the fill of the color.

Here is my sketch:

Some of the design choices I thought about were the size of the rectangles (how pixellated should the portrait be?), the fill of the rectangles (should they be the same as the image or should there be different colors, alphas, brightnesses?), the framerate of the drawing (how fast should the rectangles be created?).

An interesting part of the code to me was the .get() method I learned about in the Coding Train video. This method essentially gets the color of the image at the x,y point. You can see the code below.

PImage me;
//define size of the rectangle
int pixelSize = 20;

void setup() {
  size(600,715);
  me = loadImage("me.jpg");
  //controls speed of drawing pixels
  frameRate(300);
}

void draw() {
    //create random x,y point within the sketch
    float x = random(width);
    float y = random(height);
    //learned about .get() from from Daniel Shiffman's Processing tutorial on pixels https://www.youtube.com/watch?v=NbX3RnlAyGU
    //get color from image at the x,y point
    color c = me.get(int(x), int(y));
    fill(c);
    noStroke();
    //draws rectangle at the x,y point with the color from the image
    rect(x, y, pixelSize, pixelSize);
}

The whole sketch is available here.