GDALRaster Processing

gdal_contour

What is gdal_contour?

gdal_contour walks a raster and emits vector features where pixel values cross specified thresholds, producing either polyline contours or filled polygon bands. The canonical use is generating topographic contour lines from a digital elevation model, but the tool works on any continuous-value raster — bathymetry, temperature, noise levels, dose rates — as long as the pixel values are meaningfully orderable.

Shell
gdal_contour [options] <src_filename> <dst_filename>

Commonly used options:

  • -b <band> — source band (default 1)
  • -a <attribute> — attribute name for the contour value (default elev)
  • -amin <attribute> / -amax <attribute> — attribute names for polygon band min/max
  • -i <interval> — contour interval (e.g. 10 for every 10 m)
  • -fl <level>... — explicit fixed levels rather than an interval
  • -off <offset> — offset applied to -i interval
  • -p — produce polygons (filled bands) instead of lines
  • -f <format> — output OGR format (ESRI Shapefile, GPKG, GeoJSON, …)
  • -3d — include elevation as the Z coordinate of each vertex
  • -snodata <value> — override NoData
  • -e <expNumber> — exponential base for exponentially spaced levels

When would you use gdal_contour?

Use it whenever a continuous raster needs a vector representation of its iso-surfaces. Typical jobs: generating 10-metre contour lines from a LiDAR DEM for a cartographic map (gdal_contour -a elev -i 10 dem.tif contours.gpkg), producing filled elevation bands for cartographic shading (-p -amin elev_min -amax elev_max), or extracting bathymetric contours at specific depths using -fl -5 -10 -20 -50 -100.

For cartography, pair gdal_contour with ogr2ogr -sql to simplify or categorise the output (e.g. tag every fifth contour as an "index contour" for a heavier cartographic style). For 3D analysis, -3d embeds Z values so the contours render in globe viewers and can be extruded.

FAQs

Lines or polygons — which should I generate?

Lines (-i without -p) are the classic contour representation for cartography and overlay on base maps. Polygons (-p) produce filled elevation bands each carrying elev_min and elev_max attributes, ideal for choropleth-style hypsometric tints or for spatial overlay queries like "which buildings are above 100 m". Pick the output shape that matches downstream consumers.

Why are my contours jagged?

Contour smoothness is inherited from the source raster. Low-resolution DEMs produce stair-stepped contours around steep terrain. Options are to oversample with gdalwarp -tr and a smoothing resampler (cubicspline) before running gdal_contour, or post-smooth the output with a vector generalisation tool like ogr2ogr -simplify. Avoid over-smoothing — contours must still honour the terrain topology.

How do I honour NoData correctly?

If the DEM has NoData, gdal_contour respects it and does not generate contours across gaps. If NoData is not set but a sentinel value is used (e.g. -9999), pass -snodata -9999 so the tool treats those pixels correctly. Without this, contours will erroneously run through voids.

Can I generate contours at non-uniform levels?

Yes — use -fl with an explicit list: gdal_contour -fl 50 100 250 500 1000 dem.tif out.gpkg. For exponential or logarithmic spacing (useful on rainfall or concentration data with wide dynamic range), -e produces geometric level progressions.