You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, action = 'grayscale', value = '1') {
// Determine target canvas dimensions
let width = originalImg.width;
let height = originalImg.height;
// Normalize inputs
const actionStr = String(action).toLowerCase();
let numValue = parseFloat(value);
if (isNaN(numValue)) numValue = 1;
let cropOpts = null;
// Handle transformations that change canvas size
if (actionStr === 'rotate') {
const rad = (numValue * Math.PI) / 180;
width = Math.abs(originalImg.width * Math.cos(rad)) + Math.abs(originalImg.height * Math.sin(rad));
height = Math.abs(originalImg.width * Math.sin(rad)) + Math.abs(originalImg.height * Math.cos(rad));
} else if (actionStr === 'scale' || actionStr === 'resize') {
if (typeof value === 'string' && value.toLowerCase().includes('x')) {
const parts = value.toLowerCase().split('x');
const w = parseInt(parts[0], 10);
const h = parseInt(parts[1], 10);
if (!isNaN(w) && !isNaN(h)) {
width = w;
height = h;
} else {
width = originalImg.width * numValue;
height = originalImg.height * numValue;
}
} else {
width = originalImg.width * numValue;
height = originalImg.height * numValue;
}
} else if (actionStr === 'crop') {
if (typeof value === 'string' && value.includes(',')) {
// Expected format: "x, y, w, h"
const parts = value.split(',').map(n => parseFloat(n.trim()));
if (parts.length === 4 && parts.every(n => !isNaN(n))) {
width = Math.max(1, parts[2]);
height = Math.max(1, parts[3]);
cropOpts = parts; // [x, y, w, h]
}
}
// Fallback: Center crop based on a fraction (0.1 to 1.0)
if (!cropOpts) {
const factor = Math.min(1, Math.max(0.01, numValue));
width = originalImg.width * factor;
height = originalImg.height * factor;
cropOpts = [
(originalImg.width - width) / 2,
(originalImg.height - height) / 2,
width,
height
];
}
}
// Set up canvas
const canvas = document.createElement('canvas');
canvas.width = Math.round(width) || 1;
canvas.height = Math.round(height) || 1;
const ctx = canvas.getContext('2d');
ctx.save();
// 1. Apply Coordinate Transformations
if (actionStr === 'rotate') {
const rad = (numValue * Math.PI) / 180;
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(rad);
ctx.translate(-originalImg.width / 2, -originalImg.height / 2);
} else if (actionStr === 'flip_horizontal' || actionStr === 'fliph') {
ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
} else if (actionStr === 'flip_vertical' || actionStr === 'flipv') {
ctx.translate(0, canvas.height);
ctx.scale(1, -1);
}
// 2. Apply Image Filters (Browser standard Canvas filter property)
let filterStr = 'none';
switch (actionStr) {
case 'grayscale':
case 'greyscale': filterStr = `grayscale(${numValue * 100}%)`; break; // value 1 = 100%
case 'invert': filterStr = `invert(${numValue * 100}%)`; break;
case 'sepia': filterStr = `sepia(${numValue * 100}%)`; break;
case 'brightness': filterStr = `brightness(${numValue * 100}%)`; break;
case 'contrast': filterStr = `contrast(${numValue * 100}%)`; break;
case 'saturate': filterStr = `saturate(${numValue * 100}%)`; break;
case 'blur': filterStr = `blur(${numValue}px)`; break; // value in pixels
case 'hue_rotate':
case 'hue-rotate': filterStr = `hue-rotate(${numValue}deg)`; break; // value in degrees
}
ctx.filter = filterStr;
// 3. Draw Image
if (actionStr === 'crop' && cropOpts) {
// Crop rendering
ctx.drawImage(
originalImg,
cropOpts[0], cropOpts[1], cropOpts[2], cropOpts[3], // source (x, y, w, h)
0, 0, width, height // destination (x, y, w, h)
);
} else if (actionStr === 'scale' || actionStr === 'resize') {
// Resized rendering
ctx.drawImage(originalImg, 0, 0, width, height);
} else {
// Default / Transformed / Filtered rendering
ctx.drawImage(originalImg, 0, 0, originalImg.width, originalImg.height);
}
ctx.restore();
// 4. Post-processing Overlays
if (actionStr === 'add_text' || actionStr === 'watermark') {
const textToDraw = (value !== undefined && value !== null) ? String(value) : 'Watermark';
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
// Dynamic font sizing relative to canvas size
const fontSize = Math.max(20, Math.floor(canvas.height / 10));
ctx.font = `bold ${fontSize}px sans-serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// Text drop-shadow for improved visibility on mixed backgrounds
ctx.shadowColor = 'rgba(0, 0, 0, 0.7)';
ctx.shadowBlur = Math.max(5, fontSize / 5);
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.fillText(textToDraw, canvas.width / 2, canvas.height / 2);
}
return canvas;
}
Apply Changes