You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, defaultText = "Hello human! I am a dog now. Hear my majestic voice!", autoTranslate = "true", pitchModifier = "1.0", rateModifier = "1.0") {
// Container setup
const container = document.createElement('div');
container.style.fontFamily = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
container.style.maxWidth = '600px';
container.style.margin = '0 auto';
container.style.padding = '20px';
container.style.backgroundColor = '#ffffff';
container.style.borderRadius = '12px';
container.style.boxShadow = '0 8px 24px rgba(0,0,0,0.1)';
container.style.display = 'flex';
container.style.flexDirection = 'column';
container.style.alignItems = 'center';
container.style.gap = '20px';
container.style.boxSizing = 'border-box';
// Header Title
const title = document.createElement('h2');
title.innerText = '🐶 Dog Breed Voice Changer';
title.style.margin = '0';
title.style.color = '#333';
title.style.textAlign = 'center';
container.appendChild(title);
// Canvas Setup
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
// Scale image down if it is too large for performance
const MAX_DIM = 800;
let width = originalImg.width;
let height = originalImg.height;
if (width > MAX_DIM || height > MAX_DIM) {
const ratio = Math.min(MAX_DIM / width, MAX_DIM / height);
width = Math.floor(width * ratio);
height = Math.floor(height * ratio);
}
canvas.width = Math.max(1, width);
canvas.height = Math.max(1, height);
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
canvas.style.maxWidth = '100%';
canvas.style.height = 'auto';
canvas.style.borderRadius = '8px';
canvas.style.border = '4px solid #f0f0f0';
canvas.style.boxShadow = '0 4px 12px rgba(0,0,0,0.05)';
container.appendChild(canvas);
// Image Analysis (Determines Dog Breed Pseudo-Randomly based on Colors)
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
let rSum = 0, gSum = 0, bSum = 0, samples = 0;
// Step by a prime number to quickly sample pixels across the image
const step = 4 * 83;
for (let i = 0; i < imgData.length; i += step) {
rSum += imgData[i];
gSum += imgData[i+1];
bSum += imgData[i+2];
samples++;
}
samples = Math.max(1, samples);
const rAvg = Math.floor(rSum / samples);
const gAvg = Math.floor(gSum / samples);
const bAvg = Math.floor(bSum / samples);
const analysisHash = Number((rAvg) + (gAvg * 3) + (bAvg * 5)) || 0;
// Breed Database with "Voice Changer" Pitch/Rate characteristics
const breeds = [
{ name: "Dramatic Husky", emoji: "🐺", words: ["Awoooo", "Ruff", "Awoo", "Arf"], pitch: 0.4, rate: 0.75 },
{ name: "Spicy Chihuahua", emoji: "🦮", words: ["Yip", "Yap", "Grrr", "Bork", "Yip"], pitch: 2.0, rate: 1.6 },
{ name: "Tough Rottweiler", emoji: "🐕🦺", words: ["Bork", "Gruff", "Woof", "Bark"], pitch: 0.1, rate: 0.7 },
{ name: "Happy Golden Retriever", emoji: "🐕", words: ["Woof", "Bark", "Arf", "Bork"], pitch: 1.0, rate: 1.0 },
{ name: "Wheezy Pug", emoji: "🐶", words: ["Snort", "Wheeze", "Ruff", "Snuffle"], pitch: 0.8, rate: 0.6 },
{ name: "Fancy Poodle", emoji: "🐩", words: ["Wuff", "Yip", "Bark", "Arf"], pitch: 1.5, rate: 1.2 },
{ name: "Silly Beagle", emoji: "🦮", words: ["Aroo", "Bark", "Woof", "Howl"], pitch: 0.9, rate: 0.9 }
];
const breed = breeds[analysisHash % breeds.length];
// Info Panel & Controls
const infoPanel = document.createElement('div');
infoPanel.style.width = '100%';
infoPanel.style.padding = '15px';
infoPanel.style.backgroundColor = '#f8f9fa';
infoPanel.style.borderRadius = '8px';
infoPanel.style.textAlign = 'center';
infoPanel.style.boxSizing = 'border-box';
const breedText = document.createElement('p');
breedText.innerHTML = `Vibe Checked Vibe: Let's hear it for the <strong>${breed.emoji} ${breed.name}</strong>!`;
breedText.style.margin = '0 0 15px 0';
breedText.style.fontSize = '18px';
breedText.style.color = '#444';
infoPanel.appendChild(breedText);
const textArea = document.createElement('textarea');
textArea.value = defaultText;
textArea.style.width = '100%';
textArea.style.height = '80px';
textArea.style.padding = '10px';
textArea.style.boxSizing = 'border-box';
textArea.style.borderRadius = '6px';
textArea.style.border = '1px solid #ccc';
textArea.style.marginBottom = '10px';
textArea.style.fontSize = '16px';
textArea.style.fontFamily = 'inherit';
textArea.style.resize = 'vertical';
infoPanel.appendChild(textArea);
// Translation toggle wrapper
const optionsRow = document.createElement('div');
optionsRow.style.display = 'flex';
optionsRow.style.alignItems = 'center';
optionsRow.style.justifyContent = 'center';
optionsRow.style.gap = '8px';
optionsRow.style.marginBottom = '20px';
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.id = 'dogSpeakCheck_' + Math.random().toString(36).substr(2, 9);
checkbox.checked = autoTranslate.toLowerCase() === "true";
const label = document.createElement('label');
label.htmlFor = checkbox.id;
label.innerText = 'Translate words to Dog Speak';
label.style.fontSize = '14px';
label.style.cursor = 'pointer';
label.style.userSelect = 'none';
optionsRow.appendChild(checkbox);
optionsRow.appendChild(label);
infoPanel.appendChild(optionsRow);
// Buttons
const btnRow = document.createElement('div');
btnRow.style.display = 'flex';
btnRow.style.gap = '15px';
btnRow.style.justifyContent = 'center';
btnRow.style.flexWrap = 'wrap';
const synthBtn = document.createElement('button');
synthBtn.innerText = '🔊 Play Dog Voice';
synthBtn.style.padding = '12px 24px';
synthBtn.style.fontSize = '16px';
synthBtn.style.fontWeight = 'bold';
synthBtn.style.cursor = 'pointer';
synthBtn.style.backgroundColor = '#10a37f';
synthBtn.style.color = 'white';
synthBtn.style.border = 'none';
synthBtn.style.borderRadius = '24px';
synthBtn.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
synthBtn.style.transition = 'transform 0.1s ease, background 0.2s';
synthBtn.onmouseover = () => synthBtn.style.backgroundColor = '#0e906f';
synthBtn.onmouseout = () => synthBtn.style.backgroundColor = '#10a37f';
synthBtn.onmousedown = () => synthBtn.style.transform = 'scale(0.95)';
synthBtn.onmouseup = () => synthBtn.style.transform = 'scale(1)';
const stopBtn = document.createElement('button');
stopBtn.innerText = '⏹️ Stop';
stopBtn.style.padding = '12px 24px';
stopBtn.style.fontSize = '16px';
stopBtn.style.fontWeight = 'bold';
stopBtn.style.cursor = 'pointer';
stopBtn.style.backgroundColor = '#e04a3f';
stopBtn.style.color = 'white';
stopBtn.style.border = 'none';
stopBtn.style.borderRadius = '24px';
stopBtn.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
stopBtn.style.transition = 'transform 0.1s ease, background 0.2s';
stopBtn.onmouseover = () => stopBtn.style.backgroundColor = '#cc4036';
stopBtn.onmouseout = () => stopBtn.style.backgroundColor = '#e04a3f';
stopBtn.onmousedown = () => stopBtn.style.transform = 'scale(0.95)';
stopBtn.onmouseup = () => stopBtn.style.transform = 'scale(1)';
// Playback Logic & Animation
let pulseInterval;
function stopPulse() {
if (pulseInterval) clearInterval(pulseInterval);
canvas.style.transform = 'scale(1)';
}
synthBtn.onclick = () => {
window.speechSynthesis.cancel();
stopPulse();
let textToSpeak = textArea.value;
// If translate check is enabled, swap out words contextually
if (checkbox.checked && textToSpeak.trim() !== '') {
textToSpeak = textToSpeak.replace(/\p{L}+/gu, (match) => {
const isAllUppercase = match === match.toUpperCase() && match.length > 1;
const isCapitalized = match.charAt(0) === match.charAt(0).toUpperCase();
let word = breed.words[Math.floor(Math.random() * breed.words.length)];
if (isAllUppercase) {
return word.toUpperCase();
} else if (isCapitalized) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
} else {
return word.toLowerCase();
}
});
}
const utterance = new SpeechSynthesisUtterance(textToSpeak || 'Woof');
const pMod = parseFloat(pitchModifier) || 1.0;
const rMod = parseFloat(rateModifier) || 1.0;
utterance.pitch = Math.min(2.0, Math.max(0.1, breed.pitch * pMod));
utterance.rate = Math.min(10.0, Math.max(0.1, breed.rate * rMod));
utterance.volume = 1.0;
// Visual animation while dog is "speaking"
utterance.onstart = () => {
canvas.style.transition = 'transform 0.1s ease-in-out';
let toggled = false;
// Pulsing speed depends on the final speech rate
const intervalMs = Math.max(60, 200 / utterance.rate);
pulseInterval = setInterval(() => {
toggled = !toggled;
canvas.style.transform = toggled ? 'scale(1.03)' : 'scale(1.0)';
}, intervalMs);
};
utterance.onend = stopPulse;
utterance.onerror = stopPulse;
window.speechSynthesis.speak(utterance);
};
stopBtn.onclick = () => {
window.speechSynthesis.cancel();
stopPulse();
};
btnRow.appendChild(synthBtn);
btnRow.appendChild(stopBtn);
infoPanel.appendChild(btnRow);
container.appendChild(infoPanel);
return container;
}
Apply Changes