You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
contrast = 1.6,
brightness = -15,
noiseAmount = 30,
vignetteStrength = 0.8,
text = "Чёрная суббота"
) {
// Create canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
// Draw the initial image
ctx.drawImage(originalImg, 0, 0);
// Get image data to apply "Black Sunday" / "Чёрная суббота" dark, gritty B&W effect
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
const numContrast = Number(contrast);
const numBrightness = Number(brightness);
const numNoise = Number(noiseAmount);
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
// 1. Apply Brightness offset
r += numBrightness;
g += numBrightness;
b += numBrightness;
// 2. Apply Contrast
r = numContrast * (r - 128) + 128;
g = numContrast * (g - 128) + 128;
b = numContrast * (b - 128) + 128;
// Clamp values to valid 0-255 range
r = Math.max(0, Math.min(255, r));
g = Math.max(0, Math.min(255, g));
b = Math.max(0, Math.min(255, b));
// 3. Convert to Grayscale (Luminance formula)
let gray = 0.299 * r + 0.587 * g + 0.114 * b;
// 4. Apply Film Grain Noise
if (numNoise > 0) {
let noise = (Math.random() - 0.5) * numNoise;
gray += noise;
gray = Math.max(0, Math.min(255, gray));
}
// Apply updated grayscale value to RGB channels (ignoring alpha channel at i+3)
data[i] = gray;
data[i + 1] = gray;
data[i + 2] = gray;
}
// Write the manipulated image data back into the canvas
ctx.putImageData(imageData, 0, 0);
// 5. Apply Dark Vignette for a gloomy aesthetic
const numVignette = Number(vignetteStrength);
if (numVignette > 0) {
const gradient = ctx.createRadialGradient(
width / 2, height / 2, Math.min(width, height) * 0.2,
width / 2, height / 2, Math.max(width, height) * 0.7
);
gradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
gradient.addColorStop(1, `rgba(0, 0, 0, ${numVignette})`);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
}
// 6. Apply the horror/thriller text meme overlay if provided
if (text) {
const fontSize = Math.max(20, Math.floor(width * 0.08));
ctx.font = `bold ${fontSize}px "Courier New", Courier, monospace`;
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
const textX = width / 2;
const textY = height - Math.max(20, height * 0.05);
// Heavy dark shadow to separate from background
ctx.shadowColor = "rgba(0, 0, 0, 0.9)";
ctx.shadowBlur = Math.max(5, fontSize * 0.3);
ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
ctx.fillStyle = "#ffffff";
ctx.fillText(text, textX, textY);
// Secondary subtle dark-red shadow to give it that "Black Sunday" horror vibe
ctx.shadowColor = "rgba(100, 0, 0, 0.8)";
ctx.shadowBlur = Math.max(3, fontSize * 0.1);
ctx.shadowOffsetX = -2;
ctx.shadowOffsetY = -2;
ctx.fillText(text, textX, textY);
// Reset context shadows
ctx.shadowColor = "transparent";
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
}
return canvas;
}
Apply Changes