You can edit the below JavaScript code to customize the image tool.
async function processImage(
originalImg,
cellSize = 10, // number: Size of the grid cellsåºto analyze (e.g., 10 means 10x10 pixel blocks)
symbolColor = "black", // string: Color of the dots and dashes (e.g., "black", "#FF0000")
backgroundColor = "white", // string: Background color of the canvas (e.g., "white", "transparent")
darkThreshold = 85, // number: Brightness (0-255) below which a dash is drawn
lightThreshold = 170, // number: Brightness (0-255) below which a dot is drawn (and above darkThreshold)
dotScale = 0.3, // number: Radius of dots as a factor of cellSize (e.g., 0.3 means dot radius is 0.3 * cellSize)
dashWidthScale = 0.7, // number: Width of dashes as a factor of cellSize (e.g., 0.7 means dash width is 0.7 * cellSize)
dashHeightScale = 0.25 // number: Height of dashes as a factor of cellSize (e.g., 0.25 means dash height is 0.25 * cellSize)
) {
// Ensure cellSize is a positive integer
cellSize = Math.max(1, Math.floor(cellSize));
// Clamp thresholds to the valid 0-255 range
darkThreshold = Math.max(0, Math.min(255, darkThreshold));
lightThreshold = Math.max(0, Math.min(255, lightThreshold));
// Ensure scales are non-negative
dotScale = Math.max(0, dotScale);
dashWidthScale = Math.max(0, dashWidthScale);
dashHeightScale = Math.max(0, dashHeightScale);
const imgWidth = originalImg.naturalWidth;
const imgHeight = originalImg.naturalHeight;
// Handle cases where the image might not be loaded or is invalid
if (imgWidth === 0 || imgHeight === 0) {
console.error("Original image not loaded or has zero dimensions.");
const errorCanvas = document.createElement('canvas');
errorCanvas.width = 250;
errorCanvas.height = 60;
const eCtx = errorCanvas.getContext('2d');
if (eCtx) {
eCtx.fillStyle = "#FFAAAA"; // Light red background for error
eCtx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
eCtx.fillStyle = "black";
eCtx.font = "12px Arial";
eCtx.fillText("Error: Invalid image provided.", 10, 25);
eCtx.fillText(`Dimensions: ${imgWidth}x${imgHeight}. Check if loaded.`, 10, 45);
}
return errorCanvas;
}
// 1. Create a source canvas to draw the original image.
// This allows access to its pixel data via getImageData.
const sourceCanvas = document.createElement('canvas');
sourceCanvas.width = imgWidth;
sourceCanvas.height = imgHeight;
const sourceCtx = sourceCanvas.getContext('2d', {
willReadFrequently: true // Optimization hint for frequent getImageData calls
});
if (!sourceCtx) { // Should not happen in modern browsers unless canvas is disabled/unsupported
console.error("Could not get 2D context for source canvas.");
return originalImg; // Fallback or handle error appropriately
}
sourceCtx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
// 2. Create the output canvas where the "Morse code" effect will be rendered
const outputCanvas = document.createElement('canvas');
outputCanvas.width = imgWidth;
outputCanvas.height = imgHeight;
const ctx = outputCanvas.getContext('2d');
if (!ctx) { // Should not happen
console.error("Could not get 2D context for output canvas.");
return originalImg;
}
// 3. Fill the output canvas with the specified background color
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, imgWidth, imgHeight);
// 4. Process the image in grid cells
for (let y = 0; y < imgHeight; y += cellSize) {
for (let x = 0; x < imgWidth; x += cellSize) {
// Determine the actual width and height of the current cell.
// This handles cells at the image's edges that might be smaller than cellSize.
const currentCellWidth = Math.min(cellSize, imgWidth - x);
const currentCellHeight = Math.min(cellSize, imgHeight - y);
if (currentCellWidth <= 0 || currentCellHeight <= 0) {
continue;
}
// a. Calculate the average brightness of the pixels in the current cell
let imageData;
try {
imageData = sourceCtx.getImageData(x, y, currentCellWidth, currentCellHeight);
} catch (e) {
// This error typically occurs if the canvas is "tainted"
// (e.g., image loaded from a different origin without CORS headers).
console.error("Error getting imageData (possibly tainted canvas):", e);
// Draw an error message directly onto the output canvas and return it.
ctx.fillStyle = 'rgba(255, 0, 0, 0.7)'; // Semi-transparent red overlay
ctx.fillRect(0, 0, imgWidth, imgHeight);
ctx.fillStyle = 'white';
ctx.font = "bold 16px Arial";
ctx.textAlign = "center";
const messageY = imgHeight / 2;
ctx.fillText("ERROR: Cannot process image.", imgWidth / 2, messageY - 10);
ctx.font = "14px Arial";
ctx.fillText("Cross-origin security issue (tainted canvas).", imgWidth / 2, messageY + 10);
return outputCanvas; // Return the canvas with the error message
}
const data = imageData.data;
let totalBrightness = 0;
const numPixelsInCell = currentCellWidth * currentCellHeight;
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i+1];
const b = data[i+2];
// Standard luminance formula for grayscale conversion (perceived brightness)
const brightness = 0.299 * r + 0.587 * g + 0.114 * b;
totalBrightness += brightness;
}
// averageBrightness will be between 0 (black) and 255 (white)
const averageBrightness = numPixelsInCell > 0 ? totalBrightness / numPixelsInCell : 0;
// b. Set the fill color for the symbols (dots/dashes)
ctx.fillStyle = symbolColor;
// c. Decide which symbol to draw based on average brightness.
// Symbols are drawn relative to the top-left of the conceptual 'full' cell (x,y)
// and centered within that cellSize x cellSize area for a consistent grid appearance.
if (averageBrightness < darkThreshold) {
// Draw a dash (horizontal rectangle)
const dashActualWidth = cellSize * dashWidthScale;
const dashActualHeight = cellSize * dashHeightScale;
// Calculate top-left corner for the dash to be centered in the conceptual cell
const rectX = x + (cellSize - dashActualWidth) / 2;
const rectY = y + (cellSize - dashActualHeight) / 2;
ctx.fillRect(rectX, rectY, dashActualWidth, dashActualHeight);
} else if (averageBrightness < lightThreshold) {
// Draw a dot (circle)
const dotRadius = cellSize * dotScale;
// Calculate center for the dot in the conceptual cell
const centerX = x + cellSize / 2;
const centerY = y + cellSize / 2;
ctx.beginPath();
ctx.arc(centerX, centerY, dotRadius, 0, 2 * Math.PI);
ctx.fill();
}
// Else (averageBrightness >= lightThreshold):
// This area is considered "light" and will remain background color (already drawn).
}
}
return outputCanvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Morse Code Filter Effect Tool allows users to transform images into a unique visual interpretation resembling Morse code. By analyzing the image pixel-by-pixel, the tool generates dashes and dots based on brightness levels, creating a grid effect that can serve both artistic and practical purposes. This tool can be used for creative projects, such as generating artistic prints, enhancing digital content, or simply having fun with image manipulation. Users can customize parameters such as symbol color and background color, allowing for versatile application across various media and styles.