Search code examples
jpegrasterr-raster

Split images losing color when saving RasterBrick array as *jpg


#Packages
library(raster)  
library(rgeos)
library(rgdal)
library(jpeg)

I have a RGB color *jpg image:

## Open my RGB image 
 path<-"https://raw.githubusercontent.com/Leprechault/trash/main/IMG_191022_134242_0000_RGB.JPG" # Image path
download.file(path, "IMG_191022_134242_0000_RGB.JPG", mode = "wb")
rc<-stack(raster("IMG_191022_134242_0000_RGB.JPG")) #Open as a raster and stack
plot(rc)

bigimage

When I try to split in 16 images of equal size:

# This function spatially aggregates the original raster
# it turns each aggregated cell into a polygon
# then the extent of each polygon is used to crop
# the original raster.
# The function returns a list with all the pieces
# it saves and plots each piece
# The arguments are:
# raster = raster to be chopped            (raster object)
# ppside = pieces per side                 (integer)
# save   = write raster                    (TRUE or FALSE)
# plot   = do you want to plot the output? (TRUE or FALSE)
SplitRas <- function(raster,ppside,save,plot){
  h        <- ceiling(ncol(raster)/ppside)
  v        <- ceiling(nrow(raster)/ppside)
  agg      <- aggregate(raster,fact=c(h,v))
  agg[]    <- 1:ncell(agg)
  agg_poly <- rasterToPolygons(agg)
  names(agg_poly) <- "polis"
  r_list <- list()
  for(i in 1:ncell(agg)){
    e1          <- extent(agg_poly[agg_poly$polis==i,])
    r_list[[i]] <- crop(raster,e1)
  }
  if(save==T){
    for(i in 1:length(r_list)){
      options(max.print=999999) 
      #EBImage::writeImage(as.array(r_list[[i]]/255), paste0("sample_",i,".jpg",sep=""),quality = 100)
      writeJPEG(as.array(r_list[[i]]/255), target = paste0("sample_",i,".jpg",sep=""),quality = 1,color.space="RGBA")
    }
  }
  return(r_list)
}

#Slip RGB raster in 16 subimages
splitRBG<-SplitRas(raster=rc,ppside=4,save=TRUE)
# 

The results are greyscaled images, eg. 1 (sample_1.jpg) of the 16 images: enter image description here

I try to make a lot of changes in writeJPEG() function (something is wrong in the as.array(r_list[[i]]/255)code or in the color.space) without success, please any ideas?


Solution

  • Solution: split each RGB channel in a individual raster layer (rst.blue,rst.green nad rst.red) and stack before the crop operation with SplitRas custom function and works!!

    #Packages
    library(raster)  
    library(rgeos)
    library(rgdal)
    library(jpeg)
    
    ## download RGB image 
    path<-"https://raw.githubusercontent.com/Leprechault/trash/main/IMG_191022_134242_0000_RGB.JPG" # Image path
    download.file(path, "IMG_191022_134242_0000_RGB.JPG", mode = "wb")
    
    # Open jpeg file
    jpg<-readJPEG("IMG_191022_134242_0000_RGB.JPG")
    
    # Convert imagedata to raster
    rst.blue <- raster(jpg[,,1])
    rst.green <- raster(jpg[,,2])
    rst.red <- raster(jpg[,,3])
    rc<-stack(rst.blue, rst.green, rst.red)
    
    
    # This function spatially aggregates the original raster
    # it turns each aggregated cell into a polygon
    # then the extent of each polygon is used to crop
    # the original raster.
    # The function returns a list with all the pieces
    # it saves and plots each piece
    # The arguments are:
    # raster = raster to be chopped            (raster object)
    # ppside = pieces per side                 (integer)
    # save   = write raster                    (TRUE or FALSE)
    # plot   = do you want to plot the output? (TRUE or FALSE)
    SplitRas <- function(raster,ppside,save,plot){
      h        <- ceiling(ncol(raster)/ppside)
      v        <- ceiling(nrow(raster)/ppside)
      agg      <- aggregate(raster,fact=c(h,v))
      agg[]    <- 1:ncell(agg)
      agg_poly <- rasterToPolygons(agg)
      names(agg_poly) <- "polis"
      r_list <- list()
      for(i in 1:ncell(agg)){
        e1          <- extent(agg_poly[agg_poly$polis==i,])
        r_list[[i]] <- crop(raster,e1)
      }
      if(save==T){
        for(i in 1:length(r_list)){
          writeJPEG(as.array(r_list[[i]]), target = paste0("sample_",i,".jpg",sep=""),quality = 1)
        }
      }
      return(r_list)
    }
    
    #Slip RGB raster in 4 equal parts
    splitRBG<-SplitRas(raster=rc,ppside=4,save=TRUE)
    #