def createImageParams():
      def finished():
        def addParams():
          def getJsonImages():
            vmap = {}
            for l in self.paramProcess['layerImages']:
              vmap[ l.name() ] = l.source()
            return json.dumps( vmap )

          e =  self.paramProcess['canvas'].extent()
          imgWidth, imgHeight = image.width(), image.height()
          resX, resY = e.width() / imgWidth, e.height() / imgHeight
          self.paramProcess['json_images'] = getJsonImages()
          self.paramProcess['crs_map'] = self.paramProcess['canvas'].mapSettings().destinationCrs().authid()
          self.paramProcess['extent_map'] = e.asWktCoordinates() # xMin, yMin, xMax, yMax
          self.paramProcess['res'] = { 'X': resX, 'Y': resY } 

        image = job.renderedImage()
        if bool( self.paramProcess['canvas'].property('retro') ):
          image = image.scaled( image.width() / 3, image.height() / 3 )
          image = image.convertToFormat( QImage.Format_Indexed8, Qt.OrderedDither | Qt.OrderedAlphaDither )
        image.save( self.paramProcess['pathfileImage'], "TIFF", 100 ) # 100: Uncompressed
        addParams()

      settings = QgsMapSettings( self.paramProcess['canvas'].mapSettings() )
      settings.setBackgroundColor( QColor( Qt.transparent ) )
      
      layers = self.paramProcess['layerImages']
      if 'layerPolygon' in self.paramProcess:
        layers = [ self.paramProcess['layerPolygon'] ] + layers
      settings.setLayers( layers )
      job = QgsMapRendererParallelJob( settings ) 
      job.start()
      job.finished.connect( finished) 
      job.waitForFinished()
def render_layer():

    projectpath = Path('./data/france_parts.qgs')

    prj = QgsProject()
    prj.read(str(projectpath.absolute()))

    layers = layers = prj.mapLayersByName('france_parts')

    xt = layers[0].extent()
    width = 1200
    height = int(width * xt.height() / xt.width())

    options = QgsMapSettings()
    options.setLayers(layers)
    options.setBackgroundColor(QColor(255, 255, 255))
    options.setOutputSize(QSize(width, height))
    options.setExtent(xt)

    render = QgsMapRendererParallelJob(options)
    render.start()
    render.waitForFinished()

    image = render.renderedImage()

    return image
Пример #3
0
    def test_render_via_job(self):
        """
        Test rendering an annotation layer via a map render job
        """
        layer = QgsAnnotationLayer('test', QgsAnnotationLayer.LayerOptions(QgsProject.instance().transformContext()))
        self.assertTrue(layer.isValid())

        item = QgsAnnotationPolygonItem(
            QgsPolygon(QgsLineString([QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13)])))
        item.setSymbol(
            QgsFillSymbol.createSimple({'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2'}))
        item.setZIndex(1)
        i1_id = layer.addItem(item)

        item = QgsAnnotationLineItem(QgsLineString([QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)]))
        item.setSymbol(QgsLineSymbol.createSimple({'color': '#ffff00', 'line_width': '3'}))
        item.setZIndex(2)
        i2_id = layer.addItem(item)

        item = QgsAnnotationMarkerItem(QgsPoint(12, 13))
        item.setSymbol(QgsMarkerSymbol.createSimple({'color': '100,200,200', 'size': '6', 'outline_color': 'black'}))
        item.setZIndex(3)
        i3_id = layer.addItem(item)

        layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))

        settings = QgsMapSettings()
        settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        settings.setExtent(QgsRectangle(10, 10, 18, 18))
        settings.setOutputSize(QSize(200, 200))
        settings.setLayers([layer])

        job = QgsMapRendererParallelJob(settings)
        job.start()
        job.waitForFinished()

        # check rendered item results
        item_results = job.takeRenderedItemResults()
        item_details = item_results.renderedItems()
        self.assertEqual(len(item_details), 3)
        self.assertEqual([i.layerId() for i in item_details], [layer.id()] * 3)
        self.assertCountEqual([i.itemId() for i in item_details], [i1_id, i2_id, i3_id])
        self.assertCountEqual(
            [i.itemId() for i in item_results.renderedAnnotationItemsInBounds(QgsRectangle(0, 0, 1, 1))], [])
        self.assertCountEqual(
            [i.itemId() for i in item_results.renderedAnnotationItemsInBounds(QgsRectangle(10, 10, 11, 18))], [i2_id])
        self.assertCountEqual(
            [i.itemId() for i in item_results.renderedAnnotationItemsInBounds(QgsRectangle(10, 10, 12, 18))],
            [i1_id, i2_id, i3_id])

        # bounds should be in map crs
        self.assertEqual([i.boundingBox() for i in item_details if i.itemId() == i1_id][0],
                         QgsRectangle(11.5, 13, 12, 13.5))
        self.assertEqual([i.boundingBox() for i in item_details if i.itemId() == i2_id][0],
                         QgsRectangle(11, 13, 12, 15))
        self.assertEqual([i.boundingBox().toString(1) for i in item_details if i.itemId() == i3_id][0],
                         '11.5,12.5 : 12.5,13.5')
