Skip to content

GeoTrellis 3.0 Examples

Jean-Denis Giguère edited this page Aug 6, 2020 · 2 revisions

Windowed Reads of a Raster on S3

import geotrellis.raster._
import geotrellis.vector._
import org.locationtech.jts.geom._

val s3Path = "s3://bucket/key/path/to/cog.tif"
val rasterSource = RasterSource(s3Path)
val geom: Geometry = ???
val extent = Extent(geom.getEnvelopeInternal)
val multiBandRaster: Option[Raster[MultibandTile]] =
  rasterSource.read(extent)

// Do whatever with the result!

Note: If you don't have COG, the tiling of the GeoTiff may be really useful.

Tile Mask with known Geometry

/* This example demonstrates how to mask tiles
 * loaded from a RasterSource on S3 with a geometry
 */
import geotrellis.raster._
import geotrellis.raster.rasterize.Rasterizer
import geotrellis.vector._

val s3Path = "s3://bucket/key/to/cog.tif"
val rasterSource = RasterSource(s3Path)
val extent = rasterSource.extent

// Just get the first Tile from the RasterSource
// You could do other things here like loop each tile or
// check to ensure that the read was successful
val tile = rasterSource.read(Seq(0)).get.band(0).tile
val rasterExtent = RasterExtent(extent, tile)
// Geom can be loaded from a number of sources, out
// of scope of this example
val geom: Geometry = ???

val options: Rasterizer.Options =
  Rasterizer.Options(true, PixelIsArea)
val colorMap = ColorRamps.BlueToOrange
  .toColorMap(tile.histogramDouble)

// Example 1 - Mask so that only pixels intersecting
// the geometry are kept
tile
  .mask(extent, geom, options)
  .renderPng(colorMap)
  .write("/path/to/tile.png")

// Example 2 - Inverse mask so that only pixels that
// do not intersect the geometry are kept
val geomMask =
  geom.rasterizeWithValue(rasterExtent,
                          1,
                          IntConstantNoDataCellType,
                          options)
tile
  .localMask(geomMask, 1, NODATA)
  .renderPng(colorMap)
  .write("/path/to/tile.png")

Render PNG Image from Tile

import geotrellis.raster._

val tile: Tile = ???
// ColorRamps define a list of color values
val colorRamp = ColorRamps.BlueToOrange
// ColorMap defines a map of tile value to bin in
// a ColorRamp.
// There are a number of different ways to generate
// a ColorMap, the simplest of which is to use
// a histogram generated from the Tile
val colorMap = colorRamp.toColorMap(tile.histogramDouble)
// Render to a Png using a ColorMap then write to disk
tile.renderPng(colorMap).write("/path/to/tile.png")

Generate Image Pyramid from Input Dataset

import geotrellis.layer._
import geotrellis.proj4.WebMercator
import geotrellis.raster._
import geotrellis.raster.reproject.Reproject
import geotrellis.spark._
import geotrellis.spark.pyramid._
import geotrellis.spark.store.s3._
import org.apache.spark.rdd.RDD

// There are a number of ways to generate this input
// which is out of scope of this example
val tileRdd: RDD[(SpatialKey, Tile)] = ???
// Use whichever of the overloads correspond to the
// information you know about your tileRdd
val metadata: TileLayerMetadata[SpatialKey] =
  tileRdd.collectMetadata(???)
val resampleOptions = Reproject.Options.DEFAULT
// This is the layout scheme compatible with tiled slippy maps
val pyramidLayoutScheme = ZoomedLayoutScheme(WebMercator, 256)
// Convert your RDD to the correct layout/projection
val (targetZoom, tileLayerRdd) = 
	TileLayerRDD(tileRdd, metadata)
  		.reproject(pyramidLayoutScheme, resampleOptions)

// You can explicitly set the zoom levels to generate,
// or let GeoTrellis figure out the optimal zoom levels,
// as is done here.
val pyramid =
  Pyramid.fromLayerRDD(tileLayerRdd, Some(targetZoom), None)
pyramid.levels.foreach {
  // Write each zoom level sequentially
  case (zoom, tileRdd) => {
    // Feel free to generate a fancier colormap here
    val colorRamp = ColorRamps.BlueToOrange
    val histogram = tileRdd.histogram(colorRamp.numStops)
    val colorMap = colorRamp.toColorMap(histogram)
    val keyToPath = (k: SpatialKey) =>
      s"s3://bucket/key/path/${zoom}/${k.col}/${k.row}.png"
    tileRdd.map {
      case (key, tile) => {
        (key, tile.renderPng(colorMap).bytes)
      }
    }.saveToS3(keyToPath)
  }
}