Example #1
0
    def get_one(self, tile: Tile) -> Optional[Tile]:
        bbox = self.tilegrid.extent(tile.tilecoord, self.buffer)
        bbox2d = mapnik.Box2d(bbox[0], bbox[1], bbox[2], bbox[3])

        size = tile.tilecoord.n * self.tilegrid.tile_size + 2 * self.buffer
        self.mapnik.resize(size, size)
        self.mapnik.zoom_to_box(bbox2d)

        if self.output_format == "grid":
            grid = mapnik.Grid(self.tilegrid.tile_size,
                               self.tilegrid.tile_size)
            for n, l in enumerate(self.mapnik.layers):
                if l.name in self.layers_fields:
                    mapnik.render_layer(self.mapnik,
                                        grid,
                                        layer=n,
                                        fields=self.layers_fields[l.name])

            encode = grid.encode("utf", resolution=self.resolution)
            if self.drop_empty_utfgrid and len(encode["data"].keys()) == 0:
                return None
            tile.data = dumps(encode).encode()
        else:
            # Render image with default Agg renderer
            im = mapnik.Image(size, size)
            mapnik.render(self.mapnik, im)
            tile.data = im.tostring(self.output_format)

        return tile
def _decode_tile(data: bytes, tile: Tile) -> None:
    """Decode a tile."""
    image_len = struct.unpack("q", data[:8])[0]
    tile.data = data[8:(image_len + 8)]
    other = json.loads((data[(8 + image_len):]).decode("utf-8"))
    tile.content_encoding = other["content_encoding"]
    tile.content_type = other["content_type"]
Example #3
0
    def get(self, tiles: Iterable[Tile]) -> Iterator[Tile]:
        for metatile in tiles:
            if isinstance(metatile.data, bytes):
                metaimage = Image.open(BytesIO(metatile.data))
                for tilecoord in metatile.tilecoord:
                    if metatile.error:
                        yield Tile(tilecoord,
                                   metadata=metatile.metadata,
                                   error=metatile.error,
                                   metatile=metatile)
                        continue
                    if metatile.data is None:
                        yield Tile(
                            tilecoord,
                            metadata=metatile.metadata,
                            error="Metatile data is None",
                            metatile=metatile,
                        )
                        continue

                    x = self.border + (tilecoord.x -
                                       metatile.tilecoord.x) * self.tile_size
                    y = self.border + (tilecoord.y -
                                       metatile.tilecoord.y) * self.tile_size
                    image = metaimage.crop(
                        (x, y, x + self.tile_size, y + self.tile_size))
                    bytes_io = BytesIO()
                    image.save(bytes_io, FORMAT_BY_CONTENT_TYPE[self.format])
                    yield Tile(
                        tilecoord,
                        data=bytes_io.getvalue(),
                        content_type=self.format,
                        metadata=metatile.metadata,
                        metatile=metatile,
                    )
Example #4
0
 def get_one(self, tile: Tile) -> Optional[Tile]:
     try:
         tile.content_type = self.content_type
         tile.data = self.db[str(tile.tilecoord).encode("utf-8")]
         return tile
     except KeyError:
         return None
Example #5
0
    def get(self, tiles):
        for metatile in tiles:
            metaimage = None if metatile.data is None else Image.open(BytesIO(metatile.data))
            for tilecoord in metatile.tilecoord:
                if metatile.error:
                    yield Tile(
                        tilecoord, metadata=metatile.metadata, error=metatile.error, metatile=metatile
                    )
                    continue
                if metatile.data is None:
                    yield Tile(
                        tilecoord, metadata=metatile.metadata,
                        error="Metatile data is None", metatile=metatile
                    )
                    continue

                x = self.border + (tilecoord.x - metatile.tilecoord.x) * self.tile_size
                y = self.border + (tilecoord.y - metatile.tilecoord.y) * self.tile_size
                image = metaimage.crop((x, y, x + self.tile_size, y + self.tile_size))
                string_io = BytesIO()
                image.save(string_io, FORMAT_BY_CONTENT_TYPE[self.format])
                yield Tile(
                    tilecoord, data=string_io.getvalue(), content_type=self.format,
                    metadata=metatile.metadata, metatile=metatile
                )
Example #6
0
 def __call__(self, tile: Tile) -> Tile:
     if tile.content_type != self.content_type:
         assert tile.data is not None
         bytes_io = BytesIO()
         PIL.Image.open(BytesIO(tile.data)).save(bytes_io, self.format, **self.kwargs)
         tile.content_type = self.content_type
         tile.data = bytes_io.getvalue()
     return tile
