###### 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) } ```