Пример #4
0
def render_layer(settings, layer, width, height):
    settings.setLayers([layer.id()])
    settings.setFlags(settings.flags() ^ QgsMapSettings.Antialiasing)
    settings.setOutputSize(QSize(width, height))
    job = QgsMapRendererParallelJob(settings)
    job.start()
    job.waitForFinished()
    image = job.renderedImage()
    # image.save(r"/media/nathan/Data/dev/qgis-term/{}.jpg".format(layer.name()))
    return image
Пример #5
0
def render(name, settings):
    settings.setOutputSize(IMAGE_SIZE)
    job = QgsMapRendererParallelJob(settings)
    #job = QgsMapRendererSequentialJob(settings)
    job.start()
    job.waitForFinished()
    image = job.renderedImage()
    if not os.path.exists(image_path):
        os.mkdir(image_path)
    image.save(os.path.join(image_path, name + '.png'))
    return job.renderingTime()
Пример #6
0
  def setMap(self):
    def finished():
      super(SwipeMap, self).setContent( job.renderedImage(), self.canvas.extent() )

    settings = QgsMapSettings( self.canvas.mapSettings() )
    settings.setLayers( self.layers )
    
    job = QgsMapRendererParallelJob( settings) 
    job.start()
    job.finished.connect( finished) 
    job.waitForFinished()
Пример #7
0
def render(settings):
    """
    Render the given settings to a image and save to disk.
    name: The name of the final result file.
    settings: QgsMapSettings containing the settings to render
    exportpath: The folder for the images to be exported to.
    """
    job = QgsMapRendererParallelJob(settings)
    #job = QgsMapRendererSequentialJob(settings)
    job.start()
    job.waitForFinished()
    image = job.renderedImage()
    return image, job.renderingTime()
Пример #8
0
def render_wms_to_image(xyz=True, extent=EXTENT, width=64, height=60):
    """
    :type xyz: bool
    :type extent: tuple
    :type width: int
    :type height: int
    :rtype: QImage
    """
    # p = QgsProject.instance()
    # p = QgsProject()
    uri = QgsDataSourceUri()
    if xyz:
        uri.setParam('type', 'xyz')
        uri.setParam('crs', 'EPSG:3857')
        uri.setParam('format', '')
        # uri.setParam('zmin', '0')
        # uri.setParam('zmax', '18')
        uri.setParam('url', XYZ_URL)
    else:
        uri.setParam('tileMatrixSet', 'GoogleMapsCompatible23')
        uri.setParam('crs', 'EPSG:3857')
        uri.setParam('format', 'image/png')
        uri.setParam('styles', '')
        uri.setParam('layers', 'Combined scene layer')
        uri.setParam('url', WMS_URL)

    # Important to do this conversion, else WMS provider will double encode;
    #   instead of just `str(uri.encodedUri())`, which outputs "b'uri'"
    # This coerces QByteArray -> str ... assuming UTF-8 is valid.
    final_uri = bytes(uri.encodedUri()).decode("utf-8")
    layer = QgsRasterLayer(final_uri, "scene_layer", "wms")

    if not layer.isValid():
        print('Layer is not valid')
        return QImage()
    # p.addMapLayer(layer)

    settings = QgsMapSettings()
    settings.setExtent(QgsRectangle(*extent))
    settings.setOutputSize(QSize(width, height))
    settings.setLayers([layer])

    job = QgsMapRendererParallelJob(settings)
    job.start()

    # This blocks...
    # It should really be a QEventLoop or QTimer that checks for finished()
    # Any intermediate image can safely be pulled from renderedImage()
    job.waitForFinished()

    return job.renderedImage()