Example #7
0
 def get_one(self, tile: Tile) -> Optional[Tile]:
     try:
         tile.data = self.tiles[tile.tilecoord]
     except KeyError:
         return None
     if self.content_type is not None:
         tile.content_type = self.content_type
     return tile
Example #8
0
 def test_metadata(self) -> None:
     tilestore = MBTilesTileStore(sqlite3.connect(":memory:"))
     tilestore.put_one(Tile(TileCoord(1, 0, 0)))
     tilestore.put_one(Tile(TileCoord(2, 0, 0)))
     tilestore.set_metadata_zooms()
     self.assertEqual(int(tilestore.metadata["minzoom"]), 1)
     self.assertEqual(int(tilestore.metadata["maxzoom"]), 2)
     self.assertEqual(sorted(tilestore.metadata.itervalues()), ["1", "2"])
     self.assertEqual(sorted(tilestore.metadata.keys()), ["maxzoom", "minzoom"])
Example #9
0
 def get_one(self, tile: Tile) -> Optional[Tile]:
     if tile is None:
         return None
     if hasattr(tile, "zipinfo"):
         tile.data = self.zipfile.read(tile.zipinfo)  # type: ignore
     else:
         filename = self.layout.filename(tile.tilecoord, tile.metadata)
         tile.data = self.zipfile.read(filename)
     return tile
Example #10
0
 def test_metadata(self):
     tilestore = MBTilesTileStore(sqlite3.connect(':memory:'))
     tilestore.put_one(Tile(TileCoord(1, 0, 0)))
     tilestore.put_one(Tile(TileCoord(2, 0, 0)))
     tilestore.set_metadata_zooms()
     self.assertEqual(int(tilestore.metadata['minzoom']), 1)
     self.assertEqual(int(tilestore.metadata['maxzoom']), 2)
     self.assertEqual(sorted(tilestore.metadata.itervalues()), ['1', '2'])
     self.assertEqual(sorted(tilestore.metadata.keys()),
                      ['maxzoom', 'minzoom'])
Example #11
0
 def test_one(self):
     tilestore = DictTileStore()
     self.assertEqual(len(tilestore), 0)
     tilestream = [
         Tile(TileCoord(1, 0, 0), data='data'), None,
         Tile(TileCoord(1, 0, 1), error=True)
     ]
     tilestream = tilestore.put(tilestream)
     tiles = list(tilestream)
     self.assertEqual(len(tiles), 2)
     self.assertEqual(tiles[0].tilecoord, TileCoord(1, 0, 0))
     self.assertEqual(tiles[0].data, 'data')
     self.assertEqual(tiles[1].tilecoord, TileCoord(1, 0, 1))
     self.assertEqual(tiles[1].error, True)
     self.assertTrue(Tile(TileCoord(1, 0, 0)) in tilestore)
     self.assertTrue(Tile(TileCoord(1, 0, 1)) in tilestore)
     tilestream = [Tile(TileCoord(1, 0, 0)), Tile(TileCoord(1, 0, 1))]
     tilestream = tilestore.get(tilestream)
     consume(tilestream, None)
     tiles = list(tilestore.get_all())
     self.assertEqual(len(tiles), 2)
     self.assertEqual(tiles[0].tilecoord, TileCoord(1, 0, 0))
     self.assertEqual(tiles[0].data, 'data')
     self.assertEqual(tiles[1].tilecoord, TileCoord(1, 0, 1))
     self.assertEqual(tiles[1].error, True)
     tilestream = [Tile(TileCoord(1, 0, 0))]
     tilestream = tilestore.delete(tilestream)
     consume(tilestream, None)
     tiles = list(tilestore.get_all())
     self.assertEqual(len(tiles), 1)
     self.assertFalse(Tile(TileCoord(1, 0, 0)) in tilestore)
     self.assertTrue(Tile(TileCoord(1, 0, 1)) in tilestore)
Example #12
0
 def get_one(self, tile):
     if self.bounding_pyramid is not None:
         if tile.tilecoord not in self.bounding_pyramid:
             return None
     try:
         tile = Tile(tile.tilecoord, data=self.tiles[tile.tilecoord])
     except KeyError:
         return None
     if self.content_type is not None:
         tile.content_type = self.content_type
     return tile
Example #13
0
 def get_one(self, tile):
     if self.bounding_pyramid is not None:
         if tile.tilecoord not in self.bounding_pyramid:
             return None
     try:
         tile = Tile(tile.tilecoord, data=self.tiles[tile.tilecoord])
     except KeyError:
         return None
     if self.content_type is not None:
         tile.content_type = self.content_type
     return tile
