2

I am trying to use leaflet to show a smaller map than usual so I don't want to use the normal tiling system. I don't care about smooth zooming and loading higher resolution tiles when needed. Instead I am trying to add a raster image from an image file. Lets say this file that comes up when I google "hand drawn map"

So I try

download.file('https://external-preview.redd.it/7tYT__KHEh8FBKO6bsqPgC02OgLCHAFVPyjdVZI4bms.jpg?auto=webp&s=ff2fa2e448bb92c4ed6c049133f80370f306acb3',
              destfile = 'map.jpg')
map = raster::raster('map.jpg')

# it seems like i need a projection to use a raster image.
# not sure what controls do I have over this, especially in
# absence of a proper map layer and it's likely
# part of the solution
crs(map) = CRS("+init=epsg:4326")

leaflet() %>%
    leaflet::addRasterImage(map)

The resulting output is nothing like the input image

crappy map

How do I take an arbitrary image and place in on a leaflet map?

OganM
  • 2,543
  • 16
  • 33
  • Does this answer your question? [Overlay image on R leaflet map](https://stackoverflow.com/questions/47170828/overlay-image-on-r-leaflet-map) – Brian Feb 11 '20 at 04:36
  • I voted to close this as a duplicate, but there may be other solutions besides the one linked. As far as I would guess, try the `colors=` argument of `addRasterImage()` and also change the projection. – Brian Feb 11 '20 at 04:38
  • doesn't quite work as it still forces me to add normal map tiles and locks me to that coordinate system. I think I need to be using `L.CRS.Simple` to be able to give proper boundaries for the image – OganM Feb 11 '20 at 05:47
  • 1
    @brian by modifying that answer slightly, I was able to add the overlay image based on my specification. Not sure it deserves a separate answer here though. It was only a matter of doing `leaflet(options = leafletOptions(crs = leafletCRS('L.CRS.Simple'))) %>% htmlwidgets::onRender("...` and calling the javascript – OganM Feb 11 '20 at 06:16
  • you can always answer your own question with your solution. Documenting the problem well is useful for future readers. – Brian Feb 11 '20 at 13:10
  • wanted to leave open for a bit in case someone comes up with a way to use `addRasterImage` but will do that now – OganM Feb 11 '20 at 21:24

1 Answers1

2

I failed to find the exact reason why addRasterImage fails here but I found reports that it doesn't behave well on L.CRS.Simple projection, which is what you'll want to use to show a simple rectangle image.

Using htmlwidgets::onRender makes it possible to directly use the javascript function L.imageOverlay to add the image you want

library(leaflet)

# minimal custom image
imageURL = 'https://external-preview.redd.it/7tYT__KHEh8FBKO6bsqPgC02OgLCHAFVPyjdVZI4bms.jpg?auto=webp&s=ff2fa2e448bb92c4ed6c049133f80370f306acb3'

# get image data. we'll use this to set the image size
imageData = 
    magick::image_read(imageURL) %>% image_info()

leaflet(options = leafletOptions(crs = leafletCRS('L.CRS.Simple'))) %>% 
            htmlwidgets::onRender(glue::glue("
      function(el, x) {
        var myMap = this;
        var imageUrl = '<imageURL>';
        var imageBounds = [[<-imageData$height/2>,<-imageData$width/2>], [<imageData$height/2>,<imageData$width/2>]];

        L.imageOverlay(imageUrl, imageBounds).addTo(myMap);
      }
      ",.open = '<', .close = '>'))

For a large image like this if you want to make the image smaller you can either scale down using the imageBounds in javascript side or set minZoom to a negative value and use setView to start out zoomed out.

leaflet(options = 
            leafletOptions(crs = leafletCRS('L.CRS.Simple'),
                           minZoom = -1)) %>% 
    setView(0,0,zoom = -1) %>%
            htmlwidgets::onRender(glue::glue("
      function(el, x) {
        var myMap = this;
        var imageUrl = '<imageURL>';
        var imageBounds = [[<-imageData$height/2>,<-imageData$width/2>], [<imageData$height/2>,<imageData$width/2>]];

        L.imageOverlay(imageUrl, imageBounds).addTo(myMap);
      }
      ",.open = '<', .close = '>'))
OganM
  • 2,543
  • 16
  • 33