Please bookmark this page to avoid losing your image tool!

Domovoy Image Generator

(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.
function processImage(originalImg, operationMode = 'photobomb', position = 'bottom-right') {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    
    if (operationMode === 'portrait') {
        // Portrait Mode: Turn the uploaded image into a Domovoy character
        canvas.width = 600;
        canvas.height = 600;
        
        // 1. Background (Wooden hut planks)
        ctx.fillStyle = '#8B5A2B';
        ctx.fillRect(0, 0, 600, 600);
        ctx.strokeStyle = '#5C3A21';
        ctx.lineWidth = 4;
        for (let i = 0; i < 600; i += 80) {
            ctx.beginPath();
            ctx.moveTo(0, i);
            ctx.lineTo(600, i);
            ctx.stroke();
            // Draw some knotholes in the wood
            if (i % 160 === 0) {
                ctx.beginPath();
                ctx.ellipse(100 + i / 2, i + 40, 20, 5, 0, 0, Math.PI * 2);
                ctx.stroke();
                ctx.beginPath();
                ctx.ellipse(100 + i / 2, i + 40, 10, 2, 0, 0, Math.PI * 2);
                ctx.stroke();
            }
        }
        
        // 2. Body (Traditional red shirt - Kosovorotka)
        ctx.fillStyle = '#C21E56';
        ctx.beginPath();
        ctx.moveTo(220, 320);
        ctx.quadraticCurveTo(100, 450, 80, 600);
        ctx.lineTo(520, 600);
        ctx.quadraticCurveTo(500, 450, 380, 320);
        ctx.fill();
        
        // Shirt pattern (polka dots)
        ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';
        for (let i = 0; i < 30; i++) {
            ctx.beginPath();
            ctx.arc(100 + Math.random() * 400, 350 + Math.random() * 250, 4, 0, Math.PI * 2);
            ctx.fill();
        }

        // Collar
        ctx.fillStyle = '#FFF';
        ctx.fillRect(290, 320, 20, 120);

        // Arms
        ctx.fillStyle = '#B31B4D';
        ctx.beginPath();
        ctx.moveTo(170, 400); // Left arm
        ctx.lineTo(60, 500);
        ctx.lineTo(90, 530);
        ctx.lineTo(200, 480);
        ctx.fill();
        
        ctx.beginPath();
        ctx.moveTo(430, 400); // Right arm
        ctx.lineTo(540, 500);
        ctx.lineTo(510, 530);
        ctx.lineTo(400, 480);
        ctx.fill();

        // Props (Spoon & Broom)
        // Left - Wooden Spoon
        ctx.save();
        ctx.translate(75, 515);
        ctx.rotate(-Math.PI / 4);
        ctx.fillStyle = '#D2B48C';
        ctx.fillRect(-5, -80, 10, 80);
        ctx.beginPath();
        ctx.ellipse(0, -90, 20, 30, 0, 0, Math.PI * 2);
        ctx.fill();
        ctx.restore();

        // Right - Besom (Broom)
        ctx.save();
        ctx.strokeStyle = '#8B5A2B';
        ctx.lineWidth = 10;
        ctx.beginPath();
        ctx.moveTo(540, 350);
        ctx.lineTo(510, 600);
        ctx.stroke();
        
        ctx.fillStyle = '#DEB887';
        ctx.beginPath();
        ctx.moveTo(540, 350);
        ctx.lineTo(500, 200);
        ctx.lineTo(580, 200);
        ctx.fill();
        
        ctx.strokeStyle = '#CD853F';
        ctx.lineWidth = 2;
        for (let i = 0; i < 16; i++) {
            ctx.beginPath();
            ctx.moveTo(540, 350);
            ctx.lineTo(500 + i * 5.3, 200);
            ctx.stroke();
        }
        ctx.strokeStyle = '#8B5A2B';
        ctx.lineWidth = 4;
        ctx.beginPath();
        ctx.moveTo(525, 320);
        ctx.lineTo(555, 315);
        ctx.stroke();
        ctx.restore();

        // Hands (Drawn over props)
        ctx.fillStyle = '#E8B48F';
        ctx.beginPath();
        ctx.arc(75, 515, 20, 0, Math.PI * 2);
        ctx.arc(525, 515, 20, 0, Math.PI * 2);
        ctx.fill();

        // 3. User Image (Cropped inside the Face)
        ctx.save();
        ctx.beginPath();
        ctx.arc(300, 250, 95, 0, Math.PI * 2);
        ctx.closePath();
        ctx.clip();
        
        const imgAspect = originalImg.width / originalImg.height;
        let drawW, drawH;
        if (imgAspect > 1) {
            drawH = 190;
            drawW = 190 * imgAspect;
        } else {
            drawW = 190;
            drawH = 190 / imgAspect;
        }
        ctx.drawImage(originalImg, 300 - drawW / 2, 250 - drawH / 2, drawW, drawH);
        ctx.restore();

        // 4. Beard and Hair (Frames the face to complete the Domovoy look)
        ctx.fillStyle = '#4A3326';

        const beardCircles = [
            { x: 215, y: 280, r: 40 }, { x: 235, y: 320, r: 45 }, { x: 265, y: 350, r: 50 },
            { x: 300, y: 360, r: 55 }, { x: 335, y: 350, r: 50 }, { x: 365, y: 320, r: 45 },
            { x: 385, y: 280, r: 40 }
        ];
        beardCircles.forEach(c => {
            ctx.beginPath(); ctx.arc(c.x, c.y, c.r, 0, Math.PI * 2); ctx.fill();
        });

        const hairCircles = [
            { x: 210, y: 210, r: 40 }, { x: 230, y: 160, r: 45 }, { x: 265, y: 130, r: 50 },
            { x: 300, y: 120, r: 55 }, { x: 335, y: 130, r: 50 }, { x: 370, y: 160, r: 45 },
            { x: 390, y: 210, r: 40 }
        ];
        hairCircles.forEach(c => {
            ctx.beginPath(); ctx.arc(c.x, c.y, c.r, 0, Math.PI * 2); ctx.fill();
        });

        // Inner lighter texture loops for volume
        ctx.fillStyle = '#6E4D3A';
        beardCircles.forEach(c => {
            ctx.beginPath(); ctx.arc(c.x, c.y - 5, c.r * 0.6, 0, Math.PI * 2); ctx.fill();
        });
        hairCircles.forEach(c => {
            ctx.beginPath(); ctx.arc(c.x, c.y + 5, c.r * 0.6, 0, Math.PI * 2); ctx.fill();
        });

        // 5. Title Text
        ctx.fillStyle = '#4A3326';
        ctx.font = 'bold 46px "Trebuchet MS", "Arial", sans-serif';
        ctx.textAlign = 'center';
        ctx.fillText('ДОМОВОЙ', 303, 63);
        ctx.fillStyle = '#FFD700';
        ctx.fillText('ДОМОВОЙ', 300, 60);

    } else {
        // Photobomb Mode: Add a mini Domovoy secretly visiting your photo
        canvas.width = originalImg.width;
        canvas.height = originalImg.height;
        ctx.drawImage(originalImg, 0, 0);

        const size = Math.max(100, Math.min(originalImg.height, originalImg.width) * 0.4);
        const marginX = size * 0.4;
        const marginY = 0; 
        
        // Positioning logic
        let cx, cy;
        switch (position) {
            case 'bottom-left':
                cx = marginX; cy = originalImg.height - marginY; break;
            case 'top-left':
                cx = marginX; cy = size; break;
            case 'top-right':
                cx = originalImg.width - marginX; cy = size; break;
            case 'bottom-right':
            default:
                cx = originalImg.width - marginX; cy = originalImg.height - marginY; break;
        }

        ctx.save();
        ctx.translate(cx, cy);
        
        const scale = size / 200; // Base drawing is scaled off a 200px height frame
        ctx.scale(scale, scale);
        ctx.translate(0, -100);

        // Body 
        ctx.fillStyle = '#C21E56';
        ctx.beginPath();
        ctx.ellipse(0, 50, 40, 50, 0, 0, Math.PI * 2);
        ctx.fill();

        ctx.fillStyle = '#222';
        ctx.fillRect(-38, 55, 76, 8); // Belt

        // Lapti (Bark Shoes)
        ctx.fillStyle = '#D2B48C';
        ctx.beginPath();
        ctx.ellipse(-20, 100, 15, 10, 0, 0, Math.PI * 2);
        ctx.ellipse(20, 100, 15, 10, 0, 0, Math.PI * 2);
        ctx.fill();
        ctx.strokeStyle = '#AA8050';
        ctx.lineWidth = 2;
        for (let j = -25; j <= -15; j += 3) { ctx.beginPath(); ctx.moveTo(j, 95); ctx.lineTo(j + 5, 105); ctx.stroke(); }
        for (let j = 15; j <= 25; j += 3) { ctx.beginPath(); ctx.moveTo(j, 95); ctx.lineTo(j + 5, 105); ctx.stroke(); }

        // Left Hand
        ctx.fillStyle = '#E8B48F';
        ctx.beginPath();
        ctx.arc(-40, 50, 10, 0, Math.PI * 2);
        ctx.fill();

        // Broom
        ctx.strokeStyle = '#8B5A2B';
        ctx.lineWidth = 4;
        ctx.beginPath();
        ctx.moveTo(55, 80);
        ctx.lineTo(20, -10);
        ctx.stroke();
        
        ctx.fillStyle = '#DEB887';
        ctx.beginPath();
        ctx.moveTo(55, 80);
        ctx.lineTo(40, 100);
        ctx.lineTo(70, 100);
        ctx.fill();

        // Right Hand (over broom)
        ctx.fillStyle = '#E8B48F';
        ctx.beginPath();
        ctx.arc(40, 50, 10, 0, Math.PI * 2);
        ctx.fill();

        // Thick Beard
        ctx.fillStyle = '#5C4033';
        ctx.beginPath();
        ctx.arc(0, 0, 45, 0, Math.PI);
        ctx.quadraticCurveTo(50, 60, 0, 80);
        ctx.quadraticCurveTo(-50, 60, -45, 0);
        ctx.fill();

        // Face
        ctx.fillStyle = '#E8B48F';
        ctx.beginPath();
        ctx.ellipse(0, -10, 25, 25, 0, 0, Math.PI * 2);
        ctx.fill();

        // Eyes
        ctx.fillStyle = 'white';
        ctx.beginPath();
        ctx.arc(-10, -15, 6, 0, Math.PI * 2);
        ctx.arc(10, -15, 6, 0, Math.PI * 2);
        ctx.fill();
        ctx.fillStyle = 'black';
        ctx.beginPath();
        ctx.arc(-10, -15, 3, 0, Math.PI * 2);
        ctx.arc(10, -15, 3, 0, Math.PI * 2);
        ctx.fill();

        // Nose
        ctx.fillStyle = '#D9A05B';
        ctx.beginPath();
        ctx.arc(0, -5, 7, 0, Math.PI * 2);
        ctx.fill();

        // Wild Hair
        ctx.fillStyle = '#5C4033';
        ctx.beginPath();
        ctx.arc(0, -20, 35, Math.PI, Math.PI * 2);
        ctx.fill();
        ctx.beginPath(); ctx.arc(-25, -25, 15, 0, Math.PI * 2); ctx.fill();
        ctx.beginPath(); ctx.arc(25, -25, 15, 0, Math.PI * 2); ctx.fill();
        
        ctx.restore();
    }
    
    return canvas;
}

Free Image Tool Creator

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

Description

The Domovoy Image Generator is a creative tool that allows users to transform their photos using folklore-inspired themes. It offers two unique modes: ‘Portrait Mode,’ which crops a user’s face into a stylized Domovoy character complete with traditional clothing, a wooden background, and iconic props like a broom and spoon; and ‘Photobomb Mode,’ which overlays a small, whimsical Domovoy character into the corner of an existing image. This tool is ideal for creating fun, themed social media avatars or adding a playful, mythical touch to personal photographs.

Leave a Reply

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