Please bookmark this page to avoid losing your image tool!

Image Manners Enhancer Tool

(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.
async function processImage(
    originalImg,
    politeText = "Моё почтение, сударь!",
    frameTheme = "gold",
    borderThickness = "30",
    applyVintageFilter = "1"
) {
    // 1. Dynamically load a classy Google Font
    const fontName = 'Marck Script'; // Elegant font that supports Cyrillic and Latin
    const fontUrl = 'https://fonts.googleapis.com/css2?family=Marck+Script&display=swap';
    
    try {
        if (!document.querySelector(`link[href="${fontUrl}"]`)) {
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = fontUrl;
            document.head.appendChild(link);
        }
        if (document.fonts && document.fonts.load) {
            await document.fonts.load(`16px "${fontName}"`);
        } else {
            // Fallback delay if API is unavailable
            await new Promise(r => setTimeout(r, 800));
        }
    } catch (e) {
        console.warn("Could not load manners font. Using fallback.", e);
    }

    // 2. Base calculations to ensure it looks proportionally "proper" on any size image
    const maxDim = Math.max(originalImg.width, originalImg.height);
    const scale = Math.max(maxDim / 1000, 0.3); // Responsive scaling, minimum bound
    const bSize = parseInt(borderThickness, 10) * scale;
    const bottomAreaHeight = 140 * scale;

    const totalW = originalImg.width + bSize * 2;
    const totalH = originalImg.height + bSize * 2 + bottomAreaHeight;

    const canvas = document.createElement('canvas');
    canvas.width = totalW;
    canvas.height = totalH;
    const ctx = canvas.getContext('2d');

    // 3. Create elegant frame background
    let frameGradient;
    if (frameTheme === "silver") {
        frameGradient = ctx.createLinearGradient(0, 0, totalW, totalH);
        frameGradient.addColorStop(0, "#757F9A");
        frameGradient.addColorStop(0.5, "#E0E5EC");
        frameGradient.addColorStop(1, "#757F9A");
    } else if (frameTheme === "wood") {
        frameGradient = ctx.createLinearGradient(0, 0, totalW, totalH);
        frameGradient.addColorStop(0, "#3e2723");
        frameGradient.addColorStop(0.3, "#5d4037");
        frameGradient.addColorStop(0.7, "#795548");
        frameGradient.addColorStop(1, "#3e2723");
    } else { // default to "gold"
        frameGradient = ctx.createLinearGradient(0, 0, totalW, totalH);
        frameGradient.addColorStop(0, "#BF953F");
        frameGradient.addColorStop(0.25, "#FCF6BA");
        frameGradient.addColorStop(0.5, "#B38728");
        frameGradient.addColorStop(0.75, "#FBF5B7");
        frameGradient.addColorStop(1, "#AA771C");
    }

    ctx.fillStyle = frameGradient;
    ctx.fillRect(0, 0, totalW, totalH);

    // Frame 3D Outer Bevels
    ctx.lineWidth = 4 * scale;
    ctx.strokeStyle = "rgba(255,255,255,0.5)";
    ctx.beginPath(); ctx.moveTo(0, totalH); ctx.lineTo(0,0); ctx.lineTo(totalW, 0); ctx.stroke();
    
    ctx.strokeStyle = "rgba(0,0,0,0.7)";
    ctx.beginPath(); ctx.moveTo(totalW, 0); ctx.lineTo(totalW, totalH); ctx.lineTo(0, totalH); ctx.stroke();

    // Subtle dark groove inner border
    ctx.lineWidth = 4 * scale;
    ctx.strokeStyle = "rgba(0,0,0,0.9)";
    ctx.strokeRect(bSize, bSize, originalImg.width, originalImg.height);
    // Subtle bright lip
    ctx.strokeStyle = "rgba(255,255,255,0.3)";
    ctx.strokeRect(bSize - 4*scale, bSize - 4*scale, originalImg.width + 8*scale, originalImg.height + 8*scale);

    // 4. Draw Image with optional "Polite/Distinguished" Vintage Filter
    if (String(applyVintageFilter) === "1") {
        // Refined sepia and contrast boost to embody proper vintage manners
        ctx.filter = 'sepia(0.35) contrast(1.1) brightness(1.05)';
    }
    ctx.drawImage(originalImg, bSize, bSize);
    ctx.filter = 'none'; // reset filter for overlays

    // Useful drawing abstraction
    const drawRoundRect = (c, x, y, w, h, r) => {
        c.beginPath();
        c.moveTo(x + r, y);
        c.arcTo(x + w, y, x + w, y + h, r);
        c.arcTo(x + w, y + h, x, y + h, r);
        c.arcTo(x, y + h, x, y, r);
        c.arcTo(x, y, x + w, y, r);
        c.closePath();
    };

    // 5. Layout and Draw "Good Manners" Plaque
    const plaqueW = totalW * 0.8;
    const plaqueH = 80 * scale;
    const plaqueX = (totalW - plaqueW) / 2;
    // Position vertically centered in the newly created bottom padding space
    const plaqueY = originalImg.height + bSize + (bottomAreaHeight / 2) - (plaqueH / 2) + (10 * scale);

    // Substantive plaque background
    ctx.fillStyle = "#161616";
    drawRoundRect(ctx, plaqueX, plaqueY, plaqueW, plaqueH, 12 * scale);
    ctx.fill();
    ctx.strokeStyle = frameGradient;
    ctx.lineWidth = 4 * scale;
    ctx.stroke();

    // Inner subtle bright engraving line
    ctx.strokeStyle = "rgba(255,255,255,0.2)";
    ctx.lineWidth = 2 * scale;
    drawRoundRect(ctx, plaqueX + 4*scale, plaqueY + 4*scale, plaqueW - 8*scale, plaqueH - 8*scale, 9*scale);
    ctx.stroke();

    // 6. Sophisticated Dissenting Accessories (Top Hat, Bow Tie, Monocle Watermark)
    
    // --> Dangle a Monocle from the top-left inner frame
    const monocleStartX = bSize; 
    const monocleStartY = bSize;
    const monocleDrop = 100 * scale;
    const mX = monocleStartX + 50 * scale;
    const mY = monocleStartY + monocleDrop;
    const mRadius = 24 * scale;

    ctx.beginPath(); // Solid gold Monocle Chain
    ctx.moveTo(monocleStartX, monocleStartY);
    ctx.quadraticCurveTo(monocleStartX + 15*scale, monocleStartY + monocleDrop*0.6, mX, mY - mRadius);
    ctx.strokeStyle = "#FFD700";
    ctx.lineWidth = 2.5 * scale;
    ctx.stroke();

    ctx.beginPath(); // Monocle Glass
    ctx.arc(mX, mY, mRadius, 0, Math.PI*2);
    ctx.fillStyle = "rgba(255, 255, 255, 0.25)";
    ctx.fill();
    ctx.lineWidth = 4 * scale;
    ctx.strokeStyle = "#DAA520";
    ctx.stroke();

    ctx.beginPath(); // Monocle rim shine reflection
    ctx.arc(mX, mY, mRadius - 3*scale, Math.PI*1.1, Math.PI*1.5);
    ctx.strokeStyle = "#FFF";
    ctx.lineWidth = 2 * scale;
    ctx.stroke();

    // --> Draw the Bow Tie perfectly centered resting above the Plaque
    const tieW = 40 * scale;
    const tieH = 24 * scale;
    const tieCenterX = totalW / 2;
    const tieCenterY = plaqueY; // Sits evenly overlapping top edge

    ctx.fillStyle = frameTheme === 'gold' ? '#B8860B' : '#8B0000';
    ctx.strokeStyle = "#000";
    ctx.lineWidth = 2 * scale;
    
    ctx.beginPath(); // Left flipper
    ctx.moveTo(tieCenterX, tieCenterY);
    ctx.lineTo(tieCenterX - tieW, tieCenterY - tieH);
    ctx.lineTo(tieCenterX - tieW, tieCenterY + tieH);
    ctx.closePath();
    ctx.fill(); ctx.stroke();
    
    ctx.beginPath(); // Right flipper
    ctx.moveTo(tieCenterX, tieCenterY);
    ctx.lineTo(tieCenterX + tieW, tieCenterY - tieH);
    ctx.lineTo(tieCenterX + tieW, tieCenterY + tieH);
    ctx.closePath();
    ctx.fill(); ctx.stroke();
    
    ctx.beginPath(); // Tie knot
    ctx.ellipse(tieCenterX, tieCenterY, tieW * 0.25, tieH * 0.45, 0, 0, Math.PI * 2);
    ctx.fill(); ctx.stroke();

    // --> Sit a distinguished Gentleman's Top Hat centering the upper image edge
    const hatBaseY = bSize;
    const hw = 50 * scale; // Half width representation
    const ch = 80 * scale; // Cylinder height
    const cw = hw * 0.7; // Cylinder half width

    ctx.translate(totalW / 2, hatBaseY);
    
    ctx.fillStyle = "#111"; // Brim Base
    ctx.beginPath();
    ctx.ellipse(0, 0, hw, 14 * scale, 0, 0, Math.PI * 2);
    ctx.fill();
    ctx.strokeStyle = "#050505";
    ctx.stroke();

    ctx.fillStyle = "#1C1C1C"; // Cylinder Body
    ctx.fillRect(-cw, -ch, cw*2, ch);
    ctx.beginPath(); // Cylinder bottom overlap
    ctx.ellipse(0, 0, cw, 8 * scale, 0, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath(); // Cylinder top cap (3D angle offset)
    ctx.ellipse(0, -ch, cw, 8 * scale, 0, 0, Math.PI * 2);
    ctx.fill();

    const rh = 16 * scale; // Ribbon wrapping the base
    ctx.fillStyle = "#6B0000";
    ctx.fillRect(-cw, -rh - (6*scale), cw*2, rh);
    ctx.beginPath(); // Ribbon base curve mapping
    ctx.ellipse(0, -6*scale, cw, 8 * scale, 0, 0, Math.PI * 2);
    ctx.fill();
    ctx.fillStyle = "#4A0000";
    ctx.beginPath(); 
    ctx.ellipse(0, -rh - (6*scale), cw, 8 * scale, 0, 0, Math.PI * 2);
    ctx.fill();

    ctx.resetTransform();

    // 7. Write polite inscription on plaque
    let fSize = 55 * scale;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillStyle = "#FFFFFF";

    ctx.font = `${fSize}px "${fontName}", Georgia, serif`;
    
    // Scale text down to prevent overflow and maintain etiquette bounds
    let textMetrics = ctx.measureText(politeText);
    while (textMetrics.width > plaqueW - 40 * scale && fSize > 12 * scale) {
        fSize -= 2 * scale;
        ctx.font = `${fSize}px "${fontName}", Georgia, serif`;
        textMetrics = ctx.measureText(politeText);
    }

    ctx.shadowColor = 'rgba(255, 255, 255, 0.2)';
    ctx.shadowBlur = 10 * scale;
    ctx.fillText(politeText, totalW / 2, plaqueY + (plaqueH / 2) + 2*scale);
    ctx.shadowBlur = 0; // Reset Shadow

    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 Image Manners Enhancer Tool allows users to transform standard photos into sophisticated, vintage-style portraits. The tool adds elegant decorative elements such as ornate frames (available in gold, silver, or wood themes), a classic plaque for custom inscriptions, and distinguished accessories like a top hat, bow tie, and monocle. It also includes a vintage filter to provide a refined sepia-toned aesthetic. This tool is ideal for creating humorous, high-class themed social media posts, digital keepsakes, or stylized portraits for themed events.

Leave a Reply

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