How GeoLibre's Browser-Based COG Conversion Works: Client-Side Cloud-Optimized GeoTIFF Processing

GeoLibre converts standard GeoTIFF rasters to Cloud-Optimized GeoTIFFs (COGs) entirely within the browser using the geolibre-wasm WebAssembly module, eliminating server dependencies and enabling immediate streaming to MapLibre layers.

GeoLibre delivers browser-based COG conversion through its @geolibre/processing package, allowing users to transform massive geospatial rasters without uploading data to a server. This client-side architecture leverages a Rust-compiled WebAssembly module to handle the computationally intensive tasks of re-tiling and overview generation that traditionally require Python GDAL bindings.

WebAssembly Initialization and Setup

The conversion pipeline begins with a one-time initialization of the geolibre-wasm module. In packages/processing/src/cog-convert.ts, the initCogWasm helper wraps the WebAssembly loader, ensuring the init function runs only once per page session.

This initialization accepts an optional WASM binary or URL parameter, enabling the same code to function in non-browser hosts like Tauri desktop applications or Jupyter embeddings. Once loaded, the module exposes GeoTiffReader and CogBuilder classes that handle the heavy lifting of TIFF parsing and reconstruction.

The Five-Stage COG Conversion Pipeline

Stage 1: Lightweight Metadata Extraction

Before processing pixels, GeoLibre extracts critical metadata using readGeoTiffInfo from the WASM module. This function parses the TIFF header via geotiff_info without loading the actual raster data, making it safe for large files.

The resulting GeoTiffInfo object contains dimensions, band count, EPSG code, nodata values, and whether the source is already tiled. This metadata drives all downstream configuration decisions.

Stage 2: Tiling Verification

The isTiledGeoTiff function checks the info.tiled boolean. If the source raster already uses internal tiling—meaning it is a valid COG— GeoLibre bypasses the conversion entirely and streams the file directly to the MapLibre raster source. This short-circuit prevents unnecessary re-encoding of already-optimized data.

Stage 3: Overview Pyramid Calculation

For non-tiled sources, overviewLevels calculates the decimation factors needed for fast multi-resolution rendering. The algorithm generates powers of 2 (1, 2, 4, 8...) until the largest image dimension falls below 256 pixels.

These factors determine the number of overview layers embedded in the output COG, ensuring smooth zooming performance from full resolution down to thumbnail scale.

Stage 4: Core Re-encoding with CogBuilder

The convertGeoTiffToCog function in packages/processing/src/cog-convert.ts orchestrates the heavy processing:

  1. Normalization: Calls reader.read_all_f64() to normalize any source data type (Int16, Float32, etc.) to 64-bit floating point.
  2. Builder Setup: Instantiates a CogBuilder with source width, height, and band count.
  3. Metadata Transfer: Copies geospatial metadata—including EPSG code, GeoTransform, and nodata values—from the reader to the builder.
  4. Configuration: Sets the tile size to 512 pixels (COG_TILE_SIZE), selects compression from COG_WASM_COMPRESSIONS (defaulting to "deflate"), and applies the calculated overview levels.
  5. Type-Specific Writing: If the source is 8-bit unsigned (sample_format === "uint" and bits_per_sample ≤ 8), the builder uses write_u8. Otherwise, it outputs 32-bit float using write_f32.

Stage 5: Output Generation

The function returns a Uint8Array containing the fully-formed COG. This byte array can be wrapped in a Blob and converted to an object URL for immediate consumption by MapLibre's raster layer, requiring zero server round-trips.

Configuration Options and Compression Settings

GeoLibre fixes the COG tile size at 512 pixels (COG_TILE_SIZE) for optimal browser rendering performance. Users can select compression algorithms via the UI dropdown bound to the COG_WASM_COMPRESSIONS array, which supports:

  • "deflate" (default)
  • "lzw"
  • "packbits"
  • "none"

The compression selection passes directly to the WASM layer during the CogBuilder configuration phase.

UI Integration and MapLibre Consumption

The raster panel UI (typically found in the plugins package) wires the conversion workflow to user interactions. When a user selects a file and clicks "Convert to COG":

  1. The FileReader API loads the source as bytes
  2. convertGeoTiffToCog processes the buffer with the selected compression
  3. The resulting Uint8Array becomes a Blob URL via URL.createObjectURL
  4. MapLibre consumes this blob URL as a raster layer source

Because the conversion runs entirely client-side, the same implementation works across web builds, Tauri desktop applications, and Jupyter embedded widgets.

Python Side-Car Fallback

When browser security policies (CSP) or unsupported browsers block WebAssembly loading, GeoLibre falls back to the backend/geolibre_server Python side-car. This backend uses rio-cogeo to perform the conversion, though this path is rarely triggered for typical web users with modern browsers.

Summary

  • Zero-server processing: GeoLibre's @geolibre/processing package converts GeoTIFFs to COGs entirely in the browser using the geolibre-wasm WebAssembly module.
  • Smart optimization: The pipeline checks existing tiling status, calculates overview pyramids down to 256px, and configures 512px tiles with configurable compression.
  • Type-aware output: The system automatically selects 8-bit unsigned or 32-bit float output based on source data characteristics.
  • Universal compatibility: The same conversion code runs in web browsers, desktop apps, and Jupyter notebooks, with a Python fallback for restricted environments.

Frequently Asked Questions

Does GeoLibre require Python or GDAL installed locally for COG conversion?

No. The browser-based conversion runs entirely client-side using the geolibre-wasm WebAssembly module. While GeoLibre includes a Python side-car that uses rio-cogeo as a fallback for restricted environments, typical users convert Cloud-Optimized GeoTIFFs without any server dependencies or local GDAL installations.

What compression algorithms does GeoLibre support for browser-based COG creation?

GeoLibre supports "deflate" (default), "lzw", "packbits", and "none" through the COG_WASM_COMPRESSIONS array defined in the processing package. Users select their preferred compression via the UI dropdown, and the value passes directly to the CogBuilder configuration before writing the output tiles.

Why does GeoLibre normalize raster data to 64-bit floating point during conversion?

The read_all_f64() method normalizes Int16, Float32, and other source formats to 64-bit floating point for consistent internal processing within the WebAssembly module. After processing, the CogBuilder writes the final output as either 8-bit unsigned (via write_u8) for compatible sources or 32-bit float (via write_f32) for higher bit-depth data, ensuring the COG maintains appropriate precision while optimizing file size.

Can GeoLibre convert GeoTIFFs that are already Cloud-Optimized?

Yes. The isTiledGeoTiff function checks the info.tiled property during the metadata extraction phase. If the source is already internally tiled and structured as a valid COG, GeoLibre bypasses the re-encoding process entirely and creates a raster layer pointing directly to the original file, avoiding unnecessary computation and quality degradation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →