Как скачать блестящее изображение приложения в Rmarkdown pdf? - PullRequest
2 голосов
/ 02 октября 2019

Я хочу загрузить изображения и текст в блестящую сеть (не вставляя изображение в коде), а затем загрузить в виде документа PDF.

Я застреваю при загрузке изображений в PDF-документ.

В «output $ report <- downloadHandler (...)» параметры не могут быть «наблюдаем» или «выводим $ image»,Как написать правильные параметры для изображений? </p>

library(shiny)

ui<-navbarPage("Report",
                 tabPanel("Upload Images", uiOutput('page1')),
                 tabPanel("Input Text", uiOutput('page2')),
                 tabPanel("Download Report", uiOutput('page3'))
)

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


    output$page1 <- renderUI({
        fluidPage(
            fluidRow(
                column(5,
                       fileInput(inputId = 'files', 
                                 label = 'Select 1st Image',
                                 multiple = TRUE,
                                 accept=c('image/png', 'image/jpeg'),
                                 width = '400px')
                       ))) }) 

output$page2 <- renderUI({
        fluidPage(
            fluidRow(
                column(8,
                       textInput("Text1", "(1)", " ",width = '600px')
                       #verbatimTextOutput("Value1")
                       ),
                column(4, uiOutput('Image1'))
            ))
    })

    files <- reactive({
        files <- input$files
        files$datapath <- gsub("\\\\", "/", files$datapath)
        files
    })


    output$Image1 <- renderUI({
        if(is.null(input$files)) return(NULL)
        image_output_list <- 
            lapply(1:nrow(files()),
                   function(i)
                   {
                       imagename = paste0("image", i)
                       imageOutput(imagename)
                   })

        do.call(tagList, image_output_list)
    })

    IMAGE1 <- observe({
        if(is.null(input$files)) return(NULL)
        for (i in 1:nrow(files()))
        {
            print(i)
            local({
                my_i <- i
                imagename = paste0("image", my_i)
                print(imagename)
                output[[imagename]] <- 
                    renderImage({
                        list(src = files()$datapath[my_i], 
                             width = 250,
                             height = 250,
                             alt = "Image failed to render")
                    }, deleteFile = FALSE)
            })
        }
    })   ######!!!! Parms cannot be observe or output$Image1 




    output$page3 <- renderUI({ downloadButton("report", "Generate report")})

    output$report <- downloadHandler(
        filename = "report.pdf",
        content = function(file) {
            tempReport <- file.path(tempdir(), "VIWpdf.Rmd")
            file.copy("VIWpdf.Rmd", tempReport, overwrite = TRUE)
            params <- list(
                Text1 = input$Text1,
                Image1 =  IMAGE1 ######!!!!!Here this the Problem######
                )


            out<- rmarkdown::render(tempReport, output_file = file,
                                    params = params,
                                    envir = new.env(parent = globalenv()))
            file.rename(out, file) 
        }
    )}
shinyApp(ui=ui,server=server)

Вот .rmd

---
title: "Report"
date: "`r format(Sys.time(), '%d %B, %Y')`"
always_allow_html: yes
output: 
  pdf_document:
    fig_caption: yes
    keep_tex: yes
    toc: true
    toc_depth: 2
params:
  Text1: 'NULL'
  Image1: 'NULL'

---
(1) `r params$Text1`  

`r params$Image1`  


Я ожидаю, что вывод изображения может отображаться в Rmarkdown PDF, но фактический выводпуст.

1 Ответ

0 голосов
/ 03 октября 2019

Ваши операторы renderImage работают путем анализа путей к изображениям. Точно так же вам нужно передать пути к изображениям в params при рендеринге Rmd. Вы также хотите, чтобы изображения были скопированы в tempdir. И, наконец, в Rmd вам необходимо оценить params$Image inline, когда вы ссылаетесь на файлы изображений.

Вот необходимые изменения:

  1. Rmd должен прочитать что-то вроде этого. Обратите внимание, что мы вставляем значение params$Image1 при ссылке на файл изображения r paste0(params$Image1)
---
title: "Report"
date: "`r format(Sys.time(), '%d %B, %Y')`"
always_allow_html: yes
output: 
  pdf_document:
  fig_caption: yes
  keep_tex: yes
  toc: true
  toc_depth: 2
