I have a shiny app that uses fileInput
and magick
to read a user chosen image, and display it as a ggplot.
library(shiny)
library(magick)
library(ggplot2)
ui <- fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
fileInput("current_image", "Choose image file")),
mainPanel(
plotOutput("current_image_plot")
)
)
)
server <- function(input, output) {
output$current_image_plot <- renderPlot({
req(input$current_image)
myplot <- magick::image_read(input$current_image$datapath)
myplot <- image_ggplot(myplot)
return(myplot)
})
}
shinyApp(ui = ui, server = server)
However, I'd like to separate the logic of reading the image, from the logic of plotting the image. I tried putting the image_read
inside its own observeEvent
, but this threw the error The 'image' argument is not a magick image object.
I know that when I print class(myplot)
within the observeEvent
, it returns a magick-image
object, so what has changed by the time I'm trying to access active_image
?
library(shiny)
library(magick)
library(ggplot2)
ui <- fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
fileInput("current_image", "Choose image file")),
mainPanel(
plotOutput("current_image_plot")
)
)
)
server <- function(input, output) {
active_image <- observeEvent(input$current_image, {
req(input$current_image)
myplot <- magick::image_read(input$current_image$datapath)
return(myplot)
})
output$current_image_plot <- renderPlot({
req(input$current_image)
myplot <- image_ggplot(active_image)
return(myplot)
})
}
shinyApp(ui = ui, server = server)
An observeEvent
does not return an object. Use eventReactive
instaed, that is, replace
active_image <- observeEvent(input$current_image, {
req(input$current_image)
myplot <- magick::image_read(input$current_image$datapath)
return(myplot)
})
with
active_image <- eventReactive(input$current_image, {
req(input$current_image)
myplot <- magick::image_read(input$current_image$datapath)
return(myplot)
})
or more concisely:
active_image <- eventReactive(input$current_image, {
req(input$current_image)
magick::image_read(input$current_image$datapath)
})
Now, active_image
is a reactive conductor, it is not the value returned. You have to do active_image()
to get the returned value:
output$current_image_plot <- renderPlot({
req(input$current_image)
image_ggplot(active_image())
})