Hi there,
I need to extract the pixel values from a px.imshow()
with the argument binary_string=True
via a client-side callback. I managed to this with a regular callback, but I really would prefer doing this client -side as the figure is quite big.
MRE:
from dash import Dash, html, dcc, Input, Output, State, clientside_callback
import plotly.express as px
import numpy as np
from PIL import Image
import base64
import io
app = Dash(
__name__,
)
app.layout = html.Div([
dcc.Graph(
id='graph',
figure=px.imshow(
np.random.randint(0, 255, size=(50, 50)),
binary_string=True
)
),
html.Button(id='btn_py', children=['python']),
html.Button(id='btn_JS', children=['JS']),
html.Div(id='out_py'),
html.Div(id='out_JS'),
])
@app.callback(
Output('out_py', 'children'),
Input('btn_py', 'n_clicks'),
State('graph', 'figure'),
prevent_initial_call=True
)
def update(_, figure):
full_string = figure.get('data')[0].get('source')
_, image_string = full_string.split(',')
image_bytes = base64.b64decode(image_string)
image = Image.open(io.BytesIO(image_bytes))
image_np = np.array(image)
return str(image_np)
clientside_callback(
"""
function(click, fig) {
if (click == undefined) {
throw window.dash_clientside.PreventUpdate;
} else {
// extract pixel values from figure
const full_string = fig.data[0].source
const image_string = full_string.split(',')[1]
const decoded = atob(image_string)
// const array_with_pixel_values = Uint8Array.from(decoded, c => c.charCodeAt(0))
// return array_with_pixel_values
// ^^ this does not work
return "array_with_pixel_values"
}
}
""",
Output('out_JS', 'children'),
Input('btn_JS', 'n_clicks'),
State('graph', 'figure'),
prevent_initial_call=True
)
if __name__ == '__main__':
app.run(debug=True)