A workflow of converting pictures into p5js drawing functions

Here’s the final output(hint: try to move the mouse around the portrait).

Inspiration:

From long ago, I watched the Love Death + Robots series produced by Netflix and loved the story of Zima Blue. https://www.imdb.com/title/tt9788510/ . I love the plot and the artistic choice, so when it comes to a chance to digitally create something related to my self-portrait, I decided to draw a painting in the style of Zima Blue.

However, I am not good at drawing and learn how to draw picture quickly in p5js almost seems impossible. Thanks to the development of computer vision and the style transfer algorithm(https://en.wikipedia.org/wiki/Neural_style_transfer), I was able to upload my picture and a photo of Zima Blue to ChatGPT and ask it to perform style transfer.

Here’s the Zima Blue original episode screenshot and the photo I obtained after style transferring to one of my photos.

Zima Blue. My most watched episode. : r/LoveDeathAndRobots

(original episode screenshot)

(style-transferred picture)

Work Flow:

However, the produced format is in jpg style and it is impossible to convert it into drawing functions that are built in p5js. And directly asking GPT to transfer the image to p5js code produces unintended effects.

 

(direct p5js conversion)

 

I consulted previous student Pi(pi.ko@nyu.edu) for assistance and solution is followed:

  1. upload the jpg file to websites like(https://www.cutout.pro/photo-enhancer-sharpener-upscaler) to increase the number of pixels in the photo.
  2. load the file into Adobe Illustrator use the Make Trace Command to receive the SVG file(https://en.wikipedia.org/wiki/SVG) which contains all the x,y coordinate of the lines so it is possible for it to be converted into built-in functions in p5js(the parser could be found in the appendix)

After this, I worked with GPT to color the drawing. Since they are of irregular shapes and the parser convert them into coordinates, it is hard for me to identify which parts to color. So, I ask GPT to write a helper function to label the region of the curves and the coloring comes after.

In the end, I want to add an effect of changing the background color with mouse moving, so the central logic behind is as followed:

// Normalize mouse to 0..1 (works even when mouse is outside the canvas)
const mx = constrain(mouseX / width,  0, 1);
const my = constrain(mouseY / height, 0, 1);

// Use mouseX to steer hue, mouseY to steer saturation/brightness.
// Feel free to tweak the ranges to taste.
const baseHue = map(mx, 0, 1, 20, 220, true);     // left→right: orange → blue
const sat     = map(my, 0, 1, 70, 90,  true);     // bottom→top: more vivid
const bTop    = map(my, 0, 1, 95, 70,  true);     // top band gets darker as you go down
const bMid    = map(my, 0, 1, 90, 65,  true);
const bBot    = map(my, 0, 1, 80, 60,  true);

The complete code and the parser could be found on:

  1. complete code(copy and paste the code into p5js and you will receive what’s above): https://github.com/dr04002/Intro_IM/blob/acaed841ba9257a17bef0dad063c0cf1d1e4a1bb/sketch.js
  2. parser:https://github.com/dr04002/Intro_IM/blob/acaed841ba9257a17bef0dad063c0cf1d1e4a1bb/svg_conversion

Here are future improvements that I could make:

  1. the left shoulder should be blue but they are left blank in this drawing
  2. the size of the canvas should fit the size of the main portrait so there’s no blank on the bottom,

Self-portrait – Aizhan

Concept:

When I began thinking about how I wanted to represent myself in a self-portrait, the moon immediately came to mind. My name, Aizhan, means “moonsoul” in Kazakh, and I feel that the moon will be the great representation of who I am. I wanted my portrait to convey not just my physical appearance, but also my personality and identity. Before bringing the portrait to life in p5, I started with sketches on paper. These first drawings helped me organize my ideas and experiment with shapes, composition, and visual elements, allowing me to see how I could best represent myself.

One of the interactive features of the final portrait is that when viewers click on it, my eyes move from side to side. This small animation gives the portrait a sense of life and presence, making it feel as though it is observing and engaging with the viewer. Another feature is a falling star across the background. The star represents an aspect of my inner self, like a spark of energy, curiosity, or imagination that is always part of who I am.

Highlight of the code I am proud of:

The part of my project that I am most proud of is the code that makes the eyes move when the viewer clicks on the portrait and it was probably the most time consuming part. I chose this feature because it adds a sense of life and interaction to my self-portrait, making it feel like the portrait is really engaging with the viewer. The tutorials and references helped me to figure out how to add interactive elements to my portrait. They guided me through understanding on how to track time with millis() and the lerp() allowed me to make the eyes and star transitions smoother with coordinates.

function mousePressed() { 
  //eye movement and star movement when mouse clicked
  toLeft = !toLeft;      
  anim = true; s = 0; t0 = millis();

 

//pupils
fill(0);
ellipse(pupilX(L0), CY, 5, 5);   
ellipse(pupilX(R0), CY, 5, 5);  


//pupils animation
if (anim) {
  s = (millis() - t0) / 250;
  if (s >= 1) { s = 1; anim = false; }
}

function pupilX(base){
  if (anim) return lerp(toLeft ? base : base + DX, toLeft ? base + DX : base, s);
  return toLeft ? base + DX : base;
}

Sketch:

Reflection:

This was my first time creating this kind of work in p5 and adding animation, and it was really exciting to see how the commands work together to make the portrait come alive. It helped me understand the concept better and gave me new ideas for future projects. In the future, I want to make my work even more interactive and add more details. For example, instead of having just one star falling, I could have several stars falling from the top of the screen. I could also make the moon shine or glow to make the scene feel more magical.

I also would like to add some body parts. For instance, I could add hands, change the outfit, or use different shapes to represent parts of the body. I also want to experiment more with colors to make the portrait more vibrant and expressive.

Self Portrait Assignment 1

Full Screen Sketch 



My concept:

  • For this assignment, I made a self-portrait using basic shapes in p5.js. I drew the face, hair, and features with ellipses, rectangles, and arcs, and added a fun starry background to make it playful. The goal was to practice placing shapes with coordinates and layering them correctly, like using red ellipses to add a blush effect and adding the star effect in the background. 

Code Highlight: 

  • A highlight of some code that i’m particularly proud of is probably the eyes. I spent some extra time making sure the pupils, whites, and tiny highlights looked good together. Even though it’s all basic shapes, adding the little white highlights made the eyes feel alive and gave the portrait more personality. I made sure the codes are in the right order so they overlay the way i want them to and I kept it simple like what we learnt in class and what’s available on the reference website. Also, including the categories for each code really helped keep it organized and easier for me to process and edit.
//eyes
noStroke();
fill(255);
ellipse(170, 170, 25, 16);
ellipse(230, 170, 25, 16);

//pupils
fill(30);
ellipse(170, 170, 12, 12); 
ellipse(230, 170, 12, 12); 

fill(255);
ellipse(170, 168, 4, 4); 
ellipse(230, 168, 4, 4);

Reflection and ideas for future work or improvements: 

  • This was my first time making a self-portrait in p5.js, so I definitely struggled a bit with getting the coordinates right and making the shapes look exactly how I imagined. Positioning everything took some time, but it was a good way to practice patience and planning. Next time, I want to experiment with more than just solid shapes; maybe using lines, gradients, or patterns to make the drawings more interesting. I’d also like to learn how to make the sketches interactive, so they respond to the mouse or keyboard, and generally make them look more polished and professional. Overall, it was a fun way to practice layering shapes, arranging them carefully, and thinking about composition, and I feel like I can improve a lot on these ideas in future projects and maybe further my creativity more with the new skills I’ll learn. 

Self Portrait

Concept

In this assignment , I wanted to  create a simple cartoon-style portrait using  p5.js. I wanted to practice how basic shapes like circles, rectangles, and arcs can be layered to form a face. Instead of making it realistic, I focused on keeping it playful and expressive.

I also wanted my portrait to react to the viewer. That’s why I added interactivity with the mouse. The eyes follow the mouse pointer around the screen, and the mouth changes its size depending on how high or low the mouse is. This makes the portrait feel alive, almost as if it is looking back at you.

Code Highlight

One part of the code I am most proud of is how I handled the pupils. Normally, if you just link the pupils to mouseX and mouseY, they will move all over the canvas and leave the eyeballs. To fix this, I used the constrain() function. This keeps the pupils inside a specific range so they stay within the white part of the eyes.

// Pupils follow the mouse but stay inside the eyes
let pupilLeftX = constrain(mouseX, 140, 180);
let pupilLeftY = constrain(mouseY, 225, 255);
let pupilRightX = constrain(mouseX, 220, 260);
let pupilRightY = constrain(mouseY, 225, 255);

fill(0);
ellipse(pupilLeftX, pupilLeftY, 20, 20);
ellipse(pupilRightX, pupilRightY, 20, 20);

Here is my portrait:

Reflection

This assignment has  showed me how even the simplest shapes can be combined to make something expressive. The interactivity made it more engaging, and I enjoyed seeing how the eyes and mouth could “react” to movement.

If I had more time, I would like to:

  1. Add more details to the hair using curved lines or shapes to make it less blocky.

  2. Experiment with different facial expressions (for example, changing the mouth to a frown when the mouse is at the top of the screen, or raising the eyebrows).

  3. Change the background color based on the mouse position to give the portrait different moods.

  4. Add accessories like glasses or a hat using more shapes.In all , I enjoyed creating this portrait.

Self Portrait – Zeina Khadem

Concept

From the moment we got this assignment, I knew I wanted to create a self-portrait in a cartoon style that I loved as a kid. The first thing that came to mind was the Toca Boca games my cousins and I played all the time. Those characters had such a simple yet distinct style that really stuck with me, so I decided to take an inspiration picture from the game and model my self-portrait on it as closely as I could. I wanted my version to capture the charm of those characters while also being recognizable as me.

 The Inspiration Picture

I’m Particularly Proud of…

One part of the code I’m especially proud of is the mouth and eyebrows. I used arcs to draw them, which turned out to be trickier than I expected. Getting the curves and angles right took some trial and error, but it was so satisfying to see them finally come together.

//mouth
fill(0);
arc(200, 265, 20, 5, 0, PI, CHORD);

//eyebrows
fill('#D3A45F');
noStroke();
arc(158, 195, 30, 11, PI, TWO_PI, OPEN);
arc(242, 195, 30, 11, PI, TWO_PI, OPEN);

The Portrait

             

Always Room for Improvement

I think my portrait leans toward simplicity, which was partly intentional because I wanted it to reflect that clean, cartoonish style. That said, there’s so much room for improvement! In the future, I’d love to experiment with adding a more dynamic background to give the portrait some life. I’d also like to attempt a full-body version, which would be a fun challenge in balancing proportions and keeping the cartoon aesthetic consistent.

Another thing I want to work on is making my code more efficient and modular. Right now, some parts are repetitive, and I can see ways to organize it better with functions or loops. Overall, this project was a great opportunity to combine coding with creativity, and I’m really proud of the result.

Week 1: Self-Portrait

Concept

For my self-portrait, I decided to base it on my Animal Crossing Avatar. I thought it would be a fun way to represent myself since my character in the game feels like a version of me. Also, the cartoon style of the avatar fits perfectly for this kind of assignment!

Here’s my character for reference:

Favorite Code

Although I didn’t do anything super complex, I’m especially proud of how the eyes turned out. I think they gave the portrait a lot of personality and helped bring the whole thing together.

//left eye
  fill("black");
  ellipse(175, 225, 38, 50);

  fill("white");
  ellipse(174, 213, 18, 12);
  ellipse(182, 235, 6, 10);

  fill("black");
  triangle(158, 220, 152, 200, 163, 210);

  //right eye
  fill("black");
  ellipse(265, 225, 38, 50);

  fill("white");
  ellipse(265, 213, 18, 12);
  ellipse(274, 235, 6, 10);

  fill("black");
  triangle(248, 220, 241, 200, 251, 210);

Here’s the self-portrait I created:

Reflection and Future Improvements

While working on the portrait, I experimented with different shapes for the mouth and lashes. I tried using curves and Bezier functions, but they didn’t turn out the way I had hoped. In the end, I used an arc for the mouth and a triangle for the lashes, which worked better for the style I was going for.

I also used a semicircle arc for the bangs, but it stuck out a little awkwardly. To fix it, I placed a triangle in the same color as the background on top of the part that was sticking out, but I’m sure there’s probably a cleaner way to handle this.

In the future, I’d like to practice more shapes and figure out better techniques for handling these things.

Overall, this project was a fun way to explore coding and experiment with shapes. I’m excited to keep practicing and see how much more expressive I can make my sketches in the future!

Self Portrait

For this assignment, I wanted to make an interactive self portrait that actually looked like me without overcomplicating it. I began by making the head, hair, neck, ears, and shirt using basic shapes. I wasn’t satisfied with how round the face was, especially at the chin, so I used the beginShape function to create a custom face that was sharper. I used blue and white ellipses for the eyes and a triangle for a simplistic nose. The pupils follow the mouse’s coordinates, but are clamped with the map function so they are forced to stay inside the eye.

Code Highlight

I wanted to make the portrait smile/frown depending on the mouse’s Y coordinate, so I made the mouth’s curve a custom shape that stretches from a predefined vertex to another using the quadraticVertex function. The first and second arguments of the function are the coordinates of the point that will “pull” the curve towards itself, and its Y coordinate depends on the Y coordinate of the mouse.

// Mouth
  stroke(150, 0, 0);
  strokeWeight(5);
  noFill();

  // Fixed corners of the mouth
  let x1 = 170,
    y1 = 285;
  let x2 = 230,
    y2 = 285;

  // Higher mouse = happy 
  // Lower mouse = sad 
  let controlY = map(mouseY, 0, height, 310, 260);

  // Mouth Curve
  beginShape();
  vertex(x1, y1);
  quadraticVertex(200, controlY, x2, y2);
  endShape();

Sketch

Reflection and Ideas

Overall, I’m happy with how the portrait turned out, since it balances simplicity with interactivity. The use of basic shapes combined with custom shapes gave me flexibility while still keeping the code manageable. I especially liked how the mouth animation added a sense of personality and expression to the face. For improvement, I would make the hair more natural by experimenting with arcs, curves, or irregular shapes rather than just rectangles and ellipses. Another possible improvement would be adding subtle shading or color gradients to give the portrait more depth and realism.

Self-Portrait – Shota Matsumoto

Fullscreen sketch

Main Concept / Background:

My original concept was to draw the most beautiful self-portrait that I’ve ever made in my life, because, honestly, I’ve only drawn the worst self-portraits ever my friends used to make fun of. So, I wanted to capture every tiny detail of my face as accurately as possible. This was my first plan. But, once I looked at my passport picture, I realized that it was not going to happen due to the complicated structure of my hairstyle. 

What I struggled with and How I overcame it:

During the ideation phase, I came up with the idea of trying to use as many different shapes as possible for my hairstyle to make it as realistic as possible. For example, I realized that the sides of my hair can be represented by two ovals tilted at 30 degrees to make fluffiness. The top of my hair can be imitated by a trapezoid, and the bottom sides can be represented by two opposite triangles. I also added the feature where users can move the top of my hair up and down because I wanted to incorporate a funny interactive element. At the same time, I embedded my personal wish that I don’t go bald in the future. You can make me bald by moving your cursor downward from the middle of the self-portrait! This is my self-portrait: 

I drew a Japanese flag and cherry blossom at each corner to represent Japan. It was really hard to locate each petal at the correct transformation (position and rotation). I first used for loops but they did not work in a way I wanted, so I calculated each position and rotation one by one.

My Favorite Code:

The part of the code that I particularly like is the sides of my hair composed of two ovals. I struggled to position and rotate them in a way that matched the structure of my face. After about  half an hour of searching methods online, I found three functions that were really useful for controlling transformations of those geometries. These functions are push(), pop(), and translate(). The translate() function allows you to reset the origin, while push and pop() allow you to apply changes only to specific objects you want. 

//sides of hair 
  fill(0); 
  stroke(0); 
  push(); 
  translate(x1, y1);
  rotate(10); 
  ellipse(0, 0, hairWidth, hairHeight); 
  pop();   
  
  push(); 
  translate(x2, y2);
  rotate(-10); 
  ellipse(0, 0, hairWidth, hairHeight); 
  pop();

 

Reflections & Future Improvements:

Since it was my first time using p5, it took some time for me to get used to some functions. But, after using the same geometry functions multiple times and exploring new functions that I’ve never seen before, I was able to build a solid foundation in how p5 works. Although I believe I could have made a better self-portrait, considering the fact that I am bad at drawing, I think I did relatively well this time!

In terms of future improvements, I think I should use for loops for the cherry blossom part to make the codes more readable and reduce repetition. I tried to auto-generate all five ellipses simultaneously, but due to strange positions and rotations, I was not able to achieve it, even  after I tried multiple times. Also, all the objects are not fully centered, so the shapes are slightly misaligned. Next time I create my self-portrait again, I want to reduce the number of values I use for positions of each shape and use more variables instead to centralize each shape and improve the readability of my code. 

Self-portrait Prakrati

When I saw the examples in class, I knew I wanted my self-portrait to have an element of fun. A touch of movement to make it more interesting. So after brainstorming I decided to add a small cute wink in it. I didn’t have any answers to how to do it or when it would happen, but I knew starting was the best way to develop the idea.

I started by building the background. I chose a beach scene because it’s bright, fun, and resonates with my personality. Using just four rectangles, I created the sand, sky, and beach.

Next, I focused on the structure of my portrait. I used an ellipse for the face, and for the neck, I initially tried combining a circle and rectangle. After exploring the documentation, I realised a rounded rectangle could give the same effect with fewer shapes, so I went with that.

Then, the sweater collar was created using two triangles, traced easily with the print(mouseX, mouseY) trick taught in class. The body was a simple rounded rectangle to echo the shape of the shoulders. Once the structure was in place, I added details such as the nose, eyes, and sweater textures.

Finally, I added the wink. I wanted the portrait to respond to time or interaction. I decided that whenever the cursor moves to the right side of the canvas, the portrait would wink. Hence, I set the if condition that when position of mouseX is greater than 300 (middle of canvas) then draw a different shape. If condition made this simple because the eye now has two states: open or closed.

if (mouseX > 300) {
    stroke('black');
    strokeWeight(2);
    line(315, 190, 325, 190); // closed eye line
  } else {
    circle(320, 190, 10); // open eye
  }

The hardest part of this portrait was the hair. I initially considered straight hair, but that looked too robotic. After several iterations, I decided on curly hair with circles on the ends to give a flowing effect. By leaving one side slightly incomplete, it adds the sense of wind moving through my hair.

In the future, I’d like to make the portrait even more dynamic: perhaps animated clouds or waves in the background, and more detailed facial features. I also hard-coded most values, so I want to explore making my code more dynamic and flexible, so changes in one area automatically adjust related elements.

Self Portrait- Elyazia Abbas

My Concept:

I wanted to create a self-portrait that depicted my features using colors that i like such as burgundy and pink, and also using the basic p5 shapes. I wanted to make a piece that felt warm and friendly, so I chose soft pink and peachy colors. The goal was to make something that looks like me but also shows my personality through the style and colors.

Most basic shapes were a good fit for the features of the portrait. For instance, basic ellipses of varying sizes were a good fit for the eyes when overlapped with different colours. Additionally for the cheeks, lips, chin, and face shape ellipses were suitable. Thin rectangles were good for the eyebrows as well.

As for the hair, I used a new shape that I used chatGPT to recommend which is the bezier shape. The bezier shape has 8 parameters, every two being an x and y pair. The first and last coordinate pairs control where the bezier starts and ends, and the middle two control the pull of the curve.

60 Pink Color Palette: Best Color Combinations with Codes - Eggradients.com

Code Snippet:

bezier(350, 160, 380, 150, 300, 220, 170, 280);
bezier(300, 160, 320, 180, 380, 220, 155, 310);
bezier(400, 160, 110, 170, 260, 380, 190, 480);
bezier(190, 480, 150, 520, 210, 580, 240, 650);
bezier(240, 650, 200, 690, 260, 740, 230, 810);
bezier(230, 810, 190, 850, 250, 890, 220, 950);
bezier(390, 180, 100, 160, 240, 400, 170, 500);
bezier(170, 500, 130, 540, 190, 600, 220, 670);
bezier(220, 670, 180, 710, 240, 760, 210, 830);
bezier(210, 830, 170, 870, 230, 910, 200, 970);
bezier(400, 160, 115, 170, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);
bezier(400, 140, 115, 150, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);
bezier(400, 130, 115, 140, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);
bezier(400, 120, 115, 130, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);
bezier(400, 110, 115, 120, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);

The bezier curve is a new shape that i worked with. It has has four points each of which has 2 coordinates, x and y. First, the Start point: Where the curve begins, End point: Where the curve ends, Two control points: These are like invisible magnets that “pull” the curve in different directions to create the bend.

So in the context of my self portrait the first point would be, the top of my head, the last point would be the tip of my hair, and the middle two points are where the curves occur due to the pulling in those spots.

Embedded Sketch:

Reflections and Future Improvements:

Through this assignment I learnt more about how shapes and colours could overlap in p5.js to make dimension and depth. I also learnt about the bezier shape and it added a very creative element to my sketch.

As for future improvements, I hope to be able to start making for-loops instead of manually repeating the same structures and editing the coordinates. This will not only save time, but it will also give me a less error prone program, and will create some kind of symmetry in my work.

For loop Syntax - GeeksforGeeks