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 of1
. -
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();
}