Apply mosaic rule to rasters

View on GitHub
Sample viewer app

Apply a mosaic rule to a mosaic dataset of rasters.

Apply mosaic rule to rasters

Use case

An image service can use a mosaic rule to mosaic multiple rasters on-the-fly. A mosaic rule can specify which rasters are selected, and how the selected rasters are z-ordered. It can also specify how overlapping pixels from different rasters at the same location are resolved.

For example, when using the "By Attribute" mosaic method, the values in an attribute field are used to sort the images, and when using the "Center" method, the image closest to the center of the display is positioned as the top image in the mosaic. Additionally, the mosaic operator allows you to define how to resolve the overlapping cells, such as choosing a blending operation.

Specifying mosaic rules is useful for viewing overlapping rasters. For example, using the "By Attribute" mosaic method to sort the rasters based on their acquisition date allows the newest image to be on top. Using "mean" mosaic operation makes the overlapping areas contain the mean cell values from all the overlapping rasters.

How to use the sample

When the rasters are loaded, choose from a list of preset mosaic rules to apply to the rasters.

How it works

  1. Create an AGSImageServiceRaster using the service's URL.
  2. Create an AGSMosaicRule object and set it to the mosaicRule property of the image service raster, if it does not specify a mosaic rule.
  3. Create an AGSRasterLayer from the image service raster and add it to the map.
  4. Set the mosaicMethod, mosaicOperation and other properties of the mosaic rule object accordingly to specify the rule on the raster dataset.

Relevant API

  • AGSImageServiceRaster
  • AGSMosaicMethod
  • AGSMosaicOperation
  • AGSMosaicRule

About the data

This sample uses a raster image service hosted on ArcGIS Online that shows aerial images of Amberg, Germany.

Additional information

For more information, see Understanding the mosaicking rules from ArcGIS Desktop documentation. To learn more about how to define certain mosaic rules, see Mosaic rule objects from ArcGIS for Developers.

Tags

image service, mosaic method, mosaic rule, raster

Sample Code

ApplyMosaicRuleToRastersViewController.swift
                                                                                                                                            
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2020 Esri
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import UIKit
import ArcGIS

class ApplyMosaicRuleToRastersViewController: UIViewController {
    // MARK: Storyboard views and properties

    /// A label to show status messages.
    @IBOutlet var statusLabel: UILabel!
    /// The KVO on draw status of the map view.
    private var drawStatusObservation: NSKeyValueObservation?

    /// The map view managed by the view controller.
    @IBOutlet var mapView: AGSMapView! {
        didSet {
            mapView.map = makeMap()
            // Observe the map view's drawing status to see when the new mosaic rule is loaded.
            drawStatusObservation = mapView.observe(\.drawStatus, options: .initial) { mapView, _ in
                if mapView.drawStatus == .completed {
                    UIApplication.shared.hideProgressHUD()
                }
            }
        }
    }
    /// The image service raster to demo mosaic rules.
    var imageServiceRaster = AGSImageServiceRaster(url: URL(string: "https://sampleserver7.arcgisonline.com/server/rest/services/amberg_germany/ImageServer")!)
    /// A preset of mosaic rules for demonstration purpose.
    let mosaicRulePairs: KeyValuePairs<String, AGSMosaicRule> = {
        // A default mosaic rule object, with mosaic method as none.
        let noneRule = AGSMosaicRule()
        noneRule.mosaicMethod = .none

        // A mosaic rule object with northwest method.
        let northWestRule = AGSMosaicRule()
        northWestRule.mosaicMethod = .northwest
        northWestRule.mosaicOperation = .first

        // A mosaic rule object with center method and blend operation.
        let centerRule = AGSMosaicRule()
        centerRule.mosaicMethod = .center
        centerRule.mosaicOperation = .blend

        // A mosaic rule object with byAttribute method and sort on "OBJECTID" field of the service.
        let byAttributeRule = AGSMosaicRule()
        byAttributeRule.mosaicMethod = .attribute
        byAttributeRule.sortField = "OBJECTID"

        // A mosaic rule object with lockRaster method and locks 3 image rasters.
        let lockRasterRule = AGSMosaicRule()
        lockRasterRule.mosaicMethod = .lockRaster
        lockRasterRule.lockRasterIDs = [1, 7, 12]

        return ["None": noneRule,
                "NorthWest": northWestRule,
                "Center": centerRule,
                "ByAttribute": byAttributeRule,
                "LockRaster": lockRasterRule]
    }()

    // MARK: Methods

    /// Create a map.
    ///
    /// - Returns: An `AGSMap` object.
    func makeMap() -> AGSMap {
        // Check if a mosaic rule exists. If not, create one.
        if imageServiceRaster.mosaicRule == nil {
            imageServiceRaster.mosaicRule = AGSMosaicRule()
        }
        // Create a raster layer.
        let rasterLayer = AGSRasterLayer(raster: imageServiceRaster)
        let map = AGSMap(basemapStyle: .arcGISTopographic)
        // Add raster layer as an operational layer to the map.
        map.operationalLayers.add(rasterLayer)
        UIApplication.shared.showProgressHUD(message: "Loading")
        rasterLayer.load { [weak self] error in
            guard let self = self else { return }
            if let error = error {
                UIApplication.shared.hideProgressHUD()
                self.presentAlert(error: error)
            } else {
                // When loaded, set the map view's viewpoint to the image service raster's center.
                if let center = self.imageServiceRaster.serviceInfo?.fullExtent?.center {
                    self.mapView.setViewpoint(AGSViewpoint(center: center, scale: 25000.0))
                }
                self.setStatus(message: "Image service raster loaded.")
            }
        }
        return map
    }

    // MARK: UI

    func setStatus(message: String) {
        statusLabel.text = message
    }

    // MARK: Actions

    @IBAction func chooseMosaicRule(_ sender: UIBarButtonItem) {
        let alertController = UIAlertController(
            title: "Choose a mosaic rule to apply to the image service.",
            message: nil,
            preferredStyle: .actionSheet
        )
        mosaicRulePairs.forEach { name, rule in
            let action = UIAlertAction(title: name, style: .default) { _ in
                UIApplication.shared.showProgressHUD(message: "Loading mosaic rule")
                self.setStatus(message: "\(name) selected.")
                self.imageServiceRaster.mosaicRule = rule
            }
            alertController.addAction(action)
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
        alertController.addAction(cancelAction)
        alertController.popoverPresentationController?.barButtonItem = sender
        present(alertController, animated: true)
    }

    // MARK: UIViewController

    override func viewDidLoad() {
        super.viewDidLoad()
        // Add the source code button item to the right of navigation bar.
        (navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["ApplyMosaicRuleToRastersViewController"]
    }
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.