oxigdal-wasm 0.1.3

WebAssembly bindings for OxiGDAL - Browser-based geospatial processing
Documentation

oxigdal-wasm

WebAssembly bindings for OxiGDAL - geospatial processing in the browser.

Documentation License

Overview

oxigdal-wasm enables client-side geospatial processing in the browser:

  • COG Viewer - Display Cloud Optimized GeoTIFFs without a backend
  • Tile Caching - LRU cache for optimal performance
  • Web Workers - Parallel tile loading
  • Image Processing - Contrast enhancement, color manipulation
  • Zero Server - All processing happens client-side

Features

  • ✅ Browser-based COG viewing
  • ✅ HTTP range request support
  • ✅ Tile pyramid navigation
  • ✅ Viewport management (pan/zoom)
  • ✅ Image enhancement
  • ✅ Statistics computation
  • ✅ GeoJSON export

Building

# Install wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

# Build
wasm-pack build --target web

Installation (when published)

npm install @cooljapan/oxigdal

Quick Start

Basic COG Viewing

<!DOCTYPE html>
<html>
<head>
    <title>COG Viewer</title>
</head>
<body>
    <canvas id="map" width="800" height="600"></canvas>

    <script type="module">
        import init, { WasmCogViewer } from './pkg/oxigdal_wasm.js';

        await init();

        const viewer = new WasmCogViewer();
        await viewer.open('https://example.com/satellite.tif');

        console.log(`Size: ${viewer.width()}x${viewer.height()}`);
        console.log(`Bands: ${viewer.band_count()}`);
        console.log(`EPSG: ${viewer.epsg_code()}`);

        // Read and display a tile
        const imageData = await viewer.read_tile_as_image_data(0, 0, 0);

        const canvas = document.getElementById('map');
        const ctx = canvas.getContext('2d');
        ctx.putImageData(imageData, 0, 0);
    </script>
</body>
</html>

Advanced Viewer with Caching

import { AdvancedCogViewer } from './pkg/oxigdal_wasm.js';

const viewer = new AdvancedCogViewer();

// Open with 50MB cache
await viewer.open(url, 50);

// Set viewport
viewer.setViewportSize(800, 600);
viewer.fitToImage();

// Pan and zoom
viewer.pan(100, 100);
viewer.zoomIn();

// Read with caching
const imageData = await viewer.readTileAsImageData(0, 0, 0);

// Check cache stats
const stats = JSON.parse(viewer.getCacheStats());
console.log('Cache hit rate:', stats.hitRate);

Interactive Map

class InteractiveMap {
    constructor(canvasId) {
        this.canvas = document.getElementById(canvasId);
        this.ctx = this.canvas.getContext('2d');
        this.viewer = new AdvancedCogViewer();
        this.setupInteraction();
    }

    async open(url) {
        await this.viewer.open(url, 100);
        this.viewer.setViewportSize(
            this.canvas.width,
            this.canvas.height
        );
        this.viewer.fitToImage();
        await this.render();
    }

    setupInteraction() {
        let dragging = false;
        let lastX, lastY;

        this.canvas.addEventListener('mousedown', (e) => {
            dragging = true;
            lastX = e.clientX;
            lastY = e.clientY;
        });

        this.canvas.addEventListener('mousemove', async (e) => {
            if (dragging) {
                const dx = e.clientX - lastX;
                const dy = e.clientY - lastY;
                this.viewer.pan(-dx, -dy);
                await this.render();
                lastX = e.clientX;
                lastY = e.clientY;
            }
        });

        this.canvas.addEventListener('mouseup', () => {
            dragging = false;
        });

        this.canvas.addEventListener('wheel', async (e) => {
            e.preventDefault();
            if (e.deltaY < 0) {
                this.viewer.zoomIn();
            } else {
                this.viewer.zoomOut();
            }
            await this.render();
        });
    }

    async render() {
        // Render visible tiles
        const imageData = await this.viewer.readTileAsImageData(0, 0, 0);
        this.ctx.putImageData(imageData, 0, 0);
    }
}

// Usage
const map = new InteractiveMap('map');
await map.open('https://example.com/satellite.tif');

Image Enhancement

// Read tile with contrast enhancement
const imageData = await viewer.readTileWithContrast(
    0, 0, 0,
    'linear'  // 'linear', 'histogram', or 'adaptive'
);

// Compute statistics
const stats = JSON.parse(await viewer.computeStats(0, 0, 0));
console.log('Min:', stats.min, 'Max:', stats.max);

// Compute histogram
const hist = JSON.parse(await viewer.computeHistogram(0, 0, 0));

Batch Tile Loading

import { BatchTileLoader } from './pkg/oxigdal_wasm.js';

const loader = new BatchTileLoader(4); // 4 parallel requests
await loader.open(url, 50);

const coords = [
    0, 0,  // Tile (0, 0)
    1, 0,  // Tile (1, 0)
    0, 1,  // Tile (0, 1)
    1, 1,  // Tile (1, 1)
];

const results = await loader.loadTilesBatch(0, coords);
results.forEach((imageData, i) => {
    // Render each tile
});

Web Workers

import { WasmWorkerPool } from './pkg/oxigdal_wasm.js';

const pool = new WasmWorkerPool(4);
await pool.init();

await pool.loadCog(url);

const tasks = [
    { level: 0, x: 0, y: 0 },
    { level: 0, x: 1, y: 0 },
];

const results = await Promise.all(
    tasks.map(task => pool.processTile(task))
);

pool.terminate();

API Reference

WasmCogViewer

Basic COG viewer:

  • open(url) - Open a COG file
  • width() - Get image width
  • height() - Get image height
  • tile_width() - Get tile width
  • tile_height() - Get tile height
  • band_count() - Get number of bands
  • overview_count() - Get number of overviews
  • epsg_code() - Get EPSG code
  • read_tile(level, x, y) - Read tile bytes
  • read_tile_as_image_data(level, x, y) - Read as ImageData

AdvancedCogViewer

Advanced viewer with caching and viewport:

  • open(url, cache_size_mb) - Open with cache
  • setViewportSize(width, height) - Set viewport
  • fitToImage() - Fit viewport to image
  • pan(dx, dy) - Pan viewport
  • zoomIn() / zoomOut() - Zoom controls
  • setZoom(level) - Set zoom level
  • readTileAsImageData(level, x, y) - Read with cache
  • readTileWithContrast(level, x, y, method) - Read with enhancement
  • computeStats(level, x, y) - Compute statistics
  • getCacheStats() - Get cache statistics
  • clearCache() - Clear cache

Demo Application

A complete COG viewer demo is available in demo/cog-viewer/:

cd demo/cog-viewer
npm install
npm run dev

Browser Support

Browser Minimum Version
Chrome 87+
Firefox 89+
Safari 15+
Edge 87+

Requires WebAssembly, ES6 modules, and Fetch API.

Performance Tips

  1. Enable caching - Use AdvancedCogViewer with appropriate cache size
  2. Use overviews - Read from appropriate zoom level
  3. Batch requests - Use BatchTileLoader for parallel fetching
  4. Prefetch - Set prefetch strategy for smoother navigation
  5. Web Workers - Offload processing to background threads

COOLJAPAN Policies

  • ✅ Pure Rust (compiles to WASM)
  • ✅ No unwrap() - Safe error handling
  • ✅ Zero external dependencies
  • ✅ Production ready

License

Licensed under Apache-2.0.

Copyright © 2025 COOLJAPAN OU (Team Kitasan)

See Also