How can I save multiple images in a single html file?

Is there any way to save multiple images in one html file?

I am using figure’s image_url to display the images.
I’ve kept all the instances of figure to display each image, and saved them, but
However, the last image is only saved in the html, and the other images are not displayed.

For the record, here is the source code I wrote.

from bokeh.plotting import figure, show, output_file
from bokeh.io import output_notebook, save
from skimage import io
from bokeh.models import LinearAxis, Range1d
from bokeh.layouts import column
import numpy as np
import glob 

output_notebook()

lst_imgs = glob.glob(r".\imgs\*.png")


plts = []
for img_path in lst_imgs:
    image = io.imread(img_path)
    h, w, c = image.shape
    x_min = 0; x_max = w
    y_min = 0; y_max = h

    PLOT_SIZE_OPTIONS = \
        dict(
            x_axis_location='above',
            x_range=(x_min, x_max),
            y_range=(y_max, y_min), 
            plot_width=x_max, 
            plot_height=y_max
            )
    PLOT_OPTIONS = dict(sizing_mode='scale_width', id="plt_fig")
    ASPECT_OPTIONS = dict(match_aspect=True, aspect_scale=1.0)
    plt = figure(**PLOT_OPTIONS, **ASPECT_OPTIONS, **PLOT_SIZE_OPTIONS)

    print(img_path)
    plt.image_url(url=[img_path], x=x_min, y=y_min, w=x_max, h=y_max)
    plts.append(plt)
    # show(plt)

output_file("sample.html")
save(plts)
# show(column(*plts))

Please let me know if there is a better way.
Thank you in advance.

You need to put all the plots inside a single layout, and save that:

1 Like

@Bryan
Thank you for your answer.

I was able to achieve this by using bokeh.layouts.column.

The complete code is given below.

from bokeh.plotting import figure, show, output_file
from bokeh.io import output_notebook, save
from skimage import io
from bokeh.models import LinearAxis, Range1d
from bokeh.layouts import column
import numpy as np
import glob 

output_notebook()

def rgb_to_rgba32(im):
    """
    Convert an RGB image to a 32 bit-encoded RGBA image.
    """
    # Ensure it has three channels
    if len(im.shape) != 3 or im.shape[2] !=3:
        raise RuntimeError('Input image is not RGB.')
    
    # Get image shape
    n, m, _ = im.shape

    # Convert to 8-bit, which is expected for viewing
    im_8 = skimage.img_as_ubyte(im)

    # Add the alpha channel, which is expected by Bokeh
    im_rgba = np.dstack((im_8, 255*np.ones_like(im_8[:,:,0])))
    
    # Reshape into 32 bit. Must flip up/down for proper orientation
    return np.flipud(im_rgba.view(dtype=np.int32).reshape(n, m))


lst_imgs = glob.glob(r".\imgs\*.png")


plts = []
for img_path in lst_imgs:
    image = io.imread(img_path)
    h, w, c = image.shape
    x_min = 0; x_max = w
    y_min = 0; y_max = h

    PLOT_SIZE_OPTIONS = \
        dict(
            x_axis_location='above',
            x_range=(x_min, x_max),
            y_range=(y_max, y_min), 
            plot_width=x_max, 
            plot_height=y_max
            )
    PLOT_OPTIONS = dict(sizing_mode='scale_width')
    ASPECT_OPTIONS = dict(match_aspect=True, aspect_scale=1.0)
    plt = figure(**PLOT_OPTIONS, **ASPECT_OPTIONS, **PLOT_SIZE_OPTIONS)

    # plt.image_url(url=[img_path], x=x_min, y=y_min, w=x_max, h=y_max)
    plt.image_rgba(image=[rgb_to_rgba32(image)], x=x_min, y_max, dw=x_max, dh=y_max)
    plts.append(plt)

output_file("sample.html")

show(column(*plts))