Пример #9
0
def renderMapToImage(mapsettings, parallel=False):
    """
    Render current map to an image, via multi-threaded renderer
    :param QgsMapSettings mapsettings:
    :param bool parallel: Do parallel or sequential render job
    :rtype: QImage
    """
    if parallel:
        job = QgsMapRendererParallelJob(mapsettings)
    else:
        job = QgsMapRendererSequentialJob(mapsettings)
    job.start()
    job.waitForFinished()

    return job.renderedImage()
Пример #10
0
    def setMap(self):
        def finished():
            super(SwipeMap, self).setContent(job.renderedImage(),
                                             self.canvas.extent())

        if len(self.layers) == 0:
            return

        settings = QgsMapSettings(self.canvas.mapSettings())
        settings.setLayers(self.layers)

        job = QgsMapRendererParallelJob(settings)
        job.start()
        job.finished.connect(finished)
        job.waitForFinished()
Пример #11
0
def renderMapToImage(mapsettings, parallel=False):
    """
    Render current map to an image, via multi-threaded renderer
    :param QgsMapSettings mapsettings:
    :param bool parallel: Do parallel or sequential render job
    :rtype: QImage
    """
    if parallel:
        job = QgsMapRendererParallelJob(mapsettings)
    else:
        job = QgsMapRendererSequentialJob(mapsettings)
    job.start()
    job.waitForFinished()

    return job.renderedImage()
    def _process(self):
        def finished():
            image = job.renderedImage()
            if bool(self.data['canvas'].property('retro')):
                image = image.scaled(image.width() / 3, image.height() / 3)
                image = image.convertToFormat(
                    QImage.Format_Indexed8,
                    Qt.OrderedDither | Qt.OrderedAlphaDither)
            image.save(self.data['filepath'], "TIFF", 100)  # 100: Uncompressed
            self._setParamsSendData(image)

        settings = QgsMapSettings(self.data['canvas'].mapSettings())
        settings.setBackgroundColor(QColor(Qt.transparent))

        settings.setLayers(self.data['layers'])
        job = QgsMapRendererParallelJob(settings)
        job.start()
        job.finished.connect(finished)
        job.waitForFinished()
Пример #13
0
    def render_qgis_map(self):
        logging.info("Rendering QGIS map")
        # Gross. Fix me
        if not self.settings and project:
            self.settings = project.map_settings

        # TODO We should only get visible layers here but this will do for now
        self.settings.setLayers(QgsMapLayerRegistry.instance().mapLayers().keys())
        self.settings.setFlags(self.settings.flags() ^ QgsMapSettings.Antialiasing)
        logging.info(self.settings.flags())
        logging.info(self.settings.testFlag(QgsMapSettings.Antialiasing))
        height, width = self.mapwin.getmaxyx()
        logging.info("Setting output size to {}, {}".format(width, height))
        self.settings.setOutputSize(QSize(width, height))
        job = QgsMapRendererParallelJob(self.settings)
        job.start()
        job.waitForFinished()
        image = job.renderedImage()
        logging.info("Saving rendered image for checks...")
        image.save(r"F:\dev\qgis-term\render.jpg")
        return image
Пример #14
0
    def create_image(self, extent, width, height, canvas_name, output_dir):
        '''
        This method create an image

        :param extent: Extent
        :param width: Output image width
        :param height: Output image height
        :param canvas_name: Map name
        :param output_dir: Output directory for image
        '''

        if not extent:
            raise_exception('extent is empty')

        if not width:
            raise_exception('width is empty')

        if not height:
            raise_exception('height is empty')

        if not canvas_name:
            raise_exception('canvas name is empty')

        if not output_dir:
            raise_exception('output_dir is empty')

        file_name = '{0}/{1}.png'.format(output_dir, canvas_name)
        settings = QgsMapSettings()
        settings.setLayers(iface.mapCanvas().layers())
        settings.setBackgroundColor(QColor(255, 255, 255))
        settings.setOutputSize(QSize(width, height))
        settings.setExtent(extent)
        render = QgsMapRendererParallelJob(settings)
        render.start()
        render.waitForFinished()
        image = render.renderedImage()
        image.save(file_name, "png")

        return file_name
