Please bookmark this page to avoid losing your image tool!

City Topic Image Search 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.
function processImage(originalImg, searchTopic = "City", themeColor = "#2a52be", backgroundColor = "#efefef") {
    const canvas = document.createElement('canvas');
    canvas.width = 840;
    canvas.height = 750;
    const ctx = canvas.getContext('2d');

    // Background
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Context Header
    ctx.fillStyle = themeColor;
    ctx.fillRect(0, 0, canvas.width, 100);

    // Header hamburger menu icon
    ctx.fillStyle = "#ffffff";
    ctx.fillRect(30, 42, 24, 3);
    ctx.fillRect(30, 49, 24, 3);
    ctx.fillRect(30, 56, 24, 3);

    // Helper to draw a rounded rectangle for standard browser support safely
    function drawRoundedRect(context, x, y, width, height, radius) {
        context.beginPath();
        context.moveTo(x + radius, y);
        context.lineTo(x + width - radius, y);
        context.quadraticCurveTo(x + width, y, x + width, y + radius);
        context.lineTo(x + width, y + height - radius);
        context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
        context.lineTo(x + radius, y + height);
        context.quadraticCurveTo(x, y + height, x, y + height - radius);
        context.lineTo(x, y + radius);
        context.quadraticCurveTo(x, y, x + radius, y);
        context.closePath();
        context.fill();
    }

    // Search Bar Body
    ctx.fillStyle = "#ffffff";
    drawRoundedRect(ctx, 100, 25, 640, 50, 25);

    // Magnifying Glass
    ctx.strokeStyle = "#888";
    ctx.lineWidth = 3;
    ctx.beginPath();
    ctx.arc(135, 50, 8, 0, Math.PI * 2);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(141, 56);
    ctx.lineTo(149, 64);
    ctx.stroke();

    // Search Text Content
    ctx.fillStyle = "#333";
    ctx.font = "bold 20px Arial, sans-serif";
    ctx.textAlign = "left";
    ctx.textBaseline = "middle";
    ctx.fillText(searchTopic + " skyline themes", 165, 50);

    // Generic default user Avatar
    ctx.fillStyle = "#ffffff";
    ctx.beginPath();
    ctx.arc(790, 50, 18, 0, Math.PI * 2);
    ctx.fill();
    ctx.fillStyle = themeColor;
    ctx.beginPath();
    ctx.arc(790, 45, 7, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    ctx.arc(790, 61, 10, Math.PI, 0);
    ctx.fill();

    // Simulated "Results" Header Info
    ctx.fillStyle = "#666";
    ctx.font = "16px Arial, sans-serif";
    ctx.textBaseline = "alphabetic";
    ctx.fillText("Showing interpreted image search results for topic: " + searchTopic, 30, 140);

    // Pre-defined city visual interpretations
    const filters = [
        { title: "Standard Origin", col: 0, row: 0 },
        { title: "Metropolis Nightscape", col: 1, row: 0 },
        { title: "Neon Cyberpunk City", col: 2, row: 0 },
        { title: "Architectural Blueprint", col: 0, row: 1 },
        { title: "Sunset Skyline", col: 1, row: 1 },
        { title: "Urban Thermal Map", col: 2, row: 1 }
    ];

    // Applies city-genre manipulations to an offscreen canvas
    function processFilter(octx, w, h, index) {
        if (index === 0) return; // Keeps unmodified standard image

        const imgData = octx.getImageData(0, 0, w, h);
        const d = imgData.data;

        if (index === 1) { // Nightscape
            for(let i = 0; i < d.length; i += 4) {
                d[i] = d[i] * 0.2;
                d[i+1] = d[i+1] * 0.3 + 10;
                d[i+2] = d[i+2] * 0.6 + 40;
            }
            octx.putImageData(imgData, 0, 0);
            octx.fillStyle = "rgba(255, 240, 100, 0.8)";
            for(let k = 0; k < (w * h) / 300; k++) {
                let wx = Math.random() * w;
                let wy = Math.random() * h;
                if (Math.random() > 0.5) octx.fillRect(wx, wy, Math.random() * 2 + 1, Math.random() * 2 + 1);
            }
        } else if (index === 2) { // Neon Cyberpunk
            for(let i = 0; i < d.length; i += 4) {
                let r = d[i], g = d[i+1], b = d[i+2];
                let lum = r * 0.3 + g * 0.59 + b * 0.11;
                if (lum < 85) {
                    let pct = lum / 85;
                    d[i] = 15 * pct; d[i+1] = 15 * pct; d[i+2] = 61 * pct;
                } else if (lum < 170) {
                    let pct = (lum - 85) / 85;
                    d[i] = 15 + 240 * pct; d[i+1] = 15 - 15 * pct; d[i+2] = 61 + 194 * pct;
                } else {
                    let pct = (lum - 170) / 85;
                    d[i] = 255 - 255 * pct; d[i+1] = 255 * pct; d[i+2] = 255;
                }
            }
            octx.putImageData(imgData, 0, 0);
        } else if (index === 3) { // Architectural blueprint
            const copy = new Uint8ClampedArray(d);
            for(let i = 0; i < d.length; i += 4) {
                d[i] = 10; d[i+1] = 61; d[i+2] = 145;
            }
            for(let y = 0; y < h - 1; y++) {
                for(let x = 0; x < w - 1; x++) {
                    let i = (y * w + x) * 4;
                    let right = (y * w + x + 1) * 4;
                    let bottom = ((y + 1) * w + x) * 4;
                    let diff = Math.abs(copy[i]-copy[right]) + Math.abs(copy[i]-copy[bottom]) +
                               Math.abs(copy[i+1]-copy[right+1]) + Math.abs(copy[i+1]-copy[bottom+1]) +
                               Math.abs(copy[i+2]-copy[right+2]) + Math.abs(copy[i+2]-copy[bottom+2]);
                    if(diff > 40) {
                        d[i] = 255; d[i+1] = 255; d[i+2] = 255;
                    }
                }
            }
            octx.putImageData(imgData, 0, 0);
        } else if (index === 4) { // Sunset skyline addition
            for(let i = 0; i < d.length; i += 4) {
                d[i] = Math.min(255, d[i] * 1.2 + 20);
                d[i+1] = Math.min(255, d[i+1] * 0.9 + 10);
                d[i+2] = d[i+2] * 0.6;
            }
            octx.putImageData(imgData, 0, 0);
            octx.fillStyle = "#1a0f14"; 
            let currentX = 0;
            while(currentX < w) {
                let bWidth = 10 + Math.random() * 25;
                let bHeight = h * 0.15 + Math.random() * (h * 0.35);
                octx.fillRect(currentX, h - bHeight, bWidth, bHeight);
                // Add sporadic spires
                if(Math.random() > 0.6) octx.fillRect(currentX + bWidth/2 - 1.5, h - bHeight - 20, 3, 20);
                currentX += bWidth + (Math.random() > 0.7 ? 3 : 0);
            }
        } else if (index === 5) { // Urban Heatmap
            for(let i = 0; i < d.length; i += 4) {
                let v = d[i]*0.3 + d[i+1]*0.59 + d[i+2]*0.11;
                if(v < 64) {
                   d[i] = 0; d[i+1] = v*4; d[i+2] = 255;
                } else if (v < 128) {
                   d[i] = 0; d[i+1] = 255; d[i+2] = 255 - (v-64)*4;
                } else if (v < 192) {
                   d[i] = (v-128)*4; d[i+1] = 255; d[i+2] = 0;
                } else {
                   d[i] = 255; d[i+1] = 255 - (v-192)*4; d[i+2] = 0;
                }
            }
            octx.putImageData(imgData, 0, 0);
        }
    }

    // Process and draw each cell into the simulated image search grid
    filters.forEach((filter, index) => {
        const cx = 30 + filter.col * 260; 
        const cy = 160 + filter.row * 290;
        
        // Dynamically scale image resolving aspect ratio bounds 230x230
        const aspect = originalImg.width / originalImg.height;
        let w = 230, h = 230;
        if (aspect > 1) {
            h = w / aspect;
        } else {
            w = h * aspect;
        }
        const offsetX = cx + (230 - w) / 2;
        const offsetY = cy + (230 - h) / 2;

        const off = document.createElement('canvas');
        off.width = w;
        off.height = h;
        const octx = off.getContext('2d');
        octx.drawImage(originalImg, 0, 0, w, h);
        
        // Form the stylistic view
        processFilter(octx, w, h, index);
        
        // Draw frame with dropshadow
        ctx.shadowColor = "rgba(0,0,0,0.15)";
        ctx.shadowBlur = 10;
        ctx.shadowOffsetY = 5;
        ctx.fillStyle = "#fff";
        ctx.fillRect(offsetX - 5, offsetY - 5, w + 10, h + 10);
        
        // Clean drop shadow payload so it doesn't leak further down
        ctx.shadowColor = "transparent";
        ctx.shadowBlur = 0;
        ctx.shadowOffsetY = 0;
        
        // Draw altered image
        ctx.drawImage(off, offsetX, offsetY);
        
        // Annotate image
        ctx.fillStyle = "#444";
        ctx.font = "bold 13px Arial, sans-serif";
        ctx.textAlign = "center";
        ctx.fillText(filter.title, cx + 115, cy + 230 + 25);
    });

    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 City Topic Image Search Tool allows users to transform a single uploaded image into a stylized collection of various urban-themed visual interpretations. The tool applies unique artistic filters to the original image, simulating different search results such as metropolis nightscapes, neon cyberpunk aesthetics, architectural blueprints, sunset skylines, and urban thermal maps. This tool is ideal for designers, concept artists, or content creators looking to quickly generate diverse mood boards, stylistic variations, or creative urban themes from a single reference photo.

Leave a Reply

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