You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* Image Dream Generator Tool ("Грёза 3")
* Applies a surreal, hallucinogenic "dream" effect to the image using spatial wave distortion,
* ethereal color dodging, and glowing bloom layers.
*
* @param {HTMLImageElement} originalImg - The source image
* @param {number|string} dreamLevel - The intensity of the dream distortion and bloom (default: 3 for "Грёза 3")
* @param {number|string} waveFrequency - The frequency of the swirling dream wave (default: 30)
* @param {number|string} glowIntensity - The alpha opacity of the glowing bloom layer (default: 0.6)
* @returns {HTMLCanvasElement} - The visually processed image canvas
*/
function processImage(originalImg, dreamLevel = 3, waveFrequency = 30, glowIntensity = 0.6) {
// Parse parameters
const level = Number(dreamLevel) || 3;
const freq = Number(waveFrequency) || 30;
const glow = isNaN(Number(glowIntensity)) ? 0.6 : Number(glowIntensity);
// Setup main canvas
const canvas = document.createElement('canvas');
const width = canvas.width = originalImg.width;
const height = canvas.height = originalImg.height;
const ctx = canvas.getContext('2d');
// Draw the original image to extract pixel data
ctx.drawImage(originalImg, 0, 0);
// 1. SURREAL WAVE DISTORTION
const imgData = ctx.getImageData(0, 0, width, height);
const data = imgData.data;
const outputData = ctx.createImageData(width, height);
const out = outputData.data;
const amp = level * 3; // Amplitude scales with the dream level
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
// Complex sine wave combination for a melting, "dreamy" swirl
const dx = Math.sin(y / freq) * amp + Math.sin(x / (freq * 1.5)) * (amp / 2);
const dy = Math.cos(x / freq) * amp + Math.cos(y / (freq * 1.5)) * (amp / 2);
// Determine source pixel
let srcX = Math.floor(x + dx);
let srcY = Math.floor(y + dy);
// Clamp coordinates to image boundaries
srcX = Math.max(0, Math.min(width - 1, srcX));
srcY = Math.max(0, Math.min(height - 1, srcY));
const srcIdx = (srcY * width + srcX) * 4;
const dstIdx = (y * width + x) * 4;
// Copy RGBA channels
out[dstIdx] = data[srcIdx];
out[dstIdx + 1] = data[srcIdx + 1];
out[dstIdx + 2] = data[srcIdx + 2];
out[dstIdx + 3] = data[srcIdx + 3];
}
}
// Since blending modes via canvas don't apply to putImageData,
// we put the warped image to an intermediary offscreen canvas.
const tempCanvas = document.createElement('canvas');
tempCanvas.width = width;
tempCanvas.height = height;
const tempCtx = tempCanvas.getContext('2d');
tempCtx.putImageData(outputData, 0, 0);
// Clear the main canvas context for the compositing passes
ctx.clearRect(0, 0, width, height);
// Base Layer: Warped image
ctx.drawImage(tempCanvas, 0, 0);
// 2. ETHEREAL GLOW / BLOOM LAYER
// Upsaturate, blur, and screen to create a blinding, soft dream glow
ctx.globalCompositeOperation = 'screen';
ctx.globalAlpha = glow;
ctx.filter = `blur(${level * 2}px) saturate(200%) contrast(120%)`;
ctx.drawImage(tempCanvas, 0, 0);
// 3. CHROMATIC ABBERATION / OUT-OF-BODY LAYER
// Scale slightly outward, hue shift, and color-dodge to simulate a psychedelic trippy atmosphere
ctx.globalCompositeOperation = 'color-dodge';
ctx.globalAlpha = 0.3;
ctx.filter = `hue-rotate(45deg) blur(2px)`;
// Scale from the center
ctx.translate(width / 2, height / 2);
ctx.scale(1.0 + (level * 0.01), 1.0 + (level * 0.01));
ctx.translate(-width / 2, -height / 2);
ctx.drawImage(tempCanvas, 0, 0);
// Reset transformations and filters
ctx.globalCompositeOperation = 'source-over';
ctx.globalAlpha = 1.0;
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.filter = 'none';
// 4. SOFT DREAM VIGNETTE
// Using source-atop ensures we don't draw shadow over transparent background areas
ctx.globalCompositeOperation = 'source-atop';
const gradient = ctx.createRadialGradient(
width / 2, height / 2, Math.min(width, height) * 0.3,
width / 2, height / 2, Math.min(width, height) * 0.8
);
gradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
gradient.addColorStop(1, 'rgba(0, 5, 20, 0.5)'); // Slightly bluish-dark vignette for atmosphere
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
return canvas;
}
Apply Changes