How to Add Support for a New Raster Format Like COG or GeoTIFF in GeoLibre

To add a new raster format to GeoLibre, extend the file-extension detector in tauri-io.ts, add decoding logic in raster-client.ts, register the source in maplibre-raster.ts, and the UI automatically accepts the new format.

GeoLibre handles raster data through a multi-layer architecture spanning the desktop UI, client-side processing packages, and MapLibre integration. This guide walks you through adding support for any new raster format—whether a variant of GeoTIFF, Cloud Optimized GeoTIFF (COG), or a completely custom format—based on the actual source code implementation.

Architecture Overview: Where Raster Support Lives

Understanding the four layers involved in raster loading ensures you modify the right files:

Layer Purpose Key File
File-type detection Identifies raster files from extensions and MIME types apps/geolibre-desktop/src/lib/tauri-io.ts
Client-side processing Reads bytes, decodes formats, produces COG-compatible output packages/processing/src/raster-client.ts, raster-tools.ts
MapLibre source plugin Registers raster sources with the map renderer packages/plugins/src/plugins/maplibre-raster.ts
UI validation Handles drag-and-drop, file dialogs, upload workflows Uses isRasterFileName from UI components

Each layer must recognize your new format for end-to-end functionality.

Step 1: Extend the File-Extension Detector

The entry point for raster detection is isRasterFileName() in tauri-io.ts. This function determines whether a dropped or selected file should be treated as raster data.

Locate this function and add your new extension to the allowed list:

// apps/geolibre-desktop/src/lib/tauri-io.ts
export function isRasterFileName(name: string): boolean {
  const ext = fileExtension(name).toLowerCase();
  // Existing GeoTIFF/COG support plus new format
  return ['tif', 'tiff', 'jpg', 'jpeg', 'png', 'cog', 'myraster'].includes(ext);
}

The UI layer across GeoLibre calls isRasterFileName() for validation. Once updated, drag-and-drop handlers and file dialogs automatically accept your new extension without additional UI code changes.

Step 2: Add Byte-Decoding Logic in the Raster Client

The processing package handles the heavy lifting of converting raw raster bytes into renderable tile sources. Two approaches exist depending on whether you can decode client-side or need server-side conversion.

Option A: Client-Side WASM Decoding

For formats supported by GDAL-WASM or other WebAssembly decoders, add a branch in raster-client.ts:

// packages/processing/src/raster-client.ts
if (ext === 'myraster') {
  const bytes = await readFileBytes(file);
  // Convert to COG in-memory using WASM
  const cogBytes = await gdalWasm.convertToCog(bytes, { 
    format: 'myraster',
    compression: 'deflate'
  });
  return { 
    bytes: cogBytes, 
    type: 'cog',
    bounds: await extractBounds(cogBytes)
  };
}

Option B: Server-Side Conversion via Side-Car

For complex formats requiring full GDAL capabilities, route through the FastAPI backend:

// packages/processing/src/raster-client.ts
if (ext === 'myraster') {
  const sidecarResponse = await sidecarClient.convertToCog({ 
    filePath, 
    format: 'myraster',
    options: { tilingScheme: 'google' }
  });
  return { 
    bytes: sidecarResponse.bytes, 
    type: 'cog',
    url: sidecarResponse.cogUrl // byte-range accessible URL
  };
}

The raster-tools.ts file provides helper functions for band extraction, overview generation, and COG validation that your implementation can reuse.

Step 3: Register the Source in MapLibre-Raster

The plugin layer bridges processed raster data to the MapLibre renderer. In maplibre-raster.ts, register your format if it requires specialized handling:

// packages/plugins/src/plugins/maplibre-raster.ts
registerSourceType('myraster', (spec) => {
  // Reuse generic raster source with format-specific metadata
  return new RasterSource({
    url: spec.url,           // COG byte-range URL from step 2
    tileSize: 512,
    bounds: spec.bounds,     // Extracted during processing
    bandCount: spec.bandCount,
    // Expose additional properties for UI panels
    attribution: spec.attribution,
    colorinterp: spec.colorinterp
  });
});

Most formats can reuse the existing 'raster' source type if you've already converted to COG format in step 2. Registration is only necessary when the format requires unique rendering behavior.

Step 4: Validate End-to-End Integration

After implementing changes across all three layers, verify functionality:

  1. File detection: Drag a .myraster file into the application—console logs from tauri-io.ts should confirm recognition
  2. Processing: Monitor Network tab for WASM activity (client-side) or side-car API calls (server-side)
  3. Rendering: Confirm the layer appears in MapLibre with correct bounds and zoom levels

Key Files Reference

File Path Function Role in Adding New Formats
apps/geolibre-desktop/src/lib/tauri-io.ts isRasterFileName() Entry-point extension validation
packages/processing/src/raster-client.ts loadRaster(), decoding branches Byte reading and format conversion
packages/processing/src/raster-tools.ts extractBounds(), validateCog() Shared raster utilities
packages/plugins/src/plugins/maplibre-raster.ts registerSourceType() MapLibre source registration
backend/geolibre_server/app/raster.py /convert-to-cog endpoint Server-side COG conversion API

Performance Considerations

  • Client-side decoding: Best for files under 100MB; avoids network overhead but blocks the main thread during WASM initialization
  • Server-side conversion: Scales to multi-GB files; add progress callbacks in raster-client.ts for user feedback
  • COG as universal target: Always convert to Cloud Optimized GeoTIFF internally—this enables HTTP range requests and efficient pyramid rendering regardless of source format

Summary

  • Extend isRasterFileName() in tauri-io.ts to recognize the new file extension
  • Add decoding logic in raster-client.ts using either WASM or side-car conversion
  • Register specialized sources in maplibre-raster.ts only if rendering behavior differs from standard COG
  • Leverage existing utilities in raster-tools.ts for bounds extraction and validation
  • The UI updates automatically once the extension detector recognizes the new format

Frequently Asked Questions

Where does GeoLibre decide if a file is a raster?

The isRasterFileName() function in apps/geolibre-desktop/src/lib/tauri-io.ts maintains the canonical list of supported raster extensions. All UI components defer to this function for file-type validation.

Can I add support without modifying the MapLibre plugin?

Yes. If your format conversion in raster-client.ts produces a standard COG output, the existing raster source type in maplibre-raster.ts handles rendering automatically. Only formats needing specialized tile delivery require plugin modifications.

What if my format requires proprietary codecs not available in WASM?

Route processing through the FastAPI side-car in backend/geolibre_server/app/raster.py. The side-car has full access to system GDAL and can convert proprietary formats to COG before sending bytes back to the client.

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 →