You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, barWidth = 10, gap = 4, bgOpacity = 0.3, addElements = "true") {
// Parameter parsing and normalization
barWidth = parseInt(barWidth);
if (isNaN(barWidth) || barWidth < 2) barWidth = 10;
gap = parseInt(gap);
if (isNaN(gap) || gap < 0) gap = 4;
bgOpacity = parseFloat(bgOpacity);
if (isNaN(bgOpacity) || bgOpacity < 0 || bgOpacity > 1) bgOpacity = 0.3;
const shouldAddElements = String(addElements).toLowerCase() === "true";
const canvas = document.createElement("canvas");
const w = originalImg.width;
const h = originalImg.height;
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");
// 1. Draw a dark, faded version of the original image as the background
ctx.fillStyle = "#111111";
ctx.fillRect(0, 0, w, h);
ctx.globalAlpha = bgOpacity;
ctx.drawImage(originalImg, 0, 0);
ctx.globalAlpha = 1.0;
// 2. Offscreen canvas to safely read image data
const offCanvas = document.createElement("canvas");
offCanvas.width = w;
offCanvas.height = h;
const offCtx = offCanvas.getContext("2d");
offCtx.drawImage(originalImg, 0, 0);
let imgData;
try {
imgData = offCtx.getImageData(0, 0, w, h).data;
} catch (e) {
// Fallback for CORS issues, though typically handled via local environment
ctx.fillStyle = "white";
ctx.font = "20px Arial";
ctx.fillText("Error: Canvas tainted by cross-origin data.", 10, 50);
return canvas;
}
const step = barWidth + gap;
const centerY = h / 2;
ctx.lineCap = "round";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
const noteSymbols = ['♪', '♫', '♩', '♬'];
// Scale font size based on image dimensions
const fontSize = Math.max(16, barWidth * 2);
ctx.font = `${fontSize}px sans-serif`;
// 3. Process image into "soundwave" columns
for (let x = 0; x < w; x += step) {
let rSum = 0, gSum = 0, bSum = 0, brightnessSum = 0;
let count = 0;
const sampleX = Math.min(Math.floor(x + barWidth / 2), w - 1);
// Sample pixels downwards to find the column's average color and brightness
for (let y = 0; y < h; y += 5) {
const idx = (y * w + sampleX) * 4;
const r = imgData[idx];
const g = imgData[idx+1];
const b = imgData[idx+2];
rSum += r;
gSum += g;
bSum += b;
// Standard relative luminance
brightnessSum += (0.299 * r + 0.587 * g + 0.114 * b);
count++;
}
if (count === 0) continue;
const avgR = Math.round(rSum / count);
const avgG = Math.round(gSum / count);
const avgB = Math.round(bSum / count);
const avgBrightness = brightnessSum / count; // Range: 0 to 255
// Calculate visual waveform "amplitude" based on brightness
const normalizedAmplitude = avgBrightness / 255;
let amplitude = normalizedAmplitude * h * 0.85;
if (amplitude < barWidth) amplitude = barWidth; // minimum height
// Highlight peaks to make it feel like "audio"
const color = `rgb(${avgR}, ${avgG}, ${avgB})`;
// Draw the vertical "song" bar (a segment of the wave)
ctx.beginPath();
ctx.moveTo(x + barWidth / 2, centerY - amplitude / 2);
ctx.lineTo(x + barWidth / 2, centerY + amplitude / 2);
ctx.strokeStyle = color;
ctx.lineWidth = barWidth;
ctx.stroke();
// 4. Embellish peaks with birds and musical notes (The "Birdsong")
if (shouldAddElements && Math.random() > 0.8) {
const isBird = Math.random() > 0.5;
const elementY = centerY - (amplitude / 2) - 15 - (Math.random() * 30);
// Avoid drawing off-screen
if (elementY > fontSize) {
if (isBird) {
// Draw a little stylized flying bird (V shape)
const bSize = Math.max(10, barWidth);
const bx = x + barWidth / 2;
ctx.beginPath();
// Left wing
ctx.moveTo(bx - bSize, elementY - bSize * 0.6);
ctx.quadraticCurveTo(bx - bSize / 2, elementY, bx, elementY);
// Right wing
ctx.quadraticCurveTo(bx + bSize / 2, elementY, bx + bSize, elementY - bSize * 0.6);
ctx.strokeStyle = `rgba(${avgR}, ${avgG}, ${avgB}, 0.9)`;
ctx.lineWidth = Math.max(2, barWidth / 4);
ctx.stroke();
} else {
// Draw a small musical note
ctx.fillStyle = `rgba(${avgR}, ${avgG}, ${avgB}, 0.9)`;
const note = noteSymbols[Math.floor(Math.random() * noteSymbols.length)];
ctx.fillText(note, x + barWidth / 2, elementY);
}
}
}
}
return canvas;
}
Apply Changes