rpurrrfurrr

Parallel Processing With Magick image_read() with Furrr


Is there a way to use parallel processing with image_read()? The below illustrates the issue.

library(purrr)
library(magick)
#> Linking to ImageMagick 6.9.12.3
#> Enabled features: cairo, freetype, fftw, ghostscript, heic, lcms, pango, raw, rsvg, webp
#> Disabled features: fontconfig, x11
library(furrr)
#> Loading required package: future

links <- 
  c(
    'https://images.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png', 
    'https://th.bing.com/th/id/OIP.v7IDxAcM1Dw7ANwK2-MpBgHaJW?w=123&h=180&c=7&r=0&o=5&pid=1.7'
    )

# this works
map(links, image_read)
#> [[1]]
#>   format width height colorspace matte filesize density
#> 1    PNG   272     92       sRGB  TRUE     5969   72x72
#> 
#> [[2]]
#>   format width height colorspace matte filesize density
#> 1   JPEG   123    180       sRGB FALSE     4354   72x72

# this doesn't
plan(multisession, workers = 2)
future_map(links, image_read)
#> [[1]]
#> Error: Image pointer is dead. You cannot save or cache image objects between R sessions.

Created on 2023-12-04 with reprex v2.0.2


Solution

  • Instead of returning the image as read by image_read, extract the bitmap first and return that bitmap. Then, reread the bitmap as an image.

    library(purrr)
    library(magick)
    #> Linking to ImageMagick 6.9.12.93
    #> Enabled features: cairo, freetype, fftw, ghostscript, heic, lcms, pango, raw, rsvg, webp
    #> Disabled features: fontconfig, x11
    library(furrr)
    #> Loading required package: future
    
    links <- 
      c(
        'https://images.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png', 
        'https://th.bing.com/th/id/OIP.v7IDxAcM1Dw7ANwK2-MpBgHaJW?w=123&h=180&c=7&r=0&o=5&pid=1.7'
      )
    
    # this works
    map(links, image_read)
    #> [[1]]
    #>   format width height colorspace matte filesize density
    #> 1    PNG   272     92       sRGB  TRUE     5969   72x72
    #> 
    #> [[2]]
    #>   format width height colorspace matte filesize density
    #> 1   JPEG   123    180       sRGB FALSE     4354   72x72
    
    # this also works
    plan(multisession, workers = 2L)
    img_list <- future_map(links, \(l) {
      # read the file
      img <- image_read(l)
      # extract the raw bitmap and return it to caller
      img[[1L]]
    })
    
    lapply(img_list, image_read)
    #> [[1]]
    #>   format width height colorspace matte filesize density
    #> 1    PNG   272     92       sRGB  TRUE        0   72x72
    #> 
    #> [[2]]
    #>   format width height colorspace matte filesize density
    #> 1    PNG   123    180       sRGB FALSE        0   72x72
    

    Created on 2023-12-04