You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true }); // For performance with getImageData
// Ensure the canvas has the same dimensions as the image
canvas.width = originalImg.naturalWidth || originalImg.width;
canvas.height = originalImg.naturalHeight || originalImg.height;
// Draw the image onto the canvas
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
// Get the image data from the canvas
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data; // Uint8ClampedArray: [r, g, b, a, r, g, b, a, ...]
// Define the "Ironbow" thermal color map
// This palette goes from black/dark blue (cold) to red/yellow/white (hot)
const ironbowPalette = [
{ pos: 0.0, color: { r: 0, g: 0, b: 0 }}, // Black
{ pos: 0.08, color: { r: 18, g: 0, b: 77 }}, // Very dark blue/purple
{ pos: 0.16, color: { r: 50, g: 0, b: 150 }}, // Dark purple
{ pos: 0.24, color: { r: 90, g: 0, b: 180 }}, // Purple
{ pos: 0.32, color: { r: 130, g: 10, b: 170 }}, // Magenta/Reddish purple
{ pos: 0.40, color: { r: 180, g: 20, b: 120 }}, // Purplish Red
{ pos: 0.48, color: { r: 220, g: 40, b: 40 }}, // Red
{ pos: 0.56, color: { r: 240, g: 80, b: 0 }}, // Red-Orange
{ pos: 0.64, color: { r: 255, g: 130, b: 0 }}, // Orange
{ pos: 0.72, color: { r: 255, g: 180, b: 0 }}, // Yellow-Orange
{ pos: 0.80, color: { r: 255, g: 220, b: 30 }}, // Bright Yellow
{ pos: 0.88, color: { r: 255, g: 255, b: 120 }}, // Light Yellow
{ pos: 1.0, color: { r: 255, g: 255, b: 255 }} // White
];
const currentPalette = ironbowPalette;
// Helper function for linear interpolation
function lerp(a, b, t) {
return a * (1 - t) + b * t;
}
// Helper function to get the thermal color for a given value
function getThermalColor(value, palette) {
// Clamp value to the palette's range (typically 0-1)
const firstPos = palette[0].pos;
const lastPos = palette[palette.length - 1].pos;
if (value <= firstPos) {
return palette[0].color;
}
if (value >= lastPos) {
return palette[palette.length - 1].color;
}
for (let i = 0; i < palette.length - 1; i++) {
const p1 = palette[i];
const p2 = palette[i + 1];
if (value >= p1.pos && value <= p2.pos) {
// Normalize t within this segment
const t = (p2.pos - p1.pos === 0) ? 0 : (value - p1.pos) / (p2.pos - p1.pos);
return {
r: Math.round(lerp(p1.color.r, p2.color.r, t)),
g: Math.round(lerp(p1.color.g, p2.color.g, t)),
b: Math.round(lerp(p1.color.b, p2.color.b, t)),
};
}
}
// Fallback, should ideally not be reached if palette is well-defined
return palette[palette.length - 1].color;
}
// Iterate over 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];
// Alpha (data[i + 3]) will be preserved
// Calculate grayscale intensity (luminance method)
const intensity = 0.299 * r + 0.587 * g + 0.114 * b; // Value from 0 to 255
// Normalize intensity to 0-1 range
const normalizedIntensity = intensity / 255.0;
// Get the corresponding thermal color
const thermalColor = getThermalColor(normalizedIntensity, currentPalette);
// Update the pixel data
data[i] = thermalColor.r;
data[i + 1] = thermalColor.g;
data[i + 2] = thermalColor.b;
}
// Put the modified image data back onto the canvas
ctx.putImageData(imageData, 0, 0);
return canvas;
}
Apply Changes