2

I am writing a node/typescript app that analyzes raster data. It uses leaflet and esri-leaflet quite a bit (modified to work server-side). For a given map bounds, it can download a raster image from ArcGIS server, and for a given latlng, it can tell you a pixel's rgba value from the raster image.

What I want to do is then map the RGBA value to its meaning according to the map's legend. Take this layer for example:

enter image description here

There are an absolute ton of values available in the legend. I don't want to have to guess at the rgba values, or use some kind of color-getter app to do it one by one. I need a legend that has the actual RGB(A) values of these colors listed, so I can then map my latlng value back to a meaningful value.

Most of this code runs in a node server, but to give you something to play with, I reacreated a playground in a codesandbox. Let's say I'm working with layer 30 of the LANDFIRE dataset, which is vegetation condition class. I created a map which fetches the raster image based on the map's bounds and zoom, writes the image to a canvas, and then reads the RGB values on the fly:

Codesandbox Playground

Here's the app without the code. It acts a little wonky sometimes to don't be afraid to reload, and give it a second on load, zoom, and pan events.

As you mouseover the map, you get the rgb values of the pixels instantly, because the whole dataset is downloaded in one swoop as an image. For this particular raster data, arcgis online has this legend. I want to be able to map the pixels back to the actual values represented by the colors, i.e. instead of seeing the rgb values in my little box, I want to see the ground cover type, tree cover %, or whatever the legend contains.

How can I get the legend's color values as a list of RGBA: Layer Value pairs programatically?

3
  • Can you please add some details, code or a reference to the layers you are using?
    – Dror Bogin
    Jan 22, 2021 at 15:36
  • I added a codesandbox with some explanation, hopefully that will give you a clearer sense of what I'm trying to do / a glimpse of the code I'm using in my app. Jan 22, 2021 at 23:39
  • That was very helpful, I added an answer that should help you.
    – Dror Bogin
    Jan 23, 2021 at 11:33

1 Answer 1

3

I would start by getting the legend in json and not HTML.
In the case of your layer, this would be the address and how to get your specific layer:

var url = "https://landfire.cr.usgs.gov/arcgis/rest/services/Landfire/US_200/MapServer/legend?f=pjson";
var legend;
fetch(url)
   .then(response => response.json())
   .then(data => {
     legend = data.layers[30]["legend"]
   });

Thanks to this answer I found that you could then create a canvas element (without adding it to the map) where you could draw the images and get the pixel values, this is the example for the second elemn in the legend (because the first was just black No Data.

var cnvs = document.createElement('canvas')
var context = cnvs.getContext('2d')
var imageSrc = "data:image/png;base64,"+legend[5].imageData
var image = new Image(20, 20);
image.src = imageSrc;
context.drawImage(image, 0, 0)
var color = context.getImageData(10, 10, 1, 1).data

The value you get back is an array of [r,g,b,a] which you can compare to the value you are getting from your mouse, the legend has the label value which you can use in your app.

4
  • Amazing. This is a great tactic. תודה! Jan 23, 2021 at 15:25
  • Here's a codesandbox implementing your solution. Interestingly enough, some of the legend's image rgb values are frequently off by 1 (i.e. { R: 30, G: 20, B: 10 } vs { R: 31, G: 20, B: 10}), so I had to write a function to compare objects and consider them 'the same' so long as they're within a certain tolerance. Jan 24, 2021 at 6:26
  • You wouldn't by chance know if arcgis has a typescript typing available for this legend JSON anywhere, would you? I could write my own, but I figure arcgis probably already has it somewhere, maybe as part of the arcgis-js-api. Any idea? Jan 24, 2021 at 6:27
  • No idea, I don't use arcgis products.
    – Dror Bogin
    Jan 24, 2021 at 6:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.