RGB renderer

View inWPFUWPFormsiOSAndroid
View on GitHub

Apply an RGB renderer to a raster layer to enhance feature visibility.

Image of RGB renderer

Use case

An RGB renderer is used to adjust the color bands of a multispectral image. Remote sensing images acquired from satellites often contain values representing the reflection of multiple spectrums of light. Changing the RGB renderer of such rasters can be used to differentiate and highlight particular features that reflect light differently, such as different vegetation types, or turbidity in water.

How to use the sample

Choose one of the stretch parameter types. The other options will adjust based on the chosen type. Add your inputs and select the 'Update' button to update the renderer.

How it works

  1. Create a Raster from a from a multispectral raster file.
  2. Create a RasterLayer from the raster.
  3. Create a Basemap from the raster layer and set it to the map.
  4. Create an RGBRenderer, specifying the StretchParameters and other properties.
  5. Apply the renderer to the raster layer.

Relevant API

  • Basemap
  • Raster
  • RasterLayer
  • RGBRenderer
  • StretchParameters

Offline data

This sample downloads the following items from ArcGIS Online automatically:

About the data

The raster used in this sample shows an area in the south of the Shasta-Trinity National Forest, California.

Tags

analysis, color, composite, imagery, multiband, multispectral, pan-sharpen, photograph, raster, spectrum, stretch, visualization

Sample Code

RasterRgbRenderer.cs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
// Copyright 2018 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.

using Android.App;
using Android.OS;
using Android.Widget;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Rasters;
using Esri.ArcGISRuntime.UI.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using ArcGISRuntime.Samples.Managers;

namespace ArcGISRuntime.Samples.RasterRgbRenderer
{
    [Activity (ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
	[ArcGISRuntime.Samples.Shared.Attributes.OfflineData("7c4c679ab06a4df19dc497f577f111bd")]
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        name: "RGB renderer",
        category: "Layers",
        description: "Apply an RGB renderer to a raster layer to enhance feature visibility.",
        instructions: "Choose one of the stretch parameter types. The other options will adjust based on the chosen type. Add your inputs and select the 'Update' button to update the renderer.",
        tags: new[] { "analysis", "color", "composite", "imagery", "multiband", "multispectral", "pan-sharpen", "photograph", "raster", "spectrum", "stretch", "visualization" })]
    public class RasterRgbRenderer : Activity
    {
        // Reference to the MapView used in the sample.
        private MapView _myMapView;

        // Reference to the raster layer to render.
        private RasterLayer _rasterLayer;

        // Layout panels to contain the UI for entering different renderer parameters.
        private LinearLayout _minMaxLayout;
        private LinearLayout _percentClipLayout;
        private LinearLayout _stdDeviationLayout;

        // Spinner for choosing the type of parameters input to use.
        private Spinner _parameterInputTypeSpinner;

        // Input controls for minimum and maximum RGB parameter values.
        private Spinner _minRedSpinner;
        private Spinner _minGreenSpinner;
        private Spinner _minBlueSpinner;
        private Spinner _maxRedSpinner;
        private Spinner _maxGreenSpinner;
        private Spinner _maxBlueSpinner;

        // Input controls for minimum and maximum percent clip values.
        private SeekBar _minPercentClipSlider;
        private SeekBar _maxPercentClipSlider;

        // Input control for the standard deviation factor value.
        private Spinner _stdDeviationFactorSpinner;

        // Button to apply the renderer.
        private Button _applyRendererButton;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            Title = "Raster RGB renderer";

            // Create the UI for inputting renderer parameters.
            CreateLayout();

            // Initialize the map and raster layer.
            Initialize();
        }

        private void CreateLayout()
        {
            #region UI for selecting parameter type and applying the renderer
            // Create a vertical layout for the page.
            LinearLayout mainLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Vertical
            };

            // Add some padding to the layout.
            mainLayout.SetPadding(20, 0, 0, 5);

            // Create a horizontal layout for the parameter type list and button to apply the renderer.
            LinearLayout parameterTypeLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Horizontal
            };
            string[] stretchTypes = { "Min Max", "Percent Clip", "Standard Deviation" };
            ArrayAdapter<string> stretchTypesAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleSpinnerDropDownItem, stretchTypes);

            // Create the spinner control for choosing the stretch parameter input type and handle its ItemSelected event.
            _parameterInputTypeSpinner = new Spinner(this)
            {
                Adapter = stretchTypesAdapter,
                DropDownWidth = 340
            };
            _parameterInputTypeSpinner.ItemSelected += ParameterInputTypeSpinner_ItemSelected;

            // Create the button that applies the renderer and handle its Click event.
            _applyRendererButton = new Button(this)
            {
                Text = "Apply",
                Enabled = false
            };
            _applyRendererButton.Click += ApplyRendererButton_Click;

            // Add a label, parameter type spinner control, and the apply button.
            TextView parameterTypeTextView = new TextView(this)
            {
                Text = "Stretch type: "
            };
            parameterTypeLayout.AddView(parameterTypeTextView);
            parameterTypeLayout.AddView(_parameterInputTypeSpinner);
            parameterTypeLayout.AddView(_applyRendererButton);

            // Add the parameter UI choice controls to the main layout.
            mainLayout.AddView(parameterTypeLayout);
            #endregion

            #region UI for defining min/max RGB values
            // Create a horizontal layout for the min/max RGB inputs.
            _minMaxLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Horizontal
            };

            // Create a range of values from 0-255 and an adapter to display them.
            int[] minMaxValues = Enumerable.Range(0, 256).ToArray();
            ArrayAdapter<int> minMaxValuesAdapter = new ArrayAdapter<int>(this, Android.Resource.Layout.SimpleSpinnerDropDownItem, minMaxValues);

            // Get the width of the current device (in pixels).
            int widthPixels = Resources.DisplayMetrics.WidthPixels;

            // Use 1/5 of the device width for the drop down.
            int dropDownWidth = widthPixels / 5;

            // Create controls for specifying the minimum and maximum red values (0-255).
            _minRedSpinner = new Spinner(this, SpinnerMode.Dropdown)
            {
                Adapter = minMaxValuesAdapter,
                DropDownWidth = dropDownWidth
            };
            _minRedSpinner.SetSelection(0);
            _maxRedSpinner = new Spinner(this, SpinnerMode.Dropdown)
            {
                Adapter = minMaxValuesAdapter,
                DropDownWidth = dropDownWidth
            };
            _maxRedSpinner.SetSelection(255);

            // Set the background color to indicate which values the inputs are for.
            _minRedSpinner.SetBackgroundColor(Android.Graphics.Color.DarkRed);
            _maxRedSpinner.SetBackgroundColor(Android.Graphics.Color.DarkRed);

            // Create controls for specifying the minimum and maximum green values (0-255).
            _minGreenSpinner = new Spinner(this, SpinnerMode.Dropdown)
            {
                Adapter = minMaxValuesAdapter,
                DropDownWidth = dropDownWidth
            };
            _minGreenSpinner.SetSelection(0);
            _maxGreenSpinner = new Spinner(this, SpinnerMode.Dropdown)
            {
                Adapter = minMaxValuesAdapter,
                DropDownWidth = dropDownWidth
            };
            _maxGreenSpinner.SetSelection(255);

            // Set the background color to indicate which values the inputs are for.
            _minGreenSpinner.SetBackgroundColor(Android.Graphics.Color.DarkGreen);
            _maxGreenSpinner.SetBackgroundColor(Android.Graphics.Color.DarkGreen);

            // Create controls for specifying the minimum and maximum blue values (0-255).
            _minBlueSpinner = new Spinner(this, SpinnerMode.Dropdown)
            {
                Adapter = minMaxValuesAdapter,
                DropDownWidth = dropDownWidth
            };
            _minBlueSpinner.SetSelection(0);
            _maxBlueSpinner = new Spinner(this, SpinnerMode.Dropdown)
            {
                Adapter = minMaxValuesAdapter,
                DropDownWidth = dropDownWidth
            };
            _maxBlueSpinner.SetSelection(255);

            // Set the background color to indicate which values the inputs are for.
            _minBlueSpinner.SetBackgroundColor(Android.Graphics.Color.DarkBlue);
            _maxBlueSpinner.SetBackgroundColor(Android.Graphics.Color.DarkBlue);

            // Create vertical layouts for the color inputs (so they align properly).
            LinearLayout redInputsLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Vertical
            };
            LinearLayout greenInputsLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Vertical
            };
            LinearLayout blueInputsLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Vertical
            };

            // Add the color inputs to their corresponding layout.
            redInputsLayout.AddView(_minRedSpinner);
            redInputsLayout.AddView(_maxRedSpinner);
            greenInputsLayout.AddView(_minGreenSpinner);
            greenInputsLayout.AddView(_maxGreenSpinner);
            blueInputsLayout.AddView(_minBlueSpinner);
            blueInputsLayout.AddView(_maxBlueSpinner);

            // Add the vertical color inputs to the horizontal parent layout.
            _minMaxLayout.SetPadding(50, 10, 0, 10);
            _minMaxLayout.AddView(redInputsLayout);
            _minMaxLayout.AddView(greenInputsLayout);
            _minMaxLayout.AddView(blueInputsLayout);

            // Add the UI layouts to the main layout
            mainLayout.AddView(_minMaxLayout);
            #endregion

            #region UI for defining percent clip values
            // Create a (hidden) vertical layout for the min/max percent clip sliders.
            _percentClipLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Vertical,
                Visibility = Android.Views.ViewStates.Gone
            };

            // Apply some padding for the layout.
            _percentClipLayout.SetPadding(20, 5, 0, 20);

            // Create the minimum and maximum percent sliders (SeekBar).
            _minPercentClipSlider = new SeekBar(this)
            {
                Max = 100,
                Progress = 0
            };
            _maxPercentClipSlider = new SeekBar(this)
            {
                Max = 100,
                Progress = 0
            };

            // Set the SeekBar dimensions and a left margin.
            ActionBar.LayoutParams layoutParamsSeekBar = new ActionBar.LayoutParams(400, 30)
            {
                LeftMargin = 5
            };
            _minPercentClipSlider.LayoutParameters = layoutParamsSeekBar;
            _maxPercentClipSlider.LayoutParameters = layoutParamsSeekBar;

            // Create labels for minimum and maximum percent.
            TextView minimumSliderLabel = new TextView(this)
            {
                Text = "Min: "
            };
            TextView maximumSliderLabel = new TextView(this)
            {
                Text = "Max: "
            };

            // Create horizontal layouts for the minimum and maximum controls.
            LinearLayout minPercentClipLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Horizontal
            };
            LinearLayout maxPercentClipLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Horizontal
            };

            // Add min and max percent controls to their corresponding layouts.
            minPercentClipLayout.AddView(minimumSliderLabel);
            minPercentClipLayout.AddView(_minPercentClipSlider);
            maxPercentClipLayout.AddView(maximumSliderLabel);
            maxPercentClipLayout.AddView(_maxPercentClipSlider);

            // Add the slider layouts to the percent clip layout.
            _percentClipLayout.AddView(minPercentClipLayout);
            _percentClipLayout.AddView(maxPercentClipLayout);

            // Add the percent clip UI to the main layout.
            mainLayout.AddView(_percentClipLayout);
            #endregion

            #region UI for defining standard deviation factor
            // Create a range of values from 0-5 (in 0.5 increments) and an adapter to display them.
            IEnumerable<int> wholeStdDevs = Enumerable.Range(1, 10);
            List<double> halfStdDevs = wholeStdDevs.Select(i => (double)i / 2).ToList();
            ArrayAdapter<double> stdDevFactorsAdapter = new ArrayAdapter<double>(this, Android.Resource.Layout.SimpleSpinnerDropDownItem, halfStdDevs);

            // Create a drop down (Spinner) control for specifying the standard deviation factor (0.0 - 5.0).
            _stdDeviationFactorSpinner = new Spinner(this, SpinnerMode.Dropdown)
            {
                Adapter = stdDevFactorsAdapter,
                DropDownWidth = dropDownWidth
            };

            // Set the default selection to the 4th item (value of 2.0)
            _stdDeviationFactorSpinner.SetSelection(4);

            // Create a label (TextView) for the Spinner.
            TextView factorLabel = new TextView(this)
            {
                Text = "Factor: "
            };

            // Create a horizontal layout for the controls.
            LinearLayout stdDevFactorLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Horizontal
            };

            // Add the controls for selecting a standard deviation factor.
            stdDevFactorLayout.AddView(factorLabel);
            stdDevFactorLayout.AddView(_stdDeviationFactorSpinner);

            // Create the standard deviation factor layout and add the controls.
            _stdDeviationLayout = new LinearLayout(this)
            {
                Orientation = Orientation.Vertical,
                Visibility = Android.Views.ViewStates.Gone
            };
            _stdDeviationLayout.SetPadding(50, 5, 0, 5);
            _stdDeviationLayout.AddView(stdDevFactorLayout);

            // Add the standard deviation layout to the main layout.
            mainLayout.AddView(_stdDeviationLayout);
            #endregion

            // Create the map view control.
            _myMapView = new MapView(this);

            // Add the map view to the layout.
            mainLayout.AddView(_myMapView);

            // Set the layout as the sample view.
            SetContentView(mainLayout);
        }

        private async void Initialize()
        {
            // Create a map with a streets basemap.
            Map myMap = new Map(BasemapStyle.ArcGISStreets);

            // Get the file name for the local raster dataset.
            string filepath = GetRasterPath();

            // Load the raster file
            Raster rasterFile = new Raster(filepath);

            try
            {
                // Create and load a new raster layer to show the image.
                _rasterLayer = new RasterLayer(rasterFile);
                await _rasterLayer.LoadAsync();

                // Once the layer is loaded, enable the button to apply a new renderer.
                _applyRendererButton.Enabled = true;

                // Create a viewpoint with the raster's full extent.
                Viewpoint fullRasterExtent = new Viewpoint(_rasterLayer.FullExtent);

                // Set the initial viewpoint for the map.
                myMap.InitialViewpoint = fullRasterExtent;

                // Add the layer to the map.
                myMap.OperationalLayers.Add(_rasterLayer);

                // Add the map to the map view.
                _myMapView.Map = myMap;
            }
            catch (Exception e)
            {
                new AlertDialog.Builder(this).SetMessage(e.ToString()).SetTitle("Error").Show();
            }
        }

        private void ParameterInputTypeSpinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
        {
            // See which parameter (stretch) type was selected.
            string selectedStretchType = ((TextView)e.View).Text;

            // Hide all UI controls for the input parameters.
            _minMaxLayout.Visibility = Android.Views.ViewStates.Gone;
            _percentClipLayout.Visibility = Android.Views.ViewStates.Gone;
            _stdDeviationLayout.Visibility = Android.Views.ViewStates.Gone;

            // See which type was selected and show the corresponding input controls.
            switch (selectedStretchType)
            {
                case "Min Max":
                    _minMaxLayout.Visibility = Android.Views.ViewStates.Visible;
                    break;
                case "Percent Clip":
                    _percentClipLayout.Visibility = Android.Views.ViewStates.Visible;
                    break;
                case "Standard Deviation":
                    _stdDeviationLayout.Visibility = Android.Views.ViewStates.Visible;
                    break;
            }
        }

        private void ApplyRendererButton_Click(object sender, EventArgs e)
        {
            // Create the correct type of StretchParameters with the corresponding user inputs.
            StretchParameters stretchParameters = null;

            // See which type is selected and apply the corresponding input parameters to create the renderer.
            switch (_parameterInputTypeSpinner.SelectedItem.ToString())
            {
                case "Min Max":
                    // Read the minimum and maximum values for the red, green, and blue bands.
                    double minRed = Convert.ToDouble(_minRedSpinner.SelectedItem);
                    double minGreen = Convert.ToDouble(_minGreenSpinner.SelectedItem);
                    double minBlue = Convert.ToDouble(_minBlueSpinner.SelectedItem);
                    double maxRed = Convert.ToDouble(_maxRedSpinner.SelectedItem);
                    double maxGreen = Convert.ToDouble(_maxGreenSpinner.SelectedItem);
                    double maxBlue = Convert.ToDouble(_maxBlueSpinner.SelectedItem);

                    // Create an array of the minimum and maximum values.
                    double[] minValues = { minRed, minGreen, minBlue };
                    double[] maxValues = { maxRed, maxGreen, maxBlue };

                    // Create a new MinMaxStretchParameters with the values.
                    stretchParameters = new MinMaxStretchParameters(minValues, maxValues);
                    break;
                case "Percent Clip":
                    // Get the percentile cutoff below which values in the raster dataset are to be clipped.
                    double minimumPercent = Convert.ToDouble(_minPercentClipSlider.Progress);

                    // Get the percentile cutoff above which pixel values in the raster dataset are to be clipped.
                    double maximumPercent = Convert.ToDouble(_maxPercentClipSlider.Progress);

                    // Create a new PercentClipStretchParameters with the inputs.
                    stretchParameters = new PercentClipStretchParameters(minimumPercent, maximumPercent);
                    break;
                case "Standard Deviation":
                    // Read the standard deviation factor (the number of standard deviations used to define the range of pixel values).
                    double standardDeviationFactor = Convert.ToDouble(_stdDeviationFactorSpinner.SelectedItem);

                    // Create a new StandardDeviationStretchParameters with the selected number of standard deviations.
                    stretchParameters = new StandardDeviationStretchParameters(standardDeviationFactor);
                    break;
            }

            // Create an array to specify the raster bands (red, green, blue).
            int[] bands = { 0, 1, 2 };

            // Create the RgbRenderer with the stretch parameters created above, then apply it to the raster layer.
            RgbRenderer rasterRenderer = new RgbRenderer(stretchParameters, bands, null, true);
            _rasterLayer.Renderer = rasterRenderer;
        }

        private static string GetRasterPath()
        {
            return DataManager.GetDataFolder("7c4c679ab06a4df19dc497f577f111bd", "raster-file", "Shasta.tif");
        }
    }
}

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