Hammao
Hammao

Reputation: 879

Automating the creation of Rmarkdown/Xaringan Presentation slides

I have over 500 images i will like to display on a screen with some text ( image names etc). the slide format for each image will be the same. Is it possible to automate the creation of individual slide with each image from a list?

this is what i tried all day and couldn't get it to work

library(magick)
library(tidyverse)
library(magrittr)

# list files in a folder 
path="figures/stackoverflow"
image_files<-list.files(path=path, pattern = ".tif$", recursive = TRUE,full.names = TRUE,  include.dirs = TRUE)

image_files

# Extract sub directory Clean Names 
by_who<-sub(pattern = "figures/stackoverflow/", replacement = "\\1", dirname(image_files))
by_who

## Extract File names
clean_names<-sub(pattern = "(.*)\\..*$", replacement = "\\1", basename(image_files))
clean_names

# make directory for new png files 
if(!dir.exists("figures/stackoverflow_pngs")){dir.create("figures/stackoverflow_pngs")} else{print("dir already exists!")}

all_images<-list()
for (i in 1:length(image_files)){
  # Read the images from the list created in a loop
  k <- image_read(image_files[i]) %>%
    image_contrast(sharpen = 2) %>% 
    image_normalize() %>% 
    image_enhance() %>%  
    image_annotate(boxcolor = "pink",
                   text=paste("Made by",":",by_who[i],"--", clean_names[i]),
                   #clean_names[i],
                   color = "purple",
                   font = "comic sans",
                   style = "italic",
                   size = 30,
                   #refcolor = "navyblue",
                   weight = 500)%>% 
                  image_convert(format = "png")%T>%
    image_write(
      path = paste0("figures/stackoverflow_pngs/", clean_names[i], ".png"),
      density = 300,
      format = "png"
    )
  
  all_images<-k #
  print(k)
}

image_1 image_2 image_3

my images are usually in .tif format, so it was necessary for me to show the initial processing i do to the images. Also the structure of my folder is "\figures\stackoverflow\A\image_1.tif", i use both the basename and subfolder name in the final labelling of my images

for (i in seq_along(image_list)) {
  slide_name <- paste0("slide_", i)
  image <- image_list[[i]]
  by_who_value <- by_who[i]
  clean_name_value <- clean_names[i]
  
  cat('\n---\n')  # Start a new slide
  
  # Generate the R code for the current slide
  code_chunk <- paste0('knitr::include_graphics(paste0("figures/pngs/", "', clean_name_value,'", ".png"))\n')
  
  cat(code_chunk)
}

At the end, i will like to create something that may look like the code below, where info from the loop are used to label the slide

---
  class: inverse
<center><img src="figures/image_1.png"  /></center> 
  
  .footnote[`paste("Sampled by",":",by_who[i],"--", clean_names[i])`]
---

Upvotes: 2

Views: 100

Answers (1)

TarJae
TarJae

Reputation: 79204

Try out this: The images are in path images/

library(magick)
library(tidyverse)
library(magrittr)
# list files in a folder 
path="images/"
image_files<-list.files(path=path, pattern = ".png$", recursive = TRUE,full.names = TRUE,  include.dirs = TRUE)

image_files

# Extract sub directory Clean Names 
by_who<-sub(pattern = "images/", replacement = "\\1", dirname(image_files))
by_who

## Extract File names
clean_names<-sub(pattern = "(.*)\\..*$", replacement = "\\1", basename(image_files))
clean_names

# make directory for new png files 
if(!dir.exists("images_pngs")){dir.create("images_pngs")} else{print("dir already exists!")}

all_images<-list()
for (i in 1:length(image_files)){
  # Read the images from the list created in a loop
  k <- image_read(image_files[i]) %>%
    image_contrast(sharpen = 2) %>% 
    image_normalize() %>% 
    image_enhance() %>%  
    image_annotate(boxcolor = "pink",
                   text=paste("Made by",":",by_who[i],"--", clean_names[i]),
                   #clean_names[i],
                   color = "purple",
                   font = "comic sans",
                   style = "italic",
                   size = 30,
                   #refcolor = "navyblue",
                   weight = 500)%>% 
    image_convert(format = "png")%T>%
    image_write(
      path = paste0("images_pngs/", clean_names[i], ".png"),
      density = 300,
      format = "png"
    )
  
  all_images<-k #
  print(k)
}

generate_slide <- function(by_who_value, clean_name_value) {
  slide <- paste0(
    '---\n',
    'class: inverse\n',
    '<center><img src="images_pngs/', clean_name_value, '.png"  /></center>\n', 
    '.footnote[`Sampled by: ', by_who_value, ' -- ', clean_name_value, '`]\n',
    '---\n'
  )
  return(slide)
}

markdown_file <- "presentation.Rmd"
writeLines(c('---', 'title: "Presentation"', 'output: xaringan::moon_reader', '---'), markdown_file)

for (i in 1:length(image_files)) {
  slide <- generate_slide(by_who[i], clean_names[i])
  con <- file(markdown_file, "a")  # Open a connection in append mode
  writeLines(slide, con)  # Write the slide
  close(con)  # Close the connection
}

#install.packages("xaringan")
library(xaringan)
rmarkdown::render(markdown_file, output_format = "xaringan::moon_reader")


Upvotes: 2

Related Questions