Please bookmark this page to avoid losing your image tool!

Image Egyptian Hieroglyph Wall Creator

(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,
    wallColor = "#D2B48C",      // Color of the stone wall
    imageEngraveColor = "#4A2E20", // Color of the main image carving's "bottom"
    engraveDepth = 2,           // Pixel offset for shadow/highlight, creating depth illusion
    imageShadowTintFactor = -0.35, // How much to darken wallColor for shadow (-1 to 0)
    imageHighlightTintFactor = 0.15, // How much to lighten wallColor for highlight (0 to 1)
    bgGlyphColor = "#AF8F6D",   // Color of small background hieroglyphs
    bgGlyphDensity = 0.25,      // Probability (0-1) of a cell having a background glyph
    bgGlyphCellSize = 40,       // Size of the grid cells for placing background glyphs
    imageThreshold = 128        // Luminance threshold (0-255) to convert original image to a silhouette
) {

    // Helper: Convert hex to RGB object {r, g, b}
    function _hexToRgb(hex) {
        const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16)
        } : { r: 200, g: 200, b: 200 }; // Default to a light gray if parse fails
    }

    // Helper: Convert RGB components to Hex string
    function _rgbToHex(r, g, b) {
        return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
    }

    // Helper: Shade a hex color by a percentage factor (-1 darkens, 1 lightens fully)
    function _shadeColor(hexColor, percent) {
        const rgb = _hexToRgb(hexColor);
        let { r, g, b } = rgb;

        // Adjust brightness by percent
        // For darkening (percent < 0): r = r * (1 + percent)
        // For lightening (percent > 0): r = r + (255 - r) * percent
        if (percent < 0) {
            r = Math.round(Math.max(0, r * (1 + percent)));
            g = Math.round(Math.max(0, g * (1 + percent)));
            b = Math.round(Math.max(0, b * (1 + percent)));
        } else {
            r = Math.round(Math.min(255, r + (255 - r) * percent));
            g = Math.round(Math.min(255, g + (255 - g) * percent));
            b = Math.round(Math.min(255, b + (255 - b) * percent));
        }
        
        return _rgbToHex(r, g, b);
    }

    // Helper: Draw simple hieroglyph-like shapes
    function _drawSimpleGlyph(ctx, x, y, size, color) {
        ctx.save();
        ctx.strokeStyle = color;
        ctx.fillStyle = color; 
        ctx.lineWidth = Math.max(1, Math.round(size / 15)); 
        
        const type = Math.floor(Math.random() * 4);
        ctx.beginPath();

        // Effective drawing area for glyph (centered in cell)
        const S = size * 0.75; 
        const dX = x + (size - S) / 2;
        const dY = y + (size - S) / 2;

        if (type === 0) { // Eye of Horus (simplified)
            ctx.ellipse(dX + S / 2, dY + S / 2, S / 2.2, S / 4.5, 0, 0, 2 * Math.PI);
            ctx.stroke();
            ctx.beginPath();
            ctx.arc(dX + S / 2, dY + S / 2, S / 10, 0, 2 * Math.PI);
            ctx.fill();
        } else if (type === 1) { // Wavy Lines (water)
            ctx.moveTo(dX, dY + S / 3);
            ctx.bezierCurveTo(dX + S / 3, dY, dX + 2 * S / 3, dY + S / 1.5, dX + S, dY + S / 3);
            ctx.stroke();
            ctx.beginPath();
            ctx.moveTo(dX, dY + S * (2/3));
            ctx.bezierCurveTo(dX + S / 3, dY + S / 2, dX + 2 * S / 3, dY + S, dX + S, dY + S * (2/3));
            ctx.stroke();
        } else if (type === 2) { // Ankh-like cross
            ctx.moveTo(dX + S / 2, dY + S * 0.2); 
            ctx.lineTo(dX + S / 2, dY + S); 
            ctx.stroke(); // Vertical line segment by segment
            ctx.beginPath();
            ctx.moveTo(dX, dY + S * 0.4); 
            ctx.lineTo(dX + S, dY + S * 0.4);
            ctx.stroke(); // Horizontal line
        } else { // Scarab beetle (simplified oval with line)
            ctx.ellipse(dX + S / 2, dY + S / 2, S / 2.1, S / 1.6, 0, 0, 2 * Math.PI);
            ctx.stroke();
            ctx.beginPath();
            ctx.moveTo(dX + S / 2, dY + S * 0.1); 
            ctx.lineTo(dX + S / 2, dY + S * 0.9); 
            ctx.stroke();
        }
        ctx.restore();
    }

    const canvas = document.createElement('canvas');
    canvas.width = originalImg.naturalWidth || originalImg.width;
    canvas.height = originalImg.naturalHeight || originalImg.height;
    const ctx = canvas.getContext('2d');

    // 1. Draw Wall Base Color
    ctx.fillStyle = wallColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 2. Draw Wall Noise/Texture (subtle)
    const numNoisePatches = Math.floor((canvas.width * canvas.height) / 60);
    const wallRgbBase = _hexToRgb(wallColor);
    for (let i = 0; i < numNoisePatches; i++) {
        const nx = Math.random() * canvas.width;
        const ny = Math.random() * canvas.height;
        const nSize = Math.random() * 3 + 1; // Small patches 1-4px
        const lightnessOffset = (Math.random() - 0.5) * 0.1; // +/- 10% lightness fluctuation
        
        const r = Math.max(0, Math.min(255, Math.round(wallRgbBase.r * (1 + lightnessOffset))));
        const g = Math.max(0, Math.min(255, Math.round(wallRgbBase.g * (1 + lightnessOffset))));
        const b = Math.max(0, Math.min(255, Math.round(wallRgbBase.b * (1 + lightnessOffset))));
        
        ctx.fillStyle = `rgba(${r},${g},${b},0.35)`; // Semi-transparent
        ctx.fillRect(nx, ny, nSize, nSize);
    }
    
    // 3. Draw Background Hieroglyphs Pattern
    for (let y = 0; y < canvas.height - bgGlyphCellSize / 2; y += bgGlyphCellSize) {
        for (let x = 0; x < canvas.width - bgGlyphCellSize / 2; x += bgGlyphCellSize) {
            if (Math.random() < bgGlyphDensity) {
                const jitterX = (Math.random() - 0.5) * (bgGlyphCellSize / 2.5);
                const jitterY = (Math.random() - 0.5) * (bgGlyphCellSize / 2.5);
                const glyphX = x + jitterX;
                const glyphY = y + jitterY;
                const glyphSize = bgGlyphCellSize * (0.55 + Math.random() * 0.35); // Size variation
                _drawSimpleGlyph(ctx, glyphX, glyphY, glyphSize, bgGlyphColor);
            }
        }
    }

    // 4. Prepare Main Image Mask (silhouette from original image)
    const maskCanvas = document.createElement('canvas');
    maskCanvas.width = canvas.width;
    maskCanvas.height = canvas.height;
    const maskCtx = maskCanvas.getContext('2d', { willReadFrequently: true });
    
    maskCtx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    const imgData = maskCtx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imgData.data;
    for (let i = 0; i < data.length; i += 4) {
        const r = data[i], g = data[i+1], b = data[i+2], a = data[i+3];
        const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
        if (luminance < imageThreshold && a > 128) { // Darker and reasonably opaque parts form the carving
            data[i] = 255; data[i+1] = 255; data[i+2] = 255; data[i+3] = 255; // Opaque white for mask
        } else {
            data[i+3] = 0; // Transparent
        }
    }
    maskCtx.putImageData(imgData, 0, 0);

    // 5. Draw Engraved Main Image using the Mask
    const tempColoredMaskCanvas = document.createElement('canvas');
    tempColoredMaskCanvas.width = canvas.width;
    tempColoredMaskCanvas.height = canvas.height;
    const tempCtx = tempColoredMaskCanvas.getContext('2d');

    const shadowEngraveColor = _shadeColor(wallColor, imageShadowTintFactor);
    const highlightEngraveColor = _shadeColor(wallColor, imageHighlightTintFactor);

    const drawMaskWithColorAndOffset = (targetCtx, offsetX, offsetY, color) => {
        tempCtx.clearRect(0, 0, tempColoredMaskCanvas.width, tempColoredMaskCanvas.height);
        tempCtx.fillStyle = color;
        tempCtx.fillRect(0, 0, tempColoredMaskCanvas.width, tempColoredMaskCanvas.height);
        tempCtx.globalCompositeOperation = 'destination-in';
        tempCtx.drawImage(maskCanvas, 0, 0);
        tempCtx.globalCompositeOperation = 'source-over'; 
        targetCtx.drawImage(tempColoredMaskCanvas, offsetX, offsetY);
    };
    
    const d = Math.max(1, Math.round(engraveDepth)); // Ensure depth is at least 1 if > 0

    if (d > 0) {
        // Draw highlight layer (lighter wallColor, offset towards "light source")
        drawMaskWithColorAndOffset(ctx, -d, -d, highlightEngraveColor);
        // Draw shadow layer (darker wallColor, offset away from "light source")
        drawMaskWithColorAndOffset(ctx, d, d, shadowEngraveColor);
    }

    // Draw main engrave fill (the "bottom" of the carving, no offset)
    drawMaskWithColorAndOffset(ctx, 0, 0, imageEngraveColor);
    
    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 Egyptian Hieroglyph Wall Creator is an online tool that transforms images into artistic representations resembling carved hieroglyphs on a stone wall. Users can upload an image, and the tool will create a visually appealing version that incorporates various customizable elements such as wall color, engraving depth, and background glyph patterns. This tool can be utilized for artistic projects, educational purposes related to ancient Egyptian culture, or as a unique way to present images for personal or commercial use.

Leave a Reply

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