Пример #15
0
def write_image(destination_crs, extent, filepath, imagetype):
    """
    Save current QGIS canvas to image file.
    """
    settings = QgsMapSettings()  # build settings
    settings.setDestinationCrs(destination_crs)  # set output crs
    settings.setExtent(extent)  # in destination_crs
    layers = iface.mapCanvas().layers()  # get visible layers
    settings.setLayers(layers)

    w = 1920
    h = int((extent.yMaximum() - extent.yMinimum()) /
            (extent.xMaximum() - extent.xMinimum()) * w)
    settings.setOutputSize(QSize(w, h))
    settings.setOutputDpi(200)

    render = QgsMapRendererParallelJob(settings)
    render.start()
    render.waitForFinished()
    image = render.renderedImage()
    try:
        image.save(filepath, imagetype)
    except IOError:
        raise QgsProcessingException(f"Image not writable at <{filepath}>")
Пример #16
0
    def update_summary_sheet(self,lyr=None, force=None):
        '''
        Creates a summary sheet with thumbnail, layer metadata and online view link
        '''
        #create a layer snapshot and upload it to google drive

        if not lyr:
            lyr = self.lyr

        mapbox_style = self.service_sheet.sheet_cell('settings!A5')
        if not mapbox_style:
            logger("migrating mapbox style")
            self.service_sheet.set_style_mapbox(self.layer_style_to_json(self.lyr))
        
        if not force and not self.dirty and not self.restyled:
            return

        if self.restyled:
            self.service_sheet.set_style_qgis(self.layer_style_to_xml(self.lyr))
            self.service_sheet.set_style_sld(self.SLD_to_xml(self.lyr))
            self.service_sheet.set_style_mapbox(self.layer_style_to_json(self.lyr))
            self.saveMetadataState()
        
        canvas = QgsMapCanvas()
        canvas.resize(QSize(600,600))
        canvas.setCanvasColor(Qt.white)
        canvas.setExtent(lyr.extent())
        canvas.setLayers([lyr])
        canvas.refresh()
        canvas.update()
        settings = canvas.mapSettings()
        settings.setLayers([lyr])
        job = QgsMapRendererParallelJob(settings)
        job.start()
        job.waitForFinished()
        image = job.renderedImage()

        transparent_image = QImage(image.width(), image.height(), QImage.Format_ARGB32)
        transparent_image.fill(Qt.transparent)
        p = QPainter(transparent_image)
        mask = image.createMaskFromColor(QColor(255, 255, 255).rgb(), Qt.MaskInColor)
        p.setClipRegion(QRegion(QBitmap(QPixmap.fromImage(mask))))
        p.drawPixmap(0, 0, QPixmap.fromImage(image))
        p.end()

        tmp_path = os.path.join(self.parent.plugin_dir,self.service_sheet.name+".png")
        transparent_image.save(tmp_path,"PNG")
        image_istances = self.service_drive.list_files(mimeTypeFilter='image/png',filename=self.service_sheet.name+".png")
        for imagename, image_props in image_istances.items():
            self.service_drive.delete_file(image_props['id'])
        result = self.service_drive.upload_image(tmp_path)
        self.service_drive.add_permission(result['id'],'anyone','reader')
        webLink = result['webContentLink'] #'https://drive.google.com/uc?export=view&id='+result['id']
        logger("webLink:" + webLink)
        canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326))
        worldfile = QgsMapSettingsUtils.worldFileContent(settings)
        lonlat_min = self.transformToWGS84(QgsPointXY(canvas.extent().xMinimum(), canvas.extent().yMinimum()))
        lonlat_max = self.transformToWGS84(QgsPointXY(canvas.extent().xMaximum(), canvas.extent().yMaximum()))
        keymap_extent = [lonlat_min.x(),lonlat_min.y(),lonlat_max.x(),lonlat_max.y()]
        
        os.remove(tmp_path)
        #update layer metadata
        summary_id = self.service_sheet.add_sheet('summary', no_grid=True)
        appPropsUpdate = [
            ["keymap",webLink],
            ["worldfile",pack(worldfile)],
            ["keymap_extent", json.dumps(keymap_extent)]
        ]
        res = self.service_sheet.update_appProperties(self.spreadsheet_id,appPropsUpdate)
        
        self.saveMetadataState(metadata=self.get_layer_metadata())
        self.parent.public_db.setKey(self.spreadsheet_id, dict(self.get_layer_metadata()+appPropsUpdate),only_update=True)
        #merge cells to visualize snapshot and aaply image snapshot
        request_body = {
            'requests': [{
                'mergeCells': {
                    "range": {
                        "sheetId": summary_id,
                        "startRowIndex": 9,
                        "endRowIndex": 32,
                        "startColumnIndex": 0,
                        "endColumnIndex": 9,
                    },
                "mergeType": 'MERGE_ALL'
                }
            }]
        }
        self.service_sheet.service.spreadsheets().batchUpdate(spreadsheetId=self.spreadsheet_id, body=request_body).execute()
        self.service_sheet.set_sheet_cell('summary!A10','=IMAGE("%s",3)' % webLink)

        permissions = self.service_drive.file_property(self.spreadsheet_id,'permissions')
        for permission in permissions:
            if permission['type'] == 'anyone':
                public = True
                break
            else:
                public = False
        if public:
            update_range = 'summary!A9:B9'
            update_body = {
                "range": update_range,
                "values": [['public link', "https://enricofer.github.io/gdrive_provider/weblink/converter.html?spreadsheet_id="+self.spreadsheet_id]]
            }
            self.service_sheet.service.spreadsheets().values().update(spreadsheetId=self.spreadsheet_id,range=update_range, body=update_body, valueInputOption='USER_ENTERED').execute()

        #hide worksheets except summary
        sheets = self.service_sheet.get_sheets()
        #self.service_sheet.toggle_sheet('summary', sheets['summary'], hidden=None)
        for sheet_name,sheet_id in sheets.items():
            if not sheet_name == 'summary':
                self.service_sheet.toggle_sheet(sheet_name, sheet_id, hidden=True)
