You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, blurRadius = 8, saturationBoost = 1.5, brightnessBoost = 1.2, hueStart = 180, hueEnd = 300) {
// Helper: RGB to HSL
// r, g, b are 0-255. Output h is 0-360. Output s, l are 0-1.
function rgbToHsl(r, g, b) {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b), min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0; // achromatic
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h * 360, s, l];
}
// Helper: HSL to RGB
// Input h is 0-360. Input s, l are 0-1. Output r, g, b are 0-255.
function hslToRgb(h, s, l) {
let r, g, b;
h /= 360; // convert h to 0-1 domain for calculations
if (s === 0) {
r = g = b = l; // achromatic
} else {
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
// Helper: Check if hue is in range (handles wrap-around for ranges like 330-30)
function isInHueRange(hue, start, end) {
// Ensure hue, start, end are within 0-360 for consistent comparison
// (Though hue from rgbToHsl is already 0-360)
// For this problem, we assume valid numeric inputs for start/end.
if (start <= end) { // Normal range, e.g., 60-120 (yellow to green)
return hue >= start && hue <= end;
} else { // Wrapped range, e.g., 330-30 (magenta through red to orange)
return hue >= start || hue <= end;
}
}
const w = originalImg.naturalWidth || originalImg.width;
const h = originalImg.naturalHeight || originalImg.height;
if (w === 0 || h === 0) {
// Image not loaded or invalid dimensions
const emptyCanvas = document.createElement('canvas');
emptyCanvas.width = Math.max(1, w); // Avoid 0 dimension
emptyCanvas.height = Math.max(1, h);
console.warn("Original image has zero dimensions. Returning an empty (or minimal) canvas.");
return emptyCanvas;
}
const outputCanvas = document.createElement('canvas');
outputCanvas.width = w;
outputCanvas.height = h;
const ctx = outputCanvas.getContext('2d');
// Create a temporary canvas to get original image data.
// This is robust if originalImg is an HTMLImageElement that might suffer
// from cross-origin issues if its source is external and CORS isn't set.
const tempCanvas = document.createElement('canvas');
tempCanvas.width = w;
tempCanvas.height = h;
const tempCtx = tempCanvas.getContext('2d');
tempCtx.drawImage(originalImg, 0, 0, w, h);
let imageData;
try {
imageData = tempCtx.getImageData(0, 0, w, h);
} catch (e) {
console.error("Error getting image data (cross-origin issue?): ", e);
// Fallback: draw the original image on the output canvas and return it
ctx.drawImage(originalImg, 0, 0, w, h);
return outputCanvas;
}
const data = imageData.data;
// Create glow canvas for the highlight/glow mask
const glowCanvas = document.createElement('canvas');
glowCanvas.width = w;
glowCanvas.height = h;
// Hinting `willReadFrequently` for `glowCanvas` as it will be drawn later.
const glowCtx = glowCanvas.getContext('2d', { willReadFrequently: true });
const glowImageData = glowCtx.createImageData(w, h);
const glowData = glowImageData.data;
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const a = data[i + 3];
if (a === 0) { // Skip fully transparent pixels
glowData[i] = 0; glowData[i+1] = 0; glowData[i+2] = 0; glowData[i+3] = 0;
continue;
}
const [hue, originalS, originalL] = rgbToHsl(r, g, b);
// Check if pixel is in target hue range and has some minimal saturation/lightness
// to avoid glowing black/grey/white areas unintentionally unless they have a color tint.
if (isInHueRange(hue, hueStart, hueEnd) && originalS > 0.05 && originalL > 0.05) {
const newS = Math.min(1, originalS * saturationBoost);
const newL = Math.min(1, originalL * brightnessBoost);
const [newR, newG, newB] = hslToRgb(hue, newS, newL);
glowData[i] = newR;
glowData[i + 1] = newG;
glowData[i + 2] = newB;
glowData[i + 3] = a; // Preserve original alpha for the glow mask points
} else {
// Make non-glowing pixels transparent black in the glow layer
glowData[i] = 0; glowData[i + 1] = 0; glowData[i + 2] = 0; glowData[i + 3] = 0;
}
}
glowCtx.putImageData(glowImageData, 0, 0);
// --- Composite final image ---
// 1. Draw original image onto the output canvas
ctx.drawImage(originalImg, 0, 0, w, h);
// 2. Composite the blurred glow layer on top
ctx.save(); // Save current state (like default composite operation and filter)
// Use 'lighter' for an additive blending effect, common for glows.
// Other options: 'screen' (softer), 'lighten' (max of components).
ctx.globalCompositeOperation = 'lighter';
if (blurRadius > 0) {
ctx.filter = `blur(${blurRadius}px)`;
}
// Draw the glowCanvas (which contains the colored highlights).
// The blur filter applies as this is drawn onto outputCanvas.
ctx.drawImage(glowCanvas, 0, 0, w, h);
ctx.restore(); // Restore composite operation and filter to previous state (defaults)
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 Jellyfish Glow Filter Effect tool allows users to apply a colorful glow effect to their images. This effect enhances specific hues within a defined range, increasing saturation and brightness while introducing a soft blur to create a luminous appearance. It is ideal for artists, designers, and social media enthusiasts looking to add a striking and vibrant aesthetic to their photos, making them more visually appealing for presentations, digital artwork, or online sharing.