GDAL-PIPELINE(1)
β¨ gdal-pipeline β¨ β the manual page, bestie edition π
okay so this is GDAL-PIPELINE(1) from the GDAL manual. yes that GDAL. the one that eats your raster files for breakfast. sit down, grab a strawberry π, we're doing this.
π NAME π
gdal-pipeline β Process a dataset applying several steps
Added in version 3.12. π
π¦ DESCRIPTION π¦
okay so gdal pipeline execute a pipeline β it takes a raster or input dataset, runs a bunch of steps on it, and finally writes out a raster or vector dataset. it's giving assembly line but make it cartography. πβ¨
Most steps proceed in on-demand evaluation of raster blocks or features, unless otherwise stated in their documentation, without "materializing" the resulting dataset of the operation of each step. no cap, it just vibes through the data block by block. π§
ngl though, sometimes it's actually desirable for performance purposes to proceed to materializing an intermediate dataset to disk β using gdal raster materialize or gdal vector materialize. so if your pipeline is running like it's on dial-up, that's your move. π₯
β SYNOPSIS β
Usage: gdal pipeline [OPTIONS] <PIPELINE>
Process a dataset applying several steps.
Positional arguments:
Common Options:
-h, --help Display help message and exit
--json-usage Display usage as JSON document and exit
--config <KEY>=<VALUE> Configuration option [may be repeated]
-q, --quiet Quiet mode (no progress bar or warning message) [not available in pipelines]
Advanced Options:
--<user-provided-option>=<value> Argument provided by user
<PIPELINE> is of the form: read|calc|concat|create|mosaic|stack [READ-OPTIONS] ( ! <STEP-NAME> [STEP-OPTIONS] )* ! write!info!tile [WRITE-OPTIONS]
A pipeline chains several steps, separated with the ! (exclamation mark) character. π«Ά Including a ! between gdal pipeline and the first step is optional. The first step must be read, calc, concat, mosaic or stack, and the last one info, tile or write. Each step has its own positional or non-positional arguments. Apart from read, calc, concat, mosaic, stack, info, tile, partition and write, all other steps can potentially be used several times in a pipeline. (yes bestie, some steps are an β¨only childβ¨ and can only appear once.)
πΈ Example 1: Compute the footprint of a raster and apply a buffer on the footprint πΈ
$ gdal pipeline ! read in.tif ! footprint ! buffer 20 ! write out.gpkg --overwrite
see how cute that is?? ! everywhere, just vibe-separating your steps. π
π₯ STEPS π₯
For steps that have both raster data type as input and output, consult gdal raster pipeline. For steps that have both vector data type as input and output, consult gdal vector pipeline.
The list below is the little crossover episode π β steps that convert between raster and vector data. (the original had a whole table but we're doing bullets, it's giving the same energy fr fr)
contourβ Raster β Vectorfootprintβ Raster β Vectorpixel-infoβ Raster β Vectorpolygonizeβ Raster β Vectorgridβ Vector β Rasterrasterizeβ Vector β Rasterteeβ Vector β Raster
ποΈ contour ποΈ
* contour [OPTIONS]
-------------------
Creates a vector contour from a raster elevation model (DEM). literal mountain lines, slay. β°οΈβ¨
Options:
--output-layer <OUTPUT-LAYER>β Output layer name-b,--band <BAND>β Input band (1-based index) (default:1)--elevation-name <ELEVATION-NAME>β Name of the elevation field--min-name <MIN-NAME>β Name of the minimum elevation field--max-name <MAX-NAME>β Name of the maximum elevation field--3dβ Force production of 3D vectors instead of 2D--input-nodata <INPUT-NODATA>β Input pixel value to treat as 'nodata'--interval <INTERVAL>β Elevation interval between contours. Mutually exclusive with--levels,--exp-baseπ«--levels <LEVELS>β List of contour levels [may be repeated]. Mutually exclusive with--interval,--exp-baseπ«-e,--exp-base <EXP-BASE>β Base for exponential contour level generation. Mutually exclusive with--interval,--levelsπ«--off,--offset <OFFSET>β Offset to apply to contour levels-p,--polygonizeβ Create polygons instead of lines--group-transactions <GROUP-TRANSACTIONS>β Group n features per transaction (default100 000)
psst β Details for options can be found in gdal raster contour. π
π£ footprint π£
* footprint [OPTIONS]
---------------------
Compute the footprint of a raster dataset. it's the ~outline~ of your data, iconic. π
Options:
--output-layer <OUTPUT-LAYER>β Output layer name (default:footprint)-b,--band <BAND>β Input band(s) (1-based index) [may be repeated]--combine-bands <COMBINE-BANDS>β Defines how the mask bands of the selected bands are combined to generate a single mask band, before being vectorized..COMBINE-BANDS=union|intersection(default:union)--overview <OVERVIEW>β Which overview level of source file must be used. Mutually exclusive with--input-nodataπ«--input-nodata <INPUT-NODATA>β Set nodata values for input bands. [1.. values]. Mutually exclusive with--overviewπ«--coordinate-system <COORDINATE-SYSTEM>β Target coordinate system.COORDINATE-SYSTEM=georeferenced|pixel--output-crs <OUTPUT-CRS>β Output CRS--split-multipolygonsβ Whether to split multipolygons as several features each with one single polygon--convex-hullβ Whether to compute the convex hull of the footprint--densify-distance <DENSIFY-DISTANCE>β Maximum distance between 2 consecutive points of the output geometry.--simplify-tolerance <SIMPLIFY-TOLERANCE>β Tolerance used to merge consecutive points of the output geometry.--min-ring-area <MIN-RING-AREA>β Minimum value for the area of a ring--max-points <MAX-POINTS>β Maximum number of points of each output geometry (default:100)--location-field <LOCATION-FIELD>β Name of the field where the path of the input dataset will be stored. (default:location). Mutually exclusive with--no-location-fieldπ«--no-location-fieldβ Disable creating a field with the path of the input dataset. Mutually exclusive with--location-fieldπ«--absolute-pathβ Whether the path to the input dataset should be stored as an absolute path
pssst β Details for options can be found in gdal raster footprint. πΈ
πΈοΈ grid πΈοΈ
* grid <COMMAND> [OPTIONS]
--------------------------
where <COMMAND> is one of:
average: Create a regular grid from scattered points using moving average interpolation.average-distance: Create a regular grid from scattered points using the average distance between the grid node (center of the search ellipse) and all of the data points in the search ellipse.average-distance-points: Create a regular grid from scattered points using the average distance between the data points in the search ellipse.count: Create a regular grid from scattered points using the number of points in the search ellipse.invdist: Create a regular grid from scattered points using weighted inverse distance interpolation.invdistnn: Create a regular grid from scattered points using weighted inverse distance interpolation nearest neighbour.linear: Create a regular grid from scattered points using linear/barycentric interpolation.maximum: Create a regular grid from scattered points using the maximum value in the search ellipse.minimum: Create a regular grid from scattered points using the minimum value in the search ellipse.nearest: Create a regular grid from scattered points using nearest neighbor interpolation.range: Create a regular grid from scattered points using the difference between the minimum and maximum values in the search ellipse.
like, eleven flavours of "turn scattered points into a grid", each one a different lil algorithm π§β¨
Details for options can be found in gdal vector grid. π
π pixel-info π
* pixel-info [OPTIONS] <INPUT> [<POSITION-DATASET>]
---------------------------------------------------
Return information on a pixel of a raster dataset. nosy but make it GIS. π
Positional arguments:
-i,--dataset,--input <INPUT>β Input raster datasets [required] β οΈ--position-dataset <POSITION-DATASET>β Vector dataset with coordinates. Mutually exclusive with--positionπ«
Options:
-l,--layer,--input-layer <INPUT-LAYER>β Input layer name-b,--band <BAND>β Input band(s) (1-based index) [may be repeated]--overview <OVERVIEW>β Which overview level of source file must be used-p,--pos,--position <column,line> or <X,Y>β Pixel position [may be repeated]. Mutually exclusive with--position-datasetπ«--position-crs <POSITION-CRS>β CRS of position (default is'pixel'if'position-dataset'not specified)-r,--resampling <RESAMPLING>β Resampling algorithm for interpolation.RESAMPLING=nearest|bilinear|cubic|cubicspline(default:nearest)--promote-pixel-value-to-zβ Whether to set the pixel value as Z component of GeoJSON geometry--include-field <INCLUDE-FIELD>β Fields from coordinate dataset to include in output (special values:ALLandNONE) (default:ALL) [may be repeated]
Details for options can be found in gdal raster pixel-info. π
⬑ polygonize ⬑
* polygonize [OPTIONS]
----------------------
Create a polygon feature dataset from a raster band.
β¦and that's where part 1 leaves us, bestie β the rest of polygonize is coming right up in part 2. don't go anywhere. π
Options for this one, bestie β go wild:
--output-layer <OUTPUT-LAYER>β what you want the output layer to be called π-b,--band <BAND>β which input band we're reading,1-based index, and yeah it defaults to1--attribute-name <ATTRIBUTE-NAME>β the field name that holds the pixel value, defaults toDNβ¨-c,--connect-diagonal-pixelsβ treat diagonal pixels as connected (iykyk, this changes everything)
Details for options can be found in gdal raster polygonize.
π rasterize π
rasterize [OPTIONS]
Burns vector geometries into a raster. Literally just stamps your shapes onto pixels π₯
Options:
-b,--band <BAND>β the band(s) you're burning values into,1-based index [may be repeated]--invertβ invert the rasterization--all-touchedβ turns on theALL_TOUCHEDrasterization option--burn <BURN>β the burn value [may be repeated]-a,--attribute-name <ATTRIBUTE-NAME>β attribute name--3dβ says a burn value should be pulled out of the feature's Z values-l,--input-layer <INPUT-LAYER>β input layer name. Mutually exclusive with--sqlπ«--where <WHERE>β SQL where clause--sql <SQL>β SQL select statement. Mutually exclusive with--input-layerπ«--dialect <DIALECT>β SQL dialect--nodata <NODATA>β assign a specified nodata value to the output bands--init <INIT>β pre-initialize output bands with the specified value [may be repeated]--crs <CRS>β override the projection for the output file--transformer-option <NAME>=<VALUE>β set a transformer option suitable to pass toGDALCreateGenImgProjTransformer2[may be repeated]--extent <xmin>,<ymin>,<xmax>,<ymax>β set the target georeferenced extent [4 values]--resolution <xres>,<yres>β set the target resolution [2 values]. Mutually exclusive with--sizeπ«--tap,--target-aligned-pixelsβ (target aligned pixels) align the coordinates of the extent of the output file to the values of the resolution. This one depends on--resolution--size <xsize>,<ysize>β set the target size in pixels and lines [2 values]. Mutually exclusive with--resolutionπ«--ot,--datatype,--output-data-type <OUTPUT-DATA-TYPE>β output data type.OUTPUT-DATA-TYPE=UInt8|Int8|UInt16|Int16|UInt32|Int32|UInt64|Int64|CInt16|CInt32|Float16|Float32|Float64|CFloat32|CFloat64--optimization <OPTIMIZATION>β force which algorithm gets used (and yes, the results are identical either way).OPTIMIZATION=AUTO|RASTER|VECTOR(default:AUTO)
Details for options can be found in gdal vector rasterize.
π¦ tee π¦
tee [OPTIONS] [<PIPELINE>...]
Pipes the input into the output stream and side nested pipelines. Like a lil splitter, bestie π
Positional arguments:
--tee-pipeline <PIPELINE>β nested pipeline [1.. values]
Details for options can be found in Output nested pipeline.
π GDALG OUTPUT (ON-THE-FLY / STREAMED DATASET) π
Okay so a pipeline can be serialized as a JSON file using the GDALG output format. That file can then be opened as a dataset with the GDALG: GDAL Streamed Algorithm driver β and it'll apply the specified pipeline in an on-the-fly / streamed way β¨
The command_line member of the JSON file should nominally be the whole command line without the final write step, and it's what you get generated by gdal pipeline ! .... ! write out.gdalg.json.
{
"type": "gdal_streamed_alg",
"command_line": "gdal pipeline ! read in.tif ! footprint ! buffer 20"
}
You can add the final write step, but if you do it must explicitly specify the stream output format and a non-significant output dataset name. No skipping that, fr fr.
{
"type": "gdal_streamed_alg",
"command_line": "gdal pipeline ! read in.tif ! footprint ! buffer 20 ! write --output-format=streamed streamed_dataset"
}
β SUBSTITUTIONS β
You can also use gdal pipeline to run a pipeline that's already serialized in a .gdalg.json file, and customize its existing steps β usually swapping an input filename, specifying an output filename, or adding/modifying arguments of steps. Chef's kiss π
The syntax is:
gdal pipeline <filename.gdalg.json> --<step-name>.<arg-name>=value
When you specify an existing argument of a step of a pipeline, the value from the pipeline gets overridden by the one you put on the gdal pipeline command line. Simple as that π
Let's imagine we have a raster_reproject.gdalg.json with the following content:
{
"type": "gdal_streamed_alg",
"command_line": "gdal pipeline ! read in.tif ! reproject --output-crs=EPSG:4326 ! edit --metadata=CHANGES=reprojected"
}
You can run it with this command line, overriding the input argument of the read step, and implicitly adding a final write step with an output argument:
$ gdal pipeline raster_reproject.gdalg.json --read.input=other_input.tif --write.output=out.tif
When there's no ambiguity, you can also just omit the step name and specify only the argument name. And if there is an ambiguity, gdal pipeline will emit an error β so this is safe to do π«Ά
$ gdal pipeline raster_reproject.gdalg.json --input=other_input.tif --output=out.tif --co COMPRESS=LZW --overwrite
When a step shows up several times in the pipeline, you must specify it as <step-name>[<idx>], where <idx> is a zero-based index.
For example, given:
{
"type": "gdal_streamed_alg",
"command_line": "gdal pipeline ! read in.tif ! edit --metadata=before=value ! reproject --output-crs=EPSG:4326 ! edit --metadata=CHANGES=reprojected"
}
the following command line may be used:
$ gdal pipeline raster_reproject.gdalg.json --edit[0].metadata=before=modified --output=out.tif
Execution of pipelines and argument substitutions can also be done in Python with:
gdal.Run("pipeline", pipeline="raster_reproject.gdalg.json", output="out.tif", arguments={"edit[0].metadata": "before=modified"})
πΈ PLACEHOLDER DATASET NAME _PIPE_ πΈ
Added in version 3.13. π
By default, in a pipeline step that accepts multiple input dataset arguments, the first positional argument, input, is implicitly set to the output dataset from the previous step. But sometimes you want to pipe the output dataset from the previous step into one of the other input dataset arguments instead. Mood, honestly.
You do that by using the placeholder dataset name _PIPE_ (that's PIPE with a leading and trailing underscore character) as the value for the alternate dataset argument, while explicitly specifying the input positional dataset argument π«
π Example 2: Summarize mean elevation within 200m of points of interest π
gdal pipeline read points.geojson ! buffer 200 ! \
zonal-stats \
--input dem.tif
--zones _PIPE_ \
--stat mean ! \
write \
--output-format CSV \
--output /vsistdout/
You can also get the exact same result by using an input nested pipeline, which is described right below π
π§ NESTED PIPELINE π§
Yes bestie, pipelines inside pipelines. It's giving inception π
A nested pipeline is delimited by square brackets ([ and ]) surrounded by a space character.
There are 2 kinds of nested pipelines:
- input nested pipelines: where the result dataset of the nested pipeline is used as the input dataset for an argument of the main pipeline.
- output nested pipelines: where the output of a step of the main pipeline is used as the input of the nested pipeline in a following step. Output nested pipelines can only be used with the
teestep.
π Input nested pipeline
Wherever an input dataset is expected as an auxiliary dataset, you can specify it as the result of a nested pipeline. The content of an input nested pipeline is identical to the outer pipeline, except it must not end with an output-generating step like info, tile or write π«
π Example 3: Combine the output of shaded relief map and hypsometric rendering on a DEM to create a colorized shaded relief map.
$ gdal pipeline read n43.tif ! \
color-map --color-map color_file.txt ! \
blend --operator=hsv-value --overlay \
[ read n43.tif ! hillshade -z 30 ] ! \
write out.tif --overwrite
In the above example, the value of the overlay argument of the blend step is set as the output of the nested pipeline read n43.tif ! hillshade -z 30. [image]
π Output nested pipeline
The tee step in a pipeline forwards the input dataset as its output, and additionally executes one or several nested pipelines that take this input dataset as input and do other processing to eventually write the output of that processing. The first step of a tee output nested pipeline must not be read, calc, concat, mosaic or stack, and its last step must be write or tile. The tee operator can be used either in the middle of a pipeline or as its last step π«Ά
The below example shows an example where the tee operator executes two output nested pipelines.
π Example 4: Split the content of a "cities" layer according to whether its population is below or above 1 million.
$ gdal pipeline read cities.gpkg ! \
tee [ filter --where "pop < 1e6" ! write small_cities.gpkg ] \
[ filter --where "pop >= 1e6" ! write big_cities.gpkg ]
The below example shows a more complicated use case, including two occurrences of tee, with one of them being an output nested pipeline inside an input nested pipeline π
π₯ Example 5: Combine the output of shaded relief map and hypsometric rendering on a DEM to create a colorized shaded relief map, and write intermediate hillshade and colorized dataset
$ gdal pipeline read n43.tif ! \
color-map --color-map color_file.txt ! \
tee [ write colored.tif --overwrite ] ! \
blend --operator=hsv-value --overlay \
[ read n43.tif ! hillshade -z 30 ! tee [ write hillshade.tif --overwrite ] ] ! \
write colored-hillshade.tif --overwrite
[image]
π RETURN STATUS CODE π
Okay bestie, here's the vibe check on exit codes:
- The program returns status code 0 when everything went off without a hitch β¨
- It returns a non-zero status code if there was an error π
Important nuance, don't skip this: non-blocking errors that get emitted as warnings are still counted as a successful execution. So like, a warning is not a fail, it's just the program gently going "hey girl, heads up" π«Ά
π EXAMPLES π
Example 6: Compute the footprint of a raster and apply a buffer on the footprint
$ gdal pipeline ! read in.tif ! footprint ! buffer 20 ! write out.gpkg --overwrite
Read the raster, grab its footprint, buffer that bad boy by 20, and yeet it into a GeoPackage. Overwrite the whole thing while you're at it. Iconic behavior honestly π
Example 7: Rasterize and reproject
$ gdal pipeline ! read in.gpkg ! rasterize --size 1000,1000 ! reproject --output-crs EPSG:4326 ! write out.tif --overwrite
Read the GeoPackage β rasterize it at --size 1000,1000 β reproject it to --output-crs EPSG:4326 β write out a GeoTIFF with --overwrite. She does it all in one line, no cap π₯
Example 8: Use an existing pipeline that rasterizes and reprojects, but change its input file and target CRS, and specify the output file
$ gdal pipeline raster_reproject.gdalg.json --input=my.gpkg --output=out.tif --output-crs=EPSG:32631
This one is giving β¨reusabilityβ¨. You've got a saved pipeline raster_reproject.gdalg.json that already knows how to rasterize and reproject, and you just swap out the --input to my.gpkg, point --output at out.tif, and override the target CRS with --output-crs=EPSG:32631. Same pipeline, new fit. Periodt.
Example 9: Buffer a line dataset to create a new polygon dataset
So this example uses a lines.gpkg dataset containing a single layer named lines, with a geometry field named geom and an integer attribute named width. And the value of that width attribute? It gets used as the buffer distance for each feature. Chef's kiss π
gdal vector pipeline \
! read lines.gpkg \
! sql "SELECT fid, ST_Buffer(geom, width) AS geom FROM lines" \
! set-geom-type --geometry-type Polygon \
! write buffered-lines.gpkg --output-layer=BufferedLines --overwrite --overwrite-layer
Read the lines β run that sql to buffer each geometry by its own width β set-geom-type --geometry-type Polygon because buffered lines are polygons now duh π¦ β and write it all out to the layer BufferedLines inside buffered-lines.gpkg, with --overwrite --overwrite-layer because we are not here to be precious about old files.
π¨ NOTE π¨
When you're creating derived geometries using SQL, avoid using SELECT *. Like, seriously bestie. Including the original geometry field will result in multiple geometry columns in the output, and that is not the slay you think it is π Instead, explicitly list the required attributes and return a single geometry column. That's the move. π
π AUTHOR π
Even Rouault <even.rouault@spatialys.com>
π COPYRIGHT π
1998-2026
And that's the whole page bestie, we ate and left no crumbs π shoutout to the source/version and date on this one β it's the manual page GDAL-PIPELINE(1), dated Aug 18, 2026 (yep, she's from the future, main character energy fr fr πΈβ¨). Go build something iconic with your pipelines π«Άπ
π¦ where this page comes from
- alpine 3.24: gdal-doc 3.13.3-r0 Β· MIT
- arch rolling: gdal 3.13.3-6 Β· MIT
- ubuntu stonking: gdal-bin 3.13.3+dfsg-1ubuntu4 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms