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

> Learn how to add new raster formats like COG or GeoTIFF to GeoLibre. Extend file detection, add decoding logic, register the source, and your UI will automatically support the new format.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: how-to-guide
- Published: 2026-08-01

---

**To add a new raster format to GeoLibre, extend the file-extension detector in [`tauri-io.ts`](https://github.com/opengeos/GeoLibre/blob/main/tauri-io.ts), add decoding logic in [`raster-client.ts`](https://github.com/opengeos/GeoLibre/blob/main/raster-client.ts), register the source in [`maplibre-raster.ts`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/raster-client.ts), [`raster-tools.ts`](https://github.com/opengeos/GeoLibre/blob/main/raster-tools.ts) |
| **MapLibre source plugin** | Registers raster sources with the map renderer | [`packages/plugins/src/plugins/maplibre-raster.ts`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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:

```typescript
// 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`](https://github.com/opengeos/GeoLibre/blob/main/raster-client.ts):

```typescript
// 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:

```typescript
// 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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/maplibre-raster.ts), register your format if it requires specialized handling:

```typescript
// 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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/lib/tauri-io.ts) | `isRasterFileName()` | Entry-point extension validation |
| [`packages/processing/src/raster-client.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/raster-client.ts) | `loadRaster()`, decoding branches | Byte reading and format conversion |
| [`packages/processing/src/raster-tools.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/raster-tools.ts) | `extractBounds()`, `validateCog()` | Shared raster utilities |
| [`packages/plugins/src/plugins/maplibre-raster.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/maplibre-raster.ts) | `registerSourceType()` | MapLibre source registration |
| [`backend/geolibre_server/app/raster.py`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/tauri-io.ts) to recognize the new file extension
- **Add decoding logic** in [`raster-client.ts`](https://github.com/opengeos/GeoLibre/blob/main/raster-client.ts) using either WASM or side-car conversion
- **Register specialized sources** in [`maplibre-raster.ts`](https://github.com/opengeos/GeoLibre/blob/main/maplibre-raster.ts) only if rendering behavior differs from standard COG
- **Leverage existing utilities** in [`raster-tools.ts`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/raster-client.ts) produces a standard COG output, the existing `raster` source type in [`maplibre-raster.ts`](https://github.com/opengeos/GeoLibre/blob/main/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`](https://github.com/opengeos/GeoLibre/blob/main/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.