You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, visualizerType = "circle", themeColor = "gold") {
// Create container
const container = document.createElement('div');
container.style.position = 'relative';
container.style.display = 'inline-block';
container.style.fontFamily = 'Arial, sans-serif';
// Create Canvas
const canvas = document.createElement('canvas');
canvas.width = originalImg.width || 800;
canvas.height = originalImg.height || 600;
canvas.style.maxWidth = '100%';
canvas.style.display = 'block';
canvas.style.borderRadius = '8px';
canvas.style.boxShadow = '0 4px 12px rgba(0,0,0,0.5)';
container.appendChild(canvas);
// Create Play Button
const playBtn = document.createElement('button');
playBtn.innerText = 'PLAY FANFARE VISUALIZER';
playBtn.style.position = 'absolute';
playBtn.style.top = '50%';
playBtn.style.left = '50%';
playBtn.style.transform = 'translate(-50%, -50%)';
playBtn.style.padding = '16px 32px';
playBtn.style.fontSize = '20px';
playBtn.style.fontWeight = 'bold';
playBtn.style.background = 'linear-gradient(to bottom, currentColor, #997a00)';
playBtn.style.color = themeColor;
playBtn.style.border = '2px solid white';
playBtn.style.borderRadius = '30px';
playBtn.style.cursor = 'pointer';
playBtn.style.boxShadow = '0 0 20px rgba(0,0,0,0.8)';
playBtn.style.textShadow = '1px 1px 2px black';
playBtn.style.transition = 'opacity 0.3s ease';
// Add hover effect
playBtn.onmouseover = () => playBtn.style.opacity = '0.8';
playBtn.onmouseout = () => playBtn.style.opacity = '1';
container.appendChild(playBtn);
const ctx = canvas.getContext('2d');
// Draw initial image
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
// Add a dark cinematic overlay for standby
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
let audioCtx, analyser;
let isPlaying = false;
let animId;
playBtn.addEventListener('click', () => {
if (isPlaying) return;
isPlaying = true;
playBtn.style.display = 'none';
if (!audioCtx) {
const AudioContext = window.AudioContext || window.webkitAudioContext;
audioCtx = new AudioContext();
analyser = audioCtx.createAnalyser();
analyser.fftSize = 128; // Lower for thicker bars
analyser.connect(audioCtx.destination);
}
if (audioCtx.state === 'suspended') {
audioCtx.resume();
}
playCinematicFanfare(audioCtx, analyser);
drawVisualizer();
});
// Synthesize a majestic brass fanfare (Universal Pictures style motif)
function playCinematicFanfare(audioCtx, analyser) {
// Classic fanfare motif: G G G C, G G G D, C D E G
const notes = [
{ f: 196.00, t: 0.1, d: 0.2 }, // G3
{ f: 196.00, t: 0.35, d: 0.2 }, // G3
{ f: 196.00, t: 0.6, d: 0.2 }, // G3
{ f: 261.63, t: 0.9, d: 1.2 }, // C4
{ f: 196.00, t: 2.3, d: 0.2 }, // G3
{ f: 196.00, t: 2.55, d: 0.2 }, // G3
{ f: 196.00, t: 2.8, d: 0.2 }, // G3
{ f: 293.66, t: 3.1, d: 1.2 }, // D4
{ f: 261.63, t: 4.5, d: 0.4 }, // C4
{ f: 293.66, t: 5.0, d: 0.4 }, // D4
{ f: 329.63, t: 5.5, d: 0.4 }, // E4
{ f: 392.00, t: 6.0, d: 2.5 } // G4
];
notes.forEach(note => {
playBrassSynth(audioCtx, analyser, note.f, audioCtx.currentTime + note.t, note.d);
// Add harmony (octaves / fifths) to sound larger
playBrassSynth(audioCtx, analyser, note.f * 1.5, audioCtx.currentTime + note.t, note.d);
playBrassSynth(audioCtx, analyser, note.f * 2.0, audioCtx.currentTime + note.t, note.d);
});
const totalDuration = 6.0 + 2.5 + 1.0;
// Stop visualizer when fanfare completes
setTimeout(() => {
isPlaying = false;
playBtn.style.display = 'block';
playBtn.innerText = 'REPLAY FANFARE';
cancelAnimationFrame(animId);
// Redraw standby screen
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}, totalDuration * 1000);
}
function playBrassSynth(audioCtx, analyser, freq, startTime, duration) {
// Dual oscillators for a chorusing/detuned brass sound
const osc1 = audioCtx.createOscillator();
// Jerry Goldsmith / Newman fanfare usually includes bold orchestra; we approximate with sawtooths
osc1.type = 'sawtooth';
osc1.frequency.value = freq;
osc1.detune.value = -6;
const osc2 = audioCtx.createOscillator();
osc2.type = 'sawtooth';
osc2.frequency.value = freq;
osc2.detune.value = 6;
const gain = audioCtx.createGain();
const filter = audioCtx.createBiquadFilter();
// Envelopes for majestic attack
gain.gain.setValueAtTime(0, startTime);
gain.gain.linearRampToValueAtTime(0.15, startTime + 0.08);
gain.gain.setValueAtTime(0.15, startTime + duration - 0.2);
gain.gain.linearRampToValueAtTime(0, startTime + duration);
// Lowpass filter sweep to emulate brass crescendo
filter.type = 'lowpass';
filter.frequency.setValueAtTime(300, startTime);
filter.frequency.linearRampToValueAtTime(3000, startTime + 0.08);
filter.frequency.linearRampToValueAtTime(800, startTime + duration);
osc1.connect(filter);
osc2.connect(filter);
filter.connect(gain);
gain.connect(analyser); // Connect to visualizer
osc1.start(startTime);
osc2.start(startTime);
osc1.stop(startTime + duration);
osc2.stop(startTime + duration);
}
function drawVisualizer() {
if (!isPlaying) return;
animId = requestAnimationFrame(drawVisualizer);
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
analyser.getByteFrequencyData(dataArray);
// Draw Background
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
// Dynamic dark cinematic overlay pulsing with bass
const bass = dataArray[2] / 255;
ctx.fillStyle = `rgba(0, 0, 10, ${0.4 - (bass * 0.15)})`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
const cx = canvas.width / 2;
const cy = canvas.height / 2;
if (visualizerType === "circle") {
const radius = Math.min(cx, cy) * 0.45;
// Draw cinematic glowing text at center
ctx.save();
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = 'bold ' + Math.max(30, canvas.width / 18) + 'px "Arial Black", Gadget, sans-serif';
ctx.fillStyle = themeColor;
// Add lighting/3D shadow effect to text
ctx.shadowColor = themeColor;
ctx.shadowBlur = 20 * bass;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
// Inner breathing scale
const scale = 1 + bass * 0.15;
ctx.translate(cx, cy);
ctx.scale(scale, scale);
ctx.fillText("UNIVERSAL", 0, -20);
ctx.font = 'bold ' + Math.max(20, canvas.width / 24) + 'px "Times New Roman", Times, serif';
ctx.fillText("FANFARE", 0, 30);
ctx.restore();
// Draw radial visualizer bars wrap around text
for (let i = 0; i < bufferLength; i++) {
const barHeight = (dataArray[i] / 255) * (Math.min(cx, cy) * 0.45);
const angle = (i / bufferLength) * 2 * Math.PI;
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(angle);
ctx.beginPath();
ctx.moveTo(0, radius);
ctx.lineTo(0, radius + barHeight);
ctx.lineWidth = 6;
// Add a gradient tint based on intensity
ctx.strokeStyle = (dataArray[i] > 200) ? 'white' : themeColor;
ctx.lineCap = 'round';
ctx.shadowColor = themeColor;
ctx.shadowBlur = 10;
ctx.stroke();
ctx.restore();
}
} else {
// Linear blocks visualizer spanning the bottom
const barWidth = (canvas.width / bufferLength) * 1.5;
for (let i = 0; i < bufferLength; i++) {
const barHeight = (dataArray[i] / 255) * (canvas.height * 0.6);
// Color mapping overlay (gradient)
const grad = ctx.createLinearGradient(0, canvas.height, 0, canvas.height - barHeight);
grad.addColorStop(0, 'black');
grad.addColorStop(0.5, themeColor);
grad.addColorStop(1, 'white');
ctx.fillStyle = grad;
ctx.shadowColor = themeColor;
ctx.shadowBlur = 10;
ctx.fillRect(i * barWidth, canvas.height - barHeight, barWidth - 4, barHeight);
}
// Text at center-top
ctx.textAlign = 'center';
ctx.font = 'bold ' + Math.max(40, canvas.width / 12) + 'px "Arial Black", sans-serif';
ctx.fillStyle = themeColor;
ctx.shadowColor = 'black';
ctx.shadowBlur = 15;
ctx.shadowOffsetX = 4;
ctx.shadowOffsetY = 4;
ctx.fillText("FANFARE", cx, canvas.height * 0.3);
}
}
return container;
}
Apply Changes