Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image overlay using local jpg/gif #550

Closed
giswqs opened this issue Apr 19, 2020 · 4 comments
Closed

Image overlay using local jpg/gif #550

giswqs opened this issue Apr 19, 2020 · 4 comments

Comments

@giswqs
Copy link
Contributor

giswqs commented Apr 19, 2020

It seems ImageOverlay and VideoOverlay can only display images/videos on the Internet via the url parameter. It would be nice if it can also display images/videos stored locally.

from ipyleaflet import Map, VideoOverlay

m = Map(center=(25, -115), zoom=4)

video = VideoOverlay(
    url="https://www.mapbox.com/bites/00188/patricia_nasa.webm",
    # url="/path/to/local/demo.webm"
    bounds=((13, -130), (32, -100))
)

m.add_layer(video);
m
@giswqs
Copy link
Contributor Author

giswqs commented Apr 19, 2020

@davidbrochart Thank you very much for the examples. I was able to adapt the examples and create a function to display local images on the map. It can now display gif nicely. Thanks.

    def image_overlay(self, url, bounds, name):
        """Overlays an image from the Internet or locally on the map.

        Args:
            url (str): http URL or local file path to the image.
            bounds (tuple): bounding box of the image in the format of (lower_left(lat, lon), upper_right(lat, lon)), such as ((13, -130), (32, -100)).
            name (str): name of the layer to show on the layer control.
        """
        from base64 import b64encode
        from PIL import Image, ImageSequence
        from io import BytesIO
        try:
            if not url.startswith('http'):
                ext = os.path.splitext(url)[1][1:] # file extension
                image = Image.open(url)

                f = BytesIO()
                if ext.lower() == 'gif':
                    frames = []
                    # Loop over each frame in the animated image
                    for frame in ImageSequence.Iterator(image):
                        frame = frame.convert('RGBA')
                        b = BytesIO()
                        frame.save(b, format="gif")
                        frame = Image.open(b)
                        frames.append(frame)
                    frames[0].save(f, format='GIF', save_all=True, append_images=frames[1:], loop=0)
                else:                 
                    image.save(f, ext)

                data = b64encode(f.getvalue())
                data = data.decode('ascii')
                url = 'data:image/{};base64,'.format(ext) + data
            img = ipyleaflet.ImageOverlay(url=url, bounds=bounds, name=name)
            self.add_layer(img)
        except Exception as e:
            print(e)
            return

@giswqs giswqs closed this as completed Apr 19, 2020
@martinRenou
Copy link
Member

Using a data url will definitely be slower.

Note that you can provide a path to a local file, but the behaviour is different in Jupyter Notebook and JupyterLab, see https://ipyleaflet.readthedocs.io/en/latest/api_reference/local_tile_layer.html for a comment about local paths. Maybe this should be added in the Image Overlay documentation page. Same for marker icons.

@giswqs
Copy link
Contributor Author

giswqs commented Apr 23, 2020

@martinRenou This is great to know. I just tested it, and it works with the relative path but not an absolute path. At least the relative path works so that I don't have to convert path to URL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants