You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, saturation = 1.8, contrast = 1.4, warmth = 0.2, outlineColor = "#201005", outlineStrength = 0.3, posterizeLevels = 0) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const w = originalImg.naturalWidth || originalImg.width;
const h = originalImg.naturalHeight || originalImg.height;
if (w === 0 || h === 0) {
console.error("Image has zero width or height. Ensure the image is loaded before processing.");
// Return a minimal canvas or handle as an error
canvas.width = 1;
canvas.height = 1;
return canvas;
}
canvas.width = w;
canvas.height = h;
// 1. Initial draw of the original image
ctx.drawImage(originalImg, 0, 0, w, h);
// 2. Apply base filters (saturation, contrast) using ctx.filter
// These filters affect subsequent drawing operations.
let filterString = "";
if (saturation !== 1.0) { // Default saturation is 1
filterString += `saturate(${saturation}) `;
}
if (contrast !== 1.0) { // Default contrast is 1
filterString += `contrast(${contrast}) `;
}
if (filterString.trim() !== "") {
ctx.filter = filterString.trim();
// Redraw the image (which is currently on the canvas) onto itself with the filter applied.
// This effectively filters the existing canvas content.
ctx.drawImage(canvas, 0, 0, w, h);
ctx.filter = 'none'; // Reset filter for any subsequent direct drawing
}
// 3. Posterization
// Reduces the number of colors in the image.
// posterizeLevels = 0 or 1 means no posterization.
if (posterizeLevels > 1 && posterizeLevels <= 256) {
const imageData = ctx.getImageData(0, 0, w, h);
const data = imageData.data;
// Ensure num_levels is an integer between 2 and 255.
const num_levels = Math.max(2, Math.min(255, Math.floor(posterizeLevels)));
const step = 255 / (num_levels - 1);
for (let i = 0; i < data.length; i += 4) {
data[i] = Math.round(data[i] / step) * step; // Red
data[i+1] = Math.round(data[i+1] / step) * step; // Green
data[i+2] = Math.round(data[i+2] / step) * step; // Blue
// Alpha (data[i+3]) remains unchanged
}
ctx.putImageData(imageData, 0, 0);
}
// 4. Warmth overlay
// Applies a warm color tint using overlay blending.
if (warmth > 0) {
ctx.globalCompositeOperation = 'overlay';
const warmR = 230, warmG = 180, warmB = 100; // An ochre/golden yellow color
// Clamp warmth value to [0, 1] for alpha
const effectiveWarmth = Math.min(1, Math.max(0, warmth));
ctx.fillStyle = `rgba(${warmR}, ${warmG}, ${warmB}, ${effectiveWarmth})`;
ctx.fillRect(0, 0, w, h);
ctx.globalCompositeOperation = 'source-over'; // Reset composite operation
}
// 5. Outlines
// Detects edges and draws them in the specified outlineColor.
if (outlineStrength > 0) {
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = w;
tempCanvas.height = h;
// Draw current state of main canvas (with all previous effects) to temp canvas for processing
tempCtx.drawImage(canvas, 0, 0, w, h);
const imageData = tempCtx.getImageData(0, 0, w, h);
const pixels = imageData.data; // Pixel data from the image with effects
// This will store the edge mask (RGB will be black, Alpha will indicate edge presence)
const outlinePixelData = new Uint8ClampedArray(pixels.length);
const getLuminance = (data, idx) => 0.299 * data[idx] + 0.587 * data[idx+1] + 0.114 * data[idx+2];
// Clamp outlineStrength to [0, 1] for calculations
const effectiveOutlineStrength = Math.min(1, Math.max(0, outlineStrength));
// Adjust edge detection threshold based on outlineStrength
// Higher strength means a lower threshold, thus more edges are detected.
const baseEdgeThreshold = 75; // Max threshold (for low strength)
const minEdgeThreshold = 15; // Min threshold (for high strength)
const actualThreshold = minEdgeThreshold + (baseEdgeThreshold - minEdgeThreshold) * (1 - effectiveOutlineStrength);
// Iterate over pixels, skipping borders to avoid out-of-bounds access
for (let y = 1; y < h - 1; y++) {
for (let x = 1; x < w - 1; x++) {
const i = (y * w + x) * 4; // Index of current pixel's R channel
const lumCurrent = getLuminance(pixels, i);
const lumRight = getLuminance(pixels, i + 4); // Pixel to the right
const lumDown = getLuminance(pixels, i + w * 4); // Pixel below
// Simple gradient calculation
const Gx = Math.abs(lumCurrent - lumRight);
const Gy = Math.abs(lumCurrent - lumDown);
const grad = Gx + Gy; // Sum of absolute differences
if (grad > actualThreshold) {
outlinePixelData[i+3] = 255; // Set alpha to full for edge pixels
} else {
outlinePixelData[i+3] = 0; // Transparent for non-edge pixels
}
// RGB values of outlinePixelData remain 0 (black) as initialized
}
}
const edgeImageData = new ImageData(outlinePixelData, w, h);
tempCtx.clearRect(0,0,w,h); // Clear the temporary canvas
tempCtx.putImageData(edgeImageData, 0, 0); // Draw the edge mask (black areas with alpha representing edges)
// Color the mask: Fill with outlineColor, but only where alpha (from edgeImageData) is non-zero
tempCtx.globalCompositeOperation = 'source-in';
tempCtx.fillStyle = outlineColor;
tempCtx.fillRect(0, 0, w, h);
tempCtx.globalCompositeOperation = 'source-over'; // Reset composite operation
// Draw the colored outlines from tempCanvas onto the main canvas
// The opacity of this outline layer is controlled by effectiveOutlineStrength
ctx.globalAlpha = effectiveOutlineStrength;
ctx.drawImage(tempCanvas, 0, 0);
ctx.globalAlpha = 1.0; // Reset globalAlpha
}
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 Indian Miniature Filter Effect Tool allows users to apply a distinct artistic effect to their images, reminiscent of traditional Indian miniature paintings. This tool enhances the image by adjusting saturation, contrast, and warmth, while also allowing for posterization to reduce color depth. It features an outline effect to emphasize edges, making images appear more illustrative. This tool can be used for enhancing personal photographs, creating unique visual artwork, or preparing images for graphic design projects, social media, and marketing materials.