Dashborg Documentation / Examples / Dynamic Images

Dynamic Images

This example shows how to show server generated images to Dashborg pages. Some examples are if you create your own graphs (e.g. Gnuplot, or Graphviz), or retrieve image blobs from a database or NoSQL store.

To show images, we’ll use the standard HTML <img> tag.

Static Images

If you want to show a normal, internet accessible, image, use the src attribute as normal

<img src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png">

Dynamic Image URLs

You can set the image to have a dynamic source by pulling the source url from the panel’s data model. Here’s an example that pulls the image from $.dynamicurl which can be set like normal from your handler code (e.g. req.set_data() or req.SetData())

<img src="*$.dynamicurl">

Dynamic Server Generated Images (Files)

If you have the image on your local file system, the simplest way to serve it is using set_blob_data_from_file() or SetBlobDataFromFile() methods on the PanelRequest object.

Let’s say you have an local image file called “test.jpg”. In order to display it in your dashborg panel you would call SetBlobFromFile to send it to the panel’s data model, and then use the attribute blobsrc to display it as an image.

Warning you’ll have to use a * in your blobsrc attribute. We want the value to come from the data model and not be the literal string “$.image1”.

<img blobsrc="*$.image1">
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
    "github.com/sawka/dashborg-go-sdk/pkg/dash"
    "github.com/sawka/dashborg-go-sdk/pkg/dashcloud"
)

const HTML = `
<app ui="dashborg">
    <h1>Image Test</h1>
    <img blobsrc="*$.image1" style="max-width: 500px; height: auto;">
</app>
`

func main() {
    config := &dashcloud.Config{ProcName: "image-test", AnonAcc: true, AutoKeygen: true}
    client, _ := dashcloud.MakeClient(config)
    app, _ := client.OpenApp("image-test")
    app.SetHtml(HTML)
    app.SetInitHandlerType(dash.InitHandlerRequired)
    app.Runtime().SetInitHandler(func(req *dash.Request) error {
        req.SetBlobFromFile("$.image1", "image/jpeg", "test.jpg")
        return nil
    })
    client.ConnectApp(app)
    client.WaitForShutdown()
}

File Image

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import asyncio
import dashborg

HTML = """
<panel>
    <h1>Image Test</h1>
    <img blobsrc="*$.image1" style="max-width: 500px; height: auto;">
</panel>
"""

async def root_handler(req):
    req.set_html(HTML)
    await req.set_blob_data_from_file("$.image1", "image/jpeg", "test.jpg")
    

async def main():
    config = dashborg.Config(proc_name="image-test", anon_acc=True, auto_keygen=True)
    await dashborg.start_proc_client(config)
    await dashborg.register_panel_handler("default", "/", root_handler)
    while True:
        await asyncio.sleep(1) # sleep forever

asyncio.run(main())

File Image

Dynamic Server Generated Images

If you have a stream of bytes (database, chart generator, API, etc.) you can use SetBlobData() directly. It works the same as SetBlobDataFromFile except it takes a stream.

In this example we’ll generate a pie chart on the fly and send it to our panel.

For Go, we’ll use the excellent go-chart library. And for Python we’ll use matplotlib.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package main

import (
    "io"

    "github.com/sawka/dashborg-go-sdk/pkg/dash"
    "github.com/sawka/dashborg-go-sdk/pkg/dashcloud"
    "github.com/wcharczuk/go-chart/v2"
)

const HTML = `
<app ui="dashborg">
    <h1>Image Test</h1>
    <img blobsrc="*$.piechart" style="height: 500px; width: 500px;"/>
</app>
`

func MakeChart(req *dash.Request) error {
    pie := chart.PieChart{
        Width:  500,
        Height: 500,
        Values: []chart.Value{
            {Value: 5, Label: "Foo"},
            {Value: 5, Label: "Bar"},
            {Value: 4, Label: "Binky"},
            {Value: 4, Label: "Baz"},
        },
    }
    reader, writer := io.Pipe()
    go func() {
        defer writer.Close()
        pie.Render(chart.PNG, writer)
    }()
    req.SetBlob("$.piechart", "image/png", reader)
    return nil
}

func main() {
    config := &dashcloud.Config{ProcName: "image-test", AnonAcc: true, AutoKeygen: true}
    client, _ := dashcloud.MakeClient(config)
    app, _ := client.OpenApp("image-test")
    app.SetHtml(HTML)
    app.SetInitHandlerType(dash.InitHandlerRequired)
    app.Runtime().SetInitHandler(MakeChart)
    client.ConnectApp(app)
    client.WaitForShutdown()
}

Golang Pie Chart Image

The third argument of set_blob_data should be a stream/file – something that read(size) can be called on. It accepts both async and non-async readers. After calling read it will test the return value using inspect.isawaitable, and await any value that returns True.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import asyncio
import dashborg
from matplotlib import pyplot as plt
from io import BytesIO

HTML = """
<panel>
    <h1>Image Test</h1>
    <img blobsrc="*$.image1" style="max-width: 500px; height: auto;">
</panel>
"""

async def root_handler(req):
    req.set_html(HTML)
    labels = ['Foo', 'Bar', 'Baz']
    data = [23, 17, 35] 
    figdata = BytesIO()
    fig, ax = plt.subplots()
    ax.pie(data, labels=labels)
    ax.axis("equal")
    fig.savefig(figdata, format="png")
    figdata.seek(0)
    await req.set_blob_data("$.image1", "image/png", figdata)
    

async def main():
    config = dashborg.Config(proc_name="image-test", anon_acc=True, auto_keygen=True)
    await dashborg.start_proc_client(config)
    await dashborg.register_panel_handler("default", "/", root_handler)
    while True:
        await asyncio.sleep(1) # sleep forever

asyncio.run(main())

Python Pie Chart Image