You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg, levelsParam = 5, colorsStrParam = "0000FF,00FF00,FFFF00,FFA500,FF0000") {
// 1. Validate and sanitize parameters
let numLevels = Number(levelsParam);
if (isNaN(numLevels) || !isFinite(numLevels) || numLevels <= 0) {
numLevels = 5; // Default levels if input is invalid or not sensible
} else {
numLevels = Math.floor(numLevels); // Ensure integer if valid number
}
let colorsStrLocal;
// Ensure colorsStrParam is treated as a string for parsing. Numbers will be converted.
if (typeof colorsStrParam === 'string') {
colorsStrLocal = colorsStrParam;
} else if (colorsStrParam === null || typeof colorsStrParam === 'undefined') {
// Use default if null or undefined is explicitly passed
colorsStrLocal = "0000FF,00FF00,FFFF00,FFA500,FF0000";
} else {
colorsStrLocal = String(colorsStrParam);
}
// 2. Parse colorsStrLocal into an array of {r, g, b} objects
let colorValues;
// Default color array (used if colorsStrLocal is empty or results in no valid colors)
const defaultColorsHexArray = ["0000FF", "00FF00", "FFFF00", "FFA500", "FF0000"]; // Blue, Green, Yellow, Orange, Red
if (colorsStrLocal.trim() === "") {
colorValues = defaultColorsHexArray;
} else {
colorValues = colorsStrLocal.split(',');
}
const parsedColors = colorValues.map(hexInput => {
let hex = String(hexInput).replace('#', '').trim();
// Validate hex string: must be 6 hexadecimal characters
if (!/^[0-9A-Fa-f]{6}$/.test(hex)) {
// console.warn(`Invalid color hex: "${hexInput}". Defaulting to black unless it's the only color.`);
return null; // Mark as invalid for now
}
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return { r, g, b };
}).filter(color => color !== null); // Remove nulls (invalid hex codes)
// Ensure there's at least one color to use after parsing.
if (parsedColors.length === 0) {
// This happens if all provided colors were invalid or colorsStrLocal was like ",,,"
// console.warn("All provided colors were invalid or the color string was effectively empty. Using default weather map colors.");
parsedColors.push(...defaultColorsHexArray.map(hex => {
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return {r, g, b};
}));
// If even defaultColorsHexArray was empty (it's not), as a last resort:
if (parsedColors.length === 0) {
parsedColors.push({ r: 0, g: 0, b: 255 }); // Absolute fallback: blue
}
}
// 3. Setup Canvas
const canvas = document.createElement('canvas');
// Use naturalWidth/Height for HTMLImageElement, fallback to width/height for others (e.g., canvas, video).
canvas.width = originalImg.naturalWidth || originalImg.width || 0;
canvas.height = originalImg.naturalHeight || originalImg.height || 0;
if (canvas.width === 0 || canvas.height === 0) {
// console.warn("Image has zero width or height. Returning an empty canvas (0x0).");
return canvas;
}
const ctx = canvas.getContext('2d');
// Draw the original image onto the canvas
try {
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
} catch (e) {
// console.error("Error drawing image to canvas:", e);
// This might happen if originalImg is not a valid image source.
// Draw an error message.
ctx.fillStyle = 'rgba(128, 128, 128, 0.8)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'black';
ctx.font = '16px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Error: Could not draw original image.', canvas.width / 2, canvas.height / 2);
return canvas;
}
// 4. Get Image Data
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// This typically happens due to CORS issues if the image is from another domain.
// console.error("Error getting image data (CORS issue?):", e);
ctx.fillStyle = 'rgba(128, 128, 128, 0.8)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'black';
ctx.font = '16px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const lines = ['Error: Could not process image pixels.', '(Possibly a cross-origin security issue)'];
const lineHeight = 20;
let y = canvas.height / 2 - (lines.length -1) * lineHeight / 2;
for(const line of lines) {
ctx.fillText(line, canvas.width / 2, y);
y += lineHeight;
}
return canvas;
}
const data = imageData.data;
// 5. Process Pixels
const numPixels = data.length / 4;
// Intensity values range from 0 to 255 (256 distinct values).
// step determines the size of each intensity band.
const step = 256 / numLevels;
for (let i = 0; i < numPixels; i++) {
const offset = i * 4;
const r = data[offset];
const g = data[offset + 1];
const b = data[offset + 2];
// Alpha (data[offset + 3]) is preserved.
// Convert to grayscale intensity (luminance formula)
const intensity = 0.299 * r + 0.587 * g + 0.114 * b;
// Quantize intensity to determine color level.
// Math.floor(intensity / step) can result in `numLevels` if intensity is 255,
// so clamp index to be within [0, numLevels-1].
let levelIndex = Math.floor(intensity / step);
levelIndex = Math.min(levelIndex, numLevels - 1);
levelIndex = Math.max(levelIndex, 0); // Ensure non-negative (should be by calculation)
// Map the quantized level to a color.
// If not enough colors were provided for all levels, use the last available color.
const colorIndex = Math.min(levelIndex, parsedColors.length - 1);
const targetColor = parsedColors[colorIndex];
data[offset] = targetColor.r;
data[offset + 1] = targetColor.g;
data[offset + 2] = targetColor.b;
}
// 6. Put Image Data Back onto the canvas
ctx.putImageData(imageData, 0, 0);
// 7. Return the processed canvas
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 Weather Map Filter Effect Tool allows users to apply a weather map-style color filter to images. Users can customize the number of color levels and select specific colors for the effect, effectively transforming standard photographs into visually appealing representations that resemble weather mapping visuals. This tool is ideal for graphic designers, weather enthusiasts, educators, or anyone looking to create artistic reinterpretations of images for presentations, social media, or personal projects.