Package osgeo :: Package utils :: Module gdalcompare
[hide private]
[frames] | no frames]

Source Code for Module osgeo.utils.gdalcompare

  1  #!/usr/bin/env python3 
  2  # -*- coding: utf-8 -*- 
  3  # ****************************************************************************** 
  4  # 
  5  #  Project:  GDAL 
  6  #  Purpose:  Compare two files for differences and report. 
  7  #  Author:   Frank Warmerdam, warmerdam@pobox.com 
  8  # 
  9  # ****************************************************************************** 
 10  #  Copyright (c) 2012, Frank Warmerdam <warmerdam@pobox.com> 
 11  # 
 12  #  Permission is hereby granted, free of charge, to any person obtaining a 
 13  #  copy of this software and associated documentation files (the "Software"), 
 14  #  to deal in the Software without restriction, including without limitation 
 15  #  the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 16  #  and/or sell copies of the Software, and to permit persons to whom the 
 17  #  Software is furnished to do so, subject to the following conditions: 
 18  # 
 19  #  The above copyright notice and this permission notice shall be included 
 20  #  in all copies or substantial portions of the Software. 
 21  # 
 22  #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 23  #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 24  #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 25  #  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 26  #  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 27  #  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 28  #  DEALINGS IN THE SOFTWARE. 
 29  # ****************************************************************************** 
 30   
 31  import os 
 32  import sys 
 33  import filecmp 
 34   
 35  from osgeo import gdal 
 36  from osgeo import osr 
 37   
 38  ####################################################### 
 39   
 40   
