Skip to content

Commit

Permalink
Fixing the list of available warp names.
Browse files Browse the repository at this point in the history
gdal.WarpOptions in GDAL < 3.4 did not handle all supported gdal.GRA_*
resampling options, instead using the incomplete set of options under
gdal.GRIORA_*.  This was fixed in GDAL 3.4.  The change introduced in
this commit handles both approaches to interpreting the resample
algorithm names available with this rough algorithm:

1. If gdal.WarpOptions() handles the name, use that.
2. Otherwise (if the name is unknown because of the gdal.GRIORA_* issue
   or if a shorthand is used instead, like '-rb' instead of '-r
   bilinear'), interpret the name from the GRA_* attribute name.

Testing this solution on my computer works on GDAL < 3.4 (3.3 tested)
and also on GDAL >= 3.4 (3.7 tested).

RE:natcap#326
  • Loading branch information
phargogh committed Aug 27, 2023
1 parent 16a84ce commit 0ceaf79
Showing 1 changed file with 38 additions and 8 deletions.
46 changes: 38 additions & 8 deletions src/pygeoprocessing/geoprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
import pprint
import queue
import re
import shutil
import sys
import tempfile
Expand Down Expand Up @@ -81,17 +82,46 @@ def __init__(self, missing_values, raster_path, value_map):
gdal.GDT_CFloat64: numpy.complex64,
}

# GDAL's python API recognizes certain strings but the only way to retrieve
# those strings is to do this conversion of gdalconst.GRA_* types to the
# human-readable labels via gdal.WarpOptions like so.
_GDAL_WARP_ALGORITHMS = []
for _warp_algo in (_attrname for _attrname in dir(gdalconst)
if _attrname.startswith('GRA_')):
# Appends ['-r', 'near'] to _GDAL_WARP_ALGORITHMS if _warp_algo is
# gdalconst.GRA_NearestNeighbor. See gdal.WarpOptions for the dict
# defining this mapping.
gdal.WarpOptions(options=_GDAL_WARP_ALGORITHMS,
resampleAlg=getattr(gdalconst, _warp_algo))
# In GDAL < 3.4, the options used were actually gdal.GRIORA_*
# instead of gdal.GRA_*, and gdal.WarpOptions would:
# * return an integer for any gdal.GRIORA options it didn't recognize
# * Return an abbreviated string (e.g. -rb instead of 'bilinear') for
# several warp algorithms
# This behavior was changed in GDAL 3.4, where the correct name is
# returned in all cases.
#
# In GDAL < 3.4, an error would be logged if GDAL couldn't recognize the
# option. Pushing a null error handler avoids this and cleans up the
# logging.
gdal.PushErrorHandler(lambda *args: None)
_options = []
# GDAL's python bindings only offer this one way of translating gdal.GRA_*
# options to their string names (but compatibility is limited in different
# GDAL versions, see notes above)
warp_opts = gdal.WarpOptions(
options=_options, # Add rendered flags to this list.
resampleAlg=getattr(gdalconst, _warp_algo), # use GRA_* name.
overviewLevel=None) # Don't add overview parameters.
gdal.PopErrorHandler()

for _item in _options:
is_int = False
try:
int(_item)
is_int = True
except ValueError:
pass

if _item == '-r':
continue
elif (_item.startswith('-r') and len(_item) > 2) or is_int:
# (GDAL < 3.4) Translate shorthand params to name.
# (GDAL < 3.4) Translate unrecognized (int) codes to name.
_item = re.sub('^gra_', '', _warp_algo.lower())

_GDAL_WARP_ALGORITHMS = set(_GDAL_WARP_ALGORITHMS)
_GDAL_WARP_ALGORITHMS.discard('-r')
_GDAL_WARP_ALGOS_FOR_HUMAN_EYES = "|".join(_GDAL_WARP_ALGORITHMS)
Expand Down

0 comments on commit 0ceaf79

Please sign in to comment.