Thursday, May 9, 2013

gvSIG CE using GDAL 1.9.2 to read raster data, including ECW, JP2, MrSID and Lidar files

Recently, I've been working for gvSIG CE project, thanks to the folks of geomati.co (I'm part of the team now!). I was solving some GDAL related open cases (this, this and this). the aim is to get a functional and stable gvSIG CE 1.0 version. There are still a couple of cases to solve (this and this), but I think we're pretty close. I'd like to explain what I did to solve these cases.
Make gvSIG CE work with GDAL 1.9.x
This bug was hard to find but easy to fix.  First, a 1-minute introduction to GDAL use in gvSIG CE. gvSIG CE uses a JNI wrapper (based on GDAL 1.7.x GDAL packed JNI wrapper) to make C++ native calls to GDAL library. There are 2 important GDAL JNI wrapper classes involved in most GDAL operations:
Gdal.java (it interacts with native C++ GDALDataset class)
GdalRasterBand,java (it interacts with native C++ GDALRasterBand class)

Both classes inherit from the same base class: JNIBase. This class defines a function named baseSimpleFunctions that calls one of several native C functions, depending on an input parameter. But some of these native C functions are GDALDataset-based, and other are GDALRasterBand-based. I mean, the pointer passed to them doesn't hold the same C structure (wrapping C++ object) in all cases.
And here was the thing. To actually read the raster data, the Java function GdalRasterBand::readRaster is called. This function checks the position and size of the region being accessed, comparing it with the raster dimensions. To check this, the C functions getRasterXSize and getRasterYSize are called. These functions expect a pointer to a GDALDataset C object, but the GdalRasterBand Java class provides a pointer to a GDALRasterBand C object. I had to replace those Dataset-based calls to RasterBand based calls, to match the underlying C structure.
Replace ECW and MrSID driver with GDAL
First, a few comments on these formats. ECW stands for enhanced compression wavelet. This propietary format is a high-performance image-compression format designed specifically for geospatial imagery. It's patented and owned by Intergraph. More information here.
Intergraph provides a license needed SDK for encoding data and a free SDK for reading. Since version 4.1, this free SDK is only available for Desktop development on Windows systems. There are promises to include Linux support since 5.0 version, but gvSIG CE doesn't plan to support ECW and other proprietary formats. So, I worked with the last known version working on Linux systems too. This is 3.3.
About MrSID, it stands for multiresolution seamless image database. It's a proprietary format too, owned by LizardTech. As happens with ECW, there's a free SDK to read MrSID files. It can be downloaded from here (MrSID SDK, under Tools & Utilities. Free register required). And as happens with ECW too, gvSIG CE won't directly support this format. So, it delegates in GDAL.
In both cases, we'll need to compile GDAL with the proper support. So, I had to download and compile MrSID and ECW libraries and build GDAL using --with-ecw and --with-mrsid options.
As there is a JNI wrapper for GDAL, there are JNI wrappers for ECW and MrSID. The goal was: get rid of them, and give GDAL credentials to handle these formats. Four steps involved here:
- Compile GDAL with ECW and MrSID support, as said
- Tell GDAL to take care of those formats for reading (class GdalDriver)
- Unregister ECW and MrSID drivers from gvSIG CE raster library (libRaster)
- Delete ECW and MrSID wrappers and native code.
Once done, you have gvSIG CE using GDAL 1.9.2 to read raster data, including ECW, JP2, MrSID and Lidar files (previously managed by ECW and MrSID drivers).

1 comment:

  1. Thanks for your great work Jorge! We now have amazingly good GDAL drivers support in gvSIG CE. The issue with the latest ECW SDK on Linux just confirms a basic truth: proprietary, closed-source code will _always_ cause trouble in open source projects and must be removed eventually. Neither ECW nor MrSID can do anything that you couldn't do with GeoTIFF...

    ReplyDelete