Example #14
0
 def __call__(self, tile: Tile) -> Tile:
     if self.content_type is None and tile.content_encoding is None and tile.data is not None:
         data = str(tile.data)
         if data.startswith("{"):
             tile.content_type = "application/json"
         elif data.startswith("\x89PNG\x0d\x0a\x1a\x0a"):
             tile.content_type = "image/png"
         elif data.startswith("\xff\xd8"):
             tile.content_type = "image/jpeg"
     else:
         tile.content_type = self.content_type
     return tile
Example #15
0
 def __call__(self, tile: Tile) -> Tile:
     assert tile.data is not None
     assert tile.content_encoding is None
     bytes_io = BytesIO()
     gzip_file = GzipFile(compresslevel=self.compresslevel,
                          fileobj=bytes_io,
                          mode="w")
     gzip_file.write(tile.data)
     gzip_file.close()
     tile.content_encoding = "gzip"
     tile.data = bytes_io.getvalue()
     return tile
Example #16
0
 def get_one(self, tile: Tile) -> Optional[Tile]:
     key_name = self.tilelayout.filename(tile.tilecoord, tile.metadata)
     try:
         response = self.client.get_object(Bucket=self.bucket, Key=key_name)
         tile.data = response["Body"].read()
         tile.content_encoding = response.get("ContentEncoding")
         tile.content_type = response.get("ContentType")
     except botocore.exceptions.ClientError as exc:
         if _get_status(exc) == 404:
             return None
         else:
             tile.error = exc
     return tile
Example #17
0
 def get_one(self, tile: Tile) -> Optional[Tile]:
     key_name = self.tilelayout.filename(tile.tilecoord, tile.metadata)
     try:
         blob = self.container_client.get_blob_client(blob=key_name)
         tile.data = blob.download_blob().readall()
         properties = blob.get_blob_properties()
         tile.content_encoding = properties.content_settings.content_encoding
         tile.content_type = properties.content_settings.content_type
     except ResourceNotFoundError:
         return None
     except Exception as exc:
         LOGGER.exception(exc)
         tile.error = exc
     return tile
Example #18
0
 def get_one(self, tile):
     if not tile:
         return None
     test_tile = Tile(tile.tilecoord)
     while test_tile.tilecoord:
         if test_tile in self.tilestore:
             tmp_tilecoord = tile.tilecoord
             tile.tilecoord = test_tile.tilecoord
             tile = self.tilestore.get_one(tile)
             if tile:
                 tile.tilecoord = tmp_tilecoord
             return tile
         else:
             test_tile.tilecoord = self.tile_structure.parent(test_tile.tilecoord)
     return None
Example #19
0
 def get_one(self, tile):
     if not tile:
         return None
     test_tile = Tile(tile.tilecoord)
     while test_tile.tilecoord:
         if test_tile in self.tilestore:
             tmp_tilecoord = tile.tilecoord
             tile.tilecoord = test_tile.tilecoord
             tile = self.tilestore.get_one(tile)
             if tile:
                 tile.tilecoord = tmp_tilecoord
             return tile
         else:
             test_tile.tilecoord = self.tilegrid.parent(test_tile.tilecoord)
     return None
Example #20
0
 def list(self):
     # FIXME warn that this consumes file
     filename_re = re.compile(self.tilelayout.pattern)
     for line in self.file:
         match = filename_re.search(line)
         if match:
             yield Tile(self.tilelayout.tilecoord(match.group()), line=line)
Example #21
0
 def get_one(self, tile):
     try:
         return Tile(tile.tilecoord,
                     content_type=self.content_type,
                     data=self.db[str(tile.tilecoord)])
     except KeyError:
         return None
Example #22
0
    def __call__(self, tile):
        if len(tile.data) != self.size or \
                sha1(tile.data).hexdigest() != self.sha1code:
            return tile
        else:
            if self.store is not None:
                if tile.tilecoord.n != 1:
                    for tilecoord in tile.tilecoord:
                        self.store.delete_one(
                            Tile(tilecoord, metadata=tile.metadata))
                else:
                    self.store.delete_one(tile)
            logger.info("The tile {} {} is dropped".format(
                tile.tilecoord, tile.formated_metadata))
            if hasattr(tile, 'metatile'):
                tile.metatile.elapsed_togenerate -= 1
                if tile.metatile.elapsed_togenerate == 0 and self.queue_store is not None:
                    self.queue_store.delete_one(
                        tile.metatile)  # pragma: no cover
            elif self.queue_store is not None:  # pragma: no cover
                self.queue_store.delete_one(tile)

            if self.count:
                self.count()

            return None