Пример #17
0
    def update_summary_sheet(self):
        '''
        Creates a summary sheet with thumbnail, layer metadata and online view link
        '''
        #create a layer snapshot and upload it to google drive
        mapbox_style = self.service_sheet.sheet_cell('settings!A5')
        if not mapbox_style:
            print "migrating mapbox style"
            self.service_sheet.set_style_mapbox(self.layer_style_to_json(self.lyr))
        if not self.dirty:
            return
        canvas = QgsMapCanvas()
        canvas.resize(QSize(300,300))
        canvas.setCanvasColor(Qt.white)
        canvas.setExtent(self.lyr.extent())
        canvas.setLayerSet([QgsMapCanvasLayer(self.lyr)])
        canvas.refresh()
        canvas.update()
        settings = canvas.mapSettings()
        settings.setLayers([self.lyr.id()])
        job = QgsMapRendererParallelJob(settings)
        job.start()
        job.waitForFinished()
        image = job.renderedImage()
        tmp_path = os.path.join(self.parent.plugin_dir,self.service_sheet.name+".png")
        image.save(tmp_path,"PNG")
        image_istances = self.service_drive.list_files(mimeTypeFilter='image/png',filename=self.service_sheet.name+".png")
        for imagename, image_props in image_istances.iteritems():
            print imagename, image_props['id']
            self.service_drive.delete_file(image_props['id'])
        result = self.service_drive.upload_image(tmp_path)
        print "UPLOADED", result
        self.service_drive.add_permission(result['id'],'anyone','reader')
        webLink = 'https://drive.google.com/uc?export=view&id='+result['id']
        os.remove(tmp_path)
        print 'result',result,webLink

        #update layer metadata
        summary_id = self.service_sheet.add_sheet('summary', no_grid=True)
        self.service_sheet.erase_cells('summary')
        metadata = self.get_layer_metadata()
        range = 'summary!A1:B8'
        update_body = {
            "range": range,
            "values": metadata,
        }
        print "update", self.service_sheet.service.spreadsheets().values().update(spreadsheetId=self.spreadsheet_id,range=range, body=update_body, valueInputOption='USER_ENTERED').execute()

        #merge cells to visualize snapshot and aaply image snapshot
        request_body = {
            'requests': [{
                'mergeCells': {
                    "range": {
                        "sheetId": summary_id,
                        "startRowIndex": 9,
                        "endRowIndex": 32,
                        "startColumnIndex": 0,
                        "endColumnIndex": 9,
                    },
                "mergeType": 'MERGE_ALL'
                }
            }]
        }
        print "merge", self.service_sheet.service.spreadsheets().batchUpdate(spreadsheetId=self.spreadsheet_id, body=request_body).execute()
        print "image", self.service_sheet.set_sheet_cell('summary!A10','=IMAGE("%s",3)' % webLink)

        permissions = self.service_drive.file_property(self.spreadsheet_id,'permissions')
        for permission in permissions:
            if permission['type'] == 'anyone':
                public = True
                break
            else:
                public = False
        if public:
            range = 'summary!A9:B9'
            update_body = {
                "range": range,
                "values": [['public link', "https://enricofer.github.io/GooGIS2CSV/converter.html?spreadsheet_id="+self.spreadsheet_id]]
            }
            print "update_public_link", self.service_sheet.service.spreadsheets().values().update(spreadsheetId=self.spreadsheet_id,range=range, body=update_body, valueInputOption='USER_ENTERED').execute()

        #hide worksheets except summary
        sheets = self.service_sheet.get_sheets()
        #self.service_sheet.toggle_sheet('summary', sheets['summary'], hidden=None)
        for sheet_name,sheet_id in sheets.iteritems():
            if not sheet_name == 'summary':
                print sheet_name, sheet_id
                self.service_sheet.toggle_sheet(sheet_name, sheet_id, hidden=True)
