Please bookmark this page to avoid losing your image tool!

Image Topographic Map Filter Effect

(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, numLevels = 5, colorsStr = "") {
    
    // Helper function to convert HEX color to RGB object
    // It's defined inside processImage to keep it self-contained.
    const _hexToRgb = (hexColor) => {
        // Trim and remove '#'
        const hex = String(hexColor).trim().replace(/^#/, '');

        // Validate hex format (3 or 6 hex characters)
        if (!/^(?:[0-9a-fA-F]{3}){1,2}$/.test(hex)) {
            return null; 
        }

        let fullHex = hex;
        if (hex.length === 3) {
            fullHex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
        }

        const bigint = parseInt(fullHex, 16);

        // Check if parsing was successful (it should be if regex passed)
        if (isNaN(bigint)) {
            return null;
        }

        const r = (bigint >> 16) & 255;
        const g = (bigint >> 8) & 255;
        const b = bigint & 255;
        return { r, g, b };
    };

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Use naturalWidth/Height for <img> elements, or width/height for Image objects
    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

    // Handle cases where image dimensions are invalid
    if (width === 0 || height === 0) {
        canvas.width = 1; // Return a 1x1 canvas
        canvas.height = 1;
        return canvas;
    }

    canvas.width = width;
    canvas.height = height;

    try {
        // Draw the original image onto the canvas
        ctx.drawImage(originalImg, 0, 0, width, height);
    } catch (e) {
        console.error("Error drawing original image: ", e);
        // Return the blank canvas (correctly sized) if drawing fails
        return canvas;
    }

    let imageData;
    try {
        // Get pixel data from the canvas
        imageData = ctx.getImageData(0, 0, width, height);
    } catch (e) {
        console.error("Error getting ImageData (possibly due to CORS or tainted canvas): ", e);
        // If pixel data cannot be accessed, return the canvas with the original image drawn
        // (as drawing was successful above)
        return canvas; 
    }
    
    const data = imageData.data; // Pixel data array (R,G,B,A, R,G,B,A, ...)

    // Validate and prepare the number of levels for quantization
    // Ensure numLevels is an integer and at least 1
    numLevels = Math.max(1, Math.floor(Number(numLevels)));

    // Prepare the color palette
    let parsedColors = [];
    if (typeof colorsStr === 'string' && colorsStr.trim() !== "") {
        parsedColors = colorsStr.split(',')
            .map(c => _hexToRgb(c)) // _hexToRgb handles trimming and '#'
            .filter(c => c !== null); // Filter out any invalid colors
    }

    // Default color palette for a topographic map effect
    const defaultColorPalette = [
        { r: 68, g: 114, b: 196 },  // ~Blue (representing water/low elevation)
        { r: 112, g: 173, b: 71 },  // ~Green (representing lowlands/vegetation)
        { r: 255, g: 217, b: 102 }, // ~Yellow (representing mid-altitude/sandy areas)
        { r: 198, g: 89, b: 17 },   // ~Brown (representing higher altitude/rocky areas)
        { r: 220, g: 220, b: 220 }  // ~Light Gray/White (representing peaks/snow)
    ];
    
    const colorPalette = parsedColors.length > 0 ? parsedColors : defaultColorPalette;
    
    // Safeguard: if the effective colorPalette is empty for any reason, add a fallback color
    if (colorPalette.length === 0) { 
        colorPalette.push({r: 0, g: 0, b: 0}); // Fallback to black
    }

    // Iterate over each pixel in the image data
    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i + 1];
        const b = data[i + 2];
        // Alpha (data[i+3]) is preserved

        // Convert the pixel to grayscale using the luminosity method
        const gray = 0.299 * r + 0.587 * g + 0.114 * b; // Value from 0 (black) to 255 (white)

        // Quantize the grayscale value to determine its level index
        const grayNormalized = gray / 255; // Normalize to 0-1 range
        
        // Calculate the level index. For numLevels, indices are 0 to numLevels-1.
        // E.g., if numLevels = 5:
        // grayNormalized = 0    -> levelIndex = floor(0*5) = 0
        // grayNormalized = 0.19 -> levelIndex = floor(0.19*5) = floor(0.95) = 0
        // grayNormalized = 0.2  -> levelIndex = floor(0.2*5) = floor(1.0) = 1
        // ...
        // grayNormalized = 1    -> levelIndex = floor(1*5) = 5. This needs clamping.
        let levelIndex = Math.floor(grayNormalized * numLevels);
        
        // Clamp the index to the valid range [0, numLevels-1]
        levelIndex = Math.min(levelIndex, numLevels - 1);
        
        // Select the color for this level from the_REPLACE palette
        // Cycle through palette colors if numLevels is greater than palette size
        const selectedColor = colorPalette[levelIndex % colorPalette.length];

        // Update the pixel data with the new color
        data[i] = selectedColor.r;
        data[i + 1] = selectedColor.g;
        data[i + 2] = selectedColor.b;
    }

    // Put the modified pixel data back onto the canvas
    ctx.putImageData(imageData, 0, 0);

    // Return the processed 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 Topographic Map Filter Effect tool allows users to transform images into stylized topographic representations. By processing the input image, it reduces the color levels and applies a customizable color palette to create distinct layers typical of topographic maps, using predefined colors that signify different elevations. This tool is useful for graphic designers, educators, and outdoor enthusiasts who wish to visualize landscapes, create maps for presentations, or enhance images for creative projects.

Leave a Reply

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