Example #23
0
 def test_empty(self) -> None:
     ts = TileStore()
     self.assertEqual(ts.bounding_pyramid, None)
     self.assertEqual(ts.content_type, None)
     self.assertEqual(len(ts), 0)
     self.assertRaises(NotImplementedError, next, ts.delete((Tile(TileCoord(0, 0, 0)),)))
     self.assertRaises(NotImplementedError, ts.delete_one, None)
     self.assertEqual(ts.get_cheap_bounding_pyramid(), None)
     self.assertRaises(NotImplementedError, next, ts.get((Tile(TileCoord(0, 0, 0)),)))
     self.assertEqual(list(ts.get_all()), [])
     self.assertRaises(NotImplementedError, ts.get_one, None)
     self.assertEqual(list(ts.list()), [])
     self.assertRaises(NotImplementedError, next, ts.put((Tile(TileCoord(0, 0, 0)),)))
     self.assertRaises(NotImplementedError, ts.put_one, None)
     self.assertFalse(None in ts)
     self.assertEqual(ts.get_bounding_pyramid(), BoundingPyramid())
Example #24
0
def main():
    # Create our RenderingTheWorld tile store that will manage the queue and subdivision.
    # We pass it the function that decides whether a tile should be subdivided, and an initial tile.
    rendering_the_world_tilestore = RenderingTheWorldTileStore(subdivide, seeds=(Tile(TileCoord(0, 0, 0)),))
    # Start the tilestream by getting a list of all tiles to be generated.
    tilestream = rendering_the_world_tilestore.list()
    tilestream = imap(Logger(logger, logging.INFO, 'get %(tilecoord)s'), tilestream)
    # Create the tile store that will generate our tiles, in this case it's a demo WMTS server at OpenGeo.
    # Getting tiles from this store will either return the tile as a PNG file, or set an error on the tile
    # if there are no features in this tile.
    generate_tilestore = WMTSTileStore(
        url='http://v2.suite.opengeo.org/geoserver/gwc/service/wmts/',
        layer='medford:buildings',
        style='_null',
        format='image/png',
        tile_matrix_set='EPSG:900913',
        tile_matrix=lambda z: 'EPSG:900913:{0:d}'.format(z))
    tilestream = generate_tilestore.get(tilestream)
    tilestream = imap(Logger(logger, logging.INFO, 'got %(tilecoord)s, error=%(error)s'), tilestream)
    # Put the tile back into the RenderingTheWorld tile store.  This check whether the tile should be
    # subdivided, and, if so, adds the tile's children to the list of tiles to be generated.
    tilestream = rendering_the_world_tilestore.put(tilestream)
    # Get rid of tiles that returned an error (i.e. where there was no data).
    tilestream = imap(DropErrors(), tilestream)
    # Store the generated tiles in the output tile store, in our case a local MBTiles file.
    output_tilestore = MBTilesTileStore(sqlite3.connect('medford_buildings.mbtiles'))
    tilestream = output_tilestore.put(tilestream)
    tilestream = imap(Logger(logger, logging.INFO, 'saved %(tilecoord)s'), tilestream)
    # Go!
    consume(tilestream, None)
Example #25
0
def test_dropping_too_many_retries(store):
    if REDIS_VERSION < [5, 0, 4]:
        # Bug in redis x5.0.3 that doesn't increment the retry counter.
        pytest.skip("Bug in redis")
    for y in range(10):
        store.put_one(Tile(TileCoord(0, 0, y)))

    count = 0
    nb_tries = 0
    # max_retries=2 => 2 iterations to have the error two times and a third one to drop the message
    for _ in range(3):
        try:
            for tile in store.list():
                if tile.tilecoord.y == 0:  # this tile always fails and will be dropped after two tries
                    nb_tries += 1
                    assert nb_tries <= 2
                    raise SlaveException
                count += 1
                store.delete_one(tile)
        except SlaveException:
            pass
    assert 9 == count

    # test we see the tile in the list of errors
    messages = store.get_status()
    assert messages["Approximate number of tiles to generate"] == 0
    assert messages["Approximate number of generating tiles"] == 0
    assert messages["Tiles in error"] == "0/0/0"

    # test old errors deleting
    time.sleep(1.1)
    messages = store.get_status()
    assert messages["Approximate number of tiles to generate"] == 0
    assert messages["Approximate number of generating tiles"] == 0
    assert messages["Tiles in error"] == ""
Example #26
0
 def list(self):
     for zipinfo in self.zipfile.infolist():
         try:
             yield Tile(self.layout.tilecoord(zipinfo.filename),
                        zipinfo=zipinfo)
         except ValueError:
             pass