params:
  Text1: 'NULL'
  Image1: 'NULL'

---

```{r}
message("this is the text passed as a parameter")
message(params$Text1)
## Omitting one tick mark to render 'correctly' in SO answer
``

Here is the image

![Some image](`r paste0(params$Image1)`)
Далее, внутри downloadHandler мы работаем с input$files, а не с IMAGE1 (наблюдатели не возвращают значения), потому что все, что нам нужно, это пути к выбранным изображениям. Кроме того, нам нужно скопировать изображения в тот же tempdir, где отображается Rmd. Обработчик загрузки должен выглядеть следующим образом (заголовок, я изменил имя Rmd):
  output$report <- downloadHandler(
    filename = "report.pdf",
    content = function(file) {
      tempReport <- file.path(tempdir(), "image.rmd")
      file.copy("image.rmd", tempReport, overwrite = TRUE)
      # copy the image to the tempdir
      # otherwise `render` will not know where it is
      imgOne <- file.path(tempdir(), input$files[[1]])
      file.copy(input$files[[1]], imgOne, overwrite = TRUE)

      params <- list(Text1 = input$Text1,
      # pass the path to the image in the tempdir
                     Image1 =  imgOne)

      out <- rmarkdown::render(
        tempReport,
        output_file = file,
        params = params,
        envir = new.env(parent = globalenv())
      )
      file.rename(out, file)
    }
  )
В downloadHandler вам нужно будет перебрать список изображений для копирования в tempdir и добавить элемент в список params. В Rmd вам нужно будет зациклить params$Image*, чтобы создать ссылки на все изображения.

Полное приложение, которое работало для меня с 1 только изображение :

library(shiny)

ui <- navbarPage(
  "Report",
  tabPanel("Upload Images", uiOutput('page1')),
  tabPanel("Input Text", uiOutput('page2')),
  tabPanel("Download Report", uiOutput('page3'))
)

server <- function(input, output, session) {
  output$page1 <- renderUI({
    fluidPage(fluidRow(column(
      5,
      fileInput(
        inputId = 'files',
        label = 'Select 1st Image',
        multiple = TRUE,
        accept = c('image/png', 'image/jpeg'),
        width = '400px'
      )
    )))
  })

  output$page2 <- renderUI({
    fluidPage(fluidRow(column(
      8,
      textInput("Text1", "(1)", " ", width = '600px')
      #verbatimTextOutput("Value1")
    ),
    column(4, uiOutput('Image1'))))
  })

  files <- reactive({
    files <- input$files
    files$datapath <- gsub("\\\\", "/", files$datapath)
    files
  })


  output$Image1 <- renderUI({
    if (is.null(input$files))
      return(NULL)
    image_output_list <-
      lapply(1:nrow(files()),
             function(i)
             {
               imagename = paste0("image", i)
               imageOutput(imagename)
             })

    do.call(tagList, image_output_list)
  })

  observe({
    if (is.null(input$files))
      return(NULL)
    for (i in 1:nrow(files()))
    {
      print(i)
      print(input$files[[i]])
      local({
        my_i <- i
        imagename = paste0("image", my_i)
        print(imagename)
        output[[imagename]] <-
          renderImage({
            list(
              src = files()$datapath[my_i],
              width = 250,
              height = 250,
              alt = "Image failed to render"
            )
          }, deleteFile = FALSE)
      })
    }
  })   ######!!!! Parms cannot be observe or output$Image1

  output$page3 <-
    renderUI({
      downloadButton("report", "Generate report")
    })

  output$report <- downloadHandler(
    filename = "report.pdf",
    content = function(file) {
      tempReport <- file.path(tempdir(), "image.rmd")
      file.copy("image.rmd", tempReport, overwrite = TRUE)
      imgOne <- file.path(tempdir(), input$files[[1]])
      file.copy(input$files[[1]], imgOne, overwrite = TRUE)

      params <- list(Text1 = input$Text1,
                     Image1 =  imgOne) ######!!!!!Here this the Problem######

      out <- rmarkdown::render(
        tempReport,
        output_file = file,
        params = params,
        envir = new.env(parent = globalenv())
      )
      file.rename(out, file)
    }
  )

}

shinyApp(ui = ui, server = server)
...