kindofhungry
kindofhungry

Reputation: 464

How to display multiple pictures (png) that are stored locally on Shiny

I tried searching online a lot for a similar question but could not find one that helps with my case. I am very new to Shiny so I hope you all can help me out. Below is a form of the code I have. I am having some trouble pulling some images locally. In the UI you can see in the drop down menu I can select multiple counties and combo them with a reason. In my folder I have many png files titled in this generic format: "CountyX reasonY .png" (there is a space before the file extension).

What I want to do is be able to render multiple pictures in a grid so I can compare the combinations of counties and reason (i.e. see County2 reason1 and County1 reason3 and County2 reason3 and County4 reason2 in a 2x2 grid (or 3x4 if I have 12 etc)). To make it easier, I have uploaded some png files here for experimentation: PNG 1, PNG 2, PNG 3, PNG 4.

The output$plots I have tried only works for displaying one image.

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
  titlePanel("Compare"),
  sidebarLayout(
    sidebarPanel(
      pickerInput(inputId = "countyInput", label = "Filter county",
                  choices = c("County1", "County2", "County3", "County4", "County5"),
                  options = list(`actions-box` = TRUE,size = 10, `selected-text-format` = "count > 9"),
                  multiple = TRUE),
      checkboxGroupInput(inputId = "reasonInput", label = "Filter reason",
                         choices = c("reason1", "reason2", "reason3"))
    ),
    mainPanel(
      plotOutput("plot")
    )
  )
)

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

  output$plot <- renderImage({
    filename <- normalizePath(file.path("<local path name to png files>", paste(input$countyInput, " ", input$reasonInput, " .png", sep = "")))
    list(src = filename)  
    }, deleteFile = FALSE)

}

shinyApp(ui = ui, server = server)

Thanks for all your help.

Upvotes: 3

Views: 2819

Answers (1)

annhak
annhak

Reputation: 662

With grid, gridExtra and png you can render the pngs into one "plot".

library(shiny)
library(shinyWidgets)
library(gridExtra)
library(png)
library(grid)

ui <- fluidPage(
  titlePanel("Compare"),
  sidebarLayout(
    sidebarPanel(
      pickerInput(inputId = "countyInput", label = "Filter county",
                  choices = c("County1", "County2", "County3", "County4", "County5"),
                  options = list(`actions-box` = TRUE,size = 10, `selected-text-format` = "count > 9"),
                  multiple = TRUE),
      checkboxGroupInput(inputId = "reasonInput", label = "Filter reason",
                         choices = c("reason1", "reason2", "reason3"))
    ),
    mainPanel(
      plotOutput("plot")
    )
  )
)

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

  output$plot <- renderPlot({
    filename <- normalizePath(file.path("<path>", paste0(input$countyInput, " ", input$reasonInput, ".png", sep = ""))) # you had one extra space before .png
    filename <- filename[file.exists(filename)]
    pngs = lapply(filename, readPNG)
    asGrobs = lapply(pngs, rasterGrob)
    p <- grid.arrange(grobs=asGrobs, nrow = 1)
    }, width = 1000)
}

shinyApp(ui = ui, server = server)

You will of course need some error handling for incomplete filenames. Also, you can use length(filename) as a condition for nrow and ncol to get the wanted number of cells in the grid.

Upvotes: 3

Related Questions