GDAL-RASTER-CALC(1)

๐ŸŽ€ gdal-raster-calc(1) โ€” the GDAL manual, bestie edition ๐ŸŽ€

okay so hi ๐Ÿ’– welcome to the GDAL corner of the terminal. this is the page for gdal-raster-calc, and honestly? it's giving math-girl era. pixel-by-pixel math-girl era. let's get into it ๐Ÿงฎโœจ


โœจ NAME โœจ

gdal-raster-calc โ€” Perform pixel-wise calculations on a raster ๐Ÿ’…

Added in version 3.11.

like... every pixel gets math'd. no cap.


๐Ÿซถ SYNOPSIS ๐Ÿซถ

here's the whole shape of the thing:

Usage: gdal raster calc [OPTIONS] <INPUTS>... <OUTPUT>

Perform raster algebra

Positional arguments:
  -i, --input <INPUTS>                                     Input raster datasets [1.. values] [required] [not available in pipelines]
  -o, --output <OUTPUT>                                    Output raster dataset [required] [not available in pipelines]

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]

Options:
  -f, --of, --format, --output-format <OUTPUT-FORMAT>      Output format ("GDALG" allowed) [not available in pipelines]
  --co, --creation-option <KEY>=<VALUE>                    Creation option [may be repeated] [not available in pipelines]
  --overwrite                                              Whether overwriting existing output dataset is allowed [not available in pipelines]
                                                           Mutually exclusive with --append
  --append                                                 Append as a subdataset to existing output [not available in pipelines]
                                                           Mutually exclusive with --overwrite
  --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
  --no-check-crs                                           Do not check consistency of input coordinate reference systems
  --no-check-extent                                        Do not check consistency of input extents
  --propagate-nodata                                       Whether to set pixels to the output NoData value if any of the input pixels is NoData
  --calc <CALC>                                            Expression(s) to evaluate [1.. values] [required]
  --dialect <DIALECT>                                      Expression dialect. DIALECT=muparser|builtin (default: muparser)
  --flatten                                                Generate a single band output raster per expression, even if input datasets are multiband
  --nodata <NODATA>                                        Assign a specified nodata value to output bands ('none', numeric value, 'nan', 'inf', '-inf')

Advanced Options:
  --if, --input-format <INPUT-FORMAT>                      Input formats [may be repeated] [not available in pipelines]
  --oo, --open-option <KEY>=<VALUE>                        Open options [may be repeated] [not available in pipelines]

quick vibe check on the little tags in there: [required] means you literally cannot skip it, [may be repeated] means stack as many as you want, and [not available in pipelines] means this one sits out when you're chaining things through a pipeline. noted ๐Ÿ“


๐ŸŒธ DESCRIPTION ๐ŸŒธ

gdal raster calc performs pixel-wise calculations on one or more input GDAL datasets. and it can do that two ways, bestie: eagerly, writing results to a conventional raster format, or lazily, written as a set of derived bands in a VRT (Virtual Dataset). sleepy mode or eager mode, your call ๐Ÿ˜ด๐Ÿ”ฅ

The list of input GDAL datasets can be specified at the end of the command line or put in a text file (one input per line) for very long lists. If more than one input dataset is used, it should be prefixed with a name by which it will be referenced in the calculation, e.g. A=my_data.tif. (If a single dataset is used, it will be referred to with the variable X in formulas.) so like โ€” one raster, you're X. multiple rasters, you gotta give them names or the math can't find them ๐Ÿ™ˆ

Starting with GDAL 3.12, it is also possible to use a VRT C++ pixel function (such a sum, mean, min, max) by specifying --dialect to builtin.

The inputs should have the same spatial reference system and should cover the same spatial extent but are not required to have the same spatial resolution. The spatial extent check can be disabled with --no-check-extent, in which case the inputs must have the same dimensions. The spatial reference system check can be disabled with --no-check-crs. heads up though: turn off the extent check and you're on the hook for same dimensions yourself. don't come for me ๐Ÿ’€

Since GDAL 3.12, this algorithm can be part of a gdal pipeline or gdal raster pipeline. slay, it's pipeline-able โœจ


๐Ÿฆ‹ GDALG OUTPUT (ON-THE-FLY / STREAMED DATASET) ๐Ÿฆ‹

This program supports serializing the command line as a JSON file using the GDALG output format. The resulting file can then be opened as a raster dataset using the GDALG: GDAL Streamed Algorithm driver, and apply the specified pipeline in a on-the-fly / streamed way.

basically: you write your whole command down as a little JSON, and later a driver picks it up and re-runs the vibe live. iconic honestly ๐ŸŒˆ


๐Ÿ’… PROGRAM-SPECIFIC OPTIONS ๐Ÿ’…

๐Ÿ’– --calc ๐Ÿ’–

An expression to be evaluated using the muparser math parser library. The expression may refer to individual bands of each input (e.g., X[1] + 3) or it may be applied to all bands of an input (X + 3).