def render_scene_to_image(item_keys: List[str],
                          extent_json: Union[str, dict],
                          api_key: str,
                          node: Optional[PlanetNode] = None,
                          width: int = 512,
                          height: int = 512) -> QImage:

    img = QImage()

    if not item_keys:
        log.debug('No item type_id keys list object passed')
        return img

    if not extent_json:
        log.debug('Extent is invalid')
        return img

    if node and node.node_type() != NodeT.DAILY_SCENE:
        log.debug('Item type is not a Daily Scene')
        return img

    if not api_key:
        log.debug('No API in passed')
        return img

    # p = QgsProject.instance()

    ext: QgsRectangle = \
        qgsgeometry_from_geojson(extent_json).boundingBox()

    if ext.width() > ext.height():
        height = int(ext.height() / ext.width() * height)
    elif ext.height() > ext.width():
        width = int(ext.width() / ext.height() * width)

    # noinspection PyArgumentList
    transform = QgsCoordinateTransform(
        QgsCoordinateReferenceSystem("EPSG:4326"),
        QgsCoordinateReferenceSystem("EPSG:3857"), QgsProject.instance())

    transform_extent = transform.transformBoundingBox(ext)

    data_src_uri = tile_service_data_src_uri(item_keys, api_key)
    log.debug(f'data_src_uri:\n' f'{data_src_uri}')

    rlayer = QgsRasterLayer(data_src_uri, "scene_layer", "wms")

    if not rlayer.isValid():
        log.debug('Layer is not valid')
        return img

    # p.addMapLayer(rlayer)

    settings = QgsMapSettings()
    settings.setExtent(transform_extent)
    settings.setOutputSize(QSize(width, height))
    settings.setLayers([rlayer])

    job = QgsMapRendererParallelJob(settings)
    job.start()

    # This blocks...
    # It should really be a QEventLoop or QTimer that checks for finished()
    # Any intermediate image can safely be pulled from renderedImage()
    job.waitForFinished()

    return job.renderedImage()
