Please bookmark this page to avoid losing your image tool!

Image Based City Identifier 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, googleVisionApiKey = "") {
    // Determine the strategy used to identify city
    // 1. First tries to extract standard EXIF GPS Metadata locally.
    // 2. Looks up exact City/Country via free OpenStreetMap Geocoding.
    // 3. Fallbacks to Google Cloud Vision AI (if API key is provided) to analyze visual landmarks.

    // 1. Build the UI Component
    const container = document.createElement('div');
    container.style.fontFamily = '"Segoe UI", Roboto, Helvetica, Arial, sans-serif';
    container.style.padding = '25px';
    container.style.borderRadius = '12px';
    container.style.boxShadow = '0 8px 24px rgba(0,0,0,0.12)';
    container.style.backgroundColor = '#ffffff';
    container.style.maxWidth = '550px';
    container.style.margin = '20px auto';
    container.style.textAlign = 'center';

    const title = document.createElement('h2');
    title.innerText = 'City Identifier Tool';
    title.style.margin = '0 0 20px 0';
    title.style.color = '#2c3e50';
    title.style.fontSize = '22px';
    container.appendChild(title);

    const displayImg = new Image();
    displayImg.src = originalImg.src;
    displayImg.style.maxWidth = '100%';
    displayImg.style.maxHeight = '350px';
    displayImg.style.borderRadius = '8px';
    displayImg.style.objectFit = 'contain';
    displayImg.style.backgroundColor = '#f4f6f8';
    displayImg.style.border = '1px solid #e1e4e8';
    container.appendChild(displayImg);

    const resultContainer = document.createElement('div');
    resultContainer.style.marginTop = '20px';
    resultContainer.style.padding = '20px';
    resultContainer.style.borderRadius = '10px';
    resultContainer.style.backgroundColor = '#fdfefe';
    resultContainer.style.border = '1px solid #dcdfe6';
    resultContainer.style.minHeight = '60px';
    resultContainer.style.display = 'flex';
    resultContainer.style.flexDirection = 'column';
    resultContainer.style.justifyContent = 'center';
    
    const loader = document.createElement('div');
    loader.innerHTML = '<span style="color: #3498db; font-size: 16px;">⟳ Analyzing image data...</span>';
    resultContainer.appendChild(loader);

    container.appendChild(resultContainer);

    // Helper functions for UI
    const updateLoader = (text) => {
        loader.innerHTML = `<span style="color: #3498db; font-size: 16px;">⟳ ${text}</span>`;
    };

    const showResult = (html, type = 'success') => {
        resultContainer.innerHTML = html;
        if (type === 'success') {
            resultContainer.style.backgroundColor = '#e8f8f5';
            resultContainer.style.borderColor = '#1abc9c';
            resultContainer.style.color = '#0e6251';
        } else if (type === 'error') {
            resultContainer.style.backgroundColor = '#fdedec';
            resultContainer.style.borderColor = '#e74c3c';
            resultContainer.style.color = '#7b241c';
        } else {
            resultContainer.style.backgroundColor = '#fef9e7';
            resultContainer.style.borderColor = '#f1c40f';
            resultContainer.style.color = '#7d6608';
        }
    };

    // 2. Execute Identification Logic asynchronously
    setTimeout(async () => {
        try {
            updateLoader('Extracting EXIF GPS coordinates...');
            
            // Dynamically import EXIF reader library
            const exifrModule = await import('https://cdn.jsdelivr.net/npm/exifr@7.1.3/dist/full.esm.mjs');
            const exifr = exifrModule.default;
            
            let gps = null;
            try {
                // Parses GPS directly from the image. Subject to CORS if image is hosted externally.
                gps = await exifr.gps(originalImg);
            } catch (e) {
                console.warn('EXIF extraction issue (possibly missing data or CORS block):', e);
            }

            // Route A: EXIF Metadata Success
            if (gps && gps.latitude && gps.longitude) {
                updateLoader(`GPS Coordinates spotted. Determining city...`);
                
                // Reverse geocoding via OpenStreetMap Nominatim
                const osmRes = await fetch(`https://nominatim.openstreetmap.org/reverse?lat=${gps.latitude}&lon=${gps.longitude}&format=json`, {
                    headers: { 'Accept-Language': 'en-US,en;q=0.9' }
                });
                
                if (!osmRes.ok) throw new Error("Could not reach Geocoding API.");
                
                const geoData = await osmRes.json();
                
                if (geoData && geoData.address) {
                    const city = geoData.address.city || geoData.address.town || geoData.address.village || geoData.address.municipality || 'Unknown Locality';
                    const country = geoData.address.country || 'Unknown Country';
                    
                    showResult(`
                        <span style="font-size: 13px; font-weight: bold; text-transform: uppercase;">Location Extracted via Metadata</span><br><br>
                        <span style="font-size: 26px; font-weight: bold;">📍 ${city}</span><br>
                        <span style="font-size: 16px; margin-top: 5px; display: inline-block;">${country}</span>
                    `, 'success');
                    return;
                }
            }

            // Route B: Fallback to AI Vision
            if (googleVisionApiKey.trim() !== '') {
                updateLoader('No GPS found. Analyzing distinct landmarks via AI Vision...');
                
                // Convert image to Base64 to supply payload
                const canvas = document.createElement('canvas');
                canvas.width = originalImg.naturalWidth || originalImg.width;
                canvas.height = originalImg.naturalHeight || originalImg.height;
                const ctx = canvas.getContext('2d');
                ctx.drawImage(originalImg, 0, 0);
                const base64Data = canvas.toDataURL('image/jpeg', 0.9).split(',')[1];

                const visionUrl = `https://vision.googleapis.com/v1/images:annotate?key=${googleVisionApiKey}`;
                const visionRes = await fetch(visionUrl, {
                    method: 'POST',
                    body: JSON.stringify({
                        requests: [{
                            image: { content: base64Data },
                            features: [
                                { type: 'LANDMARK_DETECTION', maxResults: 3 },
                                { type: 'WEB_DETECTION', maxResults: 5 }
                            ]
                        }]
                    })
                });

                const visionData = await visionRes.json();
                
                if (visionData.error) {
                    throw new Error(visionData.error.message);
                }

                const annotations = visionData.responses?.[0] || {};
                let identifiedCityOrLandmark = null;

                if (annotations.landmarkAnnotations && annotations.landmarkAnnotations.length > 0) {
                    identifiedCityOrLandmark = annotations.landmarkAnnotations[0].description;
                } else if (annotations.webDetection && annotations.webDetection.webEntities) {
                    // Try inferring from high-confidence web matches
                    const bestEntity = annotations.webDetection.webEntities.find(e => e.description && e.score > 0.95);
                    if (bestEntity) {
                        identifiedCityOrLandmark = bestEntity.description;
                    }
                }

                if (identifiedCityOrLandmark) {
                    showResult(`
                        <span style="font-size: 13px; font-weight: bold; text-transform: uppercase;">Location Identified via Ai Vision</span><br><br>
                        <span style="font-size: 22px; font-weight: bold;">👁️ ${identifiedCityOrLandmark}</span>
                    `, 'success');
                } else {
                    showResult(`
                        <strong style="font-size: 16px;">City Unidentifiable.</strong><br>
                        <span style="font-size: 14px;">No recognized landmarks found and no EXIF data present.</span>
                    `, 'warning');
                }
            } else {
                // Route C: No EXIF and No API key given
                showResult(`
                    <strong style="font-size: 16px;">No EXIF GPS Data Found.</strong><br><br>
                    <span style="font-size: 14px; opacity: 0.85;">Tip: To identify cities via visual recognition instead of metadata, pass a valid <br><code>googleVisionApiKey</code> parameter to the processImage function.</span>
                `, 'warning');
            }

        } catch (err) {
            showResult(`<strong>Error Processing Image:</strong><br>${err.message}`, 'error');
        }
    }, 300);

    return container;
}

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 Based City Identifier Tool is designed to determine the location of a city or landmark within an uploaded image. It uses a multi-layered approach to identify locations, first attempting to extract GPS metadata directly from the image’s EXIF data and performing a reverse geocode lookup. If metadata is unavailable, the tool can utilize AI-powered visual recognition to analyze landmarks and web entities within the image to identify the setting. This tool is useful for photographers looking to organize their work by location, travelers wanting to identify landmarks in their travel photos, or for any application requiring automated geographical context for visual media.

Leave a Reply

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