A Trip Down Memory Lane
Concept and Inspiration:
For my final project I was inspired by an idea I had for a film I made last semester. The film’s idea revolved around the concept of archives and old retrieved footage which immediately sparks the thought of old film strips in my mind. Now that films are, for the most part, recorded on digital cameras, I think the idea of recreating the feel of old running film strips through different forms of art is very interesting. I have not seen this exactly being done by any artist however I have definitely came across several who have experimented with developing film tapes in interesting unconventional ways to observe the possible artistic outcomes. One of these artists was an MFA student at NYUAD whose work, similar to the images below, generated films that had a glitching effect because of the way they were developed. Having his work, as well as my film and these images images in mind, I decided to have my final project be a running film strip that is of the color pink, similar to the theme of my film. I also had the added element of user interactivity to it through creating an effect that allows the user’s image to be reflected through the film strip to create the experience of being part of the memory or the archived footage.
Final Result:
Methodology and Application:
I began by experimenting with different ways through which I could achieve the intended design. I started first with the cellular automata mechanisms applying them to a simple sketch that somewhat generated the feel I was going for. In this sketch I mainly worked on applying the regular game of life rules, with an added element of movement, to attempt to generate the running effect of a film strip.
This was simply done by incrementing the horizontal position of the next alive cell as shown below:
// Move the special cells in the next generation for (let cell of movingCells) { let newX = (cell.x + 1) % cols; next[newX][cell.y] = { alive: 1, color: cell.color }; }
This code provided the basis of what I ended up creating however, I initially was not satisfied with the outcome because I felt like it felt somewhat static and did not deliver the idea I was going for. I tried to continue experimenting with cellular automata but I felt stuck so I moved on to work with the physics libraries, and I used the video below as inspiration for what my design would look like exactly:
In this draft I started simply by working on the scrolling effect. This was fairly simple to achieve, I create a function that generated squares that spread across the canvas and have basic physics that allows them to update their position, velocity and acceleration.
// Update scroll speed based on direction if (moveDirection !== 0) { scrollSpeed = min(scrollSpeed + SCROLL_ACCELERATION, MAX_SCROLL_SPEED); } else { scrollSpeed = 0; }
Moving on from there I worked on the static in the background. I created a class of columns that are basically small rectangles that update their horizontal positions while keeping their vertical positions static, this way they appear as though they’re lines moving across the screen. I also worked on adding forces between the rectangles and between the different columns to accentuate the glitching effect within and between the columns.
update(speed) { this.vel.x = speed; this.pos.add(this.vel); this.vel.mult(0.95); this.pos.y += random(-1, 1); } edges() { if (this.pos.x - this.originalX > width / NUM_COLUMNS) { this.pos.x = this.originalX; this.pos.y = random(height); } } display() { fill(255, this.opacity); noStroke(); rect(this.pos.x, this.pos.y, 1, 10); } applyForce(force) { this.vel.add(force); } } function applyGlitch(particle) { if (random(1) < 0.05) { particle.pos.y += random(-10, 10); particle.opacity = random(50, 255); } }
To further amplify the design I also created a class of different sized dots that play the role of the grain in the background. From there I worked on having the colors change based on columns’ proximities and I also added sounds to create the nostalgic feel of memories.
I then came across this sketch that generated a pixelated image of the user through webcam input. It basically did so by incrementing the position of the pixel from the webcam input so that it displays in a pixelated manner. I really liked the aesthetic of it and decided to include it in my sketch.
I did so by creating a layer that only appears when the flashing effect occurs. This layer appears as the opacity of the main sketch decreases. Below is the final outcome of what I created.
I did basic user testing and presented this sketch to the class and received two main comments, one that it is too slow and two that there is somewhat of a disconnect between the film strip and the image that appears. Hence I decided to give it another try and experiment once again with what I had created earlier using cellular automata.
I started off by adding the squares to my sketch that used regular game of life rules because I felt like it is what adds the essence of a film strip to the sketch. I then moved on to work on the part I found most challenging in my sketch which is coordinating between the webcam and the cellular automata mechanisms. I looked into several tutorials and learnt different methods from each of them.
From this tutorial I understood the way in which I could translate the pixels inputted from the webcam in order to be able to generate them as pixels based on cellular automata rules. It showed that the indices of the pixels inputted could be read as well as their colors and opacities through the function below which generally reads the red, green, blue, and opacity levels of each pixel inputted.
//Capture the webcam input as pixels capture.loadPixels(); // Calculate the scale based on board columns and rows let captureScaleX = capture.width / columns; let captureScaleY = capture.height / rows; // Loop through all columns and rows of board for (let i = 0; i < columns; i++) { for (let j = 0; j < rows; j++) { // Then calculate the position corresponding to the cell from the webcam input let x = i * captureScaleX; let y = j * captureScaleY; // Also calculate the index of each pixel in the webcam input to access its brightness and adjust its life //Multiplying by 4 because each pixel has 4 color channels to go through let webcamPixelIndex = (floor(y) * capture.width + floor(x)) * 4; // Calculate the brightness of the webcam input as average of RGB values let brightness = (capture.pixels[webcamPixelIndex] + capture.pixels[webcamPixelIndex + 1] + capture.pixels[webcamPixelIndex + 2]) / 3;
I then applied a general cellular automata rule to have the cells alive or dead based on their brightness. Following that I added other elements that I had included in previous iterations of this project such as the random pink color generating function, the grain in the background, the trail of the squares and the cells, the sounds, the image exporting function, and finally the menu and return button.
The menu I created was quite simple, it used the film strip’s squares to keep the aesthetic continuous, and contained simple instructions to guide the user through using the program. The button was something I hadn’t worked with in this class but it was simple to achieve, I just had to match the mouse coordinates with the position of the button and edit the mouse clicked function.
//.. This function draws the menu with the instructions function drawMenu() { background(0); fill(0, TRAIL_OPACITY); rect(0, 0, width, height); // Draw the squares in the menu drawAndUpdateSquares(); const buttonWidth = 200; const buttonHeight = 50; const buttonX = (width - buttonWidth) / 2; const playButtonY = height / 2 - 65; .... text('Press the key "e" to export your image', width / 2, height / 4 + 280); text('Press the key "b" to return back to the main menu', width / 2, height / 4 + 300); fill(randomPink()); rect(buttonX, playButtonY, buttonWidth, buttonHeight, 20); fill(255); textSize(28); text('START', buttonX + 93, playButtonY + 25); }
Challenges and Aspects I am Proud of:
In terms of challenges I think the main challenge I faced was in terms of translating the webcam input as mentioned previously, but also understanding the general idea of how cellular automata works was something I had to figure out to be able to generate results that did not seem so static like my initial sketch. I relied on the sketches we did in class for reference as well as a few tutorials like the one below that showed me how I could create my own rules that are based on cellular automata which is what inspired me to have the cells react to brightness and work accordingly.
User Testing:
Once I had the code working I tested it with some of my friends who really enjoyed exporting their pixelated images and running through the film tape but made a comment on the way the image appears and dies instantly when the mouse is released. Below are some of the images I took while they were testing the project:
Based on my friend’s comment I worked on the part that I think I am most proud of which is the speed at which the images die or disappear. When I first managed to get the effect to work, the cells inputted from the webcam would die as soon as the mouse was released, leaving somewhat of a disconnect between the two effects. This was a simple fix that I feel really transformed the effect and made it a lot nicer and fun to interact with because it allowed the user to view their image as it passed through the film strip and slowly disappeared.
// Determine the life of the cells based on the brightness of webcam input if (brightness > 128) { // If pixel is bright cell is alive and lifespan is 15 so it stays on canvas for a while board[i][j].alive = 1; lifespan[i][j] = 15; } else { // If pixel is dark cell is dead board[i][j].alive = 0; }
Ideas and Further Improvement:
For future improvements I think I would add more interactivity in terms of color, I want to add more choices for the user to allow them to create their own color pallet and generate their own film strip that is based on how they picture their memories. I think the mouse clicked function could also be switched to a key or something that is easier for the users to interact with to allow them to enjoy their images without having to worry about clicking any buttons. One thing I also think I should work on improving is the general reaction to light and brightness because I found after the show last night that users dressed in lighter clothing had their clothing appear as alive cells and everything else as dead which meant that their faces were barely visible. This was also due to the fact that the area we were presenting in was very well-lit which meant that the camera detected other brighter objects from the background. With that said, I think the project was fun to work on and generally interact with.
Images from IM Show: