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

Errors loading tiff files #32

Closed fernandomantoan closed 4 years ago

fernandomantoan commented 4 years ago

Describe the bug I'm trying to use this library to display some tiff files on my application but some errors are being thrown when loading some specific files. I'm not sure if this is a bug with the lib itself but maybe you can give me some insights about the issues. The code I used is mostly the same as in the georaster-layer-for-leaflet-example repository I even forked it to host the tiff files I mentioned, if you want to check it: https://github.com/fernandomantoan/georaster-layer-for-leaflet-example, the files are ndvi_contrast_Field_4960_2020-01-24.tiff, ndvi_contrast_FieldGroup_1_2020-02-10.tiff, visual_FieldGroup_1_2020-02-10.tiff, exemplotiff.tif. The only difference is that I had to add the proj4 library.

Some Logs:

Uncaught (in promise) RangeError: Invalid typed array length: 528
georaster projection is 32621
bundle.js:3156 georaster projection is UTM
bundle.js:3051 Uncaught (in promise) TypeError: Cannot read property '131' of undefined
    at bundle.js:3051
    at Array.map (<anonymous>)
    at _loop2 (bundle.js:3050)
    at bundle.js:3087
    at _loop (bundle.js:3091)
    at bundle.js:3098
(anonymous) @ bundle.js:3051
_loop2 @ bundle.js:3050
(anonymous) @ bundle.js:3087
_loop @ bundle.js:3091
(anonymous) @ bundle.js:3098
bundle.js:3051 Uncaught (in promise) TypeError: Cannot read property '78' of undefined
    at bundle.js:3051
    at Array.map (<anonymous>)
    at _loop2 (bundle.js:3050)
    at bundle.js:3087
    at _loop (bundle.js:3091)
    at bundle.js:3098
(anonymous) @ bundle.js:3051
_loop2 @ bundle.js:3050
(anonymous) @ bundle.js:3087
_loop @ bundle.js:3091
(anonymous) @ bundle.js:3098
bundle.js:3051 Uncaught (in promise) TypeError: Cannot read property '5' of undefined
    at bundle.js:3051
    at Array.map (<anonymous>)
    at _loop2 (bundle.js:3050)
    at bundle.js:3087
    at _loop (bundle.js:3091)
    at bundle.js:3098
(anonymous) @ bundle.js:3051
_loop2 @ bundle.js:3050
(anonymous) @ bundle.js:3087
_loop @ bundle.js:3091
(anonymous) @ bundle.js:3098
bundle.js:3051 Uncaught (in promise) TypeError: Cannot read property '133' of undefined
    at bundle.js:3051
    at Array.map (<anonymous>)
    at _loop2 (bundle.js:3050)
    at bundle.js:3087
    at _loop (bundle.js:3091)
    at bundle.js:3098
bundle.js:3051 Uncaught (in promise) TypeError: Cannot read property '22' of undefined
    at bundle.js:3051
    at Array.map (<anonymous>)
    at _loop2 (bundle.js:3050)
    at bundle.js:3087
    at _loop (bundle.js:3091)
    at bundle.js:3098
bundle.js:3051 Uncaught (in promise) TypeError: Cannot read property '130' of undefined
    at bundle.js:3051
    at Array.map (<anonymous>)
    at _loop2 (bundle.js:3050)
    at bundle.js:3087
    at _loop (bundle.js:3091)
    at bundle.js:3098
bundle.js:3051 Uncaught (in promise) TypeError: Cannot read property '126' of undefined
    at bundle.js:3051
    at Array.map (<anonymous>)
    at _loop2 (bundle.js:3050)
    at bundle.js:3087
    at _loop (bundle.js:3091)
    at bundle.js:3098
bundle.js:3051 Uncaught (in promise) TypeError: Cannot read property '4' of undefined

It's important to note that when I use the tiff files provided from your original repo everything works fine.

I also tried uploading my files to http://app.geotiff.io/load and the errors are also being thrown there.

To Reproduce Steps to reproduce the behavior:

  1. Download any of the aforementioned tiff files
  2. Change main.js to point to the tiff file
  3. Build
  4. Run in browser (I used apache)

Expected behavior The tiff files should be presented.

Screenshots Each screenshot is a different tiff file.

screen1 screen2 screen3

Desktop (please complete the following information):

DanielJDufour commented 4 years ago

Hi, @fernandomantoan . Thanks for raising this issue. I'll take a look and let you know what I discover.

DanielJDufour commented 4 years ago

I just published a new version with some fixes. visual_FieldGroup_1_2020-02-10.tiff and exemplotiff.tif appear to be working now.

nvdi_... tiffs are still broken. I'll continue to investigate over the next few days...

thank you for your patience.

fernandomantoan commented 4 years ago

Hello @DanielJDufour I just gave it a try and the 2 files you mentioned are now working!

Thank you very much for putting effort into this.

If you have any news about these issues please let me know, but thanks to you I can advance further with my feature.

Regards and thanks again.

DanielJDufour commented 4 years ago

Hi, @fernandomantoan . I found the issue with ndvi_contrast_FieldGroup_1_2020-02-10.tiff. GeoRasterLayer automatically assumes 4-band rasters are RGBA, so the fourth band is interpreted as opacity. I'm assuming as it's titled NDVI, it's Near Infrared (NIR). Any easy fix is to use the pixelValuesToColorFn to map a pixel to a color:

pixelValuesToColorFn: function(values) {
  if (values[3] === 0) return null;
  return `rgb(${values[0]},${values[1]},${values[2]})`;
}

Here's a picture of it working

Screen Shot 2020-07-18 at 2 07 34 AM

Here's the larger code of it working:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css"/>
    <style>
      #map {
        bottom: 0;
        left: 0;
        position: absolute;
        right: 0;
        top: 0;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script src="https://unpkg.com/browse/whatwg-fetch@3.2.0/dist/fetch.umd.js"></script>
    <script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
    <script src="https://unpkg.com/georaster"></script>
    <script src="https://unpkg.com/proj4"></script>
    <script src="../georaster-layer-for-leaflet.min.js"></script>
    <script>
      // initalize leaflet map
      var map = L.map('map').setView([0, 0], 5);

      // add OpenStreetMap basemap
      L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
          attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      }).addTo(map);

      var url_to_geotiff_file = "../ndvi_contrast_FieldGroup_1_2020-02-10.tiff";

      fetch(url_to_geotiff_file)
        .then(function (response) { return response.arrayBuffer(); })
        .then(function (arrayBuffer) {
          parseGeoraster(arrayBuffer).then(function (georaster) {
            console.log("georaster:", georaster);
            var layer = new GeoRasterLayer({
              georaster: georaster,
              resolution: 512,
              pixelValuesToColorFn: function(values) {
                if (values[3] === 0) return null;
                return `rgb(${values[0]},${values[1]},${values[2]})`;
              }
            });
            layer.addTo(map);
            map.fitBounds(layer.getBounds());
        });
      });
    </script>
  </body>
</html>
DanielJDufour commented 4 years ago

The same approach works for ndvi_contrast_Field_4960_2020-01-24.tiff

Screen Shot 2020-07-18 at 2 09 48 AM
DanielJDufour commented 4 years ago

On second thought, it seems that the fourth band isn't NIR, but a mask that tells programs whether the pixel is no data or not. I'm honestly not sure how to fix it more generically, but if we see this issue pop up for others, we can think of a better fix.

I'm going to close this issue now, but please reopen or open another issue if you have any more issues.