26

I'm working with a map created using python, folium, and geojson, similar to this one.

However, instead of this image being an interactive HTML document, I would rather simply export it to png or svg.

Using the syntax:

m = folium.Map( # etc..)
m.save("filename.png")

Saves a file, but it is still HTML, rather than png. What's the correct output command to render not-to-html?

Mittenchops
  • 18,633
  • 33
  • 128
  • 246
  • Isn't [converting HTML to an image](https://pypi.org/project/imgkit/) a solved problem? – Jongware Nov 30 '18 at 22:58
  • 5
    [This page](https://github.com/python-visualization/folium/issues/833#issuecomment-381313915) seems to have a workaround using selenium – G. Anderson Nov 30 '18 at 23:03
  • Thanks, usr2564301, but rendering to HTML includes a lot of zoom and metadata for other regions of the map beyond my view portal. I'd really rather just render directly to the image I've created, versus the interactive map provided by the default html render. – Mittenchops Nov 30 '18 at 23:13
  • @G.Anderson's workaround no longer works in 2023. Selenium does not include PhantomJS in its newer versions, per the last comment in the thread he linked to – Kristen G. Aug 20 '23 at 13:15

3 Answers3

27

I use this:

... where m is my map object. And 5 is the time (seconds) to render the map.

import io
from PIL import Image

img_data = m._to_png(5)
img = Image.open(io.BytesIO(img_data))
img.save('image.png')
Michel Metran
  • 513
  • 5
  • 15
  • 16
    It requires SELENIUM. And thus webriver in path. Good that I have found this answer. If the selenium requirement was mentioned in the beginning, I wouldnt bother with folium. – jaromrax Sep 05 '20 at 11:01
  • 1
    If this doesn't work, giving you an `Expected browser binary location, but unable to find binary in default...` error: download the Firefox browser. Worked immediately for me. Note that the PhantomJS solution (linked in a comment above) is out of date and no longer works. – Jordan MacLachlan Feb 09 '23 at 21:48
0

After working through this same problem I found this solution using pdfkit, wkthmltopdf, and fitz, yet without SElENIUM or anything else that requires opening a browser (I’ve been challenging myself by only coding on my IPhone/IPad with Google Colab): Convert Folium Map to PNG Without SELENIUM.

First I converted the folium map from HTML to PDF using pdfkit, then I converted the PDF to PNG using fitz & cut the image out using pillow.

Its hacky and could use a lot of improvement, but it works for me now.

More details in the Colab link above.

def convert_map_png(folium_map, file_name):
  mapName = file_name
  
  # Get HTML File of Map
  folium_map.save(mapName + '.html')
  htmlfile = mapName + '.html'

  # Convert Map from HTML to PDF, Delay to Allow Rendering
  options = {'javascript-delay': 500,
    'page-size': 'Letter',
    'margin-top': '0.0in',
    'margin-right': '0.0in',
    'margin-bottom': '0.0in',
    'margin-left': '0.0in',
    'encoding': "UTF-8",
    'custom-header': [
        ('Accept-Encoding', 'gzip')
    ]}
  pdfkit.from_file(htmlfile,  (mapName + '.pdf'), options=options)
  pdffile = mapName + '.pdf'

  # Convert Map from PDF to PNG
  doc = fitz.open(pdffile)
  page = doc.load_page(0)
  pix = page.get_pixmap()
  output = mapName + '.png'
  pix.save(output)
  pngfile = mapName + '.png'
  doc.close()

  # Crop Out Map Image
  pilImage = Image.open(pngfile)
  
  croppedImage = pilImage.crop((0,0,287,287)) # Adjust this if your map renders differently on PDF

  return croppedImage
0

In such cases I find PrintScreen a boon its a one key programme but you can do similar by using the browser in headless screenshot mode too. Just much faster by hand. Not all options will be needed just my zealous overkill, as Edge only produced/output fixed size 800x600 image.

"C:\Apps\Browsers\GoogleChrome\GoogleChromePortable.exe" --headless --start-maximized --start-fullscreen --window-size="2000,1000" --hide-scrollbars --virtual-time-budget=5000 --screenshot="c:\Data\MySampleData\screen.png"  "C:\Data\MySampleData\map.html" &&timeout 6 &&screen.png

enter image description here

K J
  • 8,045
  • 3
  • 14
  • 36