Пример #19
0
    def make_coco_dataset(self):
        layers = QgsProject.instance().mapLayers().values()
        vectorlayers = [layer for layer in layers if layer.type() == VectorLayer]
        rasterLayers = [layer for layer in layers if layer.type() == RasterLayer]

        vectorlayer = vectorlayers[self.dlg.vectorlayerselector.currentIndex()]
        rasterlayer = rasterLayers[self.dlg.rasterlayerselector.currentIndex()]

        img_size = int(self.dlg.imagesizeselector.currentText())
        scale_realworld = int(self.dlg.zoomlevel.currentText())
        buffer_size = int(self.dlg.buffersize.text()) / 100
        target_dir = self.dlg.dirselectline.text()
        dataset_description = str(self.dlg.datasetdescription.text())
        contributor = str(self.dlg.creatorname.text())
        url = str(self.dlg.url.text())
        version = str(self.dlg.datasetversion.text())
        license = str(self.dlg.licenseselector.currentText())

        # to implement
        scale_to_fit = self.dlg.scaletofit.isChecked()
        use_fieldcategory = bool(self.dlg.usecategoryfields.isChecked())
        categoryfield = self.dlg.categoryfields.currentText()


        QgsMessageLog.logMessage(str(scale_to_fit), "cocotrainer", level=Qgis.Info)
        QgsMessageLog.logMessage(str(use_fieldcategory), "cocotrainer", level=Qgis.Info)

        # prepare directories
        os.makedirs(os.path.join(target_dir, "train"), exist_ok=True)
        os.makedirs(os.path.join(target_dir, "val"), exist_ok=True)

        QgsMessageLog.logMessage("====================================", "cocotrainer", level=Qgis.Info)

        # TODO:
        #  - use field categories

        features_iterator = vectorlayer.getFeatures(QgsFeatureRequest().setFilterExpression('$area > 1'))

        features = [feature for feature in features_iterator]
        QgsMessageLog.logMessage("vector layer: " + vectorlayer.name(), "cocotrainer", level=Qgis.Info)
        QgsMessageLog.logMessage("Filtered polygons smaller than 1m2 from data", "cocotrainer", level=Qgis.Info)
        QgsMessageLog.logMessage("features: " + str(len(list(features))), "cocotrainer", level=Qgis.Info)

        options = QgsMapSettings()
        options.setLayers([rasterlayer])
        options.setOutputSize(QSize(int(img_size), int(img_size)))

        QgsMessageLog.logMessage(str(scale_realworld), "cocotrainer", level=Qgis.Info)
        QgsMessageLog.logMessage(str(img_size), "cocotrainer", level=Qgis.Info)

        date = datetime.now()

        cat_dict = {}
        if use_fieldcategory:
            categories = []
            # uniqueprovider = rasterlayer.dataProvider()
            fields = vectorlayer.fields()
            id = fields.indexFromName(categoryfield)
            uniquevalues = vectorlayer.uniqueValues(id)
            for i, val in enumerate(uniquevalues):
                categories.append({"supercategory": "object", "id": i, "name": str(val)})
                cat_dict[str(val)] = i
        else:
            categories = [{"supercategory": "object", "id": 0, "name": "CATEGORYNAME"}]
            cat_dict["CATEGORYNAME"] = 0

        coco_annotation = {
            "info": {
                "description": dataset_description,
                "url": url,
                "version": version,
                "year": int(date.strftime("%Y")),
                "contributor": contributor,
                "date_created": date.strftime("%d/%m/%y")
            },
            "licenses": [self.license_dict[license]],
            "images": [],
            "annotations": [],
            "categories": categories,
            # < -- Not in Captionsannotations
            "segment_info": []  # < -- Only in Panoptic annotations
        }

        bboxes, polygons = {}, {}
        for i, feature in enumerate(features):
            polygons[i] = feature.geometry()
            bboxes[i] = feature.geometry().boundingBox()

        if use_fieldcategory:
            cats = {}
            for i, feature in enumerate(features):
                cats[i] = str(feature[categoryfield])

        image_id = 0
        annotation_id = 0

        for i, feature in enumerate(features):
            self.dlg.progressBar.setValue((i / len(polygons) * 100))
            QgsMessageLog.logMessage("something is happening", "cocotrainer", level=Qgis.Info)
            geoms = feature.geometry()
            bbox = geoms.boundingBox()

            if scale_to_fit:
                xmax = bbox.xMaximum()
                ymax = bbox.yMaximum()
                ymin = bbox.yMinimum()
                xmin = bbox.xMinimum()

                diffx = xmax - xmin
                diffy = ymax - ymin
                xmax = xmax + (buffer_size * diffx)
                xmin = xmin - (buffer_size * diffx)
                ymax = ymax + (buffer_size * diffy)
                ymin = ymin - (buffer_size * diffy)

            else:
                midpoint = bbox.center()
                QgsMessageLog.logMessage("trying to log centerpoint", "cocotrainer", level=Qgis.Info)
                QgsMessageLog.logMessage(str(midpoint.x()), "cocotrainer", level=Qgis.Info)
                QgsMessageLog.logMessage(str(midpoint.y()), "cocotrainer", level=Qgis.Info)
                xmin = midpoint.x() - scale_realworld / 2
                xmax = midpoint.x() + scale_realworld / 2
                ymin = midpoint.y() - scale_realworld / 2
                ymax = midpoint.y() + scale_realworld / 2

            extent = QgsRectangle(xmin, ymin, xmax, ymax)

            fileid = "{}_{}_{}".format(xmin, ymin, scale_realworld)

            image = {
                "license": 0,
                "file_name": fileid + ".png",
                "coco_url": None,
                "height": img_size,
                "width": img_size,
                "date_captured": date.strftime("%d/%m/%y"),
                "flickr_url": None,
                "id": image_id
            }

            coco_annotation["images"].append(image)

            for j, geo in bboxes.items():
                if extent.contains(geo) or extent.intersects(geo):
                    points = polygons[j].asMultiPolygon()
                    xs = np.array([p.x() - xmin for p in points[0][0]])
                    ys = np.array([(ymax - ymin) - (p.y() - ymin) for p in points[0][0]])

                    xs *= (img_size / scale_realworld)
                    xs = np.round(xs)
                    xs = xs.astype(np.int32)

                    ys *= (img_size / scale_realworld)
                    ys = np.round(ys)
                    ys = ys.astype(np.int32)

                    ys[ys < 0] = 0
                    xs[xs < 0] = 0

                    polygon = [[int(p[0]), int(p[1])] for p in zip(xs, ys)]
                    flat_list = [item for sublist in polygon for item in sublist]
                    QgsMessageLog.logMessage(str(flat_list), "cocotrainer", level=Qgis.Info)

                    pixelposbbox = [int(np.min(xs)), (int(np.min(ys))), geo.width() * (img_size / scale_realworld),
                                    geo.height() * (img_size / scale_realworld)]
                    pixelposbbox = [number if number > 0 else 0 for number in pixelposbbox]

                    QgsMessageLog.logMessage(str([geo.xMinimum(), geo.yMaximum(), geo.width(), geo.height()]),
                                             "cocotrainer", level=Qgis.Info)
                    QgsMessageLog.logMessage(str(pixelposbbox), "cocotrainer", level=Qgis.Info)

                    annotation = {
                        "segmentation": [flat_list],  # format is [x1,y1,x2,y2]
                        "area": polygons[j].area(),
                        "iscrowd": 0,
                        "image_id": image_id,
                        "bbox": pixelposbbox,  # format is [top left x position, top left y position, width, height]
                        "category_id": cat_dict[cats[j]],
                        "id": annotation_id
                    }
                    annotation_id += 1
                    coco_annotation["annotations"].append(annotation)

            options.setExtent(extent)
            render = QgsMapRendererParallelJob(options)

            def finished():
                QgsMessageLog.logMessage("saving image to disk", "cocotrainer", level=Qgis.Info)
                fname = os.path.join(target_dir, 'train', "{}.png".format(fileid))
                img = render.renderedImage()
                if not img.save(fname, "png"):
                    print("Error saving image")

            render.finished.connect(finished)
            render.start()
            render.waitForFinished()
            image_id += 1

        QgsMessageLog.logMessage(str(coco_annotation), "cocotrainer", level=Qgis.Info)

        with open(os.path.join(target_dir, "annotation.json"), "w") as outfile:
            json.dump(coco_annotation, outfile)

        self.dlg.progressBar.setValue(100)
        self.dlg.finished_label.setText("parsed {} features".format(len(list(features))))