Cesium supports drawing and layering high-resolution imagery (maps) from several standard services. Layers can be ordered, and blended together. Each layer’s brightness, contrast, gamma, hue, and saturation can be dynamically changed. This tutorial introduces imagery layer concepts and the related Cesium APIs.

Quick start

Let’s ignore the details for the moment and just jump in by writing code to add a few imagery layers. Open the Hello World example in Sandcastle. This example creates a Viewer widget which, which, by default, has a single layer rendering Bing Maps imagery. We can specify a different base layer by providing an additional parameter to the Viewer constructor. Let’s use a layer from an Esri ArcGIS MapServer:

var viewer = new Cesium.Viewer('cesiumContainer', {
    imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
        url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'
    }),
    baseLayerPicker : false
});

After modifying the example, press F8 to run it.

We can zoom in and out, and the layer streams in as needed.

Next, add another layer: NASA Black Marble imagery available using Tile Map Service (TMS):

var layers = viewer.scene.imageryLayers;
var blackMarble = layers.addImageryProvider(new Cesium.TileMapServiceImageryProvider({
    url : '//cesiumjs.org/tilesets/imagery/blackmarble',
    maximumLevel : 8,
    credit : 'Black Marble imagery courtesy NASA Earth Observatory'
}));

Since it was added last and covers the full extent of the globe, the Black Marble layer covers up the Esri layer. We could move Black Marble to the bottom with layers.lower(blackMarble);, but instead let’s blend it with the Esri layer so we have a better sense of how the two layers relate:

blackMarble.alpha = 0.5; // 0.0 is transparent.  1.0 is opaque.

Next, increase the brightness of the lights:

blackMarble.brightness = 2.0; // > 1.0 increases brightness.  < 1.0 decreases.

To finish, add a third layer that draws a single image over a particular extent.

layers.addImageryProvider(new Cesium.SingleTileImageryProvider({
    url : '../images/Cesium_Logo_overlay.png',
    rectangle : Cesium.Rectangle.fromDegrees(-75.0, 28.0, -67.0, 29.75)
}));

The complete code is:

var viewer = new Cesium.Viewer('cesiumContainer', {
    imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
        url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'
    }),
    baseLayerPicker : false
});

var layers = viewer.scene.imageryLayers;
var blackMarble = layers.addImageryProvider(new Cesium.TileMapServiceImageryProvider({
    url : '//cesiumjs.org/tilesets/imagery/blackmarble',
    maximumLevel : 8,
    credit : 'Black Marble imagery courtesy NASA Earth Observatory'
}));

blackMarble.alpha = 0.5; // 0.0 is transparent.  1.0 is opaque.

blackMarble.brightness = 2.0; // > 1.0 increases brightness.  < 1.0 decreases.

layers.addImageryProvider(new Cesium.SingleTileImageryProvider({
    url : '../images/Cesium_Logo_overlay.png',
    rectangle : Cesium.Rectangle.fromDegrees(-75.0, 28.0, -67.0, 29.75)
}));

See the full example in Sandcastle.

Next, we’ll look at the most important imagery layer features in more detail. First, we’ll look at imagery providers which support several standards for accessing imagery.

Ready-to-use imagery

We maintain a catalog of Internet-accessible imagery tilesets on cesiumjs.org. These tilesets can be used in your own Cesium-based applications, usually just by adding a couple of lines of code.

Imagery providers

High-resolution imagery like the first two layers used above is too large to fit into memory or often even a single disk, so imagery is divided into smaller images, called tiles, that can be streamed to a client as needed based on the view. Cesium supports several standards for requesting tiles using imagery providers. Most imagery providers use a REST interface over HTTP to request tiles. Imagery providers differ based on how requests are formatted and how tiles are organized. Cesium has the following imagery providers:

We can access other imagery services by implementing the ImageryProvider interface. If you do so, and think it is generally useful, please contribute it to Cesium for everyone’s benefit.

See the reference documentation for how to construct a particular imagery provider. We’ll look at the SingleTileImageryProvider here since many imagery providers share its construction properties:

  • url - The url to the image. Like many imagery providers, this is the only required property. In other imagery providers this url points to the server or the root url of the service.
  • extent - An optional longitude-latitude rectangle that the image should cover. The default is to cover the entire globe.
  • credit - An optional string crediting the data source, which is displayed on the canvas. Some imagery providers, like BingMapsImageryProvider and ArcGIS Server REST API, get a credit logo or string directly from their service.
  • proxy - An optional proxy to use for requests to the service, which brings us to Cross-Origin Resource Sharing.

Cross-origin resource sharing

As a security measure, today’s web browsers take pains to prevent Javascript code from reading the pixels of an image that comes from a different site. In particular, WebGL applications like Cesium are forbidden from using images as textures if those images - imagery tiles in our case - come from a different host name or port and the server does not explicitly allow the images to be used in this way. The server indicates that the images do not contain confidential information, and it is therefore safe for other sites to read their pixels, by including Cross-Origin Resource Sharing (CORS) headers in the HTTP response.

Unfortunately, not all imagery services support CORS. For those that don’t, a proxy server at the same origin as the website hosting Cesium must be used. When using such a proxy, tiles appear to the web browser and the Cesium client as if they came from the same origin as the Cesium-based website. To use a proxy with an imagery provider, use the proxy property when constructing the imagery provider. Cesium includes a simple proxy written in Node.js for development purposes.

layers.addImageryProvider(new Cesium.ArcGisMapServerImageryProvider({
    url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer',
    proxy : new Cesium.DefaultProxy('/proxy/')
}));

If you are hosting public imagery, we encourage enabling CORS as described here instead of using a proxy.

Imagery providers vs. layers

So far we haven’t clearly differentiated between imagery providers and layers. An imagery provider makes requests for tiles using a particular service, while a layer represents displayed tiles from an imagery provider. Code like

var layer = layers.addImageryProvider(imageryProvider);

is shorthand for

var layer = new ImageryLayer(imageryProvider);
layers.add(layer);

We usually construct an imagery provider just to create a layer, then we manipulate the layer to change its visual appearance using its properties like show, alpha, brightness, and contrast. See ImageryLayer. Decoupling imagery providers and layers makes it easier to write new imagery providers.

An imagery layer collection, like layers in the above examples, determines the order in which layers are drawn. Layers are drawn bottom-to-top based on the order they are added. Imagery layer collections are manipulated like any other collection in Cesium using functions like add, remove, and get. In addition, layers can be reordered using raise, raiseToTop, lower, and lowerToBottom. See ImageryLayerCollection.

Resources

Checkout the imagery layers examples in Sandcastle:

In addition, checkout the reference documentation: