← Back to list

How to Extract ECW Files for Free Using Docker: Skip the $$$$ Proprietary Software

The Problem: Expensive and Incompatible ECW Extraction Tools

Rahul Bhat · 2025-12-04 12:11 · 0 claps · 6.4 min read
#geospatial-data #gis #docker #gdal #ecw-files
Open on Medium ↗
Wiki topics: ☁️ · DevOps & Cloud

How to Extract ECW Files for Free Using Docker: Skip the $$$$ Proprietary Software

The Problem: Expensive and Incompatible ECW Extraction Tools

If you work with geospatial data, you’ve probably encountered ECW (Enhanced Compressed Wavelets) files. They’re great for compressing satellite imagery and aerial photos, but extracting them is a nightmare.

Here’s why:

Proprietary Software Costs: The official ECW SDK from Hexagon Geospatial comes with hefty licensing fees. We’re talking hundreds to thousands of dollars depending on your use case. For small projects, research, or individual developers, this isn’t feasible.

Compatibility Issues: Popular GIS software like QGIS and ArcGIS can struggle with ECW support across different operating systems. ArcGIS on Linux? Forget about it. QGIS with full ECW support on Windows? Hit or miss depending on your build version.

Platform Limitations: Traditional extraction methods lock you into specific operating systems or require complex library installations that break between different system versions.

Time-Consuming Setup: Installing ECW libraries directly on your system means dealing with dependency hell — conflicting versions, missing packages, and hours of troubleshooting.

Sound familiar? I hit all these walls recently on a Chile drone imagery project. That’s when Docker came to the rescue.

Skip proprietary software costs. Extract ECW files free using Docker on any operating system.

Skip proprietary software costs. Extract ECW files free using Docker on any operating system.

The Solution: Free, Cross-Platform ECW Extraction with Docker

Here’s the good news: Docker lets you extract ECW files for free using GDAL (Geospatial Data Abstraction Library) without any proprietary software or costly licenses.

Even better? It works on Linux, Windows (WSL2), and macOS — all with the same setup.

Why This Approach is Better

Completely free — No licensing fees Cross-platform — Works on Linux, Windows (via WSL2), and Mac No library conflicts — Everything runs in an isolated container Reproducible — Same results on every machine Scalable — Process hundreds of files automatically No bloatware — Just what you need, nothing extra

Getting Started: System Requirements

For this method, you’ll need:

Linux: Ubuntu 20.04+ (or any modern Linux distro) Windows: Windows 10/11 with WSL2 enabled + Docker Desktop macOS: Docker Desktop for Mac General: Python 3.8+, at least 2GB disk space, sudo/admin access

Installation Guide

For Linux (Ubuntu/Debian)

First, update your system:

sudo apt update
sudo apt upgrade -y

sudo apt install -y \
    curl \
    wget \
    git \
    python3 \
    python3-pip \
    python3-venv

Install Docker:

sudo apt remove -y docker docker-engine docker.io containerd runc

sudo apt install -y \
    ca-certificates \
    gnupg \
    lsb-release

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Verify Docker works:

sudo docker --version
sudo docker run hello-world

Optional — avoid using sudo with every docker command:

sudo usermod -aG docker $USER
newgrp docker
docker run hello-world

For Windows (via WSL2)

  1. Enable WSL2:
  • Open PowerShell as Administrator
  • Run: wsl --install
  • Restart your computer
  • Install a Linux distribution (Ubuntu 20.04 recommended) from Microsoft Store

2. Install Docker Desktop for Windows:

3. Verify in WSL2 terminal:

docker --version
docker run hello-world

For macOS

  1. Install Docker Desktop for Mac:

2. Verify installation:

docker --version 
docker run hello-world

Setting Up Your Project

Create your project directory structure:

mkdir -p ~/ecw_extraction
cd ~/ecw_extraction

mkdir -p extracted             # Your ECW files go here
mkdir -p converted_images      # Converted files will be saved here
mkdir -p scripts               # Processing scripts
mkdir -p logs                  # Log files

Pulling the GDAL Docker Image with ECW Support

docker pull geodata/gdal

Verify ECW support is available:

docker run --rm geodata/gdal gdalinfo --formats | grep -i ECW

You should see:

ECW -raster- (rw+): ERDAS Compressed Wavelets (SDK 5.5)
JP2ECW -raster,vector- (rw+v): ERDAS JPEG2000 (SDK 5.5)

Perfect!

Preparing Your ECW Files

Copy your ECW files to the extracted directory:

