shinylive-r with renderImage()

,

I am trying to replicate the code to output an image from output an image with shinylive-r inside a Quarto document.

library(shiny)
library(bslib)
#> 
#> Attaching package: 'bslib'
#> The following object is masked from 'package:utils':
#> 
#>     page

ui <- page_fluid(
  imageOutput("image")
)

server <- function(input, output) {
  output$image <- renderImage(
    {
      list(src = "shiny.png", height = "25%")
    },
    deleteFile = FALSE
  )
}

shinyApp(ui = ui, server = server)
#> 
#> Listening on http://127.0.0.1:8719

Created on 2025-06-15 with reprex v2.1.1

This works for me with a Shiny app. The image "shiny.png" is in the same directory as "app.R" But I do not know how to get the same results with a code chunk in a Quarto document using shinylive-r.

I read that the image has to be a base64 encoded file and to be included with

## file: <path name to the base64 encoded file>
## type: binary

I tried to convert the "shiny.png" file with

What were the results of this conversion?

  • In the first case, I got a file with the name "encoded-20250615060048.txt". I renamed it to "shiny_logo.txt".
  • Alternatively, in the second case, I got a huge string in the console which I copied in a file named "shiny_logo.txt" without the " at the beginning and end.

I saved the result as "shiny_logo.txt" in the same directory as "app.R". Then I replaced the line

list(src = "shiny.png", height = "25%") with
list(src = "shiny_logo.txt", height = "25%")

Rendering the Quarto document, I got the error:

Error in jsonlite::base64_dec(file$content) : Error in base64 decode.

What follows is the full Quarto document I used:

---
title: "Shinylive Image Test"
format: html
filters: 
    - shinylive
---


## Display image with shinylive-r


```{shinylive-r}
#| standalone: true
#| viewerHeight: 400
#| components: [editor, viewer]
#| layout: vertical

## file: shiny_logo.txt
## type: binary

library(shiny)
library(bslib)


ui <- page_fluid(
  imageOutput("image") 
)

server <- function(input, output) {
  output$image <- renderImage( 
    { 
      list(src = "shiny_logo.txt", height = "25%") 
    }, 
    deleteFile = FALSE 
  ) 
}

shinyApp(ui = ui, server = server)

```

What is wrong? Any help would be appreciated.

You're on the right track with the encoding, but not quite there with how to include it. This works, and b64 can just be any png encoded by base64enc::base64encode(). It might be easiest to include the base64 in another R file and then you can put tags$img(src = paste0("data:image/png;base64,", b64)) straight into the UI.

#| standalone: true
#| viewerHeight: 300

library(shiny)
library(bslib)

ui <- page_fluid(
  uiOutput("image")
)

server <- function(input, output) {

  output$image <- renderUI({
    tmp <- tempfile(fileext = ".png")
    png(tmp, width = 300, height = 200)
    plot(1,1, pch = NA, xlim = c(-1,3), ylim = c(-3, 3))
    text(1,1, "base64", cex = 2)
    dev.off()
    b64 <- base64enc::base64encode(tmp)
    tags$img(src = paste0("data:image/png;base64,", b64))
  })

  
}

shinyApp(ui = ui, server = server)

Thank you, for advising me how to output an image created internally. This was interesting for me and I learned some things I didn't know. But I think your example does not solve my problem. I am referring to include/display a static external image.

So my question is a similar one, as in shinylife-r cannot include R file, a question I asked two weeks ago and was already answered. But now it is not an R file to include with shinylive-r, but an image (binary?) file.

I tried lots of different ways to load an image in from the png directly, but none of them worked. It might be possible to use some other file format, but given R/ is sourced automatically, that seems simplest. This is what I was suggesting for you to do to be able to read from a file. In this case R/images.R just contains b64 <- "iVBORw0KGgoAAA..."

#| standalone: true
#| viewerHeight: 300

## file: R/images.R
{{< include R/images.R >}}

## file: app.R
library(shiny)
library(bslib)

ui <- page_fluid(
  tags$img(src = paste0("data:image/png;base64,", b64))
)

server <- function(input, output) {
}

shinyApp(ui = ui, server = server)

I see what you mean. I tried it with an external images in PNG format. The conversion into base64 resulted in a huge string. This string I put into an R file, added — as you have shown me — quotes at the beginning and end and assigned finally the string to the variable b64. When I ran the same code as you have suggested, I received no error, but my program deadlocked after the two lines:

:information_source: Loading metadata database
:heavy_check_mark: Loading metadata database ... done

I waited for three minutes, but nothing happened. I assume that the reason is the huge binary string. Your workaround does not seem to work with external images that must be converted into huge base64 strings.

So my question is: Did you try it with an external image or with your small, created PNG file of your last example?

Yes I only tried using the example plot and seem to run into the same issue trying to encode a 900kb file. I suspect it could be related to having 10^6 characters in one line of the file. The other alternative is to upload the images somewhere and use the URL in tags$img(src = "<URL>").

Thank you. Yes, it seems a good idea to "use the URL in tags$img(src = "<URL>")" But did you try it? It does not work for me. I get the error message:

ERROR: a character vector argument expected

Maybe something is wrong with my code. Here is my complete test file:

---
title: "Render Image Test"
format: html
filters: 
  - shinylive
---

```{shinylive-r}
#| standalone: true
#| viewerHeight: 400
#| components: [editor, viewer]

library(shiny)
library(bslib)

ui <- page_fluid(
  imageOutput("image")
)


server <- function(input, output) {
  output$image <- renderImage(
        tags$img(src = "https://quarto-dev.github.io/quarto-r/logo.png")
  )
}
  
shinyApp(ui = ui, server = server)
```

The URL is in my code chunk in one line.

There's no need to use renderImage - just put it straight in the UI like this:

#| standalone: true
#| viewerHeight: 300

library(shiny)
library(bslib)

ui <- page_fluid(
  tags$img(src = "https://quarto-dev.github.io/quarto-r/logo.png")
)

server <- function(input, output) {
}

shinyApp(ui = ui, server = server)

Sorry, I haven't expressed myself clearly: I want the loading and displaying of images reactive in reference to the UI. I shortened my example too much. What I try to reproduce with shinylive-r is section "7.3 Images" of chapter "Graphics" in "Mastering Shiny" by Hadley Wickham. See here : chapter 7 "Graphics" of the online version.

The user makes a choice which controls the output of the picture. Therefore, I need to call the image inside the server() function.

Aha I see. Then you can put the tags$img inside a renderUI like this:

#| standalone: true
#| viewerHeight: 300

library(shiny)
library(bslib)

ui <- page_fluid(
  selectInput("select", "Select image", 
              choices = c(
                "Quarto" = "https://quarto-dev.github.io/quarto-r/logo.png", 
               "Shiny" = "https://raw.githubusercontent.com/rstudio/shiny/main/man/figures/logo.png"
              )),
  uiOutput("image")
)

server <- function(input, output) {
  output$image <- renderUI({
    tags$img(src = input$select, width = "200px")
  })
}

shinyApp(ui = ui, server = server)

1 Like