You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, numLevels = 4, colorsStr = "dc041f,fef001,24a9e2,84c341") {
// Helper function to parse hex color string to an RGB object
// Defined inside processImage to keep it self-contained.
function hexToRgbLocal(hexRaw) {
const cleanHex = String(hexRaw).trim().startsWith('#') ? String(hexRaw).trim().substring(1) : String(hexRaw).trim();
// Basic check for 6-digit hex format
if (!/^[0-9A-Fa-f]{6}$/.test(cleanHex)) {
// console.warn(`Invalid hex color format "${hexRaw}", using black.`);
return { r: 0, g: 0, b: 0 };
}
const r = parseInt(cleanHex.substring(0, 2), 16);
const g = parseInt(cleanHex.substring(2, 4), 16);
const b = parseInt(cleanHex.substring(4, 6), 16);
// Check if parsing resulted in NaN (e.g., for non-hex characters within the 6 chars like "GGFFFF")
if (isNaN(r) || isNaN(g) || isNaN(b)) {
// console.warn(`Invalid hex color values in "${hexRaw}" after parsing, using black.`);
return { r: 0, g: 0, b: 0 };
}
return { r, g, b };
}
// Validate and normalize numLevels
if (typeof numLevels !== 'number' || isNaN(numLevels) || numLevels < 1) {
numLevels = 4; // Default if invalid type, NaN, or value < 1
}
numLevels = Math.floor(numLevels); // Ensure integer
// Parse the colorsStr into an array of RGB objects
// If colorsStr is empty or not a string, handle gracefully.
let palette;
if (typeof colorsStr === 'string' && colorsStr.trim() !== '') {
const colorHexStrings = colorsStr.split(',');
palette = colorHexStrings.map(hex => hexToRgbLocal(hex));
} else {
// If colorsStr is empty or not a string, use the default colors.
// This effectively re-applies the default if colorsStr is invalid.
const defaultColorsArray = "dc041f,fef001,24a9e2,84c341".split(',');
palette = defaultColorsArray.map(hex => hexToRgbLocal(hex));
}
// Final safety net: if palette ended up empty for any reason (e.g. default string was wrong), use black.
if (!palette || palette.length === 0) {
palette = [{ r: 0, g: 0, b: 0 }];
}
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Determine image dimensions, preferring natural dimensions
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
// Handle cases where image dimensions might be invalid or image not loaded
if (!imgWidth || !imgHeight || imgWidth <= 0 || imgHeight <= 0) {
// console.error("Image has invalid dimensions or is not loaded.");
canvas.width = 1; // Create a minimal 1x1 canvas
canvas.height = 1;
if(ctx) { // Draw a tiny red dot to indicate an error state
ctx.fillStyle = 'red';
ctx.fillRect(0,0,1,1);
}
return canvas;
}
canvas.width = imgWidth;
canvas.height = imgHeight;
// 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);
// Return canvas as is (it might be blank or partially drawn)
return canvas;
}
// Get image data for pixel manipulation
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// console.error("Error getting image data (e.g., CORS issue if image source is cross-origin):", e);
// If getImageData fails, return the canvas with the original image drawn (no filter applied).
return canvas;
}
const data = imageData.data;
const segmentSize = 256 / numLevels; // The size of each grayscale intensity segment
// Process each pixel
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
// const alpha = data[i+3]; // Alpha is preserved by not modifying data[i+3]
// Calculate grayscale value (luminance)
const gray = 0.299 * r + 0.587 * g + 0.114 * b;
// Determine which posterization level this grayscale value falls into
let level = Math.floor(gray / segmentSize);
// Clamp level to be within the valid range [0, numLevels - 1]
level = Math.min(level, numLevels - 1);
level = Math.max(level, 0); // Ensure level is not negative
// Get the target color from the palette, cycling through palette colors if necessary
const targetColor = palette[level % palette.length];
// Apply the new color
data[i] = targetColor.r;
data[i + 1] = targetColor.g;
data[i + 2] = targetColor.b;
}
// Put the modified image data back onto the canvas
ctx.putImageData(imageData, 0, 0);
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 Andy Warhol Filter Effect Tool allows users to apply a distinctive pop art style filter to their images, reminiscent of the iconic works of Andy Warhol. This tool enables the posterization of colors in an image, transforming it into a vibrant, multi-colored version by applying a custom color palette and adjusting the number of color levels. It is particularly useful for artists, designers, or anyone interested in creating visually striking artwork or social media graphics. Users can upload their images, customize the color palette, and adjust the effect parameters to create unique, colorful renditions of their photos.