You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, overlayText = "Kurdish Dub (Shirzad Sendi)", subtitleKurdish = "شێرزاد سەندی - Dubbing", waveColor = "#ffcc00", style = "bars", barCountStr = "64") {
// Create the canvas element to be returned
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Set dimensions
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
const barCount = parseInt(barCountStr, 10) || 64;
let animationFrameId;
// Internal state to simulate audio visualizer reacting to a voice
const bars = [];
for (let i = 0; i < barCount; i++) {
bars.push({
targetHeight: 5,
currentHeight: 5
});
}
function draw() {
// Clear and draw original image
ctx.clearRect(0, 0, width, height);
ctx.drawImage(originalImg, 0, 0, width, height);
// Draw a cinematic dark gradient overlay at the bottom 40% for visual clarity
const grad = ctx.createLinearGradient(0, height * 0.6, 0, height);
grad.addColorStop(0, 'rgba(0,0,0,0)');
grad.addColorStop(1, 'rgba(0,0,0,0.85)');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, width, height);
const time = Date.now() / 1000;
const maxBarHeight = height * 0.20;
const totalWaveWidth = width * 0.8;
const barWidth = totalWaveWidth / barCount;
const startX = (width - totalWaveWidth) / 2;
const startY = height * 0.70;
ctx.shadowColor = waveColor;
ctx.shadowBlur = 15;
// Voice simulation logic (Generates pseudo-random envelopes)
const isSpeaking = Math.sin(time * 2) > -0.5; // Controls bursts of "speech"
if (style.toLowerCase() === "line") {
ctx.beginPath();
ctx.strokeStyle = waveColor;
ctx.lineWidth = Math.max(2, width * 0.005);
ctx.lineJoin = "round";
} else {
ctx.fillStyle = waveColor;
}
for (let i = 0; i < barCount; i++) {
const b = bars[i];
// Random vocal amplitude simulation
if (isSpeaking && Math.random() < 0.2) {
// Mix sine waves to make it feel organic like voice formants
const speechSim = (Math.sin(time * 10 + i * 0.2) + Math.cos(time * 15 - i * 0.1)) / 2;
const intensity = Math.max(0, speechSim);
b.targetHeight = Math.max(5, (intensity * Math.random()) * maxBarHeight);
} else if (!isSpeaking || Math.random() < 0.1) {
b.targetHeight = 5; // Fall back to baseline
}
// Smoothly ease the current height to the target for realistic motion
b.currentHeight += (b.targetHeight - b.currentHeight) * 0.25;
const x = startX + i * barWidth;
const h = b.currentHeight;
const y = startY - h / 2;
if (style.toLowerCase() === "line") {
if (i === 0) {
ctx.moveTo(x + barWidth/2, y);
} else {
ctx.lineTo(x + barWidth/2, y);
}
} else {
// Default to bars
if (ctx.roundRect) {
ctx.beginPath();
ctx.roundRect(x + (barWidth * 0.1), y, barWidth * 0.8, h, barWidth / 2);
ctx.fill();
} else {
ctx.fillRect(x + (barWidth * 0.1), y, barWidth * 0.8, h);
}
}
}
if (style.toLowerCase() === "line") {
ctx.stroke();
}
ctx.shadowBlur = 0; // Reset shadow for text
// Text Overlay Setup (Simulating Subtitles/Dubbing Credits)
ctx.textAlign = "center";
ctx.shadowColor = "black";
ctx.shadowBlur = 8;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
// Draw Kurdish Subtitle
ctx.font = `bold ${Math.max(24, height * 0.05)}px "Courier New", Arial, sans-serif`;
ctx.fillStyle = "#ffff00"; // Subtitle Yellow
ctx.fillText(subtitleKurdish, width / 2, height * 0.86);
// Draw Main Tool/Branding Text
ctx.font = `bold ${Math.max(16, height * 0.03)}px Arial, sans-serif`;
ctx.fillStyle = "#ffffff";
ctx.fillText(overlayText, width / 2, height * 0.93);
// Reset Shadows
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
animationFrameId = requestAnimationFrame(draw);
}
// Attach method allowing developers to halt animation when canvas is removed
canvas.stopAnimation = function() {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
}
};
// Kick off the loop
draw();
return canvas;
}
Apply Changes