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

Last updated