Please bookmark this page to avoid losing your image tool!

Image Fantasy Realm Map 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.
async function processImage(
    originalImg,
    seedStr,
    numOctavesStr,
    persistenceStr,
    lacunarityStr,
    scaleStr,
    waterLevelStr,
    landLevelStr, // Renamed from forestLevel to represent general land above water
    forestLevelStr, // Added to distinguish forest patches on land
    mountainLevelStr,
    snowLevelStr,
    waterColorStr,
    landColorStr,
    forestColorStr,
    mountainColorStr,
    snowColorStr,
    useImageAsMaskStr,
    islandExponentStr
) {
    // 0. Parameter parsing and validation
    const defaultColors = {
        water: [70, 107, 146],   // Deep Blue-ish
        land: [139, 179, 92],    // Greenish
        forest: [85, 139, 47],   // Darker Green
        mountain: [130, 119, 105],// Greyish Brown
        snow: [245, 245, 245],   // Off-white
    };

    function parseNumericParam(value, defaultValue, min = -Infinity, max = Infinity) {
        let num = parseFloat(value);
        if (isNaN(num)) num = defaultValue;
        return Math.max(min, Math.min(max, num));
    }

    function parseIntegerParam(value, defaultValue, min = -Infinity, max = Infinity) {
        let num = parseInt(value, 10);
        if (isNaN(num)) num = defaultValue;
        return Math.max(min, Math.min(max, num));
    }
    
    function parseColorToArray(colorInputStr, defaultArr) {
        let str = String(colorInputStr === undefined ? "" : colorInputStr);
        try {
            const parts = str.split(',').map(s => {
                const val = parseInt(s.trim(), 10);
                if (isNaN(val) || val < 0 || val > 255) throw new Error("Invalid color component");
                return val;
            });
            if (parts.length === 3) return parts;
            return defaultArr; // Return default if not 3 parts
        } catch (e) {
            return defaultArr;
        }
    }

    seedStr = String(seedStr === undefined ? String(Date.now()) : seedStr);
    const numOctaves = parseIntegerParam(numOctavesStr, 5, 1, 10);
    const persistence = parseNumericParam(persistenceStr, 0.5, 0.1, 1.0);
    const lacunarity = parseNumericParam(lacunarityStr, 2.0, 1.1, 4.0);
    const scale = parseNumericParam(scaleStr, 80, 10, 300); // Larger scale means larger features
    const waterLevel = parseNumericParam(waterLevelStr, 0.35, 0.0, 1.0);
    const landLevel = parseNumericParam(landLevelStr, 0.55, 0.0, 1.0); // General land
    const forestLevel = parseNumericParam(forestLevelStr, 0.75, 0.0, 1.0); // Forests appear on land up to this elevation
    const mountainLevel = parseNumericParam(mountainLevelStr, 0.8, 0.0, 1.0);
    const snowLevel = parseNumericParam(snowLevelStr, 0.9, 0.0, 1.0);
    
    const wc = parseColorToArray(waterColorStr, defaultColors.water);
    const lc = parseColorToArray(landColorStr, defaultColors.land);
    const fc = parseColorToArray(forestColorStr, defaultColors.forest);
    const mc = parseColorToArray(mountainColorStr, defaultColors.mountain);
    const sc = parseColorToArray(snowColorStr, defaultColors.snow);

    useImageAsMaskStr = String(useImageAsMaskStr === undefined ? "false" : useImageAsMaskStr).toLowerCase();
    let islandExponent = parseNumericParam(islandExponentStr, 1.5, 0, 5.0);


    // 1. Canvas Setup
    const MIN_DIM = 16;
    const DEFAULT_DIM = 512;
    let W = DEFAULT_DIM, H = DEFAULT_DIM;

    if (originalImg && typeof originalImg.width === 'number' && originalImg.width > MIN_DIM &&
        typeof originalImg.height === 'number' && originalImg.height > MIN_DIM) {
        W = originalImg.width;
        H = originalImg.height;
    }

    const canvas = document.createElement('canvas');
    canvas.width = W;
    canvas.height = H;
    const ctx = canvas.getContext('2d', { willReadFrequently: true });
    if (!ctx) return document.createTextNode("Could not get 2D context.");


    // 2. Seed & PRNG (mulberry32 - provides numbers in [0,1) )
    let S = 0;
    for (let i = 0; i < seedStr.length; i++) {
        S = (S + seedStr.charCodeAt(i) * (i + 19)) & 0xFFFFFFFF; // Ensure S is a 32-bit int
    }
    if (S === 0) S = 1; // Avoid seed 0 if it creates issues with mulberry32 state

    function mulberry32(a) {
        return function() {
            a |= 0; a = a + 0x6D2B79F5 | 0;
            var t = Math.imul(a ^ a >>> 15, 1 | a);
            t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
            return ((t ^ t >>> 14) >>> 0) / 4294967296;
        }
    }
    const random = mulberry32(S);

    // 3. Noise Precomputation (for value noise)
    const VAL_GRID_SIDE_LEN = 256; // Size of the precomputed random grid
    const randomValuesForNoise = new Array(VAL_GRID_SIDE_LEN * VAL_GRID_SIDE_LEN);
    for (let i = 0; i < randomValuesForNoise.length; i++) {
        randomValuesForNoise[i] = random();
    }

    // Helper: smoothstep
    function smoothstep(t) { return t * t * (3 - 2 * t); }

    // Helper: lerp
    function lerp(a, b, t) { return a + t * (b - a); }
    
    // Helper: Get random value for grid point (ix, iy)
    function getValue(ix, iy, grid, sideLen) {
        const x_ = (ix % sideLen + sideLen) % sideLen;
        const y_ = (iy % sideLen + sideLen) % sideLen;
        return grid[y_ * sideLen + x_];
    }

    // Helper: 2D Value Noise
    function valueNoise2D(x, y, randGrid, gridSide, _getValue, _smoothstep, _lerp) {
        const ix = Math.floor(x);
        const iy = Math.floor(y);
        const fx = x - ix;
        const fy = y - iy;

        const v00 = _getValue(ix, iy, randGrid, gridSide);
        const v10 = _getValue(ix + 1, iy, randGrid, gridSide);
        const v01 = _getValue(ix, iy + 1, randGrid, gridSide);
        const v11 = _getValue(ix + 1, iy + 1, randGrid, gridSide);

        const sx = _smoothstep(fx);
        const sy = _smoothstep(fy);

        const nx0 = _lerp(v00, v10, sx);
        const nx1 = _lerp(v01, v11, sx);
        return _lerp(nx0, nx1, sy);
    }

    // Helper: Fractal Brownian Motion (FBM)
    function fbm(x, y, octaves, persist, lacun, noiseScale, randGrid, gridSide) {
        let total = 0;
        let frequency = 1;
        let amplitude = 1;
        let maxValue = 0;

        for (let i = 0; i < octaves; i++) {
            total += valueNoise2D(x * frequency / noiseScale, y * frequency / noiseScale, 
                                 randGrid, gridSide, getValue, smoothstep, lerp) * amplitude;
            maxValue += amplitude;
            amplitude *= persist;
            frequency *= lacun;
        }
        return maxValue === 0 ? 0 : total / maxValue; // Normalize
    }
    
    // 4. Image Mask Setup (if useImageAsMaskStr === "true")
    let imgMaskData = null;
    if (useImageAsMaskStr === "true" && originalImg && originalImg.width > 1 && originalImg.height > 1) {
        const maskCanvas = document.createElement('canvas');
        maskCanvas.width = W;
        maskCanvas.height = H;
        const maskCtx = maskCanvas.getContext('2d', { willReadFrequently: true });
        if (maskCtx) {
            try {
                maskCtx.drawImage(originalImg, 0, 0, W, H); // Scale originalImg to fit W, H
                imgMaskData = maskCtx.getImageData(0, 0, W, H);
            } catch (e) {
                console.warn("Could not use image as mask (tainted canvas or other error):", e);
                imgMaskData = null; // Ensure it's nullified on error
            }
        }
    }
    
    // 5. Main generation loop
    const imageData = ctx.createImageData(W, H);
    const data = imageData.data;

    for (let py = 0; py < H; py++) {
        for (let px = 0; px < W; px++) {
            const noiseX = px;
            const noiseY = py;

            let elevation = fbm(noiseX, noiseY, numOctaves, persistence, lacunarity, scale, randomValuesForNoise, VAL_GRID_SIDE_LEN);

            // Apply island effect
            if (islandExponent > 0) {
                const dx = (px / W - 0.5) * 2; // -1 to 1
                const dy = (py / H - 0.5) * 2; // -1 to 1
                // Using squared distance to avoid sqrt, then raise to exponent/2.
                // Or simpler, use Math.sqrt for clarity, performance isn't bottlenecked here.
                let distFromCenter = Math.sqrt(dx*dx + dy*dy) / Math.sqrt(2); // Normalized approx 0-1
                distFromCenter = Math.min(1, distFromCenter); // Clamp to 1
                
                let falloff = Math.pow(distFromCenter, islandExponent);
                elevation *= (1.0 - falloff);
            }

            // Apply image mask
            if (imgMaskData) {
                const maskIdx = (py * W + px) * 4;
                const alpha = imgMaskData.data[maskIdx + 3];
                if (alpha < 128) { // If transparent in mask
                    elevation = Math.min(elevation, waterLevel * 0.95); // Force to be water
                }
            }

            let r, g, b;
            if (elevation < waterLevel) { [r,g,b] = wc; }
            else if (elevation < landLevel) { [r,g,b] = lc; } // Basic land
            else if (elevation < forestLevel) { // Forests typically on mid-level land
                // Check if current elevation is also suitable for forests in general land definition
                if (elevation >= landLevel) { [r,g,b] = fc; }
                else { [r,g,b] = lc; } // if forest bands are oddly configured
            }
            else if (elevation < mountainLevel) { [r,g,b] = mc; }
            else { [r,g,b] = sc; }
           
            const idx = (py * W + px) * 4;
            data[idx] = r;
            data[idx + 1] = g;
            data[idx + 2] = b;
            data[idx + 3] = 255; // Alpha
        }
    }

    // 6. Put ImageData to canvas
    ctx.putImageData(imageData, 0, 0);

    // 7. Return canvas
    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 Fantasy Realm Map Creator is a tool designed to generate detailed fantasy-style maps using procedural noise algorithms. Users can customize various parameters such as elevation levels for water, land, forests, mountains, and snow, as well as colors for these features. This tool is ideal for game designers, writers, and artists looking to create unique and imaginative landscapes for storytelling, gaming, or artistic projects. Users can also upload an image to act as a mask to influence the generated terrain, allowing for greater control and personalization in mapping. With the ability to adjust settings like scale and noise octaves, users can produce diverse and visually appealing map styles.

Leave a Reply

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

Other Image Tools:

Image Interdimensional Travel Permit Creator

Image Mad Scientist’s Laboratory Notes Creator

Image Underground Resistance Flyer Creator

Image Retro Video Game Box Art Creator

Image Captain’s Naval Journal Creator

Image Renaissance Painting Frame Creator

Image Lost Civilization Artifact Creator

Image Da Vinci Notebook Page Creator

Image Dystopian Citizen ID Creator

Image Monster Hunter Bestiary Creator

Image Vintage Carnival Sideshow Poster Creator

Image Space Explorer’s Log Creator

Image Neolithic Petroglyph Frame Creator

Image Ukiyo-e Japanese Woodblock Print Creator

Image Persian Miniature Painting Creator

Image Sci-Fi Movie Poster Template Creator

Image Horror Movie Poster Template

Image Social Media Milestone Certificate Creator

Halloween Death Certificate Template

Image Anatomical Illustration Frame Creator

Image Romance Novel Cover Template Creator

Image Tabloid Headline Template

Image Space Mission Patch Template Creator

Image Cassette Tape Cover Template Creator

Image Passport Page Template Generator

Image Old Map Frame With Compass Rose Decorator

Image Diploma and Degree Certificate Framer

Image Soviet Propaganda Poster Style Generator

Image Yu-Gi-Oh Card Template Creator

Image Ancient Roman Greek Tablet Frame Creator

Image Marriage Certificate Template Creator

Image Video Game Achievement Frame Creator

Image Newspaper Front Page Template Creator

Image Botanical Illustration Frame Creator

Image Vinyl Record Sleeve Template Creator

Vintage Photo Booth Strip Template Generator

See All →