How to Filter ImageryTileLayer Pixel Values Client-side in ArcGIS JavaScript API

512
4
07-22-2020 11:11 AM
RyanSutcliffe
Occasional Contributor II
[updated 2020-09-06: added some CodePen examples with what I've tried]
I have a use case for an app where I would like to enable users to filter pixels based on value from an ImageryTileLayer (formerly TileImageryLayer) in a map by adjusting a UI widget. Looking through the API however I cannot see any way to do this. Is there a recommended approach for a situation like this?
If I switched to a regular ImageryLayer I believe I could accomplish this via a PixelFilter (although I haven't implemented yet). 
Update:
Here is a CodePen example showing how I've created a dynamically rendered raster layer clientside with a RasterStretchRenderer. Unfortunately, from what I've read the RasterStretchRenderer does not seem to support filtering of values (this is consistent with other platforms like Desktop). Not sure why this is.
Here is a second CodePen example showing an approach where I tried using a ClassBreaksRenderer, creating my own breaks to mimic a stretchRenderer and then enabling filtering by setting specific breaks to be transparent. It accomplishes what I am after although the performance when a user adjusts the color scheme is much worse. It could be something with my code-- note that I run functions to dynamically recalculate colors and stops-- but looking at tests these seem to be running under 2-3ms.
@ESRI Is there a better way of doing this? An ESRI support person indicated that perhaps the RasterStretchRenderer has some optimization for dynamic display but the API documentation only says,
The RasterStretchRenderer works well when you have a large range of values to display, such as in imagery, aerial photographs, or elevation models.
I'm wondering why dynamically adjusting a ClassBreaksRenderer would be so much worse. 
Any advice, guidance, is welcome. 
0 Kudos
4 Replies
RyanSutcliffe
Occasional Contributor II

ESRI Canada Technical support got back to me with this regarding performance differences between ClassBreaks and the StretchRenderer:

..the primary difference between the two is that the Class Breaks Renderer consumes more resources because it must query the attribute information on the layer first before determining how best to categorize each pixel in each class. So there is a lot of computation and logic involved behind the scenes when this renderer does its work to put each pixel value into each group. This is passed to the client, and explains the performance decrease when you dynamically change this renderer. 

The documentation notes this: 'ClassBreaksRenderer defines the symbol of each feature in a Layer based on the value of a numeric attribute. Symbols are assigned based on classes or ranges of data. Each feature is assigned a symbol based on the class break in which the value of the attribute falls.'

The Stretch Renderer is working less hard as it does not have to consider all attribute values and how they may be placed into groups of categories. It is simply just changing the values on pixels. This has less impact on the client, as is seen in your sample.

The documentation on this renderer notes: 'RasterStretchRenderer defines the symbology with a gradual ramp of colors for each pixel in a ImageryLayer based on the pixel value.'

Makes sense. There was also confirmation that there isn't much in the way of other options for a client-side renderer on an ImageryTileLayer. So sounds like for now we'll opt for this approach despite it's limitations and hope that the RasterStretchRenderer will be extended to filter values at some later point by ESRI.

If anyone comes up with better solutions or workarounds would love to hear.

0 Kudos
RyanSutcliffe
Occasional Contributor II

Update: this no longer seems to work at ArcGIS JavaScript API 4.17. Reached out to ESRI support for advice.

0 Kudos
RyanSutcliffe
Occasional Contributor II

ESRI Canada notified me that a bug (BUG-000137572) has been logged by Redlands that causes this not to work at versions 4.17+ .

0 Kudos
RyanSutcliffe
Occasional Contributor II

A simplified CodePen showing how filtering a ClassBreaksRenderer for a raster at 4.18 fails now works using "next" (4.19). 

0 Kudos