Image to sine waves

Hi,

I’ve looked at your code and tried few times before I discovered what was causing this :

  • First pixels are not stored the same way in p5.js, if you look at the reference the four R, G, B, A values are stored inline not packed into one color value.
    This means that you need to multiply the index by 4 :

    const closestPixelLoc = 4 * (round(sinePos) + y * portrait.width);
    
  • Again this is not solving the problem because it’s actually the sineIncr value that is too low so the points were too close. It’s dependent on the resolution of the sketch. It works fine with a value of 1.

  • Also I noticed that there was no way to increase the overall frequency specially for darker areas, I added a waveMultiplier that multiplies the frequency when computing the sin :

    curveVertex(sinePos, y + sin(sinePos * waveMultiplier) * (sineHeight / 2.0 - spaceBetweenRows));
    

It goes like this :

let portrait;

// // Frequency of the waves multiplier
const sineIncr = 1;
// // Height of the waves
const sineHeight = 10;
// // The space between the curve rows
const spaceBetweenRows = 2;

// Sine wave multiplier
const waveMultiplier = 2;


function preload() {
  portrait = loadImage('queens-gambit-500.jpg');
}

function setup() {
  createCanvas(500, 500);
  print(portrait.width + ' • ' + portrait.height);
}

function draw() {
  background(255);

  // Modify the stroke to have larger lines
  strokeWeight(1);

  portrait.loadPixels();

  // For every rows multiple of sineHeight
  for (let y = 0; y < portrait.height; y += sineHeight) {
    beginShape();
    // We start with a position of 0 for the sine function
    // Think of it as the x on the graphs
    let sinePos = 0;

    // Go until it fills the width
    while (sinePos < width) {
      // We have multiple points per pixel
      // So we have to pick the closest point for a x coordinate by rounding it
      const closestPixelLoc = 4 * (round(sinePos) + y * portrait.width);

      // Compute the brightness of that pixel in [0, 1]
      const c = color(portrait.pixels[closestPixelLoc]);
      const br = brightness(c) / 255.0;

      // The sine wave is oscillating above and under the pixel height
      curveVertex(sinePos, y + sin(sinePos * waveMultiplier) * (sineHeight / 2.0 - spaceBetweenRows));

      // We increase the x position of the sine wave
      // We use an exponential function to vary faster when the pixel is brighter
      sinePos += exp(br * 4) * sineIncr;
    }
    endShape();
  }

  // Break the loop
  noLoop();
}

3 Likes