Home > Enterprise >  r shiny - Plotting multiple images using the imageOutput() and renderImage()
r shiny - Plotting multiple images using the imageOutput() and renderImage()

Time:10-01

I am trying to plot several images saved in the www sub-directory folder of my shiny app folder. The image file names are in a data frame column; let’s say “img_path”. I am using the imageOutput() function in the UI and renderImage() in the server interface. Since I want to plot all the images in the www subfolder and that are referenced in the data frame, I am using a for loop. Unfortunately, instead of rendering all the images, it always displays the last image. I guess this is happening because images are being overlayed on top of each other. How do you solve this problem?

Let say that I have: my data

df_img <- data.frame(id = c(1:5), img_path = c("h1000.png", "h2000.png", "h3000.png", "h4000.png", "h000.png"))

which is stored in the data subfolder; the 5 images in the www subfolder are named as in the df_img[["img_path"]]. My basic shiny app code is:

library(shiny)
library(shinydashboard)

Define UI

ui <- fluidPage(
    # Application title
    titlePanel("Test app"),
    # to render images in the www folder 
    box(imageOutput("houz"), width = 3)
)

Define server logic

server <- function(input, output) {
    df_img <- read.csv("data/df_img.csv", header = T)
    for (i in 1:nrow(df_img)) {
        output$houz <- renderImage({
            list(
                src = file.path('www', df_img$img_path[i]),
                contentType = "image/jpeg",
                width = "100%", height = "45%"
            )
        }, deleteFile = FALSE)
        
    }
}

# Run the application 
shinyApp(ui = ui, server = server)

what_i_expect and what_i_get

CodePudding user response:

Consider using Shiny modules. A working example is below, which assumes you have images with a "jpeg" extension in a "www" subdirectory of the working directory. I use purrr for functional programming - you could use lapply() or a for loop if you prefer.

Chapter 19 of Mastering Shiny is a good introduction to Shiny modules.

library(shiny)
library(purrr)

ui_module <- function(id) {
  imageOutput(NS(id, "img"))
}

server_module <- function(id,
                          img_path) {
  moduleServer(
    id,
    function(input, output, session) {
  output$img <- renderImage({
    list(src = img_path,
         contentType = "image/jpeg",
         width = "100%",
         height = "45%")
  },
  deleteFile = FALSE)
    })
}

images <- list.files(path = "www",
                     pattern = "jpeg",
                     full.names = TRUE)

ids <- tools::file_path_sans_ext(
  basename(images)
)

ui <- fluidPage(
  map(ids, ui_module)
  )

server <- function(input, output, session) {

  map2(.x = ids,
       .y = images,
       .f = server_module)

}

shinyApp(ui, server)

CodePudding user response:

You can use renderUI to display the list of images you wish to display. Try this

df_img <- data.frame(id = c(1:5), img_path = c("h1000.png", "h2000.png", "h3000.png", "h4000.png", "h000.png"))

ui <- fluidPage(
  # Application title
  titlePanel("Test app"),
  # to render images in the www folder 
  box(uiOutput("houz"), width = 3)
)

server <- function(input, output) {
  #df_img <- read.csv("data/df_img.csv", header = T)
  
  n <- nrow(df_img)
  
  observe({
    for (i in 1:n)
    {
      print(i)
      local({
        my_i <- i
        imagename = paste0("img", my_i)
        print(imagename)
        output[[imagename]] <-
          renderImage({
            list(src = file.path('www', df_img$img_path[my_i]), 
                 width = "100%", height = "55%",
                 alt = "Image failed to render")
          }, deleteFile = FALSE)
      })
    }
  })
  
  
  output$houz <- renderUI({
    
    image_output_list <- 
      lapply(1:n,
             function(i)
             {
               imagename = paste0("img", i)
               imageOutput(imagename)
             })
    
    do.call(tagList, image_output_list)
  })
  
}

# Run the application 
shinyApp(ui = ui, server = server)
  • Related