使用 Shiny 更改大小并存储用户上传的图像文件
Changing the size and storing an image file uploaded by the user with Shiny
我正在编写一个大型 Shiny Dashboard 脚本来从用户上传的文件中收集数据。其中一些文件是图像。该脚本通过 ui
会话中的 fileInput
获取文件。通常,用户上传高分辨率的图片,但我不需要存储这样的文件,所以脚本将大小减小到 height = 200,以便将其定向到 outputImage
。它将文件发送到 Google 驱动器(没问题),但我想发送低分辨率文件。我试图从 output$showphotos1
读取它们,但是
部分剧本:
ui <- dashboardPage(
fileInput("loadphotos", label="Carregar fotos", multiple=T),
actionButton("do", "Carregar"),
imageOutput("showphotos1", height="200px"),
imageOutput("showphotos2", height="200px"),
imageOutput("showphotos3", height="200px")
)
server <- function(input, output, session) {
observeEvent(input$do, {
lst <- NULL
for(i in 1:length(input$loadphotos[,1])) {
lst[[i]] <- input$loadphotos[[i, 'datapath']]
}
output$showphotos1 <- renderImage({list(src=lst[[1]], height="200")})
output$showphotos2 <- renderImage({list(src=lst[[2]], height="200")})
output$showphotos3 <- renderImage({list(src=lst[[3]], height="200")})
# drive_upload(output$showphotos1$datapath,
# as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
# This gives an error: "Error in $.shinyoutput: Reading from shinyoutput object
# is not allowed." So I used the lines bellow, that uploads large files from
# the input:
drive_upload(input$loadphotos,
as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
})
}
我想存储 output$showphotos 中的较小文件 (200px),而不是 input@loadphotos 中的较大文件。我不精通 R
,如果有人能给我简单的解决方案,我将不胜感激。也欢迎提出避免每个图像文件重复代码的建议。
我们可以使用 magick::image_scale()
调整图像大小,然后将它们保存在工作目录中(或者创建临时文件),因为 drive_update
将路径作为 media
参数。
避免代码重复的版本:
library(shiny)
library(magick)
library(tidyverse)
library(googledrive)
n_showphotos <- 3
ui <- fluidPage(
fileInput("loadphotos", label = "Carregar fotos", multiple = TRUE),
actionButton("do", "Carregar"),
tagList(
map(str_c('showphotos', 1:n_showphotos), ~imageOutput(.x, height = '200px')))
)
server <- function(input, output, session) {
observeEvent(input$do, {
lst <- NULL
for (i in 1:length(input$loadphotos[,1])) {
lst[[i]] <- input$loadphotos[[i, 'datapath']]
}
lst %>%
map2(str_c('showphotos', 1:length(.)),~ { output[[.y]] <- renderImage({list(src = .x, height="200")},deleteFile = FALSE) })
#a list with all the images but resized to 200
#"x200" to resize by height
images_resized <- lst %>%
map(~image_scale(image = image_read(.x), "200"))
#images will be located in the project directory or home folder (getwd() to get working directory if in doubt)
images_resized %>%
walk2(str_c('image', 1:length(.)), ~ image_write(.x, path = str_c(.y, '.png'), format = "png"))
# drive_upload(image1.png,
# as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
})
}
shinyApp(ui, server)
代码重复:
library(tidyverse)
library(googledrive)
library(shiny)
library(magick)
ui <- fluidPage(
fileInput("loadphotos", label="Carregar fotos", multiple=T),
actionButton("do", "Carregar"),
imageOutput("showphotos1", height="200px"),
imageOutput("showphotos2", height="200px"),
imageOutput("showphotos3", height="200px")
)
server <- function(input, output, session) {
observeEvent(input$do, {
lst <- NULL
req(input$loadphotos)
for(i in 1:length(input$loadphotos[,1])) {
lst[[i]] <- input$loadphotos[[i, 'datapath']]
}
output$showphotos1 <- renderImage({list(src=lst[[1]], height="200")})
output$showphotos2 <- renderImage({list(src=lst[[2]], height="200")})
output$showphotos3 <- renderImage({list(src=lst[[3]], height="200")})
images_resized <- NULL
for (i in 1:length(lst)) {
image_scale(image = image_read(lst[[i]]), '200') %>%
image_write(path = str_c('image', i, '.png'), format = "png")
}
#image1.png ... image3.png are available in the working directory.
# drive_upload(image1,
# as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
})
}
shinyApp(ui, server)
编辑:
根据用户上传的图片数量调整ui。
library(shiny)
library(magick)
library(tidyverse)
library(googledrive)
ui <- fluidPage(
fileInput("loadphotos", label = "Carregar fotos", multiple = TRUE),
actionButton("do", "Carregar"),
uiOutput('images_outputs')
)
server <- function(input, output, session) {
observeEvent(input$do, {
lst <- NULL
for (i in 1:length(input$loadphotos[,1])) {
lst[[i]] <- input$loadphotos[[i, 'datapath']]
}
output$images_outputs <- renderUI({
tagList(
map(str_c('showphotos', 1:length(lst)), ~imageOutput(.x, height = '200px')))
})
lst %>%
map2(str_c('showphotos', 1:length(.)),~ { output[[.y]] <- renderImage({list(src = .x, height="200")},deleteFile = FALSE) })
#a list with all the images but resized to 200
#"x200" to resize by height
images_resized <- lst %>%
map(~image_scale(image = image_read(.x), "200"))
#images will be located in the project directory or home folder (getwd() to get working directory if in doubt)
images_resized %>%
walk2(str_c('image', 1:length(.)), ~ image_write(.x, path = str_c(.y, '.png'), format = "png"))
# drive_upload(image1.png,
# as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
})
}
shinyApp(ui, server)
注意:可能需要使用 options(shiny.maxRequestSize={size})
调整 shiny 接受的最大文件大小,如图 here
我正在编写一个大型 Shiny Dashboard 脚本来从用户上传的文件中收集数据。其中一些文件是图像。该脚本通过 ui
会话中的 fileInput
获取文件。通常,用户上传高分辨率的图片,但我不需要存储这样的文件,所以脚本将大小减小到 height = 200,以便将其定向到 outputImage
。它将文件发送到 Google 驱动器(没问题),但我想发送低分辨率文件。我试图从 output$showphotos1
读取它们,但是
部分剧本:
ui <- dashboardPage(
fileInput("loadphotos", label="Carregar fotos", multiple=T),
actionButton("do", "Carregar"),
imageOutput("showphotos1", height="200px"),
imageOutput("showphotos2", height="200px"),
imageOutput("showphotos3", height="200px")
)
server <- function(input, output, session) {
observeEvent(input$do, {
lst <- NULL
for(i in 1:length(input$loadphotos[,1])) {
lst[[i]] <- input$loadphotos[[i, 'datapath']]
}
output$showphotos1 <- renderImage({list(src=lst[[1]], height="200")})
output$showphotos2 <- renderImage({list(src=lst[[2]], height="200")})
output$showphotos3 <- renderImage({list(src=lst[[3]], height="200")})
# drive_upload(output$showphotos1$datapath,
# as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
# This gives an error: "Error in $.shinyoutput: Reading from shinyoutput object
# is not allowed." So I used the lines bellow, that uploads large files from
# the input:
drive_upload(input$loadphotos,
as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
})
}
我想存储 output$showphotos 中的较小文件 (200px),而不是 input@loadphotos 中的较大文件。我不精通 R
,如果有人能给我简单的解决方案,我将不胜感激。也欢迎提出避免每个图像文件重复代码的建议。
我们可以使用 magick::image_scale()
调整图像大小,然后将它们保存在工作目录中(或者创建临时文件),因为 drive_update
将路径作为 media
参数。
避免代码重复的版本:
library(shiny)
library(magick)
library(tidyverse)
library(googledrive)
n_showphotos <- 3
ui <- fluidPage(
fileInput("loadphotos", label = "Carregar fotos", multiple = TRUE),
actionButton("do", "Carregar"),
tagList(
map(str_c('showphotos', 1:n_showphotos), ~imageOutput(.x, height = '200px')))
)
server <- function(input, output, session) {
observeEvent(input$do, {
lst <- NULL
for (i in 1:length(input$loadphotos[,1])) {
lst[[i]] <- input$loadphotos[[i, 'datapath']]
}
lst %>%
map2(str_c('showphotos', 1:length(.)),~ { output[[.y]] <- renderImage({list(src = .x, height="200")},deleteFile = FALSE) })
#a list with all the images but resized to 200
#"x200" to resize by height
images_resized <- lst %>%
map(~image_scale(image = image_read(.x), "200"))
#images will be located in the project directory or home folder (getwd() to get working directory if in doubt)
images_resized %>%
walk2(str_c('image', 1:length(.)), ~ image_write(.x, path = str_c(.y, '.png'), format = "png"))
# drive_upload(image1.png,
# as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
})
}
shinyApp(ui, server)
代码重复:
library(tidyverse)
library(googledrive)
library(shiny)
library(magick)
ui <- fluidPage(
fileInput("loadphotos", label="Carregar fotos", multiple=T),
actionButton("do", "Carregar"),
imageOutput("showphotos1", height="200px"),
imageOutput("showphotos2", height="200px"),
imageOutput("showphotos3", height="200px")
)
server <- function(input, output, session) {
observeEvent(input$do, {
lst <- NULL
req(input$loadphotos)
for(i in 1:length(input$loadphotos[,1])) {
lst[[i]] <- input$loadphotos[[i, 'datapath']]
}
output$showphotos1 <- renderImage({list(src=lst[[1]], height="200")})
output$showphotos2 <- renderImage({list(src=lst[[2]], height="200")})
output$showphotos3 <- renderImage({list(src=lst[[3]], height="200")})
images_resized <- NULL
for (i in 1:length(lst)) {
image_scale(image = image_read(lst[[i]]), '200') %>%
image_write(path = str_c('image', i, '.png'), format = "png")
}
#image1.png ... image3.png are available in the working directory.
# drive_upload(image1,
# as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
})
}
shinyApp(ui, server)
编辑: 根据用户上传的图片数量调整ui。
library(shiny)
library(magick)
library(tidyverse)
library(googledrive)
ui <- fluidPage(
fileInput("loadphotos", label = "Carregar fotos", multiple = TRUE),
actionButton("do", "Carregar"),
uiOutput('images_outputs')
)
server <- function(input, output, session) {
observeEvent(input$do, {
lst <- NULL
for (i in 1:length(input$loadphotos[,1])) {
lst[[i]] <- input$loadphotos[[i, 'datapath']]
}
output$images_outputs <- renderUI({
tagList(
map(str_c('showphotos', 1:length(lst)), ~imageOutput(.x, height = '200px')))
})
lst %>%
map2(str_c('showphotos', 1:length(.)),~ { output[[.y]] <- renderImage({list(src = .x, height="200")},deleteFile = FALSE) })
#a list with all the images but resized to 200
#"x200" to resize by height
images_resized <- lst %>%
map(~image_scale(image = image_read(.x), "200"))
#images will be located in the project directory or home folder (getwd() to get working directory if in doubt)
images_resized %>%
walk2(str_c('image', 1:length(.)), ~ image_write(.x, path = str_c(.y, '.png'), format = "png"))
# drive_upload(image1.png,
# as_id("https://drive.google.com/drive/u/1/folders/1qj0eeee...")
})
}
shinyApp(ui, server)
注意:可能需要使用 options(shiny.maxRequestSize={size})
调整 shiny 接受的最大文件大小,如图 here