There are two methods by which an expression may be applied to multiple bands. let's do them one by one, bestie:

Method one โ€” the default one. The expression is applied to each band individually, resulting in one output band for each input band. For example, with a three-band input X, the expression --calc "X+3" would be expanded into --calc "X[1]+3" --calc "X[2]+3" --calc "X[3]+3". If the expression contains a reference to all bands of multiple inputs, those inputs must either have the same number of bands, or a single band. For example, if inputs A and B each have three bands, and input C has a single band, then the argument --calc "A + B + C" is equivalent to --calc "A[1] + B[1] + C[1]" --calc "A[2] + B[2] + C[1]" --calc "A[3] + B[3] + C[1]". Similarly, --calc "sum(A,B,C)" would be expanded to --calc "sum(A[1], B[1], C[1]" --calc "sum(A[2], B[2], C[1])" --calc "sum(A[3], B[3], C[1])".

not me pointing out that the first sum( there has a missing closing paren in the source. it is what it is, i'm not editing the canon ๐Ÿ™ˆ

Method two โ€” the one you turn on with --flatten. In this method, aggregate functions (sum, avg, min, and max) invoked on multiple bands will be applied to all bands in aggregate. In this case, sum(A) is expanded into sum(A[1], A[2], A[3]), and sum(A,C) is expanded into sum(A[1], A[2], A[3], C[1]). If the expression consists _only_ of aggregate functions, this will produce a single output band no matter how many input bands are present. However, if the expression contains a non-aggregate reference to all bands of an input, then one output band will still be produced for each input band. A simple example is the expression A / sum(A), which would produce an N-band raster where each output band contains the input band's fraction of the total. that's a whole ratios situation, we love a fraction ๐Ÿ“

Multiple calculations may be specified; output band(s) will be produced for each expression in the order they are provided.

Input rasters will be converted to 64-bit floating point numbers before performing calculations.

Starting with GDAL 3.12, it is also possible to use a VRT C++ pixel function (such a sum, mean, min, max) by specifying --dialect to builtin. Arguments to functions are passed within parentheses, like sum(k=1), min(propagateNoData=true) or interpolate_linear(t0=1,dt=1,t=10).

๐ŸŒŸ Built-in variables ๐ŸŒŸ

The following built-in variables are available in expressions:

  • _CENTER_X_: X coordinate of the pixel center, expressed in the dataset CRS
  • _CENTER_Y_: Y coordinate of the pixel center, expressed in the dataset CRS
  • NODATA: The output NoData value, if any.

These variables are useful for calculations that depend on spatial position, such as latitude-based corrections, solar angle approximations, or zonal masks.

See Example 7 for a usage example.

Note: To work with longitude/latitude values, the input dataset must be in a geographic coordinate reference system (for example, EPSG:4326).

๐Ÿ’œ --dialect muparser|builtin ๐Ÿ’œ

Added in version 3.12.

Specify the expression engine used to interpret the value of --calc. The default is muparser.

๐Ÿฆ„ --flatten ๐Ÿฆ„

Added in version 3.12.

Generate a single band output raster per expression, even if input datasets are multiband.

For the default muparser dialect, using the name of an input raster (let's say A) is equivalent to A[1],A[2],...,A[n]. Such syntax works with the min, max, sum and avg muparser functions.

For example, let's consider 2 rasters A and B with 3bands each, then --flatten --calc "avg(A)-avg(B)" is equivalent to --calc "avg(A[1],A[2],A[3])-avg(B[1],B[2],B[3])"

And --flatten --dialect=builtin --calc mean will compute a single band with the average of all 4 input bands.

๐ŸŽ€ -i [<name>=]<input> ๐ŸŽ€

Select an input dataset to be processed. If more than one input dataset is provided, each dataset must be prefixed with a name to which it will will be referenced in --calc.

๐ŸŒˆ --no-check-extent ๐ŸŒˆ

Do not verify that the input rasters have the same spatial extent. The input rasters will instead be required to have the same dimensions. The geotransform of the first input will be assigned to the output.

read that twice: dimensions have to match instead, and the FIRST input's geotransform gets handed to the output. no takebacks.

๐Ÿฉต --no-check-crs ๐Ÿฉต

Do not check the spatial reference systems of the inputs for consistency. All inputs will be assumed to have the spatial reference system of the first input, and this spatial reference system will be used for the output.

โญ --nodata โญ

Added in version 3.12.

Set the NoData value for the output dataset. May be set to "none" to leave the NoData value undefined. If --nodata is not specified, gdal raster calc will use a NoData value from the first source dataset to have one.

๐Ÿซง --propagate-nodata ๐Ÿซง

Added in version 3.12.

If set, a NoData value in any input dataset used an in expression will cause the output value to be NoData.

one shy pixel of NoData anywhere in that expression and boom, the whole output pixel is NoData. contagious behavior, honestly ๐Ÿ’€

still with me? good, because there's more where that came from ๐Ÿงš๐Ÿ’–

โœจ STANDARD OPTIONS โœจ

These are the classics โ€” they show up in basically every GDAL program, and they're giving main character energy in this one too ๐Ÿ’…

  • --append โ€” Slap your input raster onto an existing output file as a brand new subdataset. Only works with drivers that are down to add subdatasets, like GTiff -- GeoTIFF File Format and GPKG -- GeoPackage raster. Oh and bonus: if the output dataset doesn't exist yet, this'll just make it for you. Iconic and productive ๐ŸŽ€
  • --co, --creation-option <NAME>=<VALUE> โ€” Lots of formats have optional creation options so you can control the little details of the file you're making โœจ Like the GeoTIFF driver has creation options for compression and for whether the file should be tiled.

May be repeated.

Which creation options exist depends on the format driver, and some lil simple formats have literally none. You can list what a format supports with the --formats command line option, but fr fr the format's own documentation is the definitive source of truth for driver creation options. Go look at Raster drivers format specific documentation for the legal creation options of each format ๐Ÿ‘‘

  • --if, --input-format <format> โ€” The format/driver name you want GDAL to try when opening the input file(s). Usually you don't need this at all, but it's a lifesaver when auto driver detection fumbles the bag and picks the wrong driver ๐Ÿ™ˆ This option can be repeated several times to line up several candidate drivers. Careful though: it doesn't force those drivers to open the dataset โ€” and some drivers are picky about file extensions, so no cap.

May be repeated.

  • --oo, --open-option <NAME>=<VALUE> โ€” Dataset open option (format specific). Basically the --co of reading instead of writing ๐Ÿฆ‹

May be repeated.

  • -f, --of, --format, --output-format <OUTPUT-FORMAT> โ€” Which output raster format to use. Allowed values? You can get them with gdal --formats | grep raster | grep rw | sort โ€” a whole menu, bestie ๐Ÿ“
  • --ot, --datatype, --output-data-type <OUTPUT-DATA-TYPE> โ€” Output data type, one of Byte, Int8, UInt16, Int16, UInt32, Int32, UInt64, Int64, CInt16, CInt32, Float32, Float64, CFloat32, CFloat64. Pick your fighter โœจ
  • --overwrite โ€” Lets the program overwrite an existing target file or dataset. Without it, the default behaviour is that gdal errors out if the target file or dataset already exists. So yeah โ€” no overwrite flag means hands off, bestie. ๐Ÿ’€

๐ŸŒˆ RETURN STATUS CODE ๐ŸŒˆ

The program returns status code 0 in case of success, and non-zero in case of error โ€” but ngl, non-blocking errors that get emitted as warnings still count as a successful execution ๐Ÿซถ So 0 = we ate, non-zero = it's giving error ๐Ÿ’…


๐Ÿ’– EXAMPLES ๐Ÿ’–

Example 1: Per-band sum of three files

gdal raster calc -i "A=file1.tif" -i "B=file2.tif" -i "C=file3.tif" --calc "A+B+C" -o out.tif

Example 2: Per-dataset average of all bands of each dataset

gdal raster calc -i "A=file1.tif" -i "B=file2.tif" -i "C=file3.tif" --flatten --calc "avg(A)" --calc "avg(B)" --calc "avg(C)" -o out.tif

Example 3: Per-band maximum of three files

gdal raster calc -i "A=file1.tif" -i "B=file2.tif" -i "C=file3.tif" --calc "max(A,B,C)" -o out.tif

Example 4: Setting values of zero and below to NaN

gdal raster calc -i "A=input.tif" -o result.tif --calc="A > 0 ? A : NaN"

Example 5: Compute the average (as a single band) of all bands of two input datasets

gdal raster calc -i A=input1.tif -i B=input2.tif -o result.tif --flatten --calc=mean --dialect=builtin

Example 6: Generate a masked aspect layer where the slope angle is greater than 2 degrees, using nested pipelines (since GDAL 3.12.1)

gdal raster calc -i "SLOPE=[ read dem.tif ! slope ]" -i "ASPECT=[ read dem.tif ! aspect ]" -o result.tif --calc "(SLOPE >= 2) ? ASPECT : -9999" --nodata -9999

Nested pipelines inside a calc expression? That's genuinely so much. We love a pipeline moment ๐Ÿงš

Example 7: Latitude-based calculation using _CENTER_Y_

gdal raster calc -i A=input.tif \
    --calc="sin(_CENTER_Y_ * 0.0174533)" \
    -o output.tif

๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

Dan Baston <dbaston@gmail.com>


1998-2026


And that's a wrap on this one, bestie โ€” source is GDAL, dated Aug 18, 2026, page GDAL-RASTER-CALC(1). Go calc something cute ๐Ÿ’–โœจ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from