###### tags: `R` `jpeg::readJPEG` `jpeg::writeJPEG` `unlink` `file.info`
# Resize images using R
## Resize 1 photo
```r!
# Bring installed packages to memory
library(jpeg)
library(dplyr)
library(foreach)
library(doParallel)
# Input and output directories
dir.C.drive <-"C:"
dir.G.drive <- "G:/My Drive"
# That folder is the system level package library, you need to run Rstudio as "administrator" to be able to install there.
dir.R.packages <- file.path(dir.C.drive,"R","R-4.1.3","library")
dir.main <- file.path(dir.G.drive,"a_Property")
#--------------------------------------------------
# Resize single photo
#--------------------------------------------------
input.folder.path <- file.path(dir.main,"3 Innes Close, Parkinson, Qld 4115","on-site-inspection")
output.folder.path <- file.path(input.folder.path,"on-site-inspection-resized") # dir.exists(output.folder.path)
#dir.create(output.folder.path)
# File name pattern of the photos to resize
pattern.photos <- "\\d{8}_\\d{6}.jpg"
file.paths.jpg <- list.files(path=input.folder.path
,pattern = pattern.photos
,full.names = TRUE) # length(file.paths.jpg) 6
# Reduce 1 photo
img <- jpeg::readJPEG(source=file.paths.jpg[1]
, native = TRUE) # class(img) [1] "nativeRaster"
# Export reduced object as a jpg file
output.file.path <-paste0(output.folder.path,"/resized_",basename(file.paths.jpg[2]))
jpeg::writeJPEG(image=img
,target = output.file.path
, quality = 0.5)
# Calculate % reduction
size.original <- file.info(file.paths.jpg[1])[,"size"]
size.new <- file.info(output.file.path)[,"size"]
(size.original-size.new)/size.original*100 # 67.67885% reduction
```
## Reduce all photos in a folder
```r!
#--------------------------------------------------
# Reduce all photos in a folder
#--------------------------------------------------
cl <- parallel::makeCluster(parallel::detectCores()-1
,outfile=file.path(dir.main
,paste0("image-file-size-reduction_error-log.txt")
)
)
# Use all detected cores minus 1 core (CPU) as a cluster, leaving 1 core for software or app running in the background in case desktop crashes (monitor turns black and nothing working)
doParallel::registerDoParallel(cl, cores = parallel::detectCores()-1)
# Verify that doParallel is available on the workers by executing:
clusterEvalQ(cl, library(doParallel))
# This error, if appear, the following code will show the same error
# Error in checkForRemoteErrors(lapply(cl, recvResult)) :
# 3 nodes produced errors; first error: there is no package called 'doParallel'
# Photo file name in this pattern
pattern.photos <- "^\\d{8}_\\d{6}.jpg$"
# Get a list of directories containing "/on-site-inspection"
folder.path.on.site.inspection <- list.dirs(dir.main, full.names = TRUE) %>%
# Keep directories containing "/on-site-inspection"
grep(pattern = "on-site-inspection",value = TRUE) # length(folder.path.on.site.inspection) 77
dirname.filename.matches <- list.files(path = dir.main
,pattern = pattern.photos
,recursive = TRUE
,full.names = TRUE) %>%
# Restrict file pattern search to sub-directory "/on-site-inspection"
grep(pattern = "on-site-inspection",value = TRUE) # length(dirname.filename.matches) 164
# Resize all these image files
foreach::foreach(i=1:length(dirname.filename.matches)
,.combine = 'c'
,.packages=c("foreach","dplyr","jpeg")) %dopar% {
print(paste0("=========== Processing image ",i,"============"))
# If data can be found, then subset. If data cannot be found, then copy the input image to the output
image.file.path <-dirname.filename.matches[i]
image.file.name <-basename(image.file.path)
# Name output file
output.file.path <-paste0(dirname(image.file.path),"/resized_", image.file.name)
# Read jpg file
img <- jpeg::readJPEG(source=image.file.path, native = TRUE) # class(img) [1] "nativeRaster"
# Reduce jpg file size and output jpg file
jpeg::writeJPEG(image=img
,target = output.file.path
, quality = 0.5)
# Delete input file
unlink(image.file.path)
}
```