-
Notifications
You must be signed in to change notification settings - Fork 37
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
Enable rendering of images on GitHub and after kernel restart #396
Comments
Yes, this is expected behavior for widgets. It seems you've found and linked the related issues, so I don't really know what to say other than to explain why this is happening. When a Python object is the last element in a notebook cell, the ipython kernel looks for a You can inspect the mimebundles by calling the import IPython.display
IPython.display.Image("./dog.jpg")._repr_mimebundle_()
# ({'image/jpeg': '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopG import ipywidgets
with open("./dog.jpg", "rb") as f:
data = f.read()
ipywidgets.Image(value=data)._repr_mimebundle_()
# {
# 'text/plain': "Image(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\xff\\xdb\\x00C\\x00\\x06\\x04\\x0…",
# 'application/vnd.jupyter.widget-view+json': {
# 'version_major': 2,
# 'version_minor': 0,
# 'model_id': '57bf31944747439a96a70e368d2ef891'
# }
# } This dictionary gets saved to the notebook (JSON) and then is interpreted later by whatever environment is rendering the JSON notebook. As you can see, for the It might be possible to mutate the notebook cell and save the For example you could make a notebook where the last cells runs over the notebook and mutates the notebook output cells embedding the most current import base64
import ipywidgets
with open("./dog.jpg", "rb") as f:
data = f.read()
img = ipywidgets.Image(value=data, width="500px")
img # displays a widget import json
import base64
import ipywidgets.widgets.widget
# read the current notebook file
with open("Untitled.ipynb", "r") as f:
nb = json.load(f)
# iterate over the notebook cells
for cell in nb["cells"]:
if cell["cell_type"] != "code":
continue
# iterate over the outputs for the cell
for output in cell["outputs"]:
# grab the model_id for the embeded widget output cell
if model_id := output.get("data", {}).get('application/vnd.jupyter.widget-view+json', {}).get("model_id", None):
# if there is a model_id see if we have the widget in our current session
widget = ipywidgets.widgets.widget._instances.get(model_id)
if isinstance(widget, ipywidgets.Image):
# add the image/jpeg data to the notebook cell
output["data"]["image/jpeg"] = base64.encodebytes(widget.value).decode("utf-8")
# write the new notebook to a different file
with open("with_embedded_images.ipynb", "w") as f:
f.write(json.dumps(nb)) Alternatively, you could also just override the import ipywidgets
import base64
class MyImageWidget(ipywidgets.Image):
def _repr_mimebundle_(self, *args, **kwargs):
mimebundle = super()._repr_mimebundle_(*args, **kwargs)
mimebundle["image/jpeg"] = base64.encodebytes(self.value).decode("utf-8")
return mimebundle
with open("./dog.jpg", "rb") as f:
data = f.read()
img = MyImageWidget(value=data, width="500px")
img # displays a widget and embds the image data in the notebook However, in this case if Of course, both of these examples only account for |
Thank you so much for these insights, I really appreciate your time and effort. I agree, modifying the notebook does not sound like best practice. Your last example that overwrites the repr_mimbundle with I've extended your example by import ipywidgets
import base64
class MyImageWidget(ipywidgets.Image):
def _repr_mimebundle_(self, *args, **kwargs):
mimebundle = super()._repr_mimebundle_(*args, **kwargs)
encoded_image = base64.encodebytes(self.value).decode("utf-8")
mimebundle["image/jpeg"] = encoded_image
metadata = {"image/jpeg": {"width": self.width}}
return mimebundle, metadata
with open("./cute_dog.jpg", "rb") as f:
data = f.read()
img = MyImageWidget(value=data, width="300px")
img Next, I want to explore how to embed an image into a notebook after some interactions in the widget happened. I've just written a prototype here: https://github.com/kolibril13/anywidget-image/blob/main/js/widget_convert.jsx#L5-L19 The button does not yet have an effect. embed_image = Bool(False).tag(sync=True)
@observe("embed_image")
def _observe_embed_image(self, change):
print("Converted the image to image/jpeg mime type")
# now some conversion code here. but is there maybe a way to make this conversion directly from the JavaScript/React side? |
I just wrote a small ImageWidget with anywidget and React.
Now, it would be amazing if it was possible to render that image on GitHub, and even after kernel restart! ✨
That is possible with
from IPython.display import Image
See notebook1.But that does not work when I use
from ipywidgets import Image
See notebook2Likewise, it does not work with anywidget. See notebook3
Here's an overview summary how it currently looks like:
Related issues:
jupyterlab/jupyterlab#15361
jupyter-widgets/ipywidgets#2280
The text was updated successfully, but these errors were encountered: