Bitmap Manipulations & Image Effects
Image Effects based on Bitmap Data
Simple Tints and Filters

PImage img;
// Declare a variable of type PImage to store the image that will be loaded.
float colorNoise;
// Declare a float variable to store the value generated by Perlin noise, which will be used to modify colors.
float counter = 0;
// Declare and initialize a float variable 'counter' to control the progression of the noise function.
void setup(){
size(1000,1000);
// Set the size of the canvas to 1000x1000 pixels.
img = loadImage("grimes.jpg");
// Load the image "grimes.jpg" from the sketch's data folder and store it in the 'img' variable.
}
void draw(){
background(255);
// Set the background color to white (255) at the beginning of every frame, clearing the canvas.
counter += 0.1;
// Increment the 'counter' variable by 0.1 in each frame. This controls how the noise value changes over time.
colorNoise = noise(counter) * 255;
// Generate a Perlin noise value using 'counter', scale it to range from 0 to 255, and store it in 'colorNoise'.
// Perlin noise creates smooth random variations, which will be used to adjust image colors.
tint(200, colorNoise, 155);
// Apply a tint (color filter) with red fixed at 200, green controlled by 'colorNoise', and blue fixed at 155.
// This affects the next image drawn, changing its appearance.
image(img, 0, 0, width/2, height/2);
// Draw the image at the top-left corner (0,0), scaled to half the canvas width and height.
tint(200, random(255), 200);
// Apply a new tint with red fixed at 200, green set to a random value between 0 and 255, and blue fixed at 200.
image(img, width/2, 0, width/2, height/2);
// Draw the image in the top-right corner of the canvas (width/2, 0), again scaled to half the canvas size.
tint(200, 200, colorNoise);
// Apply a tint with red and green fixed at 200, and blue controlled by 'colorNoise'.
image(img, 0, height/2, width/2, height/2);
// Draw the image in the bottom-left corner of the canvas (0, height/2), again scaled to half size.
tint(colorNoise);
// Apply a grayscale tint, where all the color components (red, green, blue) are set to 'colorNoise'.
image(img, width/2, height/2, width/2, height/2);
// Draw the image in the bottom-right corner of the canvas (width/2, height/2), again scaled to half size.
}
Pixelation, drawing shapes from color information, randomness

PImage img;
// Declare a variable to hold the image.
float resX = 30;
float resY = 30;
// Set initial values for the resolution in X and Y directions (spacing for the grid).
int shape = 2;
// Set the initial shape mode (1 for ellipse, 2 for rectangle, 3 for lines).
int thickness = 1;
// Set the initial thickness for line strokes.
int hueLevel = 0;
// Initialize a variable to adjust hue.
int savecounter = 1;
// Initialize a counter for saving screenshots.
void setup(){
size(1000,1000);
// Set the canvas size to 1000x1000 pixels.
//size(1000, 1000, PDF, "filename.pdf");
// (Commented out) Option to save the output as a PDF.
img = loadImage("grimes.jpg");
// Load the image "grimes.jpg" from the sketch's data folder.
img.loadPixels();
// Load the pixels of the image for manipulation.
colorMode(HSB);
// Set the color mode to HSB (Hue, Saturation, Brightness).
}
void draw(){
background(255);
// Clear the background with white color.
for(int y=0; y < height; y += resY){
// Loop through the canvas vertically, stepping by 'resY'.
for(int x=0; x < width; x += resX){
// Loop through the canvas horizontally, stepping by 'resX'.
int pos = x + y * width;
// Calculate the pixel position based on x and y.
color c = img.get(x, y);
// Get the color from the image at position (x, y).
fill(c, 100);
// Fill shapes with the color from the image, with transparency set to 100.
if(shape == 1){
// If the shape mode is 1, draw ellipses.
noStroke();
// Disable the outline (stroke) of the shape.
ellipse(x, y, resX * 2, resY * 2);
// Draw an ellipse at (x, y) with size scaled by resX and resY.
} else if(shape == 2){
// If the shape mode is 2, draw rectangles.
stroke(140);
// Set the outline color to grey.
noStroke();
// Disable stroke again (since stroke color is set but not used here).
rectMode(CENTER);
// Set the rectangle mode to draw from the center.
rect(x, y, resX * randomGaussian() * 10, resY * randomGaussian() * 1);
// Draw a rectangle with a random width and height, scaled by Gaussian distribution.
} else if(shape == 3){
// If the shape mode is 3, draw lines.
stroke(c, 100);
// Set the stroke color to the color from the image with transparency.
strokeWeight(thickness);
// Set the thickness of the stroke.
line(x, y, x + resX, y + resY);
// Draw a line from (x, y) to (x+resX, y+resY).
}
}
}
}
void keyPressed(){
if(key == 'h'){
hueLevel += 10;
// Press 'h' to increase the hue level (this part isn't used directly, but could be added for hue shifts).
}
if(key == '+'){
resX += 1; resY += 1;
// Press '+' to increase the resolution (make shapes larger).
}
if(key == '-' && resX > 1){
resX -= 1; resY -= 1;
// Press '-' to decrease the resolution (make shapes smaller), but prevent negative sizes.
}
if(key == '1'){ shape = 1; }
// Press '1' to switch to ellipse mode.
if(key == '2'){ shape = 2; }
// Press '2' to switch to rectangle mode.
if(key == '3'){ shape = 3; }
// Press '3' to switch to line mode.
if(key == 'y' && thickness > 1){ thickness /= 2; }
// Press 'y' to reduce the stroke thickness (but only if it's greater than 1).
if(key == 'x'){ thickness *= 2; }
// Press 'x' to double the stroke thickness.
if(key == 's'){
save("screenshot" + savecounter + ".png");
// Press 's' to save a screenshot as a PNG file.
savecounter++;
// Increment the screenshot counter so each save is a unique file.
}
}
Video
Temporality – jumping and scrubbing

import processing.video.*;
// Import the video library, which is used to load and play video files.
import oscP5.*;
// Import the oscP5 library to handle sending and receiving OSC (Open Sound Control) messages.
Movie clip;
// Declare a Movie object to store the video that will be played.
OscP5 oscP5;
// Declare an OscP5 object to handle OSC communication (listening for messages on a specific port).
int timerStart, timeCounter, interval;
// Declare variables to manage timing: 'timerStart' stores the start time, 'timeCounter' tracks the elapsed time, and 'interval' sets how often certain actions occur.
void setup() {
size(800, 600);
// Set the window size to 800x600 pixels.
oscP5 = new OscP5(this, 12000);
// Initialize oscP5 to listen for incoming OSC messages on port 12000.
clip = new Movie(this, "video-2.mp4");
// Load the video file "video-2.mp4" into the 'clip' object.
clip.play();
// Start playing the video as soon as the program runs.
interval = 500;
// Set the initial time interval to 500 milliseconds.
timerStart = millis();
// Store the current time (in milliseconds) when the program starts running.
println(clip.duration());
// Print the total duration of the video (in seconds) to the console.
}
void draw() {
interval = mouseX;
// Set the interval based on the horizontal position of the mouse (x-coordinate).
// Moving the mouse left or right will change how frequently the video skips to a new position.
timeCounter = millis() - timerStart;
// Calculate how much time has passed since the timer was started.
if (timeCounter > interval) {
// If the time that has passed exceeds the interval (set by the mouse position):
clip.jump(random(0, clip.duration() - 0.1));
// Jump to a random position in the video, anywhere from the start to almost the end (subtracting 0.1 seconds to avoid errors).
timerStart = millis();
// Reset the timer to the current time, so the countdown restarts.
}
image(clip, 0, 0, width, height);
// Display the video on the screen, stretched to fit the entire window (800x600 pixels).
println(clip.time());
// Print the current playhead position (in seconds) of the video to the console.
}
void movieEvent(Movie m) {
// This function is called automatically whenever a new frame of the video is ready to be displayed.
m.read();
// Read and process the new frame so it can be displayed in the 'image()' function in draw().
}
void oscEvent(OscMessage theOscMessage) {
// This function is triggered whenever an OSC message is received.
if (theOscMessage.checkAddrPattern("/ping") == true) {
// Check if the OSC message has the address "/ping".
clip.jump(random(0, clip.duration() - 0.5));
// If the message is "/ping", jump to a random position in the video, but not within the last 0.5 seconds to avoid errors.
}
}
Assignment
Assignment:
Write code in SuperCollider that sends OSC messages to trigger the intensity of the image effects in the earlier example.
Create sounds in SC that align with – or contradict – the visual structures.
Last updated