scanlines
2025
Made with p5.js. This piece abstracts a source image into horizontal scan lines by scanning brightness values at different x and y intervals and mapping them into discrete buckets. Then row by row, lines are drawn at varying widths is determined by that location’s corresponding bucketed brightness, creating a rhythmic, barcode-like texture. The result is a balancing act between image fidelity and reduction.
//scan lines
//by tyler porter
//load image
function preload() {
img = loadImage('6.jpg');
}
//these params define the width and height of each "pixel"
let pixelSizeWidth = 5;
let pixelSizeHeight = 20;
let currentPixel=0;
let mappedValue=0;
let bucket = 0;
let max=0, min=100;
let bucketCount=5;
//setup
function setup() {
createCanvas(600, 600);
img.resize(width,height);
background(170);
noStroke();
fill(30);
//this loop determines the minimum and maximum values to use in the remapping step. This is in case the image does not have pure white and pure black values in it.
for(let x=0; x<width;x+=pixelSizeWidth){
for(let y=0;y<height;y+=pixelSizeHeight){
currentPixel = round(brightness(img.get(x+(pixelSizeWidth/2),y+(pixelSizeHeight/2))));
if(currentPixel>max) max = currentPixel;
if(currentPixel<min) min = currentPixel;
}
}
print("min: " + min +" | max: "+ max);
//this step iterates through the image again, this time passing along the brightness value to the remapping function to remap it into set buckets. The bucketed value is returned and then drawn as a rectangle.
for(let x=0;x<width;x+=pixelSizeWidth){
for(let y=0;y<height;y+=pixelSizeHeight){
currentPixel = 100-brightness(img.get(x+(pixelSizeWidth/2),y+(pixelSizeHeight/2)));
bucket = snapToBucket(currentPixel);
mappedValue=bucket*(pixelSizeWidth/(bucketCount-1));
rect(x,y,mappedValue, pixelSizeHeight-2);
}
}
}
//the remapping function takes brightness value returns what "bucket" it is in; the range of brightness is divided up into equal buckets, and the value is clamped to those buckets
function snapToBucket(value) {
let range = max-min;
let bucketSize = range / bucketCount;
let clampedValue = constrain(value, min, max);
let bucketIndex = round(clampedValue / bucketSize);
if (clampedValue==min)bucketIndex=0;
if (clampedValue==max)bucketIndex=bucketCount-1;
return bucketIndex;
}






