From 7024d2225308e4e0eca801529c3a48f5c1c79c1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20K=C5=82osko?= Date: Tue, 22 Jun 2021 18:03:01 +0200 Subject: [PATCH] Add support for image output (#380) --- lib/livebook/notebook/cell/elixir.ex | 2 ++ lib/livebook_web/live/output/image_component.ex | 15 +++++++++++++++ .../live/output/vega_lite_static_component.ex | 5 ----- .../live/session_live/cell_component.ex | 8 ++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 lib/livebook_web/live/output/image_component.ex diff --git a/lib/livebook/notebook/cell/elixir.ex b/lib/livebook/notebook/cell/elixir.ex index e701f2b03..a60751b9d 100644 --- a/lib/livebook/notebook/cell/elixir.ex +++ b/lib/livebook/notebook/cell/elixir.ex @@ -27,6 +27,8 @@ defmodule Livebook.Notebook.Cell.Elixir do | binary() # Standalone text block | {:text, binary()} + # A raw image in the given format. + | {:image, content :: binary(), mime_type :: binary()} # Vega-Lite graphic | {:vega_lite_static, spec :: map()} # Vega-Lite graphic with dynamic data diff --git a/lib/livebook_web/live/output/image_component.ex b/lib/livebook_web/live/output/image_component.ex new file mode 100644 index 000000000..fbe305840 --- /dev/null +++ b/lib/livebook_web/live/output/image_component.ex @@ -0,0 +1,15 @@ +defmodule LivebookWeb.Output.ImageComponent do + use LivebookWeb, :live_component + + @impl true + def render(assigns) do + ~L""" + <%= tag :img, src: data_url(@content, @mime_type), alt: "output image" %> + """ + end + + defp data_url(content, mime_type) do + image_base64 = Base.encode64(content) + ["data:", mime_type, ";base64,", image_base64] + end +end diff --git a/lib/livebook_web/live/output/vega_lite_static_component.ex b/lib/livebook_web/live/output/vega_lite_static_component.ex index 5a1679b88..58da6c999 100644 --- a/lib/livebook_web/live/output/vega_lite_static_component.ex +++ b/lib/livebook_web/live/output/vega_lite_static_component.ex @@ -1,11 +1,6 @@ defmodule LivebookWeb.Output.VegaLiteStaticComponent do use LivebookWeb, :live_component - @impl true - def mount(socket) do - {:ok, socket} - end - @impl true def update(assigns, socket) do socket = assign(socket, id: assigns.id) diff --git a/lib/livebook_web/live/session_live/cell_component.ex b/lib/livebook_web/live/session_live/cell_component.ex index d07170f9a..6f907bb1f 100644 --- a/lib/livebook_web/live/session_live/cell_component.ex +++ b/lib/livebook_web/live/session_live/cell_component.ex @@ -309,6 +309,14 @@ defmodule LivebookWeb.SessionLive.CellComponent do ) end + defp render_output(_socket, {:image, content, mime_type}, id) do + live_component(LivebookWeb.Output.ImageComponent, + id: id, + content: content, + mime_type: mime_type + ) + end + defp render_output(_socket, {:error, formatted}, _id) do render_error_message_output(formatted) end