1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 import sys
33 from osgeo import gdal
34 from osgeo import osr
35
36
38 print('Usage: gdal_edit [--help-general] [-ro] [-a_srs srs_def]')
39 print(' [-a_ullr ulx uly lrx lry] [-a_ulurll ulx uly urx ury llx lly]')
40 print(' [-tr xres yres] [-unsetgt] [-unsetrpc] [-a_nodata value] [-unsetnodata]')
41 print(' [-offset value] [-scale value] [-units value]')
42 print(' [-colorinterp_X red|green|blue|alpha|gray|undefined]*')
43 print(' [-unsetstats] [-stats] [-approx_stats]')
44 print(' [-setstats min max mean stddev]')
45 print(' [-gcp pixel line easting northing [elevation]]*')
46 print(' [-unsetmd] [-oo NAME=VALUE]* [-mo "META-TAG=VALUE"]* datasetname')
47 print('')
48 print('Edit in place various information of an existing GDAL dataset.')
49 return -1
50
51
53 i = 0
54
55 while i < len(s):
56 if (s[i] < '0' or s[i] > '9') and s[i] != '.' and s[i] != 'e' and s[i] != '+' and s[i] != '-':
57 return False
58 i = i + 1
59
60 return True
61
62
64
65 argv = gdal.GeneralCmdLineProcessor(argv)
66 if argv is None:
67 return -1
68
69 datasetname = None
70 srs = None
71 ulx = None
72 uly = None
73 urx = None
74 ury = None
75 llx = None
76 lly = None
77 lrx = None
78 lry = None
79 nodata = None
80 unsetnodata = False
81 units = None
82 xres = None
83 yres = None
84 unsetgt = False
85 unsetstats = False
86 stats = False
87 setstats = False
88 approx_stats = False
89 unsetmd = False
90 ro = False
91 molist = []
92 gcp_list = []
93 open_options = []
94 offset = []
95 scale = []
96 colorinterp = {}
97 unsetrpc = False
98
99 i = 1
100 argc = len(argv)
101 while i < argc:
102 if argv[i] == '-ro':
103 ro = True
104 elif argv[i] == '-a_srs' and i < len(argv) - 1:
105 srs = argv[i + 1]
106 i = i + 1
107 elif argv[i] == '-a_ullr' and i < len(argv) - 4:
108 ulx = float(argv[i + 1])
109 i = i + 1
110 uly = float(argv[i + 1])
111 i = i + 1
112 lrx = float(argv[i + 1])
113 i = i + 1
114 lry = float(argv[i + 1])
115 i = i + 1
116 elif argv[i] == '-a_ulurll' and i < len(argv) - 6:
117 ulx = float(argv[i + 1])
118 i = i + 1
119 uly = float(argv[i + 1])
120 i = i + 1
121 urx = float(argv[i + 1])
122 i = i + 1
123 ury = float(argv[i + 1])
124 i = i + 1
125 llx = float(argv[i + 1])
126 i = i + 1
127 lly = float(argv[i + 1])
128 i = i + 1
129 elif argv[i] == '-tr' and i < len(argv) - 2:
130 xres = float(argv[i + 1])
131 i = i + 1
132 yres = float(argv[i + 1])
133 i = i + 1
134 elif argv[i] == '-a_nodata' and i < len(argv) - 1:
135 nodata = float(argv[i + 1])
136 i = i + 1
137 elif argv[i] == '-scale' and i < len(argv) :
138 scale.append(float(argv[i+1]))
139 i = i + 1
140 while i < len(argv) - 1 and ArgIsNumeric(argv[i+1]):
141 scale.append(float(argv[i+1]))
142 i = i + 1
143 elif argv[i] == '-offset' and i < len(argv) - 1:
144 offset.append(float(argv[i+1]))
145 i = i + 1
146 while i < len(argv) - 1 and ArgIsNumeric(argv[i+1]):
147 offset.append(float(argv[i+1]))
148 i = i + 1
149 elif argv[i] == '-mo' and i < len(argv) - 1:
150 molist.append(argv[i + 1])
151 i = i + 1
152 elif argv[i] == '-gcp' and i + 4 < len(argv):
153 pixel = float(argv[i + 1])
154 i = i + 1
155 line = float(argv[i + 1])
156 i = i + 1
157 x = float(argv[i + 1])
158 i = i + 1
159 y = float(argv[i + 1])
160 i = i + 1
161 if i + 1 < len(argv) and ArgIsNumeric(argv[i + 1]):
162 z = float(argv[i + 1])
163 i = i + 1
164 else:
165 z = 0
166 gcp = gdal.GCP(x, y, z, pixel, line)
167 gcp_list.append(gcp)
168 elif argv[i] == '-unsetgt':
169 unsetgt = True
170 elif argv[i] == '-unsetrpc':
171 unsetrpc = True
172 elif argv[i] == '-unsetstats':
173 unsetstats = True
174 elif argv[i] == '-approx_stats':
175 stats = True
176 approx_stats = True
177 elif argv[i] == '-stats':
178 stats = True
179 elif argv[i] == '-setstats' and i < len(argv)-4:
180 stats = True
181 setstats = True
182 if argv[i + 1] != 'None':
183 statsmin = float(argv[i + 1])
184 else:
185 statsmin = None
186 i = i + 1
187 if argv[i + 1] != 'None':
188 statsmax = float(argv[i + 1])
189 else:
190 statsmax = None
191 i = i + 1
192 if argv[i + 1] != 'None':
193 statsmean = float(argv[i + 1])
194 else:
195 statsmean = None
196 i = i + 1
197 if argv[i + 1] != 'None':
198 statsdev = float(argv[i + 1])
199 else:
200 statsdev = None
201 i = i + 1
202 elif argv[i] == '-units' and i < len(argv) - 1:
203 units = argv[i + 1]
204 i = i + 1
205 elif argv[i] == '-unsetmd':
206 unsetmd = True
207 elif argv[i] == '-unsetnodata':
208 unsetnodata = True
209 elif argv[i] == '-oo' and i < len(argv) - 1:
210 open_options.append(argv[i + 1])
211 i = i + 1
212 elif argv[i].startswith('-colorinterp_')and i < len(argv) - 1:
213 band = int(argv[i][len('-colorinterp_'):])
214 val = argv[i + 1]
215 if val.lower() == 'red':
216 val = gdal.GCI_RedBand
217 elif val.lower() == 'green':
218 val = gdal.GCI_GreenBand
219 elif val.lower() == 'blue':
220 val = gdal.GCI_BlueBand
221 elif val.lower() == 'alpha':
222 val = gdal.GCI_AlphaBand
223 elif val.lower() == 'gray' or val.lower() == 'grey':
224 val = gdal.GCI_GrayIndex
225 elif val.lower() == 'undefined':
226 val = gdal.GCI_Undefined
227 else:
228 sys.stderr.write('Unsupported color interpretation %s.\n' % val +
229 'Only red, green, blue, alpha, gray, undefined are supported.\n')
230 return Usage()
231 colorinterp[band] = val
232 i = i + 1
233 elif argv[i][0] == '-':
234 sys.stderr.write('Unrecognized option : %s\n' % argv[i])
235 return Usage()
236 elif datasetname is None:
237 datasetname = argv[i]
238 else:
239 sys.stderr.write('Unexpected option : %s\n' % argv[i])
240 return Usage()
241
242 i = i + 1
243
244 if datasetname is None:
245 return Usage()
246
247 if (srs is None and lry is None and yres is None and not unsetgt and
248 not unsetstats and not stats and not setstats and nodata is None and
249 not units and not molist and not unsetmd and not gcp_list and
250 not unsetnodata and not colorinterp and
251 scale is None and offset is None and not unsetrpc):
252 print('No option specified')
253 print('')
254 return Usage()
255
256 exclusive_option = 0
257 if lry is not None:
258 exclusive_option = exclusive_option + 1
259 if lly is not None:
260 exclusive_option = exclusive_option + 1
261 if yres is not None:
262 exclusive_option = exclusive_option + 1
263 if unsetgt:
264 exclusive_option = exclusive_option + 1
265 if exclusive_option > 1:
266 print('-a_ullr, -a_ulurll, -tr and -unsetgt options are exclusive.')
267 print('')
268 return Usage()
269
270 if unsetstats and stats:
271 print('-unsetstats and either -stats or -approx_stats options are exclusive.')
272 print('')
273 return Usage()
274
275 if unsetnodata and nodata:
276 print('-unsetnodata and -nodata options are exclusive.')
277 print('')
278 return Usage()
279
280 if open_options is not None:
281 if ro:
282 ds = gdal.OpenEx(datasetname, gdal.OF_RASTER, open_options=open_options)
283 else:
284 ds = gdal.OpenEx(datasetname, gdal.OF_RASTER | gdal.OF_UPDATE, open_options=open_options)
285
286 elif ro:
287 ds = gdal.Open(datasetname)
288 else:
289 ds = gdal.Open(datasetname, gdal.GA_Update)
290 if ds is None:
291 return -1
292
293 if scale:
294 if len(scale) == 1:
295 scale = scale * ds.RasterCount
296 elif len(scale) != ds.RasterCount:
297 print('If more than one scale value is provided, their number must match the number of bands.')
298 print('')
299 return Usage()
300
301 if offset:
302 if len(offset) == 1:
303 offset = offset * ds.RasterCount
304 elif len(offset) != ds.RasterCount:
305 print('If more than one offset value is provided, their number must match the number of bands.')
306 print('')
307 return Usage()
308
309 wkt = None
310 if srs == '' or srs == 'None':
311 ds.SetProjection('')
312 elif srs is not None:
313 sr = osr.SpatialReference()
314 if sr.SetFromUserInput(srs) != 0:
315 print('Failed to process SRS definition: %s' % srs)
316 return -1
317 wkt = sr.ExportToWkt()
318 if not gcp_list:
319 ds.SetProjection(wkt)
320
321 if lry is not None:
322 gt = [ulx, (lrx - ulx) / ds.RasterXSize, 0,
323 uly, 0, (lry - uly) / ds.RasterYSize]
324 ds.SetGeoTransform(gt)
325
326 elif lly is not None:
327 gt = [ulx, (urx - ulx) / ds.RasterXSize, (llx - ulx) / ds.RasterYSize,
328 uly, (ury - uly) / ds.RasterXSize, (lly - uly) / ds.RasterYSize]
329 ds.SetGeoTransform(gt)
330
331 if yres is not None:
332 gt = ds.GetGeoTransform()
333
334 gt = [gt[j] for j in range(6)]
335 gt[1] = xres
336 gt[5] = yres
337 ds.SetGeoTransform(gt)
338
339 if unsetgt:
340
341
342 if ds.GetDriver().ShortName == 'GTiff':
343 ds.SetGeoTransform([0, 0, 0, 0, 0, 0])
344 else:
345 ds.SetGeoTransform([0, 1, 0, 0, 0, 1])
346
347 if gcp_list:
348 if wkt is None:
349 wkt = ds.GetGCPProjection()
350 if wkt is None:
351 wkt = ''
352 ds.SetGCPs(gcp_list, wkt)
353
354 if nodata is not None:
355 for i in range(ds.RasterCount):
356 ds.GetRasterBand(i + 1).SetNoDataValue(nodata)
357 elif unsetnodata:
358 for i in range(ds.RasterCount):
359 ds.GetRasterBand(i + 1).DeleteNoDataValue()
360
361 if scale:
362 for i in range(ds.RasterCount):
363 ds.GetRasterBand(i + 1).SetScale(scale[i])
364
365 if offset:
366 for i in range(ds.RasterCount):
367 ds.GetRasterBand(i + 1).SetOffset(offset[i])
368
369 if units:
370 for i in range(ds.RasterCount):
371 ds.GetRasterBand(i + 1).SetUnitType(units)
372
373 if unsetstats:
374 for i in range(ds.RasterCount):
375 band = ds.GetRasterBand(i + 1)
376 for key in band.GetMetadata().keys():
377 if key.startswith('STATISTICS_'):
378 band.SetMetadataItem(key, None)
379
380 if stats:
381 for i in range(ds.RasterCount):
382 ds.GetRasterBand(i + 1).ComputeStatistics(approx_stats)
383
384 if setstats:
385 for i in range(ds.RasterCount):
386 if statsmin is None or statsmax is None or statsmean is None or statsdev is None:
387 ds.GetRasterBand(i+1).ComputeStatistics(approx_stats)
388 min,max,mean,stdev = ds.GetRasterBand(i+1).GetStatistics(approx_stats,True)
389 if statsmin is None:
390 statsmin = min
391 if statsmax is None:
392 statsmax = max
393 if statsmean is None:
394 statsmean = mean
395 if statsdev is None:
396 statsdev = stdev
397 ds.GetRasterBand(i+1).SetStatistics(statsmin, statsmax, statsmean, statsdev)
398
399 if molist:
400 if unsetmd:
401 md = {}
402 else:
403 md = ds.GetMetadata()
404 for moitem in molist:
405 equal_pos = moitem.find('=')
406 if equal_pos > 0:
407 md[moitem[0:equal_pos]] = moitem[equal_pos + 1:]
408 ds.SetMetadata(md)
409 elif unsetmd:
410 ds.SetMetadata({})
411
412 for band in colorinterp:
413 ds.GetRasterBand(band).SetColorInterpretation(colorinterp[band])
414
415 if unsetrpc:
416 ds.SetMetadata(None, 'RPC')
417
418 ds = band = None
419
420 return 0
421
422
424 return gdal_edit(argv)
425
426
427 if __name__ == '__main__':
428 sys.exit(main(sys.argv))
429