Example #27
0
 def list(self):
     for x in range(0, self.width):
         for y in range(0, self.height):
             if self.pixels[x, y]:
                 yield Tile(
                     TileCoord(self.z, self.xbounds.start + x,
                               self.ybounds.stop - y - 1))
Example #28
0
 def test_init_boundingpyramid(self):
     ts = TileStore(
         bounding_pyramid=BoundingPyramid.from_string('1/0/0:1/1'))
     self.assertTrue(Tile(TileCoord(1, 0, 0)) in ts)
     tiles = list(ts.list())
     self.assertEqual(len(tiles), 1)
     self.assertEqual(tiles[0].tilecoord, TileCoord(1, 0, 0))
Example #29
0
 def list(self):
     while True:
         sqs_messages = self.queue.receive_messages(
             MaxNumberOfMessages=BATCH_SIZE)
         if not sqs_messages:
             try:
                 self.on_empty(self.queue)
             except StopIteration:
                 break
         else:
             for sqs_message in sqs_messages:
                 try:
                     body = json.loads(
                         base64.b64decode(sqs_message.body.encode(
                             'utf-8')).decode('utf-8'))
                     z = body.get('z')
                     x = body.get('x')
                     y = body.get('y')
                     n = body.get('n')
                     metadata = body.get('metadata', {})
                     # FIXME deserialize other attributes
                     tile = Tile(TileCoord(z, x, y, n),
                                 sqs_message=sqs_message,
                                 metadata=metadata)
                     yield tile
                 except Exception:
                     logger.warning('Failed decoding the SQS message',
                                    exc_info=True)
                     sqs_message.delete()
Example #30
0
 def test_get(self):
     image = Image.new("RGBA", (8, 8))
     image.paste((255, 0, 0, 0), (0, 0, 4, 4))
     image.paste((0, 255, 0, 0), (0, 4, 4, 8))
     image.paste((0, 0, 255, 0), (4, 0, 8, 4))
     image.paste((0, 0, 0, 255), (4, 4, 8, 8))
     string_io = BytesIO()
     image.save(string_io, "PNG")
     tile = Tile(TileCoord(1, 0, 0, 2), data=string_io.getvalue())
     tiles = list(self.mtsts.get([tile]))
     self.assertEqual(len(tiles), 4)
     self.assertEqual(tiles[0].tilecoord, TileCoord(1, 0, 0))
     image = Image.open(BytesIO(tiles[0].data))
     self.assertEqual(image.size, (2, 2))
     self.assertEqual(image.getcolors(), [(4, (255, 0, 0, 0))])
     self.assertEqual(tiles[1].tilecoord, TileCoord(1, 0, 1))
     image = Image.open(BytesIO(tiles[1].data))
     self.assertEqual(image.size, (2, 2))
     self.assertEqual(image.getcolors(), [(4, (0, 255, 0, 0))])
     self.assertEqual(tiles[2].tilecoord, TileCoord(1, 1, 0))
     image = Image.open(BytesIO(tiles[2].data))
     self.assertEqual(image.size, (2, 2))
     self.assertEqual(image.getcolors(), [(4, (0, 0, 255, 0))])
     self.assertEqual(tiles[3].tilecoord, TileCoord(1, 1, 1))
     image = Image.open(BytesIO(tiles[3].data))
     self.assertEqual(image.size, (2, 2))
     self.assertEqual(image.getcolors(), [(4, (0, 0, 0, 255))])
Example #31
0
 def list(self) -> Iterator[Tile]:
     top = getattr(self.tilelayout, "prefix", ".")
     for dirpath, _, filenames in os.walk(top):
         for filename in filenames:
             path = os.path.join(dirpath, filename)
             tilecoord = self.tilelayout.tilecoord(path)
             if tilecoord:
                 yield Tile(tilecoord, path=path)
Example #32
0
 def get_one(self, tile: Tile) -> Optional[Tile]:
     try:
         filename = self.tilelayout.filename(tile.tilecoord, tile.metadata)
     except Exception as e:
         tile.error = e
         return tile
     try:
         with open(filename, "rb") as file:
             tile.data = file.read()
         if self.content_type is not None:
             tile.content_type = self.content_type
         return tile
     except OSError as e:
         if e.errno == errno.ENOENT:
             return None
         else:
             raise
Example #33
0
 def get_all(self):
     for tilecoord, data in self.tiles.iteritems():
         tile = Tile(tilecoord, data=data)
         if self.content_type is not None:
             tile.content_type = self.content_type
         yield tile