You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, intensity = 1.0, warmth = 1.0) {
const int = isNaN(parseFloat(intensity)) ? 1.0 : parseFloat(intensity);
const wrm = isNaN(parseFloat(warmth)) ? 1.0 : parseFloat(warmth);
const canvas = document.createElement('canvas');
const w = originalImg.width;
const h = originalImg.height;
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext('2d');
ctx.drawImage(originalImg, 0, 0);
// Get pixel data
const imgData = ctx.getImageData(0, 0, w, h);
const data = imgData.data;
// Contrast parameters for harsh sunlight
const contrastFactor = 1 + (0.2 * int);
const contrastIntercept = 128 * (1 - contrastFactor);
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
let alpha = data[i + 3];
// Skip fully transparent pixels
if (alpha === 0) continue;
// --- DESSICCATION: Convert to HSL to dry out vegetation and make the sky dusty ---
let rNorm = r / 255;
let gNorm = g / 255;
let bNorm = b / 255;
let max = Math.max(rNorm, gNorm, bNorm);
let min = Math.min(rNorm, gNorm, bNorm);
let hue = 0, sat = 0, lum = (max + min) / 2;
if (max !== min) {
let d = max - min;
sat = lum > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case rNorm: hue = (gNorm - bNorm) / d + (gNorm < bNorm ? 6 : 0); break;
case gNorm: hue = (bNorm - rNorm) / d + 2; break;
case bNorm: hue = (rNorm - gNorm) / d + 4; break;
}
hue /= 6;
}
let hueDeg = hue * 360;
// 1. Dry Flora: Target green hues (approx. 50 to 170 degrees) and shift to yellow/brown
if (hueDeg > 50 && hueDeg < 170) {
let dist = Math.abs(hueDeg - 110);
let factor = Math.max(0, 1 - (dist / 60)); // 1.0 at peak green, 0.0 at edges
// Target dead grass hue ~42 degrees
let targetHue = 42;
hueDeg = hueDeg - (hueDeg - targetHue) * factor * int * 0.95;
// Significantly reduce saturation of dead plants
sat = sat * (1 - factor * 0.65 * int);
}
// 2. Dusty Sky: Target blue hues (approx. 190 to 260) to reduce saturation and brighten (haze/dust)
if (hueDeg > 190 && hueDeg < 260) {
let dist = Math.abs(hueDeg - 225);
let factor = Math.max(0, 1 - (dist / 35));
sat = sat * (1 - factor * 0.5 * int);
lum = lum + (1 - lum) * factor * 0.15 * int;
}
hue = (hueDeg + 360) % 360 / 360; // Keep in 0-1 bounds
// Reconvert back to RGB
let newR, newG, newB;
if (sat === 0) {
newR = newG = newB = lum;
} else {
const 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;
};
let q = lum < 0.5 ? lum * (1 + sat) : lum + sat - lum * sat;
let p = 2 * lum - q;
newR = hue2rgb(p, q, hue + 1 / 3);
newG = hue2rgb(p, q, hue);
newB = hue2rgb(p, q, hue - 1 / 3);
}
newR *= 255;
newG *= 255;
newB *= 255;
// --- SAND NOISE ---
// Add subtle gritty noise for a dusty, arid texture
const noise = (Math.random() - 0.5) * 12 * int;
// --- GLOBAL CLIMATE FEEL ---
let brightnessBump = 10 * int;
// Add orange/red warmth, subtract blue, add brightness and noise
newR += (45 * wrm + brightnessBump) * int + noise;
newG += (25 * wrm + brightnessBump) * int + noise;
newB += (-25 * wrm + brightnessBump) * int + noise;
// Apply harsh sunlight contrast
newR = newR * contrastFactor + contrastIntercept;
newG = newG * contrastFactor + contrastIntercept;
newB = newB * contrastFactor + contrastIntercept;
// Blend with original pixel based on intensity & clamp values between 0-255
data[i] = Math.max(0, Math.min(255, r + (newR - r) * int));
data[i + 1] = Math.max(0, Math.min(255, g + (newG - g) * int));
data[i + 2] = Math.max(0, Math.min(255, b + (newB - b) * int));
}
ctx.putImageData(imgData, 0, 0);
// --- HARSH VIGNETTE ---
// Simulate harsh lighting and heat focus by darkening the peripheries (lens effect)
const cx = w / 2;
const cy = h / 2;
const radius = Math.max(w, h) * 0.75;
const grad = ctx.createRadialGradient(cx, cy, radius * 0.4, cx, cy, radius);
// Warm burnt edges
grad.addColorStop(0, `rgba(0, 0, 0, 0)`);
grad.addColorStop(1, `rgba(60, 20, 0, ${0.45 * int})`);
ctx.globalCompositeOperation = 'multiply';
ctx.fillStyle = grad;
ctx.fillRect(0, 0, w, h);
// Minor sun/glare overlay at the top to simulate hot skyline
const glare = ctx.createLinearGradient(0, 0, 0, h * 0.4);
glare.addColorStop(0, `rgba(255, 240, 200, ${0.25 * int})`);
glare.addColorStop(1, `rgba(255, 240, 200, 0)`);
ctx.globalCompositeOperation = 'screen';
ctx.fillStyle = glare;
ctx.fillRect(0, 0, w, h);
// Reset composite operation
ctx.globalCompositeOperation = 'source-over';
return canvas;
}
Apply Changes