Beispiel #1
0
def raster_collection_vrt(fc,
                          relative_to_vrt=True,
                          nodata=None,
                          mask_band=None):
    """Make a VRT XML document from a feature collection of GeoRaster2 objects.
    Parameters
    ----------
    rasters : FeatureCollection
        The FeatureCollection of GeoRasters.
    relative_to_vrt : bool, optional
        If True the bands simple source url will be related to the VRT file
    nodata : int, optional
        If supplied is the note data value to be used
    mask_band: int, optional
        If specified detrimes from which band to use the mask
    Returns
    -------
    bytes
        An ascii-encoded string (an ElementTree detail)
    """
    def max_resolution():
        max_affine = max(fc,
                         key=lambda f: f.raster().resolution()).raster().affine
        return abs(max_affine.a), abs(max_affine.e)

    from telluric import rasterization
    from telluric.georaster import band_names_tag
    assert all(fc.crs == f.crs
               for f in fc), "all rasters should have the same CRS"

    rasters = (f.raster() for f in fc)
    bounds = fc.convex_hull.get_bounds(fc.crs)
    resolution = max_resolution()
    width, height, affine = rasterization.raster_data(bounds, resolution)

    bands = {}  # type: Dict[str, tuple]
    band_names = []  # type: List[Any]
    vrt = BaseVRT(width, height, fc.crs, affine)

    last_band_idx = 0
    if mask_band is not None:
        mask_band_elem = vrt.add_mask_band("Byte")

    for raster in rasters:
        for i, band_name in enumerate(raster.band_names):
            if band_name in bands:
                band_element, band_idx = bands[band_name]
            else:
                last_band_idx += 1
                band_idx = last_band_idx
                band_element = vrt.add_band(
                    raster.dtype,
                    band_idx,
                    band_name_to_color_interpretation(band_name),
                    nodata=nodata)
                bands[band_name] = (band_element, last_band_idx)
                band_names.append(band_name)

            src_window = Window(0, 0, raster.width, raster.height)
            xoff = (raster.affine.xoff - affine.xoff) / affine.a
            yoff = (raster.affine.yoff - affine.yoff) / affine.e
            xsize = raster.width * raster.affine.a / affine.a
            ysize = raster.height * raster.affine.e / affine.e
            dst_window = Window(xoff, yoff, xsize, ysize)
            if raster.source_file.startswith("http"):
                file_name = "/vsicurl/%s" % raster.source_file
            elif relative_to_vrt:
                file_name = raster.source_file
            else:
                file_name = os.path.join(os.getcwd(), raster.source_file)

            vrt.add_band_simplesource(band_element, band_idx, raster.dtype,
                                      relative_to_vrt, file_name, raster.width,
                                      raster.height,
                                      raster.block_shape(i)[1],
                                      raster.block_shape(i)[0], src_window,
                                      dst_window)
            if i == mask_band:
                vrt.add_band_simplesource(mask_band_elem,
                                          "mask,%s" % (mask_band + 1), "Byte",
                                          relative_to_vrt, file_name,
                                          raster.width, raster.height,
                                          raster.block_shape(i)[1],
                                          raster.block_shape(i)[0], src_window,
                                          dst_window)

    vrt.add_metadata(items={band_names_tag: json.dumps(band_names)})
    return vrt
Beispiel #2
0
def wms_vrt(wms_file, bounds=None, resolution=None):
    """Make a VRT XML document from a wms file.
    Parameters
    ----------
    wms_file : str
        The source wms file
    bounds : GeoVector, optional
        The requested footprint of the generated VRT
    resolution : float, optional
        The requested resolution of the generated VRT
    Returns
    -------
    bytes
        An ascii-encoded string (an ElementTree detail)
    """

    from telluric import rasterization, constants
    wms_tree = ET.parse(wms_file)
    service = wms_tree.find(".//Service")
    if service is not None:
        service_name = service.attrib.get("name")
    else:
        raise ValueError("Service tag is required")
    # definition is based on https://www.gdal.org/frmt_wms.html
    if service_name == "VirtualEarth":
        left = find_and_convert_to_type(float, wms_tree,
                                        ".//DataWindow/UpperLeftX",
                                        -20037508.34)
        up = find_and_convert_to_type(float, wms_tree,
                                      ".//DataWindow/UpperLeftY", 20037508.34)
        right = find_and_convert_to_type(float, wms_tree,
                                         ".//DataWindow/LowerRightX",
                                         20037508.34)
        bottom = find_and_convert_to_type(float, wms_tree,
                                          ".//DataWindow/LowerRightY",
                                          -20037508.34)
        upper_bound_zoom = find_and_convert_to_type(int, wms_tree,
                                                    ".//DataWindow/TileLevel",
                                                    19)
        projection = find_and_convert_to_type(str, wms_tree, ".//Projection",
                                              "EPSG: 3857")
        projection = CRS(init=projection)
        blockx = find_and_convert_to_type(str, wms_tree, ".//BlockSizeX", 256)
        blocky = find_and_convert_to_type(str, wms_tree, ".//BlockSizeY", 256)
    else:
        left = find_and_convert_to_type(float, wms_tree,
                                        ".//DataWindow/UpperLeftX", -180.0)
        up = find_and_convert_to_type(float, wms_tree,
                                      ".//DataWindow/UpperLeftY", 90.0)
        right = find_and_convert_to_type(float, wms_tree,
                                         ".//DataWindow/LowerRightX", 180.0)
        bottom = find_and_convert_to_type(float, wms_tree,
                                          ".//DataWindow/LowerRightY", -90.0)
        upper_bound_zoom = find_and_convert_to_type(int, wms_tree,
                                                    ".//DataWindow/TileLevel",
                                                    0)
        projection = find_and_convert_to_type(str, wms_tree, ".//Projection",
                                              "EPSG:4326")
        blockx = find_and_convert_to_type(str, wms_tree, ".//BlockSizeX", 1024)
        blocky = find_and_convert_to_type(str, wms_tree, ".//BlockSizeY", 1024)
        projection = CRS(init=projection)

    bands_count = find_and_convert_to_type(int, wms_tree, ".//BandsCount", 3)
    data_type = find_and_convert_to_type(str, wms_tree, ".//DataType", "Byte")

    src_bounds = (left, bottom, right, up)
    bounds = bounds.get_bounds(crs=projection) or src_bounds
    src_resolution = constants.MERCATOR_RESOLUTION_MAPPING[upper_bound_zoom]
    resolution = resolution or constants.MERCATOR_RESOLUTION_MAPPING[
        upper_bound_zoom]
    dst_width, dst_height, transform = rasterization.raster_data(
        bounds=bounds, dest_resolution=resolution)
    orig_width, orig_height, orig_transform = rasterization.raster_data(
        bounds=src_bounds, dest_resolution=src_resolution)
    src_window = from_bounds(*bounds, transform=orig_transform)

    vrt = BaseVRT(dst_width, dst_height, projection, transform)

    vrt.add_metadata(domain="IMAGE_STRUCTURE", items={"INTERLEAVE": "PIXEL"})

    if bands_count != 3:
        raise ValueError("We support currently on 3 bands WMS")

    for idx, band in enumerate(["RED", "GREEN", "BLUE"]):
        bidx = idx + 1

        band_element = vrt.add_band(data_type, bidx, band)
        dst_window = Window(0, 0, dst_width, dst_height)

        vrt.add_band_simplesource(band_element, bidx, data_type, False,
                                  os.path.abspath(wms_file), orig_width,
                                  orig_height, blockx, blocky, src_window,
                                  dst_window)

    return vrt