wms_drv.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. try:
  2. from osgeo import gdal
  3. from osgeo import gdalconst
  4. except:
  5. grass.fatal(_("Unable to load GDAL python bindings"))
  6. from urllib2 import urlopen
  7. import numpy as Numeric
  8. Numeric.arrayrange = Numeric.arange
  9. import grass.script as grass
  10. from wms_base import WMSBase
  11. class WMSDrv(WMSBase):
  12. def _download(self):
  13. """!Downloads data from WMS server using own driver
  14. @return temp_map with stored downloaded data
  15. """
  16. grass.message(_("Downloading data from WMS server..."))
  17. proj = self.projection_name + "=EPSG:"+ str(self.o_srs)
  18. url = self.o_mapserver_url + "REQUEST=GetMap&VERSION=%s&LAYERS=%s&WIDTH=%s&HEIGHT=%s&STYLES=%s&BGCOLOR=%s&TRANSPARENT=%s" %\
  19. (self.o_wms_version, self.o_layers, self.tile_cols, self.tile_rows, self.o_styles, self.o_bgcolor, self.transparent)
  20. url += "&" +proj+ "&" + "FORMAT=" + self.mime_format
  21. if self.o_urlparams != "":
  22. url +="&" + self.o_urlparams
  23. cols = int(self.region['cols'])
  24. rows = int(self.region['rows'])
  25. # computes parameters of tiles
  26. num_tiles_x = cols / self.tile_cols
  27. last_tile_x_size = cols % self.tile_cols
  28. tile_x_length = float(self.tile_cols) / float(cols ) * (self.bbox['maxx'] - self.bbox['minx'])
  29. last_tile_x = False
  30. if last_tile_x_size != 0:
  31. last_tile_x = True
  32. num_tiles_x = num_tiles_x + 1
  33. num_tiles_y = rows / self.tile_rows
  34. last_tile_y_size = rows % self.tile_rows
  35. tile_y_length = float(self.tile_rows) / float(rows) * (self.bbox['maxy'] - self.bbox['miny'])
  36. last_tile_y = False
  37. if last_tile_y_size != 0:
  38. last_tile_y = True
  39. num_tiles_y = num_tiles_y + 1
  40. # each tile is downloaded and written into temp_map
  41. tile_bbox = dict(self.bbox)
  42. tile_bbox['maxx'] = self.bbox['minx'] + tile_x_length
  43. tile_to_temp_map_size_x = self.tile_cols
  44. for i_x in range(num_tiles_x):
  45. # set bbox for tile i_x,i_y (E, W)
  46. if i_x != 0:
  47. tile_bbox['maxx'] += tile_x_length
  48. tile_bbox['minx'] += tile_x_length
  49. if i_x == num_tiles_x - 1 and last_tile_x:
  50. tile_to_temp_map_size_x = last_tile_x_size
  51. tile_bbox['maxy'] = self.bbox['maxy']
  52. tile_bbox['miny'] = self.bbox['maxy'] - tile_y_length
  53. tile_to_temp_map_size_y = self.tile_rows
  54. for i_y in range(num_tiles_y):
  55. # set bbox for tile i_x,i_y (N, S)
  56. if i_y != 0:
  57. tile_bbox['miny'] -= tile_y_length
  58. tile_bbox['maxy'] -= tile_y_length
  59. if i_y == num_tiles_y - 1 and last_tile_y:
  60. tile_to_temp_map_size_y = last_tile_y_size
  61. if self.flip_coords:
  62. # flips coordinates if WMS strandard is 1.3.0 and
  63. # projection is geographic (see:wms_base.py _computeBbox)
  64. query_bbox = dict(self._flipBbox(tile_bbox))
  65. else:
  66. query_bbox = tile_bbox
  67. query_url = url + "&" + "BBOX=%s,%s,%s,%s" % ( query_bbox['minx'], query_bbox['miny'], query_bbox['maxx'], query_bbox['maxy'])
  68. grass.debug(query_url)
  69. try:
  70. wms_data = urlopen(query_url)
  71. except IOError:
  72. grass.fatal(_("Unable to fetch data from mapserver"))
  73. temp_tile = self._tempfile()
  74. # download data into temporary file
  75. try:
  76. temp_tile_opened = open(temp_tile, 'w')
  77. temp_tile_opened.write(wms_data.read())
  78. except IOError:
  79. grass.fatal(_("Unable to write data into tempfile"))
  80. finally:
  81. temp_tile_opened.close()
  82. tile_dataset_info = gdal.Open(temp_tile, gdal.GA_ReadOnly)
  83. if tile_dataset_info is None:
  84. # print error xml returned from server
  85. try:
  86. error_xml_opened = open(temp_tile, 'r')
  87. err_str = error_xml_opened.read()
  88. except IOError:
  89. grass.fatal(_("Unable to read data from tempfile"))
  90. finally:
  91. error_xml_opened.close()
  92. if err_str is not None:
  93. grass.fatal(_("WMS server error: %s") % err_str)
  94. else:
  95. grass.fatal(_("WMS server unknown error") )
  96. band = tile_dataset_info.GetRasterBand(1)
  97. cell_type_func = band.__swig_getmethods__["DataType"]#??
  98. bands_number_func = tile_dataset_info.__swig_getmethods__["RasterCount"]
  99. ##### see original r.in.wms - file gdalwarp.py line 117 ####
  100. temp_tile_pct2rgb = None
  101. if bands_number_func(tile_dataset_info) == 1 and band.GetRasterColorTable() is not None:
  102. # expansion of color table into bands
  103. temp_tile_pct2rgb = self._tempfile()
  104. tile_dataset = self._pct2rgb(temp_tile, temp_tile_pct2rgb)
  105. else:
  106. tile_dataset = tile_dataset_info
  107. # initialization of temp_map_dataset, where all tiles are merged
  108. if i_x == 0 and i_y == 0:
  109. temp_map = self._tempfile()
  110. driver = gdal.GetDriverByName(self.gdal_drv_format)
  111. metadata = driver.GetMetadata()
  112. if not metadata.has_key(gdal.DCAP_CREATE) or \
  113. metadata[gdal.DCAP_CREATE] == 'NO':
  114. grass.fatal(_('Driver %s does not supports Create() method') % drv_format)
  115. self.temp_map_bands_num = bands_number_func(tile_dataset)
  116. temp_map_dataset = driver.Create(temp_map, int(cols), int(rows),
  117. self.temp_map_bands_num, cell_type_func(band));
  118. # tile written into temp_map
  119. tile_to_temp_map = tile_dataset.ReadRaster(0, 0, tile_to_temp_map_size_x, tile_to_temp_map_size_y,
  120. tile_to_temp_map_size_x, tile_to_temp_map_size_y)
  121. temp_map_dataset.WriteRaster(self.tile_cols * i_x, self.tile_rows * i_y,
  122. tile_to_temp_map_size_x, tile_to_temp_map_size_y, tile_to_temp_map)
  123. tile_dataset = None
  124. tile_dataset_info = None
  125. grass.try_remove(temp_tile)
  126. grass.try_remove(temp_tile_pct2rgb)
  127. # georeferencing and setting projection of temp_map
  128. projection = grass.read_command('g.proj',
  129. flags = 'wf',
  130. epsg =self.o_srs).rstrip('\n')
  131. temp_map_dataset.SetProjection(projection)
  132. pixel_x_length = (self.bbox['maxx'] - self.bbox['minx']) / int(cols)
  133. pixel_y_length = (self.bbox['miny'] - self.bbox['maxy']) / int(rows)
  134. geo_transform = [ self.bbox['minx'] , pixel_x_length , 0.0 , self.bbox['maxy'] , 0.0 , pixel_y_length ]
  135. temp_map_dataset.SetGeoTransform(geo_transform )
  136. temp_map_dataset = None
  137. return temp_map
  138. def _pct2rgb(self, src_filename, dst_filename):
  139. """!Create new dataset with data in dst_filename with bands according to src_filename
  140. raster color table - modified code from gdal utility pct2rgb
  141. @return new dataset
  142. """
  143. out_bands = 4
  144. band_number = 1
  145. # open source file
  146. src_ds = gdal.Open(src_filename)
  147. if src_ds is None:
  148. grass.fatal(_('Unable to open %s ' % src_filename))
  149. src_band = src_ds.GetRasterBand(band_number)
  150. # Build color table
  151. lookup = [ Numeric.arrayrange(256),
  152. Numeric.arrayrange(256),
  153. Numeric.arrayrange(256),
  154. Numeric.ones(256)*255 ]
  155. ct = src_band.GetRasterColorTable()
  156. if ct is not None:
  157. for i in range(min(256,ct.GetCount())):
  158. entry = ct.GetColorEntry(i)
  159. for c in range(4):
  160. lookup[c][i] = entry[c]
  161. # create the working file
  162. gtiff_driver = gdal.GetDriverByName(self.gdal_drv_format)
  163. tif_ds = gtiff_driver.Create(dst_filename,
  164. src_ds.RasterXSize, src_ds.RasterYSize, out_bands)
  165. # do the processing one scanline at a time
  166. for iY in range(src_ds.RasterYSize):
  167. src_data = src_band.ReadAsArray(0,iY,src_ds.RasterXSize,1)
  168. for iBand in range(out_bands):
  169. band_lookup = lookup[iBand]
  170. dst_data = Numeric.take(band_lookup,src_data)
  171. tif_ds.GetRasterBand(iBand+1).WriteArray(dst_data,0,iY)
  172. return tif_ds