You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, dreamSplit = 0.5, zoomIntensity = 0.15, dreamDistortion = 30, realityContrast = 30) {
// Parse parameters to ensure they are properly handled
dreamSplit = Number(dreamSplit);
if (isNaN(dreamSplit)) dreamSplit = 0.5;
zoomIntensity = Number(zoomIntensity);
if (isNaN(zoomIntensity)) zoomIntensity = 0.15;
dreamDistortion = Number(dreamDistortion);
if (isNaN(dreamDistortion)) dreamDistortion = 30;
realityContrast = Number(realityContrast);
if (isNaN(realityContrast)) realityContrast = 30;
const canvas = document.createElement('canvas');
const w = canvas.width = originalImg.width;
const h = canvas.height = originalImg.height;
const ctx = canvas.getContext('2d', { willReadFrequently: true });
// Step 1: Base drawing with "Flight" radial motion blur effect
// Render the crisp original image first
ctx.drawImage(originalImg, 0, 0, w, h);
// Render multiple scaled up overlays with low opacity for the forward motion/zoom speed blur
const flightSteps = 15;
ctx.globalAlpha = 0.1;
for (let i = 1; i <= flightSteps; i++) {
const scale = 1 + (zoomIntensity * (i / flightSteps));
const translateX = (w / 2) * (1 - scale);
const translateY = (h / 2) * (1 - scale);
ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
ctx.drawImage(originalImg, 0, 0, w, h);
}
// Reset transform context
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.globalAlpha = 1.0;
// Step 2: Pixel manipulation for "Dream" (top) and "Reality" (bottom) separation
const imgData = ctx.getImageData(0, 0, w, h);
const data = imgData.data;
const outData = ctx.createImageData(w, h);
const dst = outData.data;
// Compute contrast factor for the "reality" layer (bottom section)
const factor = (259 * (realityContrast + 255)) / (255 * (259 - realityContrast));
for (let y = 0; y < h; y++) {
// Dream intensity fades continuously from 1.0 at the absolute top
// down to 0.0 at the vertical percentage of dreamSplit
let df = 1 - (y / (h * dreamSplit));
if (df < 0) df = 0; // Anything below the 0 point represents reality
for (let x = 0; x < w; x++) {
let srcX = x;
let srcY = y;
// Apply surreal, wavy distortion for the Dream realm
if (df > 0) {
srcX = Math.floor(x + Math.sin(y / dreamDistortion) * dreamDistortion * df);
srcY = Math.floor(y + Math.cos(x / dreamDistortion) * dreamDistortion * df);
}
// Clamp coordinates to bounds
srcX = Math.max(0, Math.min(w - 1, srcX));
srcY = Math.max(0, Math.min(h - 1, srcY));
const iDst = (y * w + x) * 4;
const iSrc = (srcY * w + srcX) * 4;
if (df > 0) {
// Ethereal dream color tinting: push red/blue values up playfully for a glowing hue offset
dst[iDst] = Math.min(255, data[iSrc] + 40 * df); // R
dst[iDst + 1] = Math.min(255, data[iSrc + 1] + 15 * df); // G
dst[iDst + 2] = Math.min(255, data[iSrc + 2] + 65 * df); // B
dst[iDst + 3] = data[iSrc + 3]; // A
} else {
// Reality component: apply contrast filter to make the "awake" area sharp and gritty
dst[iDst] = Math.min(255, Math.max(0, factor * (data[iSrc] - 128) + 128));
dst[iDst + 1] = Math.min(255, Math.max(0, factor * (data[iSrc + 1] - 128) + 128));
dst[iDst + 2] = Math.min(255, Math.max(0, factor * (data[iSrc + 2] - 128) + 128));
dst[iDst + 3] = data[iSrc + 3];
}
}
}
// Output visual buffer onto the canvas
ctx.putImageData(outData, 0, 0);
return canvas;
}
Apply Changes