NOTE: This page is work in progress.

OGC WMS Driver

The driver is composed of interface layer between GDAL and mini-drivers, and many small mini-drivers. Mini-driver only task is to provide image locations, actual downloads and returning data is handled by interface layer. Example:

  1. User requests (via RasterIO call) 400x400 image block starting at pixel (500, 700).
  2. Mini-driver is asked to provide list of images to download and returns:
    1. upper-left corner: (500, 500), lower-right corner: (1000, 1000)


  1. upper-left corner: (500, 1000), lower-right corner: (1000, 1500)


  1. The images are downloaded, resampled, mosaicked, cropped to fit the user request.

The interface layer implements:

        class GDALWMSDataset : public GDALPamDataset {
            virtual CPLErr IRasterIO( ... );
            virtual CPLErr AdviseRead( ... );
            virtual const char *GetProjectionRef();
            virtual CPLErr GetGeoTransform( ... );

        class GDALWMSRasterBand : public GDALPamRasterBand {
            virtual CPLErr IReadBlock( ... );
            virtual CPLErr IRasterIO( ... );
            virtual CPLErr AdviseRead( ... );
            virtual int HasArbitraryOverviews();
            virtual int GetOverviewCount();
            virtual GDALRasterBand *GetOverview( ... );

HasArbitraryOverviews? always returns true. Overview count is set in configuration file, each overview layer has half the resolution of previous layer. GetProjectionRef? returns projection as specified in configuration file. GetGeoTransform? returns geo-transform constructed from data window. IRasterIO, AdviseRead? and IReadBlock are translated into common request format:

        class ImageRequest {
            double m_x0, m_y0; // geo-referenced upper-left corner
            double m_x1, m_y1; // geo-referenced lower-right corner
            int m_xsize, m_ysize; // width and height in pixels

        class ImageBufferInfo { // see GDALDataset::RasterIO documentation
            void *m_data;
            int m_xsize, m_ysize;
            GDALDataType m_data_type;
            int m_band_count;
            int *m_band_map;
            int m_pixel_space;
            int m_line_space;
            int m_band_space;

Dataset open

  1. open, verify and read XML configuration file into CPL MiniXML tree
  2. update XML tree with arguments specified in dataset name
  3. create instance of mini-driver and pass in the XML tree

Dataset image request

  1. validate the request
  2. check if request can be satisfied from block cache only and return the data to user if possible
  3. call into mini-driver getting back list of image locations
  4. download the images, if allowed try in cache first
  5. update block cache wherever possible (resolution match, complete coverage)
  6. return the data to user

Download cache

If enabled in XML configuration file and allowed by mini-driver, downloaded images will be written to disk for future use. This should reduce load on the WMS server or even allow off-line operation. HTTP download queue Download queue is implemented using libcurl (, running in dedicated background thread to allow data preloading (AdviseRead? or guessed). Can be configured to use HTTP pipelining and multiple connections.

XML configuration file

          <HTTP> ... </HTTP>
          <DataSource> ... </DataSource>
          <DataWindow> ... </DataWindow>
          <Cache> ... </Cache>

<HTTP> configures the HTTP download queue.

          <MaxPipeline> ... </MaxPipeline>    number of requests on single connection     <MaxParallel> ... </MaxParallel>    number of parallel connections
          <UserAgent> ... </UserAgent>        custom user agent header
          <User> ... </User>                  http authentication, user
          <Password> ... </Password>          http authentication, password
          <Proxy> ... </Proxy>                proxy support, see curl for docs
          <ProxyPort> ... </ProxyPort>        
          <ProxyType> ... </ProxyType>        
          <ProxyUser> ... </ProxyUser>        
          <ProxyPassword> ... </ProxyPassword>

<DataSource?> specifies name and configuration for mini-driver.

        <DataSource driver=”some mini-driver”>
          ... mini-driver specific configuration ...

<DataWindow?> specifies projection, extents and resolution of data as visible by GDAL. Image size is in pixels, upper-left and lower-right corners are in specified projection. Overview count is optional and can be set to 0, default is calculated so last overview is bigger than 512x512. Block size is optional and defaults to 512x512.

          <Projection> ... </Projection>
          <UpperLeftX> ... </UpperLeftX>
          <UpperLeftY> ... </UpperLeftY>
          <LowerRightX> ... </LowerRightX>
          <LowerRightY> ... </LowerRightY>
          <SizeX> ... </SizeX>
          <SizeY> ... </SizeY>
          <OverviewCount> ... </OverviewCount>
          <BlockSizeX> ... </BlockSizeX>
          <BlockSizeY> ... </BlockSizeY>

Example data window (red) in global WMS layer (blue), geographic projection.


<Cache> specifies location of disk cache. If location is not set cache is disabled.



Image download request, filled in by mini-driver and returned to interface layer.

        class ImageDownloadRequest {
            CPLString m_url;       // image url to download
            double m_x0, m_y0;     // georeferenced upper-left
            double m_x1, m_y1;     // georeferenced bottom-right
            int m_xsize, m_ysize;  // width and height in pixels
            bool m_use_cache;      // should the image be cached / read from cache

        typedef std::vector<ImageDownloadRequest> ImageDownloadRequestList;


        class MiniDriver {
            MiniDriver(CPLXMLNode *config);
            virtual ~MiniDriver();

            // Process image request and add image download requests to the list
            virtual void AppendImageDownloadRequestList(
                ImageDownloadRequestList &out, const ImageRequest &in);

Mini-driver factory, used to create instance of given mini-driver.

        class MiniDriverFactory {
            virtual ~MiniDriverFactory();

            // create mini-driver instance, basically:
            // return new ExampleMiniDriver(config);
            virtual MiniDriver* New(CPLXMLNode *config);

            // destroy mini-driver instance, basically:
            // delete instance;
            virtual void Delete(MiniDriver *instance);

            const std::string &GetName() {
                return m_name;

            // <DataSource name=”...”> in configuration file
            std::string m_name;

Planned mini-drivers

OGC WMS mini-driver

  • The driver will not issue GetCapabilities? requests, all information has to be stored in XML configuration file.
  • Small utility program will be provided (probably a script) to handle GetCapabilities? requests and write configuration file.
  • Arbitrary overviews handled by WMS server.
  • Custom arguments in server URL (for example WMS Time)
  • Many download patterns:
    1. one download (light green) per image request (dark green), partial block cache (gray), disk cache not allowed
    2. one download per image request, extended to block cache grid, disk cache not allowed
    3. many downloads per image request (tiled), full block cache, disk cache allowed

OGC WMS mini-driver configuration

        <DataSource driver=”WMS”>

Example mini-driver implementation

Mini-driver for a WMS-like service with requests in format: http://server/file?width=...&height=...&bbox=...

        MyMiniDriver::MyMiniDriver(CPLXMLNode *config) {
            m_server = CPLGetXMLValue(config, "ServerURL", "");

        MyMiniDriver::~MyMiniDriver() {

        void MyMiniDriver::AppendImageDownloadRequestList(
                ImageDownloadRequestList &out, const ImageRequest &in) {
            ImageDownloadRequest req;
            req.m_use_cache = false;
            req.m_x0 = in.m_x0;
            req.m_y0 = in.m_y0;
            req.m_x1 = in.m_x1;
            req.m_y1 = in.m_y1;
            req.m_xsize = in.m_xsize;
            req.m_ysize = in.m_ysize;
                    m_server.c_str(), in.m_xsize, in.m_ysize,
                    in.m_x0, in.m_y0, in.m_x1, in.m_y1);

        MyMiniDriverFactory::MyMiniDriverFactory() {
            m_name = "MyWMS";

        MyMiniDriverFactory::~MiniDriverFactory() {

        MiniDriver* MyMiniDriverFactory::New(CPLXMLNode *p) {
            return new MyMiniDriver(p);

        void MyMiniDriverFactory::Delete(MiniDriver *p) {
            delete p;

Example XML configuration file for MyWMS mini-driver:

          <DataSource name=”MyWMS”>


Other comments and suggestions

  • What protocol versions will be supported. I think WMS 1.1.0 is the most important but 1.0.0, and 1.3.0 are also desirable (FrankW)
    • As far as GetMap? requests are concerned all three are almost equal (Nowak)
    • Looks like there are problems with the x,y or y,x ordering in 1.3.0, I will add flag to XML configuration file determining the order. However if you can, stay away from 1.3.0 and use 1.1.x version :) (Nowak)
Last modified 12 years ago Last modified on Jul 16, 2007 11:24:31 AM