wms_gdal_drv.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. """!
  2. @brief GDAL WMS driver.
  3. List of classes:
  4. - wms_drv::NullDevice
  5. - wms_drv::WMSGdalDrv
  6. (C) 2012-2021 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. @author Stepan Turek <stepan.turek seznam.cz> (Mentor: Martin Landa)
  10. """
  11. import os
  12. import grass.script as grass
  13. try:
  14. from osgeo import gdal
  15. from osgeo import gdalconst
  16. except:
  17. grass.fatal(_("Unable to load GDAL Python bindings (requires package 'python-gdal' being installed)"))
  18. import xml.etree.ElementTree as etree
  19. from wms_base import WMSBase, GetSRSParamVal
  20. class NullDevice():
  21. def write(self, s):
  22. pass
  23. class WMSGdalDrv(WMSBase):
  24. def __init__(self, createopt):
  25. super(WMSGdalDrv, self).__init__()
  26. self.proxy = None
  27. self.proxy_user_pw = None
  28. self.createopt = createopt
  29. def setProxy(self, proxy, proxy_user_pw=None):
  30. """ Set the HTTP proxy and its user and password
  31. @input proxy HTTP proxy with [IP address]:[port]
  32. @input proxy_user_pw with [user name]:[password]
  33. """
  34. self.proxy = proxy
  35. self.proxy_user_pw = proxy_user_pw
  36. def _createXML(self):
  37. """!Create XML for GDAL WMS driver
  38. @return path to XML file
  39. """
  40. self._debug("_createXML", "started")
  41. gdal_wms = etree.Element("GDAL_WMS")
  42. service = etree.SubElement(gdal_wms, "Service")
  43. name = etree.Element("name")
  44. service.set("name", "WMS")
  45. version = etree.SubElement(service, "Version")
  46. version.text = self.params['wms_version']
  47. server_url = etree.SubElement(service, "ServerUrl")
  48. server_url.text = self.params['url']
  49. srs = etree.SubElement(service, self.params['proj_name'])
  50. srs.text = GetSRSParamVal(self.params['srs'])
  51. image_format = etree.SubElement(service, "ImageFormat")
  52. image_format.text = self.params['format']
  53. image_format = etree.SubElement(service, "Transparent")
  54. image_format.text = self.params['transparent']
  55. layers = etree.SubElement(service, "Layers")
  56. layers.text = self.params['layers']
  57. styles = etree.SubElement(service, "Styles")
  58. styles.text = self.params['styles']
  59. data_window = etree.SubElement(gdal_wms, "DataWindow")
  60. upper_left_x = etree.SubElement(data_window, "UpperLeftX")
  61. upper_left_x.text = str(self.bbox['minx'])
  62. upper_left_y = etree.SubElement(data_window, "UpperLeftY")
  63. upper_left_y.text = str(self.bbox['maxy'])
  64. lower_right_x = etree.SubElement(data_window, "LowerRightX")
  65. lower_right_x.text = str(self.bbox['maxx'])
  66. lower_right_y = etree.SubElement(data_window, "LowerRightY")
  67. lower_right_y.text = str(self.bbox['miny'])
  68. size_x = etree.SubElement(data_window, "SizeX")
  69. size_x.text = str(self.region['cols'])
  70. size_y = etree.SubElement(data_window, "SizeY")
  71. size_y.text = str(self.region['rows'])
  72. # RGB + alpha
  73. self.temp_map_bands_num = 4
  74. block_size_x = etree.SubElement(gdal_wms, "BandsCount")
  75. block_size_x.text = str(self.temp_map_bands_num)
  76. block_size_x = etree.SubElement(gdal_wms, "BlockSizeX")
  77. block_size_x.text = str(self.tile_size['cols'])
  78. block_size_y = etree.SubElement(gdal_wms, "BlockSizeY")
  79. block_size_y.text = str(self.tile_size['rows'])
  80. if self.params['username'] and self.params['password']:
  81. user_password = etree.SubElement(gdal_wms, "UserPwd")
  82. user_password.text = "%s:%s" % (self.params['username'], self.params['password'])
  83. xml_file = self._tempfile()
  84. etree.ElementTree(gdal_wms).write(xml_file)
  85. self._debug("_createXML", "finished -> %s" % xml_file)
  86. return xml_file
  87. def _download(self):
  88. """!Downloads data from WMS server using GDAL WMS driver
  89. @return temp_map with stored downloaded data
  90. """
  91. grass.message("Downloading data from WMS server...")
  92. # GDAL WMS driver does not flip geographic coordinates
  93. # according to WMS standard 1.3.0.
  94. if ("+proj=latlong" in self.proj_srs or
  95. "+proj=longlat" in self.proj_srs) and \
  96. self.params['wms_version'] == "1.3.0":
  97. grass.warning(_("If module will not be able to fetch the data in this " +
  98. "geographic projection, \n try 'WMS_GRASS' driver or use WMS version 1.1.1."))
  99. self._debug("_download", "started")
  100. temp_map = self._tempfile()
  101. xml_file = self._createXML()
  102. # print xml file content for debug level 1
  103. file = open(xml_file, "r")
  104. grass.debug("WMS request XML:\n%s" % file.read(), 1)
  105. file.close()
  106. if self.proxy:
  107. gdal.SetConfigOption('GDAL_HTTP_PROXY', str(self.proxy))
  108. if self.proxy_user_pw:
  109. gdal.SetConfigOption('GDAL_HTTP_PROXYUSERPWD', str(self.proxy_user_pw))
  110. wms_dataset = gdal.Open(xml_file, gdal.GA_ReadOnly)
  111. grass.try_remove(xml_file)
  112. if wms_dataset is None:
  113. grass.fatal(_("Unable to open GDAL WMS driver"))
  114. self._debug("_download", "GDAL dataset created")
  115. driver = gdal.GetDriverByName(self.gdal_drv_format)
  116. if driver is None:
  117. grass.fatal(_("Unable to find %s driver" % format))
  118. metadata = driver.GetMetadata()
  119. if gdal.DCAP_CREATECOPY not in metadata or \
  120. metadata[gdal.DCAP_CREATECOPY] == 'NO':
  121. grass.fatal(_('Driver %s supports CreateCopy() method.') % self.gdal_drv_name)
  122. self._debug("_download", "calling GDAL CreateCopy...")
  123. if self.createopt is None:
  124. temp_map_dataset = driver.CreateCopy(temp_map, wms_dataset, 0)
  125. else:
  126. self._debug("_download", "Using GDAL createopt <%s>" % str(self.createopt))
  127. temp_map_dataset = driver.CreateCopy(
  128. temp_map, wms_dataset, 0, self.createopt
  129. )
  130. if temp_map_dataset is None:
  131. grass.fatal(_("Incorrect WMS query"))
  132. temp_map_dataset = None
  133. wms_dataset = None
  134. self._debug("_download", "finished")
  135. return temp_map