Select to view content in your preferred language

Alternative of 2d canvas getContext('2d') and getImageData() in webgl2 canvas?

271
3
Jump to solution
09-30-2024 06:56 AM
efujioka
Occasional Contributor

Hello,

I'm migrating a web mapping application from ESRI Javascript API v3 to ArcGIS Maps SDK v4. In the v3 code, I used getContext('2d') to get access to the canvas and getImageData() to get the pixel data (color RGB on a particular spot on the map).

With Maps SDK, it seems the map is drawn on a webgl2 canvas and getContext('2d') returns null. I tried getContext('webgl2', {preserveDrawingBuffer: true}) and readPixels() but it returns an empty array. So, I can't get the pixel data. It seems there is a way to preserve the drawing buffer of webgl2 canvas but I don't think it's possible because how to create a canvas is totally up to Maps SDK and I can't modify it.

So, my questions are:

- Is there a way to make readPixels() return useful information so I can get the color RGB of the pixel?

- Is there a way to force Maps SDK to use 2d canvas instead of webgl2 or setup the webgl canvas with drawing buffer on?

- Is there workaround to get the pixel color RGB?

 

Background: my application visualizes a mosaic dataset as an ImageryLayer and map services as MapImageLayers from our own ArcGIS Server and I want to allow users to get the color information in RGB when they mouse-over the map (layers). So, it's not "Identify". I use pixelFilter to render ImageryLayer. So, I know I can get the pixel data. But what I want to achieve is to get the pixel color upon a user action on both ImageryLayer and MapImageLayers.

And below is a simplified working code for the v3 application.

var x = evt.screenPoint.x;
var y = evt.screenPoint.y;
var canvasDiv = Ext.get(divId);
var canvasDom = canvasDiv.child("canvas", true);
var c2d = canvasDom.getContext('2d');
var pixelData = c2d.getImageData(x, y, 1, 1).data;
var rgb = {r: pixelData[0], g: pixelData[1], b: pixelData[2]};
// And show rgb in a popup.

 

0 Kudos
1 Solution

Accepted Solutions
JoelBennett
MVP Regular Contributor

Have you looked into the takeScreenshot method of the MapView module?  Perhaps that's the missing piece you're looking for.

View solution in original post

0 Kudos
3 Replies
JoelBennett
MVP Regular Contributor

Have you looked into the takeScreenshot method of the MapView module?  Perhaps that's the missing piece you're looking for.

0 Kudos
efujioka
Occasional Contributor

That sounds promising! Thanks for the tip. I will call takeScreenshot whenever the layer view is updated and paste it into a hidden canvas. That way, I can call getImageData.

0 Kudos
SamEngel
Occasional Contributor

Hi @efujioka! We should be returning the image data already in the takeScreenshot() result, so unless you're doing something extra I don't think you'd need to use a hidden canvas. I put together a codepen here in case it's helpful: https://codepen.io/sam11948/pen/BaXKwGQ?editors=1000

0 Kudos