You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* Simulates various types of TV screen damage on an image.
*
* @param {Image} originalImg The original javascript Image object.
* @param {string} [damageType='deadPixels'] The type of damage to apply. Options: 'deadPixels', 'stuckPixels', 'lines', 'cracks', 'static'.
* @param {number} [severity=25] The intensity of the damage, from 0 to 100.
* @param {string} [lineDirection='vertical'] For 'lines' damage, the direction of lines. Options: 'vertical', 'horizontal', 'both'.
* @param {string} [lineColor='random'] For 'lines' damage, the color of the lines (e.g., '#ff0000' or 'random').
* @param {string} [pixelColor='random'] For 'stuckPixels' damage, the color of the pixels (e.g., '#00ff00' or 'random').
* @returns {HTMLCanvasElement} A canvas element with the damaged image.
*/
function processImage(originalImg, damageType = 'deadPixels', severity = 25, lineDirection = 'vertical', lineColor = 'random', pixelColor = 'random') {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
canvas.width = width;
canvas.height = height;
// Draw the original image as the base layer
ctx.drawImage(originalImg, 0, 0);
// Ensure severity is within a 0-100 range
const clampedSeverity = Math.max(0, Math.min(100, severity));
// Helper function to get a random integer within a range
const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
switch (damageType) {
case 'deadPixels': {
const numPixels = Math.floor((width * height * clampedSeverity) / 200000);
ctx.fillStyle = '#000000';
for (let i = 0; i < numPixels; i++) {
const x = getRandomInt(0, width - 1);
const y = getRandomInt(0, height - 1);
ctx.fillRect(x, y, 1, 1);
}
break;
}
case 'stuckPixels': {
const numPixels = Math.floor((width * height * clampedSeverity) / 200000);
const stuckColors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff'];
for (let i = 0; i < numPixels; i++) {
const x = getRandomInt(0, width - 1);
const y = getRandomInt(0, height - 1);
if (pixelColor === 'random') {
ctx.fillStyle = stuckColors[getRandomInt(0, stuckColors.length - 1)];
} else {
ctx.fillStyle = pixelColor;
}
ctx.fillRect(x, y, 1, 1);
}
break;
}
case 'lines': {
const numLines = Math.ceil(clampedSeverity / 4);
const getRandomColor = () => `rgb(${getRandomInt(0, 255)}, ${getRandomInt(0, 255)}, ${getRandomInt(0, 255)})`;
for (let i = 0; i < numLines; i++) {
ctx.lineWidth = getRandomInt(1, 3);
ctx.strokeStyle = (lineColor === 'random') ? getRandomColor() : lineColor;
ctx.beginPath();
let currentDirection = lineDirection;
if (lineDirection === 'both') {
currentDirection = Math.random() < 0.5 ? 'vertical' : 'horizontal';
}
if (currentDirection === 'vertical') {
const x = getRandomInt(0, width - 1);
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
} else { // horizontal
const y = getRandomInt(0, height - 1);
ctx.moveTo(0, y);
ctx.lineTo(width, y);
}
ctx.stroke();
}
break;
}
case 'cracks': {
const centerX = getRandomInt(width * 0.1, width * 0.9);
const centerY = getRandomInt(height * 0.1, height * 0.9);
const numCracks = Math.floor(3 + clampedSeverity / 8);
ctx.strokeStyle = 'rgba(230, 230, 230, 0.7)';
for (let i = 0; i < numCracks; i++) {
ctx.lineWidth = Math.random() * 1.5 + 1;
ctx.beginPath();
ctx.moveTo(centerX, centerY);
// Find a random point on the canvas edge
const edge = getRandomInt(0, 3);
let endX, endY;
switch (edge) {
case 0: /* Top */ endX = Math.random() * width; endY = 0; break;
case 1: /* Right */ endX = width; endY = Math.random() * height; break;
case 2: /* Bottom */ endX = Math.random() * width; endY = height; break;
case 3: /* Left */ endX = 0; endY = Math.random() * height; break;
}
// Add jaggedness to the crack line
const segments = 10;
for (let j = 1; j <= segments; j++) {
const t = j / segments;
const jagX = (Math.random() - 0.5) * clampedSeverity * 0.25;
const jagY = (Math.random() - 0.5) * clampedSeverity * 0.25;
ctx.lineTo(
centerX + (endX - centerX) * t + jagX,
centerY + (endY - centerY) * t + jagY
);
}
ctx.stroke();
}
break;
}
case 'static': {
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
// Scale severity (0-100) to a noise intensity level (0-150)
const noiseLevel = clampedSeverity * 1.5;
for (let i = 0; i < data.length; i += 4) {
// Apply the same noise to R, G, and B to create grayscale static
const noise = (Math.random() - 0.5) * noiseLevel;
data[i] = data[i] + noise;
data[i + 1] = data[i + 1] + noise;
data[i + 2] = data[i + 2] + noise;
// Alpha channel (data[i + 3]) is left untouched
}
ctx.putImageData(imageData, 0, 0);
break;
}
default:
// If damageType is unknown, do nothing and return the original image on the canvas
console.warn(`Unknown damageType: "${damageType}".`);
break;
}
return canvas;
}
Apply Changes