41 -def compare_metadata(golden_md, new_md, ident, options=None):
42 # pylint: disable=unused-argument 43 44 if golden_md is None and new_md is None: 45 return 0 46 47 found_diff = 0 48 49 if len(list(golden_md.keys())) != len(list(new_md.keys())): 50 print('Difference in %s metadata key count' % ident) 51 print(' Golden Keys: ' + str(list(golden_md.keys()))) 52 print(' New Keys: ' + str(list(new_md.keys()))) 53 found_diff += 1 54 55 for key in list(golden_md.keys()): 56 if key not in new_md: 57 print('New %s metadata lacks key \"%s\"' % (ident, key)) 58 found_diff += 1 59 elif new_md[key] != golden_md[key]: 60 print('Metadata value difference for key "' + key + '"') 61 print(' Golden: "' + golden_md[key] + '"') 62 print(' New: "' + new_md[key] + '"') 63 found_diff += 1 64 65 return found_diff
66 67 68 ####################################################### 69 # Review and report on the actual image pixels that differ.
70 -def compare_image_pixels(golden_band, new_band, ident, options=None):
71 # pylint: disable=unused-argument 72 73 diff_count = 0 74 max_diff = 0 75 76 for line in range(golden_band.YSize): 77 golden_line = golden_band.ReadAsArray(0, line, golden_band.XSize, 1)[0] 78 new_line = new_band.ReadAsArray(0, line, golden_band.XSize, 1)[0] 79 diff_line = golden_line.astype(float) - new_line.astype(float) 80 max_diff = max(max_diff, abs(diff_line).max()) 81 diff_count += len(diff_line.nonzero()[0]) 82 83 print(' Pixels Differing: ' + str(diff_count)) 84 print(' Maximum Pixel Difference: ' + str(max_diff))
85 86 ####################################################### 87 88
89 -def compare_band(golden_band, new_band, ident, options=None):
90 found_diff = 0 91 92 options = [] if options is None else options 93 94 if golden_band.DataType != new_band.DataType: 95 print('Band %s pixel types differ.' % ident) 96 print(' Golden: ' + gdal.GetDataTypeName(golden_band.DataType)) 97 print(' New: ' + gdal.GetDataTypeName(new_band.DataType)) 98 found_diff += 1 99 100 if golden_band.GetNoDataValue() != new_band.GetNoDataValue(): 101 print('Band %s nodata values differ.' % ident) 102 print(' Golden: ' + str(golden_band.GetNoDataValue())) 103 print(' New: ' + str(new_band.GetNoDataValue())) 104 found_diff += 1 105 106 if golden_band.GetColorInterpretation() != new_band.GetColorInterpretation(): 107 print('Band %s color interpretation values differ.' % ident) 108 print(' Golden: ' + gdal.GetColorInterpretationName(golden_band.GetColorInterpretation())) 109 print(' New: ' + gdal.GetColorInterpretationName(new_band.GetColorInterpretation())) 110 found_diff += 1 111 112 if golden_band.Checksum() != new_band.Checksum(): 113 print('Band %s checksum difference:' % ident) 114 print(' Golden: ' + str(golden_band.Checksum())) 115 print(' New: ' + str(new_band.Checksum())) 116 found_diff += 1 117 compare_image_pixels(golden_band, new_band, ident, options) 118 119 # Check overviews 120 if golden_band.GetOverviewCount() != new_band.GetOverviewCount(): 121 print('Band %s overview count difference:' % ident) 122 print(' Golden: ' + str(golden_band.GetOverviewCount())) 123 print(' New: ' + str(new_band.GetOverviewCount())) 124 found_diff += 1 125 else: 126 for i in range(golden_band.GetOverviewCount()): 127 found_diff += compare_band(golden_band.GetOverview(i), 128 new_band.GetOverview(i), 129 ident + ' overview ' + str(i), 130 options) 131 132 # Metadata 133 if 'SKIP_METADATA' not in options: 134 found_diff += compare_metadata(golden_band.GetMetadata(), 135 new_band.GetMetadata(), 136 'Band ' + ident, options) 137 138 # Mask band 139 if golden_band.GetMaskFlags() != new_band.GetMaskFlags(): 140 print('Band %s mask flags difference:' % ident) 141 print(' Golden: ' + str(golden_band.GetMaskFlags())) 142 print(' New: ' + str(new_band.GetMaskFlags())) 143 found_diff += 1 144 elif golden_band.GetMaskFlags() in (gdal.GMF_PER_DATASET, 0): 145 found_diff += compare_band(golden_band.GetMaskBand(), 146 new_band.GetMaskBand(), 147 ident + ' mask band', 148 options) 149 150 # TODO: Color Table, gain/bias, units, blocksize, min/max 151 152 return found_diff
153 154 ####################################################### 155 156
157 -def compare_srs(golden_wkt, new_wkt):
158 if golden_wkt == new_wkt: 159 return 0 160 161 print('Difference in SRS!') 162 163 golden_srs = osr.SpatialReference(golden_wkt) 164 new_srs = osr.SpatialReference(new_wkt) 165 166 if golden_srs.IsSame(new_srs): 167 print(' * IsSame() reports them as equivalent.') 168 else: 169 print(' * IsSame() reports them as different.') 170 171 print(' Golden:') 172 print(' ' + golden_srs.ExportToPrettyWkt()) 173 print(' New:') 174 print(' ' + new_srs.ExportToPrettyWkt()) 175 176 return 1
177 178 ####################################################### 179 180
181 -def compare_db(golden_db, new_db, options=None):
182 found_diff = 0 183 184 options = [] if options is None else options 185 186 # SRS 187 if 'SKIP_SRS' not in options: 188 found_diff += compare_srs(golden_db.GetProjection(), 189 new_db.GetProjection()) 190 191 # GeoTransform 192 if 'SKIP_GEOTRANSFORM' not in options: 193 golden_gt = golden_db.GetGeoTransform() 194 new_gt = new_db.GetGeoTransform() 195 if golden_gt != new_gt: 196 print('GeoTransforms Differ:') 197 print(' Golden: ' + str(golden_gt)) 198 print(' New: ' + str(new_gt)) 199 found_diff += 1 200 201 # Metadata 202 if 'SKIP_METADATA' not in options: 203 found_diff += compare_metadata(golden_db.GetMetadata(), 204 new_db.GetMetadata(), 205 'Dataset', options) 206 207 # Bands 208 if golden_db.RasterCount != new_db.RasterCount: 209 print('Band count mismatch (golden=%d, new=%d)' 210 % (golden_db.RasterCount, new_db.RasterCount)) 211 found_diff += 1 212 213 # Dimensions 214 for i in range(golden_db.RasterCount): 215 gSzX = golden_db.GetRasterBand(i + 1).XSize 216 nSzX = new_db.GetRasterBand(i + 1).XSize 217 gSzY = golden_db.GetRasterBand(i + 1).YSize 218 nSzY = new_db.GetRasterBand(i + 1).YSize 219 220 if gSzX != nSzX or gSzY != nSzY: 221 print('Band size mismatch (band=%d golden=[%d,%d], new=[%d,%d])' % 222 (i, gSzX, gSzY, nSzX, nSzY)) 223 found_diff += 1 224 225 # If so-far-so-good, then compare pixels 226 if found_diff == 0: 227 for i in range(golden_db.RasterCount): 228 found_diff += compare_band(golden_db.GetRasterBand(i + 1), 229 new_db.GetRasterBand(i + 1), 230 str(i + 1), 231 options) 232 233 return found_diff
234 235 ####################################################### 236 237
238 -def compare_sds(golden_db, new_db, options=None):
239 found_diff = 0 240 241 options = [] if options is None else options 242 243 golden_sds = golden_db.GetMetadata('SUBDATASETS') 244 new_sds = new_db.GetMetadata('SUBDATASETS') 245 246 count = len(list(golden_sds.keys())) // 2 247 for i in range(count): 248 key = 'SUBDATASET_%d_NAME' % (i + 1) 249 250 sub_golden_db = gdal.Open(golden_sds[key]) 251 sub_new_db = gdal.Open(new_sds[key]) 252 253 sds_diff = compare_db(sub_golden_db, sub_new_db, options) 254 found_diff += sds_diff 255 if sds_diff > 0: 256 print('%d differences found between:\n %s\n %s' 257 % (sds_diff, golden_sds[key], new_sds[key])) 258 259 return found_diff
260 261 ####################################################### 262 263
264 -def find_diff(golden_file, new_file, check_sds=False):
265 # Compare Files 266 found_diff = 0 267 268 # compare raw binary files. 269 try: 270 os.stat(golden_file) 271 272 if not filecmp.cmp(golden_file, new_file): 273 print('Files differ at the binary level.') 274 found_diff += 1 275 except OSError: 276 print('Skipped binary file comparison, golden file not in filesystem.') 277 278 # compare as GDAL Datasets. 279 golden_db = gdal.Open(golden_file) 280 new_db = gdal.Open(new_file) 281 found_diff += compare_db(golden_db, new_db) 282 283 if check_sds: 284 found_diff += compare_sds(golden_db, new_db) 285 286 return found_diff
287 288 ####################################################### 289 290
291 -def Usage():
292 print('Usage: gdalcompare.py [-sds] <golden_file> <new_file>') 293 sys.exit(1)
294 295 ####################################################### 296 # 297 # Mainline 298 # 299 300
301 -def main(argv):
302 # Default GDAL argument parsing. 303 argv = gdal.GeneralCmdLineProcessor(argv) 304 if argv is None: 305 sys.exit(0) 306 307 if len(argv) == 1: 308 Usage() 309 310 # Script argument parsing. 311 golden_file = None 312 new_file = None 313 check_sds = 0 314 315 i = 1 316 while i < len(argv): 317 318 if argv[i] == '-sds': 319 check_sds = 1 320 321 elif golden_file is None: 322 golden_file = argv[i] 323 324 elif new_file is None: 325 new_file = argv[i] 326 327 else: 328 print('Unrecognised argument: ' + argv[i]) 329 Usage() 330 331 i = i + 1 332 # next argument 333 334 found_diff = find_diff(golden_file, new_file, check_sds) 335 print('Differences Found: ' + str(found_diff)) 336 sys.exit(found_diff)
337 338 339 if __name__ == '__main__': 340 sys.exit(main(sys.argv)) 341