Parente's Mindtrove

Jupyter Tidbit: Show an image gallery

November 12, 2019

This post originates from a gist that supports comments, forks, and execution in binder.


Summary

JupyterLab and Jupyter Notebook can display HTML-embedded images in notebook documents. You can use the IPython.display.HTML class to structure these images into a basic image gallery.

Example

Binder

The notebook below defines a gallery() function that accepts a list of image URLs, local image file paths, or bytes in memory. The function displays the images from left-to-right, top-to-bottom in the notebook. An optional max_height parameter scales all images to the same height to create more regular looking rows.

The notebook includes two demos of the function output.

Why is this useful?

You may find a gallery view useful when you need to visually scan a large set of images. The horizontal layout helps reduce notebook scrolling. The fixed height option lets you pack more images on the screen at once and spot coarse differences.

gallery.ipynb

In [1]:
from IPython.display import HTML, Image

def _src_from_data(data):
    """Base64 encodes image bytes for inclusion in an HTML img element"""
    img_obj = Image(data=data)
    for bundle in img_obj._repr_mimebundle_():
        for mimetype, b64value in bundle.items():
            if mimetype.startswith('image/'):
                return f'data:{mimetype};base64,{b64value}'

def gallery(images, row_height='auto'):
    """Shows a set of images in a gallery that flexes with the width of the notebook.
    
    Parameters
    ----------
    images: list of str or bytes
        URLs or bytes of images to display

    row_height: str
        CSS height value to assign to all images. Set to 'auto' by default to show images
        with their native dimensions. Set to a value like '250px' to make all rows
        in the gallery equal height.
    """
    figures = []
    for image in images:
        if isinstance(image, bytes):
            src = _src_from_data(image)
            caption = ''
        else:
            src = image
            caption = f'<figcaption style="font-size: 0.6em">{image}</figcaption>'
        figures.append(f'''
            <figure style="margin: 5px !important;">
              <img src="{src}" style="height: {row_height}">
              {caption}
            </figure>
        ''')
    return HTML(data=f'''
        <div style="display: flex; flex-flow: row wrap; text-align: center;">
        {''.join(figures)}
        </div>
    ''')

Demos

Generate URLs for images of varying sizes using Lorem Picsum.

In [2]:
import random

urls = []
for i in range(25):
    width = random.randrange(400, 800)
    height = random.randrange(400, 800)
    urls.append(f'https://picsum.photos/{width}/{height}?random={i}')

Render a gallery of the images with a row height.

In [4]:
gallery(urls, row_height='150px')
Out[4]:
https://picsum.photos/514/613?random=0
https://picsum.photos/777/400?random=1
https://picsum.photos/516/555?random=2
https://picsum.photos/433/786?random=3
https://picsum.photos/503/508?random=4
https://picsum.photos/690/574?random=5
https://picsum.photos/513/448?random=6
https://picsum.photos/764/580?random=7
https://picsum.photos/408/767?random=8
https://picsum.photos/429/690?random=9
https://picsum.photos/511/738?random=10
https://picsum.photos/594/528?random=11
https://picsum.photos/523/574?random=12
https://picsum.photos/702/625?random=13
https://picsum.photos/563/709?random=14
https://picsum.photos/468/441?random=15
https://picsum.photos/552/680?random=16
https://picsum.photos/619/421?random=17
https://picsum.photos/625/578?random=18
https://picsum.photos/536/596?random=19
https://picsum.photos/526/735?random=20
https://picsum.photos/752/408?random=21
https://picsum.photos/775/516?random=22
https://picsum.photos/424/423?random=23
https://picsum.photos/687/400?random=24

Generate in-memory PNGs for avatar characters using the pagan library.

In [5]:
import io
import pagan

pngs = []
for i in range(50):
    buffer = io.BytesIO()
    pagan.Avatar(f'{i}').img.save(buffer, 'png')
    pngs.append(buffer.getvalue())

Render a gallery of the avatars with their natural dimensions.

In [6]:
gallery(pngs)
Out[6]:

Another Read: Jupyter Tidbit: Config, data, and runtime paths »

You can get a list of standard paths Jupyter tools use for configuration, static assets, and temporary runtime files by running the command jupyter --paths.