Gdal_calc manual
Gdal_calc is introduced as :
gdal_calc.py - Command line raster calculator with numpy syntax
gdal_calc.py [-A <filename>] [--A_band] [-B...-Z filename] [other_options]
OPTIONS:
--calc=CALC calculation in gdalnumeric syntax using +-/* or any
numpy array functions (i.e. logical_and())
DESCRIPTION
Command line raster calculator with numpy syntax. Use any basic arithmetic
supported by numpy arrays such as +-*/ along with logical operators such as >.
EXAMPLE
add two files together
gdal_calc.py -A input1.tif -B input2.tif --outfile=result.tif --calc="A+B"
average of two layers
gdal_calc.py -A input.tif -B input2.tif --outfile=result.tif --calc="(A+B)/2"`
set values of zero and below to null
gdal_calc.py -A input.tif --outfile=result.tif --calc="A*(A>0)" --NoDataValue=0
Unexpected results
I made some good uses of gdal_calc in the past, yet, recent results makes no sences to me. I have 3 input files hillshades_A.tmp.tif, hillshades_B.tmp.tif, hillshades_C.tmp.tif and one output composite.tif. I want to make calculations with these inputs. I will follow pixel x=10 y=10 with values are A=222, B=220, C=224 to check the correctness of the output. Let's start.
Example:
# ASSIGN VALUE. Expect: 300.
$gdal_calc.py -A ./hillshades_A.tmp.tif --outfile=./composite.tif \
--calc="300" --NoDataValue=-1
$gdallocationinfo ./composite.tif 10 10 -valonly
>255 # Ergh? Ok, as it's a grey scale [0-255], such auto-correction is ok
Then the fun start !
# SUM: A+B or (A+B), when A=222, B=220. Expect: 442 or 255.
gdal_calc.py -A hillshades_A.tmp.tif -B hillshades_B.tmp.tif --outfile=./composite.tif \
--calc="(A+B)" --NoDataValue=-1
$gdallocationinfo ./composite.tif 10 10 -valonly
>186 # Ergh? This is A+B-256=442-256=186
# AVERAGE: (A+B)/2, when A=222, B=220. Expect: 221 or 255.
gdal_calc.py -A hillshades_A.tmp.tif -B hillshades_B.tmp.tif --outfile=./composite.tif \
--calc="(A+B)/2" --NoDataValue=-1
$gdallocationinfo ./composite.tif 10 10 -valonly
>93 # Ergh? ok, per previous 186/2=93.
# must use (A/2)+(B/2) => 221
# MULTIPLY: A*B, when A=222, B=220. Expect: 48840 or 255
gdal_calc.py -A hillshades_A.tmp.tif -B hillshades_B.tmp.tif --outfile=./composite.tif \
--calc="A*B" --NoDataValue=-1
$gdallocationinfo ./composite.tif 10 10 -valonly
>200 # Ergh? ok, it's modulo: 222*220 % 256=200
# MULTIPLY+SCALE BACK: A*B/255, when A=222, B=220. Expect: 191.5 rounded to 191 or 192.
gdal_calc.py -A hillshades_A.tmp.tif -B hillshades_B.tmp.tif --outfile=./composite.tif \
--calc="A*B/255" --NoDataValue=-1
$gdallocationinfo ./composite.tif 10 10 -valonly
>0 # Ergh? Maybe A*B/255=200/255 (per previous point) being <0 it get rounded to 0 firt. It confirms: Ergh?
And I may go again and yet again. These are not simple basic arithmetic [...] such as +-*/ .
Question
How does gdal_calc operators works ? and... Is there a comprehensive manual for this gdal_calc / numppy syntaxes equations ? (I didn't find any solid one via google)
EDIT: may this behavior be the byproduct of [0-255] greyscale hillshade as input.
$gdalinfo ./hillshades_A.tmp.tif -mm
Driver: GTiff/GeoTIFF
Files: ./hillshades_A.tmp.tif
Size is 1920, 1950
Coordinate System is `'
Origin = (66.991666666666674,37.508333333333354)
Pixel Size = (0.016666666666667,-0.016666666666667)
Image Structure Metadata:
INTERLEAVE=BAND
Corner Coordinates:
Upper Left ( 66.9916667, 37.5083333)
Lower Left ( 66.9916667, 5.0083333)
Upper Right ( 98.9916667, 37.5083333)
Lower Right ( 98.9916667, 5.0083333)
Center ( 82.9916667, 21.2583333)
Band 1 Block=1920x4 Type=Byte, ColorInterp=Gray
Computed Min/Max=1.000,255.000
NoData Value=0
Gdal_calc's numpy seems to have more operators :
+ addition
- subtraction
/ division
* multiplication
= equals to
< less than
> larger than
! not equal to
? if clause
M maximum of two values
m minimum of two values
B bit level operator
I haven't found clear and proper examples for how the exotic operators should be used. If you have something, feel free to share.
Byte? Can you reproduce the same errors when you change your inputs toFloat? – Kersten May 13 '15 at 11:04gdal_translate -ot {Byte|Flot32|Float64}should be the easiest way to change the datatype. Depending on you input you might also need the-a_nodataparameter. – Kersten May 18 '15 at 07:42