def processAlgorithm(self, parameters, context, feedback): crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context) extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs) value = self.parameterAsDouble(parameters, self.NUMBER, context) pixelSize = self.parameterAsDouble(parameters, self.PIXEL_SIZE, context) outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) outputFormat = QgsRasterFileWriter.driverForExtension(os.path.splitext(outputFile)[1]) rows = max([math.ceil(extent.height() / pixelSize), 1.0]) cols = max([math.ceil(extent.width() / pixelSize), 1.0]) writer = QgsRasterFileWriter(outputFile) writer.setOutputProviderKey('gdal') writer.setOutputFormat(outputFormat) provider = writer.createOneBandRaster(Qgis.Float32, cols, rows, extent, crs) if provider is None: raise QgsProcessingException(self.tr("Could not create raster output: {}").format(outputFile)) if not provider.isValid(): raise QgsProcessingException(self.tr("Could not create raster output {}: {}").format(outputFile, provider.error().message( QgsErrorMessage.Text))) provider.setNoDataValue(1, -9999) data = [value] * cols block = QgsRasterBlock(Qgis.Float32, cols, 1) block.setData(struct.pack('{}f'.format(len(data)), *data)) total = 100.0 / rows if rows else 0 for i in range(rows): if feedback.isCanceled(): break provider.writeBlock(block, 1, 0, i) feedback.setProgress(int(i * rows)) provider.setEditable(False) return {self.OUTPUT: outputFile}
def write(self, theRasterName): print(theRasterName) path = "%s/%s" % (self.testDataDir, theRasterName) rasterLayer = QgsRasterLayer(path, "test") if not rasterLayer.isValid(): return False provider = rasterLayer.dataProvider() tmpFile = QTemporaryFile() tmpFile.open() # fileName is no avialable until open tmpName = tmpFile.fileName() tmpFile.close() # do not remove when class is destroyed so that we can read # the file and see difference tmpFile.setAutoRemove(False) fileWriter = QgsRasterFileWriter(tmpName) pipe = QgsRasterPipe() if not pipe.set(provider.clone()): print("Cannot set pipe provider") return False projector = QgsRasterProjector() projector.setCrs(provider.crs(), provider.crs()) if not pipe.insert(2, projector): print("Cannot set pipe projector") return False fileWriter.writeRaster(pipe, provider.xSize(), provider.ySize(), provider.extent(), provider.crs()) checker = QgsRasterChecker() ok = checker.runTest("gdal", tmpName, "gdal", path) self.report += checker.report() # All OK, we can delete the file tmpFile.setAutoRemove(ok) return ok
def exportLayer(layer, fields=None, toShapefile=False, path=None, force=False, log=None): filename = layer.source().split("|")[0] destFilename = layer.name() fields = fields or [] if layer.type() == layer.VectorLayer: if toShapefile: if force or layer.fields().count() != len(fields) or (os.path.splitext(filename.lower())[1] != ".shp"): attrs = [i for i, f in enumerate(layer.fields()) if len(fields) == 0 or f.name() in fields] output = path or tempFilenameInTempFolder(destFilename + ".shp") QgsVectorFileWriter.writeAsVectorFormat(layer, output, "UTF-8", attributes=attrs, driverName="ESRI Shapefile") if log is not None: log.logInfo(QCoreApplication.translate("GeocatBridge", "Layer %s exported to %s") % (destFilename, output)) return output elif (force or os.path.splitext(filename.lower())[1] != ".gpkg" or layer.fields().count() != len(fields) or not isSingleTableGpkg(filename)): attrs = [i for i, f in enumerate(layer.fields()) if len(fields) == 0 or f.name() in fields] output = path or tempFilenameInTempFolder(destFilename + ".gpkg") QgsVectorFileWriter.writeAsVectorFormat(layer, output, "UTF-8", attributes=attrs) if log is not None: log.logInfo(QCoreApplication.translate("GeocatBridge", "Layer %s exported to %s") % (destFilename, output)) return output if log is not None: log.logInfo(QCoreApplication.translate("GeocatBridge", "No need to export layer %s stored at %s") % (destFilename, filename)) return filename else: if (force or not filename.lower().endswith("tif")): output = path or tempFilenameInTempFolder(destFilename + ".tif") writer = QgsRasterFileWriter(output) writer.setOutputFormat("GTiff"); writer.writeRaster(layer.pipe(), layer.width(), layer.height(), layer.extent(), layer.crs()) del writer if log is not None: log.logInfo(QCoreApplication.translate("GeocatBridge", "Layer %s exported to %s") % (destFilename, output)) return output else: if log is not None: log.logInfo(QCoreApplication.translate("GeocatBridge", "No need to export layer %s stored at %s") % (destFilename, filename)) return filename
def testExportToGpkgWithExtraExtent(self): tmpName = tempfile.mktemp(suffix='.gpkg') source = QgsRasterLayer( os.path.join(self.testDataDir, 'raster', 'band3_byte_noct_epsg4326.tif'), 'my', 'gdal') self.assertTrue(source.isValid()) provider = source.dataProvider() fw = QgsRasterFileWriter(tmpName) fw.setOutputFormat('gpkg') pipe = QgsRasterPipe() self.assertTrue(pipe.set(provider.clone())) self.assertEqual( fw.writeRaster(pipe, provider.xSize() + 4, provider.ySize() + 4, QgsRectangle(-3 - 2, -4 - 2, 7 + 2, 6 + 2), provider.crs()), 0) del fw # Check that the test geopackage contains the raster layer and compare rlayer = QgsRasterLayer(tmpName) self.assertTrue(rlayer.isValid()) out_provider = rlayer.dataProvider() for i in range(3): src_data = provider.block(i + 1, provider.extent(), source.width(), source.height()) out_data = out_provider.block(i + 1, provider.extent(), source.width(), source.height()) self.assertEqual(src_data.data(), out_data.data()) out_data = out_provider.block(1, QgsRectangle(7, -4, 7 + 2, 6), 2, 8) # band3_byte_noct_epsg4326 nodata is 255 self.assertEqual(out_data.data().data(), b'\xff' * 2 * 8) del out_provider del rlayer # remove result file os.unlink(tmpName)
def testImportIntoGpkg(self): # init target file test_gpkg = tempfile.mktemp(suffix='.gpkg', dir=self.testDataDir) gdal.GetDriverByName('GPKG').Create(test_gpkg, 1, 1, 1) source = QgsRasterLayer( os.path.join(self.testDataDir, 'raster', 'band3_byte_noct_epsg4326.tif'), 'my', 'gdal') self.assertTrue(source.isValid()) provider = source.dataProvider() fw = QgsRasterFileWriter(test_gpkg) fw.setOutputFormat('gpkg') fw.setCreateOptions( ['RASTER_TABLE=imported_table', 'APPEND_SUBDATASET=YES']) pipe = QgsRasterPipe() self.assertTrue(pipe.set(provider.clone())) projector = QgsRasterProjector() projector.setCrs(provider.crs(), provider.crs()) self.assertTrue(pipe.set(projector)) self.assertEqual( fw.writeRaster(pipe, provider.xSize(), provider.ySize(), provider.extent(), provider.crs()), 0) # Check that the test geopackage contains the raster layer and compare rlayer = QgsRasterLayer('GPKG:%s:imported_table' % test_gpkg) self.assertTrue(rlayer.isValid()) out_provider = rlayer.dataProvider() for i in range(3): src_data = provider.block(i + 1, provider.extent(), source.width(), source.height()) out_data = out_provider.block(i + 1, out_provider.extent(), rlayer.width(), rlayer.height()) self.assertEqual(src_data.data(), out_data.data()) # remove result file os.unlink(test_gpkg)
def _testGeneratePyramids(self, pyramidFormat): tmpName = tempfile.mktemp(suffix='.tif') source = QgsRasterLayer(os.path.join(self.testDataDir, 'raster', 'byte.tif'), 'my', 'gdal') self.assertTrue(source.isValid()) provider = source.dataProvider() fw = QgsRasterFileWriter(tmpName) fw.setBuildPyramidsFlag(QgsRaster.PyramidsFlagYes) fw.setPyramidsFormat(pyramidFormat) fw.setPyramidsList([2]) pipe = QgsRasterPipe() self.assertTrue(pipe.set(provider.clone())) projector = QgsRasterProjector() projector.setCrs(provider.crs(), provider.crs()) self.assertTrue(pipe.set(projector)) self.assertEqual(fw.writeRaster(pipe, provider.xSize(), provider.ySize(), provider.extent(), provider.crs()), 0) del fw ds = gdal.Open(tmpName) self.assertEqual(ds.RasterCount, 1) self.assertEqual(ds.GetRasterBand(1).Checksum(), 4672) self.assertEqual(ds.GetRasterBand(1).GetOverviewCount(), 1) fl = ds.GetFileList() if pyramidFormat == QgsRaster.PyramidsGTiff: self.assertEqual(len(fl), 2, fl) self.assertIn('.ovr', fl[1]) elif pyramidFormat == QgsRaster.PyramidsInternal: self.assertEqual(len(fl), 1, fl) elif pyramidFormat == QgsRaster.PyramidsErdas: self.assertEqual(len(fl), 2, fl) self.assertIn('.aux', fl[1]) os.unlink(tmpName)
def read_from_qgis_native(self, qgis_layer): """Read raster data from qgis layer QgsRasterLayer. A stub is used now: save all data in a file, then call safe.read_from_file Raises: * TypeError if qgis is not avialable * IOError if can't store temporary file * GetDataError if can't create copy of qgis_layer's dataProvider """ if not qgis_imported: # FIXME (DK): this branch isn't covered by test msg = ('Used data is QgsRasterLayer instance, ' 'but QGIS is not available.') raise TypeError(msg) base_name = unique_filename() file_name = base_name + '.tif' file_writer = QgsRasterFileWriter(file_name) pipe = QgsRasterPipe() provider = qgis_layer.dataProvider() if not pipe.set(provider.clone()): msg = "Cannot set pipe provider" raise GetDataError(msg) file_writer.writeRaster( pipe, provider.xSize(), provider.ySize(), provider.extent(), provider.crs()) # Write keywords if any write_keywords(self.keywords, base_name + '.keywords') self.read_from_file(file_name)
def testWriteAsImage(self): tmpName = tempfile.mktemp(suffix='.tif') source = QgsRasterLayer(os.path.join(self.testDataDir, 'raster', 'byte.tif'), 'my', 'gdal') source.setContrastEnhancement(algorithm=QgsContrastEnhancement.NoEnhancement) self.assertTrue(source.isValid()) provider = source.dataProvider() fw = QgsRasterFileWriter(tmpName) self.assertEqual(fw.writeRaster(source.pipe(), provider.xSize(), provider.ySize(), provider.extent(), provider.crs()), QgsRasterFileWriter.NoError) ds = gdal.Open(tmpName) self.assertEqual(ds.RasterCount, 4) self.assertEqual(ds.GetRasterBand(1).Checksum(), 4672) self.assertEqual(ds.GetRasterBand(2).Checksum(), 4672) self.assertEqual(ds.GetRasterBand(3).Checksum(), 4672) self.assertEqual(ds.GetRasterBand(4).Checksum(), 4873) ds = None del fw os.unlink(tmpName)
def testFail(self): """test error writing a layer""" path = os.path.join(unitTestDataPath(), 'raster', 'with_color_table.tif') raster_layer = QgsRasterLayer(path, "test") self.assertTrue(raster_layer.isValid()) pipe = QgsRasterPipe() self.assertTrue(pipe.set(raster_layer.dataProvider().clone())) tmp = create_temp_filename("/this/is/invalid/file.tif") writer = QgsRasterFileWriter(tmp) task = QgsRasterFileWriterTask(writer, pipe, 100, 100, raster_layer.extent(), raster_layer.crs(), QgsCoordinateTransformContext()) task.writeComplete.connect(self.onSuccess) task.errorOccurred.connect(self.onFail) QgsApplication.taskManager().addTask(task) while not self.success and not self.fail: QCoreApplication.processEvents() self.assertFalse(self.success) self.assertTrue(self.fail)
def clip_raster(raster, n_cols, n_rows, output_extent): """Clip raster to specified extent, width and height. Note there is similar utility in safe_qgis.utilities.clipper, but it uses gdal whereas this one uses native QGIS. :param raster: Raster :type raster: QgsRasterLayer :param n_cols: Desired width in pixels of new raster :type n_cols: Int :param n_rows: Desired height in pixels of new raster :type n_rows: Int :param output_extent: Extent of the clipped region :type output_extent: QgsRectangle :returns: Clipped region of the raster :rtype: QgsRasterLayer """ provider = raster.dataProvider() pipe = QgsRasterPipe() pipe.set(provider.clone()) base_name = unique_filename() file_name = base_name + '.tif' file_writer = QgsRasterFileWriter(file_name) file_writer.writeRaster( pipe, n_cols, n_rows, output_extent, raster.crs()) return QgsRasterLayer(file_name, 'clipped_raster')
def processAlgorithm(self, parameters, context, feedback): "Compute orographic precipitation." dem = raster_to_array(self.orography, self.bandNumber) x, y = grid(self.orography) dx = x[1] - x[0] dy = y[0] - y[1] # note: y is decreasing assert dx > 0 assert dy > 0 P = self.model.run(dem, dx, dy, self.truncate) outputFormat = QgsRasterFileWriter.driverForExtension( os.path.splitext(self.outputFile)[1]) writer = QgsRasterFileWriter(self.outputFile) writer.setOutputProviderKey('gdal') writer.setOutputFormat(outputFormat) provider = writer.createOneBandRaster(Qgis.Float64, x.size, y.size, self.orography.extent(), self.orography.crs()) provider.setNoDataValue(1, -9999) provider.write( bytes(P.data), 1, # band x.size, # width y.size, # height 0, 0) # offset provider.setEditable(False) return {self.OUTPUT: self.outputFile}
def create_rgb(self, raster_layer, output): '''Render and write RGB file Parameters ---------- raster_layer : QgsRasterLayer input raster layer with singleband pseudocolor output : str output file path Returns ------- error : boolean 0/1 - no error/error result : str or None output or error msg if error == 1 ''' # get raster_layer properties extent = raster_layer.extent() width, height = raster_layer.width(), raster_layer.height() renderer = raster_layer.renderer() provider = raster_layer.dataProvider() crs_raster = raster_layer.crs() # create pipe for export pipe = QgsRasterPipe() pipe.set(provider.clone()) pipe.set(renderer.clone()) # create FileWriter and write file fwriter = QgsRasterFileWriter(output) error = fwriter.writeRaster(pipe, width, height, extent, crs_raster) if error != fwriter.NoError: return 1, 'RGB file could not be rendered!' return 0, output
def convertUnsupportedFormats(self, progress): i = 0 progress.setText(self.tr('Converting outputs')) for out in self.outputs: if isinstance(out, OutputVector): if out.compatible is not None: layer = dataobjects.getObjectFromUri(out.compatible) if layer is None: # For the case of memory layer, if the # getCompatible method has been called continue provider = layer.dataProvider() writer = out.getVectorWriter(provider.fields(), provider.geometryType(), layer.crs()) features = vector.features(layer) for feature in features: writer.addFeature(feature) elif isinstance(out, OutputRaster): if out.compatible is not None: layer = dataobjects.getObjectFromUri(out.compatible) provider = layer.dataProvider() writer = QgsRasterFileWriter(out.value) format = self.getFormatShortNameFromFilename(out.value) writer.setOutputFormat(format) writer.writeRaster(layer.pipe(), layer.width(), layer.height(), layer.extent(), layer.crs()) elif isinstance(out, OutputTable): if out.compatible is not None: layer = dataobjects.getObjectFromUri(out.compatible) provider = layer.dataProvider() writer = out.getTableWriter(provider.fields()) features = vector.features(layer) for feature in features: writer.addRecord(feature) progress.setPercentage(100 * i / float(len(self.outputs)))
def testWriteAsRawGS7BG(self): ''' Test that despite writing a Byte raster, we correctly handle GS7BG creating a Float64 ''' tmpName = tempfile.mktemp(suffix='.grd') source = QgsRasterLayer(os.path.join(self.testDataDir, 'raster', 'byte.tif'), 'my', 'gdal') self.assertTrue(source.isValid()) provider = source.dataProvider() fw = QgsRasterFileWriter(tmpName) fw.setOutputFormat('GS7BG') pipe = QgsRasterPipe() self.assertTrue(pipe.set(provider.clone())) self.assertEqual(fw.writeRaster(pipe, provider.xSize(), provider.ySize(), provider.extent(), provider.crs()), QgsRasterFileWriter.NoError) del fw ds = gdal.Open(tmpName) self.assertEqual(ds.RasterCount, 1) self.assertEqual(ds.GetRasterBand(1).Checksum(), 4672) ds = None os.unlink(tmpName)
def exportRaster(layer, count, layersFolder, feedback): feedback.showFeedback("Exporting %s to PNG..." % layer.name()) name_ts = (safeName(layer.name()) + unicode(count) + unicode(int(time.time()))) # We need to create a new file to export style piped_file = os.path.join(tempfile.gettempdir(), name_ts + '_piped.tif') piped_extent = layer.extent() piped_width = layer.height() piped_height = layer.width() piped_crs = layer.crs() piped_renderer = layer.renderer() piped_provider = layer.dataProvider() pipe = QgsRasterPipe() pipe.set(piped_provider.clone()) pipe.set(piped_renderer.clone()) file_writer = QgsRasterFileWriter(piped_file) file_writer.writeRaster(pipe, piped_width, piped_height, piped_extent, piped_crs) # Extent of the layer in EPSG:3857 crsSrc = layer.crs() crsDest = QgsCoordinateReferenceSystem(3857) xform = QgsCoordinateTransform(crsSrc, crsDest) extentRep = xform.transform(layer.extent()) extentRepNew = ','.join([ unicode(extentRep.xMinimum()), unicode(extentRep.xMaximum()), unicode(extentRep.yMinimum()), unicode(extentRep.yMaximum()) ]) # Reproject in 3857 piped_3857 = os.path.join(tempfile.gettempdir(), name_ts + '_piped_3857.tif') # Export layer as PNG out_raster = os.path.join(layersFolder, safeName(layer.name()) + unicode(count) + ".png") qgis_version = QGis.QGIS_VERSION old_stdout = sys.stdout sys.stdout = mystdout = StringIO() try: processing.runalg("gdalogr:warpreproject") except: pass sys.stdout = old_stdout params = { "INPUT": piped_file, "SOURCE_SRS": layer.crs().authid(), "DEST_SRS": "EPSG:3857", "NO_DATA": "", "TR": 0, "METHOD": 2, "RAST_EXT": extentRepNew, "EXT_CRS": "EPSG:3857", "RTYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "EXTRA": "", "OUTPUT": piped_3857 } warpArgs = {} lines = mystdout.getvalue() for count, line in enumerate(lines.split("\n\t")): if count != 0 and line != " ": try: k = line.split(" ")[0] warpArgs[k] = params[k] except: pass if int(qgis_version.split('.')[1]) < 15: processing.runalg("gdalogr:warpreproject", piped_file, layer.crs().authid(), "EPSG:3857", "", 0, 1, 0, -1, 75, 6, 1, False, 0, False, "", piped_3857) processing.runalg("gdalogr:translate", piped_3857, 100, True, "", 0, "", extentRepNew, False, 0, 0, 75, 6, 1, False, 0, False, "", out_raster) else: try: procRtn = processing.runalg("gdalogr:warpreproject", warpArgs) except: shutil.copyfile(piped_file, piped_3857) try: processing.runalg("gdalogr:translate", piped_3857, 100, True, "", 0, "", extentRepNew, False, 5, 4, 75, 6, 1, False, 0, False, "", out_raster) except: shutil.copyfile(piped_3857, out_raster)
def exportRasterLayer(layer, safeLayerName, dataPath): name_ts = safeLayerName + unicode(int(time.time())) # We need to create a new file to export style piped_file = os.path.join(tempfile.gettempdir(), name_ts + '_piped.tif') piped_extent = layer.extent() piped_width = layer.height() piped_height = layer.width() piped_crs = layer.crs() piped_renderer = layer.renderer() piped_provider = layer.dataProvider() pipe = QgsRasterPipe() pipe.set(piped_provider.clone()) pipe.set(piped_renderer.clone()) file_writer = QgsRasterFileWriter(piped_file) file_writer.writeRaster(pipe, piped_width, piped_height, piped_extent, piped_crs) # Extent of the layer in EPSG:3857 crsSrc = layer.crs() crsDest = QgsCoordinateReferenceSystem(3857) xform = QgsCoordinateTransform(crsSrc, crsDest) extentRep = xform.transform(layer.extent()) extentRepNew = ','.join([ unicode(extentRep.xMinimum()), unicode(extentRep.xMaximum()), unicode(extentRep.yMinimum()), unicode(extentRep.yMaximum()) ]) # Reproject in 3857 piped_3857 = os.path.join(tempfile.gettempdir(), name_ts + '_piped_3857.tif') # Export layer as PNG out_raster = dataPath + '.png' qgis_version = QGis.QGIS_VERSION if int(qgis_version.split('.')[1]) < 15: processing.runalg("gdalogr:warpreproject", piped_file, layer.crs().authid(), "EPSG:3857", "", 0, 1, 0, -1, 75, 6, 1, False, 0, False, "", piped_3857) processing.runalg("gdalogr:translate", piped_3857, 100, True, "", 0, "", extentRepNew, False, 0, 0, 75, 6, 1, False, 0, False, "", out_raster) else: try: warpArgs = { "INPUT": piped_file, "SOURCE_SRS": layer.crs().authid(), "DEST_SRS": "EPSG:3857", "NO_DATA": "", "TR": 0, "METHOD": 2, "RAST_EXT": extentRepNew, "EXT_CRS": "EPSG:3857", "RTYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "EXTRA": "", "OUTPUT": piped_3857 } procRtn = processing.runalg("gdalogr:warpreproject", warpArgs) # force exception on algorithm fail for val in procRtn: pass except: try: warpArgs = { "INPUT": piped_file, "SOURCE_SRS": layer.crs().authid(), "DEST_SRS": "EPSG:3857", "NO_DATA": "", "TR": 0, "METHOD": 2, "RAST_EXT": extentRepNew, "RTYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "EXTRA": "", "OUTPUT": piped_3857 } procRtn = processing.runalg("gdalogr:warpreproject", warpArgs) # force exception on algorithm fail for val in procRtn: pass except: try: warpArgs = { "INPUT": piped_file, "SOURCE_SRS": layer.crs().authid(), "DEST_SRS": "EPSG:3857", "NO_DATA": "", "TR": 0, "METHOD": 2, "RTYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "EXTRA": "", "OUTPUT": piped_3857 } procRtn = processing.runalg("gdalogr:warpreproject", warpArgs) for val in procRtn: pass except: shutil.copyfile(piped_file, piped_3857) try: processing.runalg("gdalogr:translate", piped_3857, 100, True, "", 0, "", extentRepNew, False, 5, 4, 75, 6, 1, False, 0, False, "", out_raster) except: shutil.copyfile(piped_3857, out_raster)
dataOut = tempfile.mktemp('.tif') except Exception, e: raise Exception( 'Problem creating temporary file to store raster data: ' + str(e)) # TODO: Work out if the response is an XML error update.emit({'progress': 10, 'message': 'Downloading file...'}) urllib.urlretrieve(bigURL, dataOut) # Load data as QgsRasterLayer and then re-save it, ensuring it has the correct projection info a = QgsRasterLayer(dataOut, "temporary raster layer") # Double-confirm projection info (sometimes WCS has it in the meta but not the file) crs = a.crs() crs.createFromId(int(srs.split(':')[1])) a.setCrs(crs) update.emit({'progress': 90, 'message': 'Saving file...'}) writer = QgsRasterFileWriter(output_file) pipe = QgsRasterPipe() width, height = a.width(), a.height() extent = a.extent() provider = a.dataProvider() pipe.set(provider.clone()) writer.writeRaster(pipe, width, height, extent, a.crs()) a = None pipe = None provider = None # Delete temp file os.remove(dataOut) return output_file
def styleRaster(filename): # Create outfile name outfile = "".join(filename.strip().split('.raw')) # Open layer from filename rasterfile = filename.strip().split('/')[-1] rasterlayer = rasterfile.split('.')[0] rlayer = QgsRasterLayer(filename, rasterlayer, 'gdal') # Check if layer is valid if rlayer.isValid() is True: # Get layer data provider provider = rlayer.dataProvider() # Calculate histrogram provider.initHistogram(QgsRasterHistogram(), 1, 100) hist = provider.histogram(1) # Get histograms stats nbins = hist.binCount minv = hist.minimum maxv = hist.maximum # Create histogram array, bin array, and histogram index hista = np.array(hist.histogramVector) bins = np.arange(minv, maxv, (maxv - minv) / nbins) index = np.where(hista > 5) # Get bottom and top color values from bin values bottomcolor = bins[index[0][0]] topcolor = bins[index[0][-1]] # Calculate range value between the bottom and top color values if bottomcolor < 0: vrange = topcolor + bottomcolor else: vrange = topcolor - bottomcolor # Calculate values for bottom middle, and top middle color values if rasterlayer == 'maxele': bottommiddle = vrange * 0.3333 topmiddle = vrange * 0.6667 else: bottommiddle = vrange * 0.375 topmiddle = vrange * 0.75 # Create list of color values valueList = [bottomcolor, bottommiddle, topmiddle, topcolor] # Create color dictionary if rasterlayer == 'maxele': colDic = { 'bottomcolor': '#0000ff', 'bottommiddle': '#00ffff', 'topmiddle': '#ffff00', 'topcolor': '#ff0000' } else: colDic = { 'bottomcolor': '#000000', 'bottommiddle': '#ff0000', 'topmiddle': '#ffff00', 'topcolor': '#ffffff' } # Create color ramp function and add colors fnc = QgsColorRampShader() fnc.setColorRampType(QgsColorRampShader.Interpolated) lst = [QgsColorRampShader.ColorRampItem(valueList[0], QColor(colDic['bottomcolor'])),\ QgsColorRampShader.ColorRampItem(valueList[1], QColor(colDic['bottommiddle'])), \ QgsColorRampShader.ColorRampItem(valueList[2], QColor(colDic['topmiddle'])), \ QgsColorRampShader.ColorRampItem(valueList[3], QColor(colDic['topcolor']))] fnc.setColorRampItemList(lst) # Create raster shader and add color ramp function shader = QgsRasterShader() shader.setRasterShaderFunction(fnc) # Create color render and set opacity renderer = QgsSingleBandPseudoColorRenderer(provider, 1, shader) renderer.setOpacity(0.75) # Get output format output_format = QgsRasterFileWriter.driverForExtension( os.path.splitext(outfile)[1]) # Open output file for writing rfw = QgsRasterFileWriter(outfile) rfw.setOutputProviderKey('gdal') rfw.setOutputFormat(output_format) # Add EPSG 4326 to layer crs crs = QgsCoordinateReferenceSystem() crs.createFromSrid(4326) # Create Raster pipe and set provider and renderer pipe = QgsRasterPipe() pipe.set(provider.clone()) pipe.set(renderer.clone()) # Get transform context transform_context = QgsProject.instance().transformContext() # Write to file rfw.writeRaster(pipe, provider.xSize(), provider.ySize(), provider.extent(), crs, transform_context) logger.info( 'Conveted data in ' + rasterfile + ' from float64 to 8bit, added color palette and saved to tiff (' + outfile.split('/')[-1] + ') file') if not rlayer.isValid(): raise Exception('Invalid raster') return (valueList)
def exportLayer(layer, fields=None, to_shapefile=False, path=None, force=False, logger=None): logger = logger or feedback filepath, _, ext = lyr_utils.getLayerSourceInfo(layer) lyr_name, safe_name = lyr_utils.getLayerTitleAndName(layer) fields = fields or [] if layer.type() == layer.VectorLayer: if to_shapefile and (force or layer.fields().count() != len(fields) or ext != EXT_SHAPEFILE): # Export with Shapefile extension ext = EXT_SHAPEFILE elif force or ext != EXT_GEOPACKAGE or layer.fields().count() != len(fields) \ or not isSingleTableGpkg(filepath): # Export with GeoPackage extension ext = EXT_GEOPACKAGE else: # No need to export logger.logInfo( f"No need to export layer {lyr_name} stored at {filepath}") return filepath # Perform GeoPackage or Shapefile export attrs = [ i for i, f in enumerate(layer.fields()) if len(fields) == 0 or f.name() in fields ] output = path or tempFileInSubFolder(safe_name + ext) encoding = "UTF-8" driver = "ESRI Shapefile" if ext == EXT_SHAPEFILE else "GPKG" options = None if hasattr(QgsVectorFileWriter, 'SaveVectorOptions'): # QGIS v3.x has the SaveVectorOptions object options = QgsVectorFileWriter.SaveVectorOptions() options.fileEncoding = encoding options.attributes = attrs options.driverName = driver # Make sure that we are using the latest (non-deprecated) write method if hasattr(QgsVectorFileWriter, 'writeAsVectorFormatV3'): # Use writeAsVectorFormatV3 for QGIS versions >= 3.20 to avoid DeprecationWarnings result = QgsVectorFileWriter.writeAsVectorFormatV3( layer, output, QgsCoordinateTransformContext(), options) # noqa elif hasattr(QgsVectorFileWriter, 'writeAsVectorFormatV2'): # Use writeAsVectorFormatV2 for QGIS versions >= 3.10.3 to avoid DeprecationWarnings result = QgsVectorFileWriter.writeAsVectorFormatV2( layer, output, QgsCoordinateTransformContext(), options) # noqa else: # Use writeAsVectorFormat for QGIS versions < 3.10.3 for backwards compatibility result = QgsVectorFileWriter.writeAsVectorFormat( layer, output, fileEncoding=encoding, attributes=attrs, driverName=driver) # noqa # Check if first item in result tuple is an error code if result[0] == QgsVectorFileWriter.NoError: logger.logInfo(f"Layer {lyr_name} exported to {output}") else: # Dump the result tuple as-is when there are errors (the tuple size depends on the QGIS version) logger.logError( f"Layer {lyr_name} failed to export.\n\tResult object: {str(result)}" ) return output else: # Export raster if force or not filepath.lower().endswith("tif"): output = path or tempFileInSubFolder(safe_name + ".tif") writer = QgsRasterFileWriter(output) writer.setOutputFormat("GTiff") writer.writeRaster(layer.pipe(), layer.width(), layer.height(), layer.extent(), layer.crs()) del writer logger.logInfo(f"Layer {lyr_name} exported to {output}") return output else: logger.logInfo( f"No need to export layer {lyr_name} stored at {filepath}") return filepath
def response_geotiff_mode(self, request): """ Export raster as geotiff i.e: 192.168.1.137:8006/raster/api/geotiff/qdjango/190/sfondo_clip_c60533a4_743e_4734_9b95_514ac765ec4e/ 192.168.1.137:8006/raster/api/geotiff/qdjango/190/europa_dem_8f0a9c30_5b96_4661_b747_8ce4f2679d6b/?map_extent=10.515901325263899%2C43.875701513907146%2C10.55669628723769%2C43.92294901234999 :param request: Http Django request object :return: http response with attached file """ #if not self.layer.download: # return HttpResponseForbidden() tmp_dir = tempfile.TemporaryDirectory() filename = f"{self.metadata_layer.qgis_layer.name()}.tif" file_path = os.path.join(tmp_dir.name, filename) writer = QgsRasterFileWriter(file_path) provider = self.metadata_layer.qgis_layer.dataProvider() renderer = self.metadata_layer.qgis_layer.renderer() # Check for Url Params if request.query_params.get('map_extent'): me = request.query_params.get('map_extent').split(',') orig_extent =provider.extent() extent = QgsRectangle(float(me[0]), float(me[1]), float(me[2]), float(me[3])) # If crs layer is not equal to project crs if self.reproject: ct = QgsCoordinateTransform( QgsCoordinateReferenceSystem(f'EPSG:{self.layer.project.group.srid.srid}'), self.metadata_layer.qgis_layer.crs(), QgsCoordinateTransformContext() ) extent = ct.transform(extent) # Calc columns and rows cols = int((extent.xMaximum() - extent.xMinimum()) / (orig_extent.xMaximum() - orig_extent.xMinimum()) * provider.xSize()) rows = int((extent.yMaximum() - extent.yMinimum()) / (orig_extent.yMaximum() - orig_extent.yMinimum()) * provider.ySize()) # For cols or rows lower than 0, we have to recalculate extent to guarantee minimal raster cell if cols < 1: cols = 1 new_wide_x_extent = (orig_extent.xMaximum() - orig_extent.xMinimum()) / provider.xSize() off = (new_wide_x_extent - (extent.xMaximum() - extent.xMinimum())) / 2 extent.setXMinimum(extent.xMinimum() - off) extent.setXMaximum(extent.xMaximum() + off) if rows < 1: rows = 1 new_wide_y_extent = (orig_extent.yMaximum() - orig_extent.yMinimum()) / provider.ySize() off = (new_wide_y_extent - (extent.yMaximum() - extent.yMinimum())) / 2 extent.setYMinimum(extent.yMinimum() - off) extent.setYMaximum(extent.yMaximum() + off) else: extent = provider.extent() cols = provider.xSize() rows = provider.ySize() pipe = QgsRasterPipe() pipe.set(provider.clone()) pipe.set(renderer.clone()) error_code = writer.writeRaster( pipe, cols, rows, extent, self.metadata_layer.qgis_layer.crs(), self.metadata_layer.qgis_layer.transformContext() ) if error_code != QgsRasterFileWriter.NoError: tmp_dir.cleanup() raise APIException(f"An error occoured on create raster file for export") # Grab ZIP file from in-memory, make response with correct MIME-type response = HttpResponse( open(file_path, 'rb').read(), content_type='image/tif') response['Content-Disposition'] = f'attachment; filename={filename}' response.set_cookie('fileDownload', 'true') return response
def exportLayers(iface, layers, folder, precision, optimize, popupField, json, restrictToExtent, extent, feedback): canvas = iface.mapCanvas() epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326") layersFolder = os.path.join(folder, "layers") QDir().mkpath(layersFolder) for count, (layer, encode2json, popup) in enumerate(zip(layers, json, popupField)): if (layer.type() == layer.VectorLayer and (layer.providerType() != "WFS" or encode2json)): feedback.showFeedback("Exporting %s to JSON..." % layer.name()) cleanLayer = writeTmpLayer(layer, popup, restrictToExtent, iface, extent) fields = layer.pendingFields() for field in fields: exportImages(layer, field.name(), layersFolder + "/tmp.tmp") if is25d(layer, canvas, restrictToExtent, extent): provider = cleanLayer.dataProvider() provider.addAttributes([ QgsField("height", QVariant.Double), QgsField("wallColor", QVariant.String), QgsField("roofColor", QVariant.String) ]) cleanLayer.updateFields() fields = cleanLayer.pendingFields() renderer = layer.rendererV2() renderContext = QgsRenderContext.fromMapSettings( canvas.mapSettings()) feats = layer.getFeatures() context = QgsExpressionContext() context.appendScope( QgsExpressionContextUtils.layerScope(layer)) expression = QgsExpression('eval(@qgis_25d_height)') heightField = fields.indexFromName("height") wallField = fields.indexFromName("wallColor") roofField = fields.indexFromName("roofColor") renderer.startRender(renderContext, fields) cleanLayer.startEditing() for feat in feats: context.setFeature(feat) height = expression.evaluate(context) if isinstance(renderer, QgsCategorizedSymbolRendererV2): classAttribute = renderer.classAttribute() attrValue = feat.attribute(classAttribute) catIndex = renderer.categoryIndexForValue(attrValue) categories = renderer.categories() symbol = categories[catIndex].symbol() elif isinstance(renderer, QgsGraduatedSymbolRendererV2): classAttribute = renderer.classAttribute() attrValue = feat.attribute(classAttribute) ranges = renderer.ranges() for range in ranges: if (attrValue >= range.lowerValue() and attrValue <= range.upperValue()): symbol = range.symbol().clone() else: symbol = renderer.symbolForFeature2( feat, renderContext) sl1 = symbol.symbolLayer(1) sl2 = symbol.symbolLayer(2) wallColor = sl1.subSymbol().color().name() roofColor = sl2.subSymbol().color().name() provider.changeAttributeValues({ feat.id() + 1: { heightField: height, wallField: wallColor, roofField: roofColor } }) cleanLayer.commitChanges() renderer.stopRender(renderContext) sln = safeName(cleanLayer.name()) + unicode(count) tmpPath = os.path.join(layersFolder, sln + ".json") path = os.path.join(layersFolder, sln + ".js") options = [] if precision != "maintain": options.append("COORDINATE_PRECISION=" + unicode(precision)) QgsVectorFileWriter.writeAsVectorFormat(cleanLayer, tmpPath, "utf-8", epsg4326, 'GeoJson', 0, layerOptions=options) with open(path, "w") as f: f.write("var %s = " % ("geojson_" + sln)) with open(tmpPath, "r") as f2: for line in f2: if optimize: line = line.strip("\n\t ") line = removeSpaces(line) f.write(line) os.remove(tmpPath) elif (layer.type() == layer.RasterLayer and layer.providerType() != "wms"): feedback.showFeedback("Exporting %s to PNG..." % layer.name()) name_ts = (safeName(layer.name()) + unicode(count) + unicode(int(time.time()))) # We need to create a new file to export style piped_file = os.path.join(tempfile.gettempdir(), name_ts + '_piped.tif') piped_extent = layer.extent() piped_width = layer.height() piped_height = layer.width() piped_crs = layer.crs() piped_renderer = layer.renderer() piped_provider = layer.dataProvider() pipe = QgsRasterPipe() pipe.set(piped_provider.clone()) pipe.set(piped_renderer.clone()) file_writer = QgsRasterFileWriter(piped_file) file_writer.writeRaster(pipe, piped_width, piped_height, piped_extent, piped_crs) # Extent of the layer in EPSG:3857 crsSrc = layer.crs() crsDest = QgsCoordinateReferenceSystem(3857) xform = QgsCoordinateTransform(crsSrc, crsDest) extentRep = xform.transform(layer.extent()) extentRepNew = ','.join([ unicode(extentRep.xMinimum()), unicode(extentRep.xMaximum()), unicode(extentRep.yMinimum()), unicode(extentRep.yMaximum()) ]) # Reproject in 3857 piped_3857 = os.path.join(tempfile.gettempdir(), name_ts + '_piped_3857.tif') # Export layer as PNG out_raster = os.path.join( layersFolder, safeName(layer.name()) + unicode(count) + ".png") qgis_version = QGis.QGIS_VERSION if int(qgis_version.split('.')[1]) < 15: processing.runalg("gdalogr:warpreproject", piped_file, layer.crs().authid(), "EPSG:3857", "", 0, 1, 0, -1, 75, 6, 1, False, 0, False, "", piped_3857) processing.runalg("gdalogr:translate", piped_3857, 100, True, "", 0, "", extentRepNew, False, 0, 0, 75, 6, 1, False, 0, False, "", out_raster) else: try: warpArgs = { "INPUT": piped_file, "SOURCE_SRS": layer.crs().authid(), "DEST_SRS": "EPSG:3857", "NO_DATA": "", "TR": 0, "METHOD": 2, "RAST_EXT": extentRepNew, "EXT_CRS": "EPSG:3857", "RTYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "EXTRA": "", "OUTPUT": piped_3857 } procRtn = processing.runalg("gdalogr:warpreproject", warpArgs) # force exception on algorithm fail for val in procRtn: pass except: try: warpArgs = { "INPUT": piped_file, "SOURCE_SRS": layer.crs().authid(), "DEST_SRS": "EPSG:3857", "NO_DATA": "", "TR": 0, "METHOD": 2, "RAST_EXT": extentRepNew, "RTYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "EXTRA": "", "OUTPUT": piped_3857 } procRtn = processing.runalg("gdalogr:warpreproject", warpArgs) # force exception on algorithm fail for val in procRtn: pass except: try: warpArgs = { "INPUT": piped_file, "SOURCE_SRS": layer.crs().authid(), "DEST_SRS": "EPSG:3857", "NO_DATA": "", "TR": 0, "METHOD": 2, "RTYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "EXTRA": "", "OUTPUT": piped_3857 } procRtn = processing.runalg( "gdalogr:warpreproject", warpArgs) # force exception on algorithm fail for val in procRtn: pass except: shutil.copyfile(piped_file, piped_3857) try: processing.runalg("gdalogr:translate", piped_3857, 100, True, "", 0, "", extentRepNew, False, 5, 4, 75, 6, 1, False, 0, False, "", out_raster) except: shutil.copyfile(piped_3857, out_raster) feedback.completeStep()
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ if self.parameterAsRasterLayer(parameters, self.INITIAL_ROAD_NETWORK, context): initial_road_network_raster = self.parameterAsRasterLayer( parameters, self.INITIAL_ROAD_NETWORK, context) else: initial_road_network_raster = None basic_distance_cost = self.parameterAsDouble(parameters, self.BASIC_DISTANCE_COST, context) if self.parameterAsRasterLayer(parameters, self.COARSE_ELEVATION_RASTER, context): coarse_elevation_raster = self.parameterAsRasterLayer( parameters, self.COARSE_ELEVATION_RASTER, context) else: coarse_elevation_raster = None if self.parameterAsMatrix(parameters, self.COARSE_ELEVATION_COSTS, context): coarse_elevation_costs = self.parameterAsMatrix( parameters, self.COARSE_ELEVATION_COSTS, context) coarse_elevation_costs = CostRasterCreatorHelper.CollapsedTableToMatrix( coarse_elevation_costs, 3) else: coarse_elevation_costs = None if self.parameterAsRasterLayer(parameters, self.FINE_ELEVATION_RASTER, context): fine_elevation_raster = self.parameterAsRasterLayer( parameters, self.FINE_ELEVATION_RASTER, context) else: fine_elevation_raster = None if self.parameterAsMatrix(parameters, self.FINE_ELEVATION_COSTS, context): fine_elevation_costs = self.parameterAsMatrix( parameters, self.FINE_ELEVATION_COSTS, context) fine_elevation_costs = CostRasterCreatorHelper.CollapsedTableToMatrix( fine_elevation_costs, 3) else: fine_elevation_costs = None if self.parameterAsRasterLayer(parameters, self.COARSE_WATER_RASTER, context): coarse_water_raster = self.parameterAsRasterLayer( parameters, self.COARSE_WATER_RASTER, context) else: coarse_water_raster = None if self.parameterAsDouble(parameters, self.COARSE_WATER_COST, context): coarse_water_cost = self.parameterAsDouble(parameters, self.COARSE_WATER_COST, context) else: coarse_water_cost = None if self.parameterAsRasterLayer(parameters, self.FINE_WATER_RASTER, context): fine_water_raster = self.parameterAsRasterLayer( parameters, self.FINE_WATER_RASTER, context) else: fine_water_raster = None if self.parameterAsDouble(parameters, self.FINE_WATER_COST, context): fine_water_cost = self.parameterAsDouble(parameters, self.FINE_WATER_COST, context) else: fine_water_cost = None if self.parameterAsRasterLayer(parameters, self.SOIL_RASTER, context): soil_raster = self.parameterAsRasterLayer(parameters, self.SOIL_RASTER, context) else: soil_raster = None if self.parameterAsRasterLayer(parameters, self.ADDITIONAL_COST_RASTER, context): special_raster = self.parameterAsRasterLayer( parameters, self.ADDITIONAL_COST_RASTER, context) else: special_raster = None feedback.pushInfo(self.tr("Checking inputs...")) # If source was not found, throw an exception to indicate that the algorithm # encountered a fatal error. The exception text can be any string, but in this # case we use the pre-built invalidSourceError method to return a standard # helper text for when a source cannot be evaluated if basic_distance_cost is None or basic_distance_cost == 0: raise QgsProcessingException( self.invalidSourceError(parameters, self.BASIC_DISTANCE_COST)) # Now, we check to see if the CRS, extent and resolution of every raster is equal, so that their align properly. listOfRastersToCheck = list() if initial_road_network_raster is not None: listOfRastersToCheck.append(initial_road_network_raster) if coarse_elevation_raster is not None: listOfRastersToCheck.append(coarse_elevation_raster) if fine_elevation_raster is not None: listOfRastersToCheck.append(fine_elevation_raster) if coarse_water_raster is not None: listOfRastersToCheck.append(coarse_water_raster) if fine_water_raster is not None: listOfRastersToCheck.append(fine_water_raster) if soil_raster is not None: listOfRastersToCheck.append(soil_raster) if special_raster is not None: listOfRastersToCheck.append(special_raster) if len(listOfRastersToCheck) == 0: raise QgsProcessingException( self. tr("At least one input raster is needed ! Please, input one raster." )) # We check that every raster has the same CRS, extent and resolution. CostRasterCreatorHelper.CheckRastersCompatibility(listOfRastersToCheck) # We also check that the matrix of parameters entered for the coarse elevation costs and fine elevation costs # are correct : meaning that there are no holes between the thresholds, and that every lower threshold is lower # than the upper threshold. if coarse_elevation_costs is not None: CostRasterCreatorHelper.CheckThresholds(coarse_elevation_costs, "Coarse elevation costs") if fine_elevation_costs is not None: CostRasterCreatorHelper.CheckThresholds(fine_elevation_costs, "Fine elevation costs") # Then, we create the raster blocks if initial_road_network_raster is not None: initial_road_network_raster_block = CostRasterCreatorHelper.get_all_block( initial_road_network_raster) else: initial_road_network_raster_block = None if coarse_elevation_raster is not None: coarse_elevation_raster_block = CostRasterCreatorHelper.get_all_block( coarse_elevation_raster) else: coarse_elevation_raster_block = None if fine_elevation_raster is not None: fine_elevation_raster_block = CostRasterCreatorHelper.get_all_block( fine_elevation_raster) else: fine_elevation_raster_block = None if coarse_water_raster is not None: coarse_water_raster_block = CostRasterCreatorHelper.get_all_block( coarse_water_raster) else: coarse_water_raster_block = None if fine_water_raster is not None: fine_water_raster_block = CostRasterCreatorHelper.get_all_block( fine_water_raster) else: fine_water_raster_block = None if soil_raster is not None: soil_raster_block = CostRasterCreatorHelper.get_all_block( soil_raster) else: soil_raster_block = None if special_raster is not None: special_raster_block = CostRasterCreatorHelper.get_all_block( special_raster) else: special_raster_block = None feedback.pushInfo(self.tr("Preparing output...")) # We set the output to be ready : It is a QgsDataProvider outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) outputFormat = QgsRasterFileWriter.driverForExtension( os.path.splitext(outputFile)[1]) crs = listOfRastersToCheck[0].crs() extent = listOfRastersToCheck[0].extent() rows = max([ math.ceil(extent.height() / listOfRastersToCheck[0].rasterUnitsPerPixelY()), 1.0 ]) cols = max([ math.ceil(extent.width() / listOfRastersToCheck[0].rasterUnitsPerPixelX()), 1.0 ]) # We will need this value for the fine water computation later pixelSide = (listOfRastersToCheck[0].rasterUnitsPerPixelY() + listOfRastersToCheck[0].rasterUnitsPerPixelX()) / 2 writer = QgsRasterFileWriter(outputFile) writer.setOutputProviderKey('gdal') writer.setOutputFormat(outputFormat) provider = writer.createOneBandRaster(Qgis.Float32, cols, rows, extent, crs) if provider is None: raise QgsProcessingException( self.tr("Could not create raster output: {}").format( outputFile)) if not provider.isValid(): raise QgsProcessingException( self.tr("Could not create raster output {}").format( outputFile)) provider.setNoDataValue(1, -9999) # We create the data block for the output raster, and we fill it with the values we need dataBlock = QgsRasterBlock(Qgis.Float32, cols, rows) # i = float(1.0) feedback.pushInfo(self.tr("Calculating cost raster...")) progress = 0 feedback.setProgress(0) errorMessages = list() for y in range(dataBlock.height()): for x in range(dataBlock.width()): if feedback.isCanceled(): raise QgsProcessingException( self.tr("ERROR: Operation was cancelled.")) # If there is a road already on this pixel, then the cost is 0. if initial_road_network_raster_block is not None and \ (initial_road_network_raster_block.value(y, x) != 0 and not initial_road_network_raster_block.isNoData( y, x)): finalValue = 0 # If there is a water body on this pixel, we stop everything : # The cost will be the construction of a bridge elif coarse_water_raster_block is not None and coarse_water_raster_block.value( y, x) != 0: if coarse_water_cost is not None: finalValue = coarse_water_cost else: raise QgsProcessingException( self. tr("A coarse water raster has been given, but no coarse " + "water cost. Please input a coarse water cost.") ) # feedback.pushInfo("Seems like there was a road on this pixel. Final value is " + str(finalValue)) # Else, if we are not on a road or on a body of water... else: # We start with the base cost of crossing the pixel finalValue = basic_distance_cost # feedback.pushInfo("No road on this pixel, we put basic distance cost. Final value is " + str(finalValue)) # Then, if we have it, we add the soil cost if soil_raster_block is not None: finalValue += soil_raster_block.value(y, x) # feedback.pushInfo("After soils, final value is " + str(finalValue)) if special_raster_block is not None: finalValue += special_raster_block.value(y, x) # Then the coarse elevation value if coarse_elevation_raster_block is not None: additionalValue, errorMessage = CostRasterCreatorHelper.CalculateCoarseElevationCost( y, x, coarse_elevation_raster_block, coarse_elevation_costs, pixelSide) finalValue += additionalValue if errorMessage is not None: errorMessages.append(errorMessage) # feedback.pushInfo("After coarse elevation, final value is " + str(finalValue)) # Then the fine water value if fine_water_raster_block is not None: finalValue += CostRasterCreatorHelper.CalculateFineWaterCost( y, x, fine_water_raster_block, fine_water_cost, pixelSide) # feedback.pushInfo("After fine water, final value is " + str(finalValue)) # Then, we multiply everything with the fine elevation cost. if fine_elevation_raster_block is not None: finalValue, errorMessage = CostRasterCreatorHelper.CalculateFineElevationCost( y, x, fine_elevation_raster_block, fine_elevation_costs, finalValue) if errorMessage is not None: errorMessages.append(errorMessage) # feedback.pushInfo("After fine elevation, final value is " + str(finalValue)) dataBlock.setValue(y, x, float(finalValue)) progress += 1 feedback.setProgress( 100 * (progress / (dataBlock.height() * dataBlock.width()))) # We write the values in the provider of our files provider.writeBlock(dataBlock, 1) # We stop the edition of the output raster provider.setEditable(False) # We display the warning messages about the thresholds if len(errorMessages) > 0: above = 0 below = 0 for errorMessage in errorMessages: if errorMessage == "Above": above += 1 elif errorMessage == "Below": below += 1 feedback.pushInfo( self. tr("WARNING : There were " + str(below) + " situations where the value of a pixel was under" " the lowest threshold given as a parameter; and " + str(above) + " when it was above the" " highest. In those cases, the lowest or highest value of the parameter range was used." " To avoid that, please make sure to use thresholds that cover all of the range of values in" " your rasters.")) # We make the output return {self.OUTPUT: outputFile}
def exportRaster(layer, count, layersFolder, feedback, iface, matchCRS): feedback.showFeedback("Exporting %s to PNG..." % layer.name()) name_ts = (safeName(layer.name()) + unicode(count) + unicode(int(time.time()))) # We need to create a new file to export style piped_file = os.path.join(tempfile.gettempdir(), name_ts + '_piped.tif') piped_extent = layer.extent() piped_width = layer.height() piped_height = layer.width() piped_crs = layer.crs() piped_renderer = layer.renderer() piped_provider = layer.dataProvider() pipe = QgsRasterPipe() pipe.set(piped_provider.clone()) pipe.set(piped_renderer.clone()) file_writer = QgsRasterFileWriter(piped_file) file_writer.writeRaster(pipe, piped_height, -1, piped_extent, piped_crs) # Export layer as PNG out_raster = os.path.join(layersFolder, safeName(layer.name()) + "_" + unicode(count) + ".png") projectCRS = iface.mapCanvas().mapSettings().destinationCrs() if not (matchCRS and layer.crs() == projectCRS): # Extent of the layer in EPSG:3857 crsSrc = layer.crs() crsDest = QgsCoordinateReferenceSystem(3857) try: xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) except: xform = QgsCoordinateTransform(crsSrc, crsDest) extentRep = xform.transformBoundingBox(layer.extent()) extentRepNew = ','.join([unicode(extentRep.xMinimum()), unicode(extentRep.xMaximum()), unicode(extentRep.yMinimum()), unicode(extentRep.yMaximum())]) # Reproject in 3857 piped_3857 = os.path.join(tempfile.gettempdir(), name_ts + '_piped_3857.tif') qgis_version = Qgis.QGIS_VERSION old_stdout = sys.stdout sys.stdout = mystdout = StringIO() try: processing.algorithmHelp("gdal:warpreproject") except: pass sys.stdout = old_stdout params = { "INPUT": piped_file, "SOURCE_CRS": layer.crs().authid(), "TARGET_CRS": "EPSG:3857", "NODATA": 0, "TARGET_RESOLUTION": 0, "RESAMPLING": 2, "TARGET_EXTENT": extentRepNew, "EXT_CRS": "EPSG:3857", "TARGET_EXTENT_CRS": "EPSG:3857", "DATA_TYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "MULTITHREADING": False, "COPY_SUBDATASETS": False, "EXTRA": "", "OUTPUT": piped_3857 } warpArgs = {} lines = mystdout.getvalue() for count, line in enumerate(lines.split("\n")): if count != 0 and ":" in line: try: k = line.split(":")[0] warpArgs[k] = params[k] except: pass try: processing.run("gdal:warpreproject", warpArgs) except: shutil.copyfile(piped_file, piped_3857) try: processing.run("gdal:translate", {"INPUT": piped_3857, "OUTSIZE": 100, "OUTSIZE_PERC": True, "NODATA": 0, "EXPAND": 0, "TARGET_CRS": "", "PROJWIN": extentRepNew, "SDS": False, "DATA_TYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "COPY_SUBDATASETS": False, "OPTIONS": "", "OUTPUT": out_raster}) except: shutil.copyfile(piped_3857, out_raster) else: srcExtent = ','.join([unicode(piped_extent.xMinimum()), unicode(piped_extent.xMaximum()), unicode(piped_extent.yMinimum()), unicode(piped_extent.yMaximum())]) processing.run("gdal:translate", {"INPUT": piped_file, "OUTSIZE": 100, "OUTSIZE_PERC": True, "NODATA": 0, "EXPAND": 0, "TARGET_CRS": "", "PROJWIN": srcExtent, "SDS": False, "DATA_TYPE": 0, "COMPRESS": 4, "JPEGCOMPRESSION": 75, "ZLEVEL": 6, "PREDICTOR": 1, "TILED": False, "BIGTIFF": 0, "TFW": False, "COPY_SUBDATASETS": False, "OPTIONS": "", "OUTPUT": out_raster})
def processAlgorithm(self, parameters, context, feedback): ''' Here is where the processing itself takes place. ''' from PIL import ( Image, ImageDraw, ) import numpy source = self.parameterAsSource(parameters, self.INPUT, context) resolution = self.parameterAsDouble(parameters, self.RESOLUTION, context) outpath = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) result = {self.OUTPUT: outpath} # Compute the number of steps to display within the progress bar total = 100.0 / source.featureCount() if source.featureCount() else 0 # Calculate the output extent extent = source.sourceExtent() xmin = extent.xMinimum() ymax = extent.yMaximum() xsize = int((extent.xMaximum() - xmin) / resolution) + 1 ysize = int((ymax - extent.yMinimum()) / resolution) + 1 if xsize > 50000 or ysize > 50000: feedback.reportError( self.tr('Output raster size is too big: {}x{}!').format( xsize, ysize), True) # fatalError = true has no effect feedback.cancel() return result feedback.pushConsoleInfo( self.tr('Output raster size is {}x{}').format(xsize, ysize)) # Create output buffer density = numpy.zeros((ysize, xsize), dtype=numpy.uint16) # Create geometry mask buffer mask = Image.new('1', (xsize, ysize), 0) draw = ImageDraw.Draw(mask) # Iterate over features from source features = source.getFeatures() for current, feature in enumerate(features): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return result # Convert feature geometry to the image coordinates geometry = feature.geometry() geometry.convertToSingleType() polygon = geometry.asPolygon() points = [] for p in polygon: for x, y in p: x = (x - xmin) / resolution y = (ymax - y) / resolution points.append((x, y)) # Generate geometry mask draw.polygon(points, 1) # Add geometry mask to the result raster density = numpy.add(density, numpy.array(mask)) # Reset the mask draw.rectangle([0, 0, xsize, ysize], fill=0) # Update the progress bar feedback.setProgress(int(current * total)) # Write output raster writer = QgsRasterFileWriter(outpath) provider = writer.createOneBandRaster(Qgis.UInt16, xsize, ysize, extent, source.sourceCrs()) provider.write(density.astype('H').tostring(), 1, xsize, ysize, 0, 0) density = None draw = None mask = None return result
pcolor = [] pcolor.append(QgsColorRampShader.ColorRampItem(1, QColor("#d2ca97"))) pcolor.append(QgsColorRampShader.ColorRampItem(2, QColor("#f7f7f7"))) pcolor.append(QgsColorRampShader.ColorRampItem(3, QColor("#a1d99b"))) pcolor.append(QgsColorRampShader.ColorRampItem(4, QColor("#41ab5d"))) pcolor.append(QgsColorRampShader.ColorRampItem(5, QColor("#006d2c"))) pcolor.append(QgsColorRampShader.ColorRampItem(6, QColor("#00441b"))) renderer = QgsPalettedRasterRenderer(layer.dataProvider(), 1, QgsPalettedRasterRenderer.colorTableToClassData(pcolor)) layer.setRenderer(renderer) extent = layer.extent() width, height = layer.width(), layer.height() renderer = layer.renderer() provider = layer.dataProvider() crs = layer.crs().toWkt() pipe = QgsRasterPipe() pipe.set(provider.clone()) pipe.set(renderer.clone()) file_writer = QgsRasterFileWriter("C:/temp/naip/classified_res.tif") file_writer.writeRaster(pipe, width, height, extent, layer.crs()) print("Done!")
def processAlgorithm(self, parameters, context, feedback): inp_rast = self.parameterAsRasterLayer(parameters, self.INPUT, context) grib_filename = self.parameterAsString(parameters, self.OUTPUT, context) if not grib_filename: raise QgsProcessingException( self.tr('You need to specify output filename.')) idp = inp_rast.dataProvider() map_settings = iface.mapCanvas().mapSettings() crs = map_settings.destinationCrs() outputFormat = QgsRasterFileWriter.driverForExtension('.tif') height = inp_rast.height() width = inp_rast.width() inp_block = idp.block(1, idp.extent(), width, height) rfw = QgsRasterFileWriter(grib_filename + '.tif') rfw.setOutputProviderKey('gdal') rfw.setOutputFormat(outputFormat) rdp = rfw.createMultiBandRaster(Qgis.Float32, width, height, idp.extent(), crs, 2) rdp.setEditable(True) x_block = QgsRasterBlock(Qgis.Float32, width, height) y_block = QgsRasterBlock(Qgis.Float32, width, height) diag = 1. / sqrt(2) # resulting raster has no NODATA value set, which # is not treated correctly in MDAL 0.2.0. See # see https://github.com/lutraconsulting/MDAL/issues/104 # therefore set some small value to overcome the issue dir_map = { 0: (1e-7, 1), 1: (diag, diag), 2: (1, 1e-7), 3: (diag, -diag), 4: (1e-7, -1), 5: (-diag, -diag), 6: (-1, 1e-7), 7: (-diag, diag), 255: (0, 0) } for row in range(height): for col in range(width): dir_ind = inp_block.value(row, col) try: x_val, y_val = dir_map.get(dir_ind, 255) except TypeError: x_val, y_val = (0, 0) x_block.setValue(row, col, x_val) y_block.setValue(row, col, y_val) rdp.writeBlock(x_block, 1) rdp.writeBlock(y_block, 2) rdp.setNoDataValue(1, inp_block.noDataValue()) rdp.setNoDataValue(2, inp_block.noDataValue()) rdp.setEditable(False) # rewrite the resulting raster as GRIB using GDAL for setting metadata res_tif = gdal.Open(grib_filename + '.tif') grib_driver = gdal.GetDriverByName('GRIB') grib = grib_driver.CreateCopy(grib_filename, res_tif) band_names = ('x-flow', 'y-flow') for i in range(2): band_nr = i + 1 band_name = band_names[i] grib_band = grib.GetRasterBand(band_nr) grib_band.SetMetadataItem('grib_comment', band_name) grib_band.SetNoDataValue(255) grib_band.SetDescription(band_name) res_tif_band_array = res_tif.GetRasterBand(band_nr).ReadAsArray() grib_band.WriteArray(res_tif_band_array) feedback.setProgress(band_nr * 50) grib = None return {self.OUTPUT: grib_filename}
def Color(self, file_in, calcType=None): """ Color the Inbound file (Essentially the File we JUST exported) and display it to screen) :param file_in: The file that was just exported :type file_in: FileImport :return: TO SCREEN Rendered Image :rtype: None """ k = self.iface.addRasterLayer(file_in.filePath, file_in.baseName) stats = k.dataProvider().bandStatistics(1, QgsRasterBandStats.All, k.extent(), 0) minimum = stats.minimumValue maximum = stats.maximumValue self.com.log("Color func: [Min val: {0} | Max val: {1}".format( str(minimum), str(maximum)), level=0) ramp_shader = QgsColorRampShader() ramp_shader.setColorRampType(QgsColorRampShader.INTERPOLATED) if calcType is None: color_list = [ QgsColorRampShader.ColorRampItem(minimum, QColor(255, 0, 0)), QgsColorRampShader.ColorRampItem(0, QColor(255, 207, 74, 255)), QgsColorRampShader.ColorRampItem(maximum, QColor(0, 255, 0)) ] elif calcType == "EVI": color_list = [ QgsColorRampShader.ColorRampItem(-2, QColor(255, 0, 0)), QgsColorRampShader.ColorRampItem(0, QColor(255, 207, 74, 255)), QgsColorRampShader.ColorRampItem(2, QColor(0, 255, 0)) ] else: color_list = [ QgsColorRampShader.ColorRampItem(minimum, QColor(255, 0, 0)), QgsColorRampShader.ColorRampItem(0, QColor(255, 207, 74, 255)), QgsColorRampShader.ColorRampItem(maximum, QColor(0, 255, 0)) ] ramp_shader.setColorRampItemList(color_list) shader = QgsRasterShader() shader.setRasterShaderFunction(ramp_shader) renderer = QgsSingleBandPseudoColorRenderer(k.dataProvider(), 1, shader) k.setRenderer(renderer) """ Export colored image to file """ export_path = file_in.filePath + ".colored.tif" file_writer = QgsRasterFileWriter(export_path) pipe = QgsRasterPipe() provide = k.dataProvider() # Pipe Setter if not pipe.set(provide.clone()): self.com.error(Bold="PipeProviderError:", String="Cannot set pipe provider", level=1, duration=3) self.com.log( "mainPlug - Color: Pipe provider error on line 473, Continuing...", level=1) self.com.log(str(pipe.renderer()), level=0) pipe.set(renderer.clone()) file_writer.writeRaster(pipe, provide.xSize(), provide.ySize(), provide.extent(), provide.crs())
def exportRasterLayer(self, layer, destinationFile, options=None): outputFormat = self.settings[ 'rasterFormat'] if 'rasterFormat' in self.settings else 'GTiff' if os.path.splitext(destinationFile)[1] == '': formats = QgsRasterFileWriter.extensionsForFormat(outputFormat) if len(formats) > 0: destinationFile = '{}.{}'.format(destinationFile, formats[0]) provider = layer.dataProvider() cols = provider.xSize() rows = provider.ySize() if not provider.capabilities() & QgsRasterDataProvider.Size: k = float(provider.extent().width()) / float( provider.extent().height()) cols = RASTER_SIZE * k rows = RASTER_SIZE pipe = QgsRasterPipe() if not pipe.set(provider.clone()): QgsMessageLog.logMessage( self. tr('Failed to export layer "{layer}": Cannot set pipe provider.' ).format(layer=layer.name()), 'QConsolidate', Qgis.Warning) return False, None nodata = {} for i in range(1, provider.bandCount() + 1): if provider.sourceHasNoDataValue(i): value = provider.sourceNoDataValue(i) nodata[i] = QgsRasterRange(value, value) nuller = QgsRasterNuller() for band, value in nodata.items(): nuller.setNoData(band, [value]) if not pipe.insert(1, nuller): QgsMessageLog.logMessage( self.tr( 'Failed to export layer "{layer}": Cannot set pipe nuller.' ).format(layer=layer.name()), 'QConsolidate', Qgis.Warning) return False, None writer = QgsRasterFileWriter(destinationFile) writer.setOutputFormat(outputFormat) if options is not None: writer.setCreateOptions(options) success = True error = writer.writeRaster(pipe, cols, rows, provider.extent(), provider.crs()) if error != QgsRasterFileWriter.NoError: QgsMessageLog.logMessage( self.tr('Failed to export layer "{layer}": {message}.').format( layer=layer.name(), message=error), 'QConsolidate', Qgis.Warning) success = False return success, destinationFile
def exportLayer(layer, fields=None, toShapefile=False, path=None, force=False, log=None): filename = layer.source().split("|")[0] destFilename = layer.name() fields = fields or [] if layer.type() == layer.VectorLayer: if toShapefile and ( force or layer.fields().count() != len(fields) or (os.path.splitext(filename.lower())[1] != EXT_SHAPEFILE)): # Export with Shapefile extension ext = EXT_SHAPEFILE elif force or os.path.splitext(filename.lower())[1] != EXT_GEOPACKAGE or \ layer.fields().count() != len(fields) or not isSingleTableGpkg(filename): # Export with GeoPackage extension ext = EXT_GEOPACKAGE else: # No need to export if log is not None: log.logInfo( QCoreApplication.translate( "GeocatBridge", f"No need to export layer {destFilename} stored at {filename}" )) return filename # Perform GeoPackage or Shapefile export attrs = [ i for i, f in enumerate(layer.fields()) if len(fields) == 0 or f.name() in fields ] output = path or tempFilenameInTempFolder(destFilename + ext) if Qgis.QGIS_VERSION_INT < 31003: # Use writeAsVectorFormat for QGIS versions < 3.10.3 for backwards compatibility QgsVectorFileWriter.writeAsVectorFormat( layer, output, fileEncoding="UTF-8", attributes=attrs, driverName="ESRI Shapefile" if ext == EXT_SHAPEFILE else "") else: # Use writeAsVectorFormatV2 for QGIS versions >= 3.10.3 to avoid DeprecationWarnings transform_ctx = QgsProject.instance().transformContext() options = QgsVectorFileWriter.SaveVectorOptions() options.fileEncoding = "UTF-8" options.attributes = attrs options.driverName = "ESRI Shapefile" if ext == EXT_SHAPEFILE else "" QgsVectorFileWriter.writeAsVectorFormatV2(layer, output, transform_ctx, options) if log is not None: log.logInfo( QCoreApplication.translate( "GeocatBridge", f"Layer {destFilename} exported to {output}")) return output else: # Export raster if force or not filename.lower().endswith("tif"): output = path or tempFilenameInTempFolder(destFilename + ".tif") writer = QgsRasterFileWriter(output) writer.setOutputFormat("GTiff") writer.writeRaster(layer.pipe(), layer.width(), layer.height(), layer.extent(), layer.crs()) del writer if log is not None: log.logInfo( QCoreApplication.translate( "GeocatBridge", f"Layer {destFilename} exported to {output}")) return output else: if log is not None: log.logInfo( QCoreApplication.translate( "GeocatBridge", f"No need to export layer {destFilename} stored at {filename}" )) return filename