def write_image( feedback, tex_layer, tex_pixel_size, destination_crs, destination_extent, filepath, imagetype, ): """ Save current QGIS canvas to image file. """ feedback.pushInfo("Rendering texture image (timeout in 30s)...") project = QgsProject.instance() # Get extent size in meters d = QgsDistanceArea() d.setSourceCrs( crs=destination_crs, context=QgsProject.instance().transformContext() ) p00, p10, p01 = ( QgsPointXY(destination_extent.xMinimum(), destination_extent.yMinimum()), QgsPointXY(destination_extent.xMaximum(), destination_extent.yMinimum()), QgsPointXY(destination_extent.xMinimum(), destination_extent.yMaximum()), ) wm = d.measureLine(p00, p10) # euclidean dist, extent width in m hm = d.measureLine(p00, p01) # euclidean dist, extent height in m # Image settings and texture layer choice settings = QgsMapSettings() # build settings settings.setDestinationCrs(destination_crs) # set output crs settings.setExtent(destination_extent) # in destination_crs if tex_layer: layers = (tex_layer,) # chosen texture layer else: canvas = iface.mapCanvas() layers = canvas.layers() # get visible layers wpix = int(wm / tex_pixel_size) hpix = int(hm / tex_pixel_size) settings.setOutputSize(QSize(wpix, hpix)) settings.setLayers(layers) feedback.pushInfo( f"Requested texture size: {wm:.2f}x{hm:.2f} m, {wpix}x{hpix} pixels." ) # Render and save image render = QgsMapRendererParallelJob(settings) render.start() t0 = time.time() while render.isActive(): dt = time.time() - t0 QCoreApplication.processEvents() if feedback.isCanceled(): render.cancelWithoutBlocking() return if dt >= 30.0: render.cancelWithoutBlocking() feedback.reportError("Render timed out, no texture saved.") return image = render.renderedImage() try: image.save(filepath, imagetype) except IOError: raise QgsProcessingException( f"Texture not writable to <{filepath}>, cannot proceed." ) feedback.pushInfo(f"Texture saved in {dt:.2f} seconds.")
def write_texture( feedback, tex_layer, tex_extent, tex_pixel_size, utm_crs, # destination_crs filepath, imagetype, ): """ Crop and save texture to image file. """ # Calc tex_extent size in meters (it is in utm) tex_extent_xm = tex_extent.xMaximum() - tex_extent.xMinimum() tex_extent_ym = tex_extent.yMaximum() - tex_extent.yMinimum() # Calc tex_extent size in pixels tex_extent_xpix = int(tex_extent_xm / tex_pixel_size) tex_extent_ypix = int(tex_extent_ym / tex_pixel_size) # Choose exporting layers if tex_layer: # use user tex layer layers = (tex_layer,) else: # no user tex layer, use map canvas canvas = iface.mapCanvas() layers = canvas.layers() # Image settings and texture layer choice settings = QgsMapSettings() # build settings settings.setDestinationCrs(utm_crs) # set output crs settings.setExtent(tex_extent) # in utm_crs settings.setOutputSize(QSize(tex_extent_xpix, tex_extent_ypix)) settings.setLayers(layers) feedback.pushInfo( f"Texture size: {tex_extent_xpix} x {tex_extent_ypix} pixels, {tex_extent_xm:.1f} x {tex_extent_ym:.1f} meters" ) # Render and save image render = QgsMapRendererParallelJob(settings) render.start() t0 = time.time() while render.isActive(): dt = time.time() - t0 QCoreApplication.processEvents() if feedback.isCanceled(): render.cancelWithoutBlocking() return if dt >= 30.0: render.cancelWithoutBlocking() feedback.reportError("Texture render timed out, no texture saved.") return image = render.renderedImage() try: image.save(filepath, imagetype) except IOError: raise QgsProcessingException( f"Texture not writable to <{filepath}>, cannot proceed." ) feedback.pushInfo(f"Saved (in {dt:.2f} s): <{filepath}>")