Please bookmark this page to avoid losing your image tool!

Mystères De Pétersbourg Image Viewer

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
// This function creates an interactive "Mystères de Pétersbourg" (Mysteries of Petersburg) viewer.
// It transforms the base image into a moody, foggy, dark environment akin to the atmosphere 
// of a 19th-century detective mystery, and gives the user an interactive spotlight (flashlight)
// to search through visually hidden visuals, revealing the original vivid tones beneath.

function processImage(originalImg, spotRadius = 150, darknessColor = "rgba(10, 15, 25, 0.85)", blurAmount = 4) {
    const width = originalImg.width;
    const height = originalImg.height;
    
    // Parse parameters
    const radius = parseFloat(spotRadius) || 150;
    const blurNum = parseFloat(blurAmount) || 4;

    // Create the main visible canvas
    const mainCanvas = document.createElement('canvas');
    mainCanvas.width = width;
    mainCanvas.height = height;
    mainCanvas.style.maxWidth = '100%';
    mainCanvas.style.height = 'auto';
    mainCanvas.style.display = 'block';
    mainCanvas.style.cursor = 'crosshair';
    mainCanvas.style.touchAction = 'none'; // Prevents scrolling when interacting via touch
    const ctx = mainCanvas.getContext('2d');

    // Pre-render the dark, mysterious background (fog/gloom of Petersburg)
    // This optimizes performance by not applying heavy filters on every mouse movement.
    const darkBgCanvas = document.createElement('canvas');
    darkBgCanvas.width = width;
    darkBgCanvas.height = height;
    const darkCtx = darkBgCanvas.getContext('2d');

    // Apply moody, vintage filter to the background (grayscale, contrast, sepia, blur)
    darkCtx.filter = `sepia(50%) contrast(120%) brightness(80%) grayscale(80%) blur(${blurNum}px)`;
    darkCtx.drawImage(originalImg, 0, 0);
    darkCtx.filter = 'none';
        
    // Apply the heavy dark tint
    darkCtx.fillStyle = darknessColor;
    darkCtx.fillRect(0, 0, width, height);

    // Apply a subtle vignette effect to deepen the mystery at the edges
    const vignette = darkCtx.createRadialGradient(width/2, height/2, width/4, width/2, height/2, width/1.2);
    vignette.addColorStop(0, 'rgba(0,0,0,0)');
    vignette.addColorStop(1, 'rgba(0,0,0,0.8)');
    darkCtx.fillStyle = vignette;
    darkCtx.fillRect(0, 0, width, height);

    // Create a temporary overlay canvas for creating the spotlight mask
    const overlayCanvas = document.createElement('canvas');
    overlayCanvas.width = width;
    overlayCanvas.height = height;
    const overlayCtx = overlayCanvas.getContext('2d');

    // Start with spotlight dead center
    let mouseX = width / 2;
    let mouseY = height / 2;
    let isRendering = false;

    // Main render loop for interactivity
    function render() {
        // Draw the pure, vibrant original image
        ctx.clearRect(0, 0, width, height);
        ctx.drawImage(originalImg, 0, 0);

        // Prep the overlay canvas
        overlayCtx.globalCompositeOperation = 'source-over';
        overlayCtx.clearRect(0, 0, width, height);
        
        // Draw the gloomy mystery background
        overlayCtx.drawImage(darkBgCanvas, 0, 0);

        // Cut out the spotlight circle using destination-out
        overlayCtx.globalCompositeOperation = 'destination-out';
        const gradient = overlayCtx.createRadialGradient(mouseX, mouseY, 0, mouseX, mouseY, radius);
        gradient.addColorStop(0, 'rgba(0, 0, 0, 1)');
        gradient.addColorStop(0.7, 'rgba(0, 0, 0, 0.8)');
        gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');

        overlayCtx.fillStyle = gradient;
        overlayCtx.beginPath();
        overlayCtx.arc(mouseX, mouseY, radius, 0, Math.PI * 2);
        overlayCtx.fill();

        // Draw the masked dark background onto main canvas
        ctx.drawImage(overlayCanvas, 0, 0);

        // Add a subtle screen glow to the rim of the spotlight
        ctx.globalCompositeOperation = 'screen';
        ctx.beginPath();
        ctx.arc(mouseX, mouseY, radius, 0, Math.PI * 2);
        const rimGrad = ctx.createRadialGradient(mouseX, mouseY, radius * 0.9, mouseX, mouseY, radius);
        rimGrad.addColorStop(0, 'rgba(255, 255, 255, 0)');
        rimGrad.addColorStop(0.8, 'rgba(255, 255, 255, 0.08)');
        rimGrad.addColorStop(1, 'rgba(255, 255, 255, 0)');
        ctx.fillStyle = rimGrad;
        ctx.fill();
        ctx.globalCompositeOperation = 'source-over';
    }

    // Initial draw
    render();

    // Event listener helper
    function updatePointer(e) {
        const rect = mainCanvas.getBoundingClientRect();
        // Calculate canvas scaling based on responsive CSS
        const scaleX = mainCanvas.width / rect.width;
        const scaleY = mainCanvas.height / rect.height;

        if (e.touches && e.touches.length > 0) {
            mouseX = (e.touches[0].clientX - rect.left) * scaleX;
            mouseY = (e.touches[0].clientY - rect.top) * scaleY;
        } else {
            mouseX = (e.clientX - rect.left) * scaleX;
            mouseY = (e.clientY - rect.top) * scaleY;
        }
        
        // Use requestAnimationFrame to keep animation butter smooth
        if (!isRendering) {
            isRendering = true;
            requestAnimationFrame(() => {
                render();
                isRendering = false;
            });
        }
    }

    // Attach interactions
    mainCanvas.addEventListener('mousemove', updatePointer);
    mainCanvas.addEventListener('touchmove', (e) => {
        e.preventDefault();
        updatePointer(e);
    }, { passive: false });

    return mainCanvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Mystères de Pétersbourg Image Viewer is an interactive tool that transforms your photos into a dark, atmospheric, and moody experience. It applies a vintage, foggy, and dim aesthetic to an image, effectively hiding parts of the original picture under a mysterious veil. Users can then interact with the image using a virtual spotlight or flashlight, moving their cursor or finger to reveal the true colors and details hidden beneath the gloom. This tool is ideal for creating immersive digital art, designing interactive storytelling elements, or adding a sense of mystery and discovery to web-based games and creative presentations.

Leave a Reply

Your email address will not be published. Required fields are marked *