GeoTIFF / georaster-layer-for-leaflet

Display GeoTIFFs and soon other types of raster on your Leaflet Map
https://geotiff.github.io/georaster-layer-for-leaflet-example/
Apache License 2.0
286 stars 57 forks source link

Strange gridlines for specific pixelValuesToColorFn #36

Closed saveas closed 4 years ago

saveas commented 4 years ago

Hi Daniel and thanks for this amazing plugin! I run into a strange problem. I render a geotiff, and when picking this pixelValuesToColorFn:

              pixelValuesToColorFn: values => values[0] === -32768 ? null :
                            (values[0] > -70                    ) ? '#607c3c' :
                            (values[0] > -90  && values[0] <= -70) ? '#809c13' :
                            (values[0] > -100 && values[0] <= -90) ? '#abc32f' :
                            (values[0] > -115 && values[0] <= -100) ? '#b5e550' :
                            (                    values[0] <= -115) ? '#ececa3' :
                            null

everything works perfect: image

But with this function that messes with the alpha value:

              pixelValuesToColorFn: values => values[0] === -32768 ? null :
                          (values[0] > -140  && values[0] <= -65) ?  `rgba(255, 0, 0, ${((values[0]+60)/80+1).toFixed(2)})` :
                          (values[0] < -140  ) ?  `rgba(255, 0, 0, 0)` :
                          (values[0] > -65  ) ?  `rgba(255, 0, 0, 1)` :
                          null

some red grid lines appear in zoom levels >=12 image

when I zoom out, the lines disappear image

The problem appears both on latest Chrome and Firefox, Leaflet 1.6

here is the tiff file I'm using sample.zip

Any idea on why this is happening?? Thanks in advance!

DanielJDufour commented 4 years ago

I'm also seeing grid lines when I zoom in on the first example. I'm wondering if it's an issue with Leaflet, but I'm not sure:

Screen Shot 2020-06-27 at 8 04 53 PM

I'll continue to research and let you know.

DanielJDufour commented 4 years ago

I agree that the issue is more pronounced with the second function

Screen Shot 2020-06-28 at 5 53 06 AM
DanielJDufour commented 4 years ago

I believe I discovered the issue. The most immediate solution is to swap out the pixelValuesToColorFn for a customDrawFunction like

              customDrawFunction: function({ values, context, x, y, width, height }) {
                const value = values[0];
                let color = null;
                if (value > -140  && value <= -65) color = `rgba(255, 0, 0, ${((value+60)/80+1).toFixed(2)})`;
                else if (value < -140) color = `rgba(255, 0, 0, 0)`;
                else if (value > -65  ) color = `rgba(255, 0, 0, 1)`;
                context.fillStyle = color;
                context.clearRect(x, y, width, height);
                context.fillRect(x, y, width, height);                         
              }   

You'll notice the usage of clearRect. Using clearRect will drag performance, but will help erase the red lines. The issue is that by changing the alpha value / opacity of colors, there are faint overlaps between rectangles drawn on the canvas. For example, if one rectangle draws from 0 to 1 and another draws from 1 to 2, they slightly overlap at 1.

Here's an image with a customDrawFunction

Screen Shot 2020-06-28 at 6 49 56 AM

Another solution would be to return different colors (rgb, not rgba) and set the layer opacity:

            var layer = new GeoRasterLayer({
              georaster,
              opacity: 0.7,
              resolution: 1024,
              pixelValuesToColorFn: values => values[0] === -32768 ? null :
                (values[0] > -140  && values[0] <= -65) ?  `rgb(${(1- ((values[0]+60)/80+1)) * 255}, 0, 0)` :
                (values[0] > -65  ) ?  `rgb(255, 0, 0)` :
                null                                     
            });

That results in an image like:

Screen Shot 2020-06-28 at 6 58 05 AM

There may be better long-term solutions out there. If anyone else has a solution, I'd be open to a Pull Request. I've tried a few other approaches for this library before (setting values in an ImageData), but all were less performant.

I'm sorry this isn't a great answer. Hopefully, we can find something that works.

saveas commented 4 years ago

Thanks for the time you spent on this Daniel! Actually the CustomDrawFunction solution works great, there is a very small performance drag but it is on acceptable level for my project! Plus I learned more about CustomDrawFunction :) Thanks again!

DanielJDufour commented 4 years ago

Sounds great. Glad to hear it works for you!