You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* This function applies a visual effect to an image.
* Given the ambiguous tool name "Image Video Audio Voice Changer with Effects Tool",
* this implementation provides a set of image effects with names or concepts
* inspired by video and audio terminology (e.g., glitch, noise, wave, echo).
* It operates solely on the input image as required by the function signature.
*
* @param {Image} originalImg The original javascript Image object. Must be fully loaded.
* @param {string} effectType The type of effect to apply.
* Valid options: 'glitch', 'noise', 'wave', 'echo', 'hueshift', 'scanlines'.
* Defaults to 'glitch'.
* @param {number} intensity A value from 0.0 to 1.0 that controls the strength of the effect.
* Defaults to 0.5.
* @returns {HTMLCanvasElement} A new canvas element with the visual effect applied.
*/
function processImage(originalImg, effectType = 'glitch', intensity = 0.5) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
canvas.width = width;
canvas.height = height;
// Clamp intensity to the valid range [0.0, 1.0]
const clampedIntensity = Math.max(0, Math.min(1, intensity));
switch (effectType.toLowerCase()) {
case 'glitch':
{
ctx.drawImage(originalImg, 0, 0);
// Create random horizontal static-like slices
const sliceCount = Math.floor(30 + clampedIntensity * 70);
for (let i = 0; i < sliceCount; i++) {
let y = Math.random() * height;
let h = 1 + Math.random() * 20;
if (y + h > height) {
y = height - h; // Ensure slice is within canvas bounds
}
const xOffset = (Math.random() - 0.5) * 50 * clampedIntensity;
ctx.drawImage(canvas, 0, y, width, h, xOffset, y, width, h);
}
break;
}
case 'noise':
{
ctx.drawImage(originalImg, 0, 0);
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
const noiseAmount = 255 * clampedIntensity * 0.2;
for (let i = 0; i < data.length; i += 4) {
// Add random noise to R, G, B channels
const noise = (Math.random() - 0.5) * noiseAmount;
data[i] = Math.max(0, Math.min(255, data[i] + noise));
data[i + 1] = Math.max(0, Math.min(255, data[i + 1] + noise));
data[i + 2] = Math.max(0, Math.min(255, data[i + 2] + noise));
}
ctx.putImageData(imageData, 0, 0);
break;
}
case 'wave':
{
const amplitude = clampedIntensity * 30; // Max horizontal pixel shift
const frequency = 0.05 + clampedIntensity * 0.1; // Wave density
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = width;
tempCanvas.height = height;
tempCtx.drawImage(originalImg, 0, 0);
// Displace each horizontal line of pixels based on a sine wave
for (let y = 0; y < height; y++) {
const xOffset = Math.sin(y * frequency) * amplitude;
ctx.drawImage(tempCanvas, 0, y, width, 1, xOffset, y, width, 1);
}
break;
}
case 'echo':
{
const steps = 5;
const baseOffset = clampedIntensity * 20;
const initialAlpha = 0.4 * clampedIntensity;
ctx.drawImage(originalImg, 0, 0, width, height);
// Draw fading copies of the image at increasing offsets
for (let i = 1; i <= steps; i++) {
ctx.globalAlpha = initialAlpha / i;
ctx.drawImage(originalImg, i * baseOffset, 0, width, height);
}
ctx.globalAlpha = 1.0; // Reset alpha
break;
}
case 'hueshift':
{
const angle = Math.floor(clampedIntensity * 360);
if (angle > 0) {
ctx.filter = `hue-rotate(${angle}deg)`;
}
ctx.drawImage(originalImg, 0, 0);
ctx.filter = 'none'; // Reset filter
break;
}
case 'scanlines':
{
ctx.drawImage(originalImg, 0, 0, width, height);
ctx.fillStyle = `rgba(0, 0, 0, ${0.3 * clampedIntensity})`;
// Draw semi-transparent dark lines to simulate a CRT screen
for (let y = 0; y < height; y += 4) {
ctx.fillRect(0, y, width, 2);
}
break;
}
default:
// If the effect type is unknown, just draw the original image
ctx.drawImage(originalImg, 0, 0);
break;
}
return canvas;
}
Apply Changes