You can edit the below JavaScript code to customize the image tool.
function processImage(
originalImg,
charSet = "ァィゥェォャュョッアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン0123456789",
fontSize = 10,
columnDensity = 1.0,
glowColor = '#33FF33',
trailColor = '#008000',
backgroundColor = '#000000',
brightnessThreshold = 30,
leadingCharEmphasis = 1.5
) {
const canvas = document.createElement('canvas');
canvas.width = originalImg.width;
canvas.height = originalImg.height;
const ctx = canvas.getContext('2d');
// Ensure numeric parameters are indeed numbers
fontSize = Number(fontSize);
columnDensity = Number(columnDensity);
brightnessThreshold = Number(brightnessThreshold);
leadingCharEmphasis = Number(leadingCharEmphasis);
// Draw the original image to a temporary canvas to get its pixel data
const tempCanvas = document.createElement('canvas');
tempCanvas.width = originalImg.width;
tempCanvas.height = originalImg.height;
const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true }); // Hint for optimization if available
tempCtx.drawImage(originalImg, 0, 0);
const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height).data;
// Helper function to get brightness (luminance) of a pixel
function getPixelBrightness(x, y, width, imgPixelData) {
x = Math.floor(x);
y = Math.floor(y);
// Clamp coordinates to be within image bounds
x = Math.max(0, Math.min(x, width - 1));
y = Math.max(0, Math.min(y, Math.floor(imgPixelData.length / (width * 4)) - 1));
const index = (y * width + x) * 4;
const r = imgPixelData[index];
const g = imgPixelData[index + 1];
const b = imgPixelData[index + 2];
// Standard luminance calculation
return (0.299 * r + 0.587 * g + 0.114 * b);
}
// Fill background
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Prepare for drawing characters
if (fontSize < 1) fontSize = 1; // Ensure minimum font size
ctx.font = `${fontSize}px monospace`;
ctx.textBaseline = 'top'; // Makes y-coordinate handling easier (y is top of char)
const charsToUse = charSet.split('');
if (charsToUse.length === 0) { // Prevent errors if charSet is empty
charsToUse.push('X');
}
const baseColumnWidth = fontSize * 0.6; // Approx width of a monospace char relative to its height
const actualColumnWidth = Math.max(1, baseColumnWidth / Math.max(0.1, columnDensity)); // Prevent division by zero or too small density
const numColumns = Math.floor(canvas.width / actualColumnWidth);
if (numColumns <= 0) { // If image too narrow or density settings result in no columns
return canvas; // Return background-filled canvas
}
for (let i = 0; i < numColumns; i++) {
const x = i * actualColumnWidth;
// Each column gets a "stream" of characters.
// For a static image, we simulate a snapshot of these streams.
// Stream starts at a random y, potentially off-screen to simulate continuous flow.
let streamStartY = Math.random() * canvas.height * 1.5 - canvas.height * 0.5; // Start y for char at j=0
// Random length for this particular stream segment
const streamLengthInChars = Math.floor(Math.random() * (canvas.height / fontSize / 1.5)) + Math.floor(fontSize / 2) + 3; // Adjusted length
// Some streams might be designated as "brighter" overall, having more leading-style chars
const isBrightStream = Math.random() < 0.15;
for (let j = 0; j < streamLengthInChars; j++) {
const charY = streamStartY + j * fontSize; // Top Y coordinate of the current character
// Skip if character is completely out of visible canvas bounds
if (charY < -fontSize || charY > canvas.height) {
continue;
}
const randomChar = charsToUse[Math.floor(Math.random() * charsToUse.length)];
// Determine position on original image to sample brightness (center of the character cell)
const imageSampleX = x + actualColumnWidth / 2;
const imageSampleY = charY + fontSize / 2;
const imgBrightness = getPixelBrightness(imageSampleX, imageSampleY, canvas.width, imageData);
// If the underlying image area is too dark, apply a probability to skip drawing
if (imgBrightness < brightnessThreshold && Math.random() > 0.2) { // 80% chance to skip if below threshold
continue;
}
const normalizedImgBrightness = imgBrightness / 255.0; // Brightness as 0.0 - 1.0
let charColorToUse;
let charOpacity;
let charShadowBlur = 0;
let charShadowColor = 'transparent';
// Determine if this character is a "leading" character (brightest one, typically at the head of the stream)
// The first char in the stream (j=0) is always leading.
// Others in a "bright stream" have diminishing chance to also be leading style.
const isLeadingChar = (j === 0) || (isBrightStream && j < 3 && Math.random() < (0.6 - j * 0.2));
if (isLeadingChar) {
charColorToUse = glowColor;
charOpacity = Math.min(1.0, normalizedImgBrightness * leadingCharEmphasis);
charOpacity = Math.max(0.15, charOpacity); // Ensure minimum visibility for leading characters
charShadowBlur = Math.max(1, normalizedImgBrightness * fontSize * 0.6); // Shadow relative to font size
charShadowColor = glowColor;
} else {
charColorToUse = trailColor;
// Fade trail characters based on position in stream and image brightness
const trailFadeFactor = Math.pow((streamLengthInChars - j) / streamLengthInChars, 1.8); // Stronger fade for tail
charOpacity = Math.min(1.0, normalizedImgBrightness * trailFadeFactor * 0.9); // Trail chars are dimmer
charOpacity = Math.max(0.05, charOpacity); // Minimum visibility for trail characters
charShadowBlur = Math.max(0, normalizedImgBrightness * trailFadeFactor * fontSize * 0.3);
charShadowColor = trailColor;
}
ctx.fillStyle = charColorToUse;
ctx.globalAlpha = charOpacity; // This will be clamped to [0,1] by canvas
if (charShadowBlur > 0.5) { // Only apply shadow if it's somewhat visible
ctx.shadowColor = charShadowColor;
ctx.shadowBlur = charShadowBlur;
} else {
ctx.shadowBlur = 0; // Explicitly turn off shadow
ctx.shadowColor = 'transparent';
}
ctx.fillText(randomChar, x, charY);
}
}
// Reset global alpha and shadow settings that might affect subsequent drawings if canvas is reused elsewhere
ctx.globalAlpha = 1.0;
ctx.shadowBlur = 0;
ctx.shadowColor = 'transparent';
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image To Matrix-style Falling Code Art Generator transforms your images into visually striking artwork reminiscent of digital rain. By using a customizable character set, users can create a unique representation of their images, where pixels are replaced with characters that flow down the canvas in streams. This tool allows for adjustments in font size, column density, and color settings, enabling users to enhance the aesthetic according to their preferences. Ideal for artistic projects, digital designs, and creating engaging visuals for social media or presentations, this tool offers a creative way to reimagine images as fashionable code-like art.