cp /path/to/your/*.ecw extracted/
cp /path/to/your/*.eww extracted/  # World files (optional)
cp /path/to/your/*.prj extracted/  # Projection files (optional)

Verify:

ls -lh extracted/

Test Run: Manual Extraction

Before automating, let’s test one file manually.

Get information about your ECW file:

docker run --rm \
  -v $(pwd)/extracted:/input \
  geodata/gdal \
  gdalinfo /input/ortofoto.ecw

Replace ortofoto.ecw with your actual filename. You'll see detailed info like size, coordinate system, and pixel dimensions.

Now convert it to GeoTIFF (a standard, widely-compatible format):

docker run --rm \
  -v $(pwd)/extracted:/input \
  -v $(pwd)/converted_images:/output \
  geodata/gdal \
  gdal_translate \
  -of GTiff \
  /input/ortofoto.ecw \
  /output/ortofoto.tif

Check the result:

ls -lh converted_images/

See the .tif file? You're ready for batch processing! ✅

Automate with Python: Batch Processing Script

Create scripts/extract_ecw_direct.py:

#!/usr/bin/env python3
"""
ECW Extraction using Docker with direct file access
Works on Linux, Windows (WSL2), and macOS
"""

import subprocess
import os
import sys
from pathlib import Path
import logging
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class ECWExtractor:
    def __init__(self, input_dir="extracted", output_dir="converted_images"):
        self.input_dir = Path(input_dir)
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)

        logger.info(f"ECW Extractor initialized:")
        logger.info(f"  Input directory: {self.input_dir}")
        logger.info(f"  Output directory: {self.output_dir}")

    def extract_ecw_to_geotiff(self, ecw_file, output_format="GTiff"):
        """Extract ECW to GeoTIFF using Docker"""

        ecw_path = self.input_dir / ecw_file
        if not ecw_path.exists():
            logger.error(f"ECW file not found: {ecw_path}")
            return False

        output_file = ecw_path.stem + ".tif"
        output_path = self.output_dir / output_file

        logger.info(f"Converting {ecw_file} to {output_file}...")

        cmd = [
            "docker", "run", "--rm",
            "-v", f"{self.input_dir.absolute()}:/input",
            "-v", f"{self.output_dir.absolute()}:/output",
            "geodata/gdal",
            "gdal_translate",
            "-of", output_format,
            "/input/" + ecw_file,
            "/output/" + output_file
        ]

        try:
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)

            if result.returncode == 0:
                logger.info(f"✓ Successfully converted {ecw_file}")
                logger.info(f"  Output: {output_path}")
                return True
            else:
                logger.error(f"✗ Conversion failed for {ecw_file}")
                logger.error(f"  Error: {result.stderr}")
                return False

        except subprocess.TimeoutExpired:
            logger.error(f"✗ Conversion timed out for {ecw_file}")
            return False
        except Exception as e:
            logger.error(f"✗ Error converting {ecw_file}: {e}")
            return False

    def get_ecw_info(self, ecw_file):
        """Get detailed information about ECW file"""

        ecw_path = self.input_dir / ecw_file
        if not ecw_path.exists():
            logger.error(f"ECW file not found: {ecw_path}")
            return None

        logger.info(f"Getting information for {ecw_file}...")

        cmd = [
            "docker", "run", "--rm",
            "-v", f"{self.input_dir.absolute()}:/input",
            "geodata/gdal",
            "gdalinfo",
            "/input/" + ecw_file
        ]

        try:
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)

            if result.returncode == 0:
                logger.info(f"✓ Successfully retrieved info for {ecw_file}")
                return result.stdout
            else:
                logger.error(f"✗ Failed to get info for {ecw_file}")
                return None

        except Exception as e:
            logger.error(f"✗ Error getting info for {ecw_file}: {e}")
            return None

    def process_all_ecw_files(self):
        """Process all ECW files in the input directory"""

        ecw_files = list(self.input_dir.glob("*.ecw"))
        if not ecw_files:
            logger.error("No ECW files found in input directory")
            return False

        logger.info(f"Found {len(ecw_files)} ECW files to process")

        success_count = 0
        for ecw_file in ecw_files:
            logger.info(f"\nProcessing {ecw_file.name}...")

            info = self.get_ecw_info(ecw_file.name)
            if info:
                info_file = self.output_dir / f"{ecw_file.stem}_info.txt"
                with open(info_file, 'w') as f:
                    f.write(info)
                logger.info(f"  Info saved to: {info_file}")

            if self.extract_ecw_to_geotiff(ecw_file.name):
                success_count += 1

        logger.info(f"\nProcessing complete: {success_count}/{len(ecw_files)} files converted successfully")
        return success_count > 0
def main():
    """Main function"""
    logger.info("=" * 80)
    logger.info("ECW EXTRACTION USING DOCKER")
    logger.info("=" * 80)

    extractor = ECWExtractor()
    success = extractor.process_all_ecw_files()

    if success:
        logger.info("\n✓ ECW extraction completed successfully!")
        logger.info(f"Check output directory: {extractor.output_dir}")
    else:
        logger.error("\n✗ ECW extraction failed!")
        sys.exit(1)
if __name__ == "__main__":
    main()

Make it executable:

chmod +x scripts/extract_ecw_direct.py

Run it:

python3 scripts/extract_ecw_direct.py

The script will process all ECW files in your extracted/ directory and save GeoTIFF conversions to converted_images/.

Verify Your Results

Create scripts/verify_extraction.py:

#!/usr/bin/env python3
"""
Verify extracted files and validate conversion quality
"""

import subprocess
from pathlib import Path
import logging
import sys

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class ExtractionVerifier:
    def __init__(self, output_dir="converted_images"):
        self.output_dir = Path(output_dir)

    def verify_geotiff(self, tif_file):
        """Verify GeoTIFF file"""

        tif_path = self.output_dir / tif_file
        if not tif_path.exists():
            logger.error(f"GeoTIFF file not found: {tif_path}")
            return False

        logger.info(f"Verifying {tif_file}...")

        cmd = [
            "docker", "run", "--rm",
            "-v", f"{self.output_dir.absolute()}:/data",
            "geodata/gdal",
            "gdalinfo",
            "/data/" + tif_file
        ]

        try:
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)

            if result.returncode == 0:
                logger.info(f"  ✓ {tif_file} is valid")

                info = result.stdout
                lines = info.split('\n')

                for line in lines:
                    if 'Size is' in line:
                        logger.info(f"    Size: {line.split('Size is')[1].strip()}")
                    elif 'Coordinate System is' in line:
                        logger.info(f"    CRS: {line.split('Coordinate System is')[1].strip()}")

                return True
            else:
                logger.error(f"  ✗ {tif_file} is invalid: {result.stderr}")
                return False

        except Exception as e:
            logger.error(f"  ✗ Error verifying {tif_file}: {e}")
            return False

    def verify_all_files(self):
        """Verify all extracted files"""

        tif_files = list(self.output_dir.glob("*.tif"))

        if not tif_files:
            logger.error("No GeoTIFF files found for verification")
            return False

        logger.info(f"Found {len(tif_files)} GeoTIFF files to verify")

        valid_count = 0
        for tif_file in tif_files:
            if self.verify_geotiff(tif_file.name):
                valid_count += 1

        logger.info(f"\nVerification complete: {valid_count}/{len(tif_files)} files are valid")
        return valid_count > 0

def main():
    """Main function"""
    logger.info("=" * 80)
    logger.info("ECW EXTRACTION VERIFICATION")
    logger.info("=" * 80)

    verifier = ExtractionVerifier()
    success = verifier.verify_all_files()

    if success:
        logger.info("\n✓ Verification completed successfully!")
    else:
        logger.error("\n✗ Verification failed!")
        sys.exit(1)

if __name__ == "__main__":
chmod +x scripts/verify_extraction.py  ### Permissions
python3 scripts/verify_extraction.py

Troubleshooting

Can’t run docker on Windows? Make sure WSL2 is fully installed and Docker Desktop has WSL2 backend enabled in settings.

Permission denied on Linux?

sudo usermod -aG docker $USER
newgrp docker

ECW format not found?

docker run --rm geodata/gdal gdalinfo --formats | grep ECW

If empty, try: docker pull osgeo/gdal:ubuntu-small-latest

Out of disk space?

df -h
docker system prune -a

Why This Matters

Let me be real about what you’re getting here:

Instead of:

  • Paying hundreds/thousands for licenses
  • Struggling with OS-specific software
  • Hours of library installation headaches
  • Vendor lock-in to proprietary tools

You get:

  • Zero licensing costs
  • Same workflow on Linux, Windows, and Mac
  • Reproducible results every time
  • Scalable batch processing
  • Open-source sustainability

On my Chile drone imagery project, this saved us from buying expensive proprietary software. We process 50+ ECW files monthly without a single licensing fee.

What’s Next?

After extraction, you can:

  • Import GeoTIFF files into QGIS (free, open-source GIS)
  • Run machine learning models for image analysis
  • Create orthomosaics for research
  • Share files freely without licensing restrictions

Start extracting your ECW files for free today. No credit card, no licensing fees, no compatibility nightmares. Just Docker, GDAL, and clean GeoTIFF files.


메타데이터
post_id
054a91b26092
slug
how-to-extract-ecw-files-for-free-using-docker-skip-the-proprietary-software-054a91b26092
url
https://medium.com/@ra-bhat2002/how-to-extract-ecw-files-for-free-using-docker-skip-the-proprietary-software-054a91b26092
canonical_url
https://medium.com/@ra-bhat2002/how-to-extract-ecw-files-for-free-using-docker-skip-the-proprietary-software-054a91b26092
author_url
https://medium.com/@ra-bhat2002
status
ok
fetched_at
2026-06-22 05:41:33