Skip to content

image_graph device is very slow (with benchmarking code and alternative with png device) #412

@gavril0

Description

@gavril0

I found that making plot withimage_graph device is very slow. Making plots in temporary files with png (or jpeg) and reading these files with image_read is x15 faster!

Image

Figure Elapsed time to draw n plots.

n png image_draw
1 0.03 0.24
10 0.16 2.40
20 0.30 4.76

Table Elapsed time (sec).

Benchmaking:

# make plots with png device in temporarz files and read them
mk_plot_png <- function(n, tempdir="./tmp") {
    # R base device
    png(filename = paste(tempdir,"graph_%04d.png",sep="/"),
      width = 960, height = 480, res = 72)
    # make plots
    for(i in 1:n) plot(1:10, (1:10)/i)
    dev.off()
    # read graphs
    fn <- sprintf("%s/graph_%04d.png" , tempdir, 1:n)
    graphs <- magick::image_read(fn) 
    # remove files
    #unlink(fn)
    graphs
}

# make plots with image_draw device
mk_plot_image_draw <- function(n) {
    # open magick graphical device (VERY SLOW)
    graphs <- magick::image_graph(width = 960, height = 480, res = 72)
    # create an image for each time 
    for(i in 1:n) plot(1:10, (1:10)/i)
    dev.off()
    graphs
}

# both function generate n png images
mk_plot_image_draw(n=2)

   format width height colorspace matte filesize density
 1    PNG   960    480       sRGB  TRUE        0   72x72
 2    PNG   960    480       sRGB  TRUE        0   72x72

mk_plot_png(n=2, tempdir = "./tmp/")

  format width height colorspace matte filesize density
1    PNG   960    480       sRGB FALSE     2643   28x28
2    PNG   960    480       sRGB FALSE     2619   28x28

Note that density for png is in pixels/cm (28 pixed/cm = 72 dpi) because the PNG format does not support DPI (see http://www.w3.org/TR/2003/REC-PNG-20031110/#11pHYs).
In principle, it should be possible to redefine the units when displaying the info

convert r.png -units pixelsperinch -verbose info:

to get the same output but coud not find how to do it with R magick.

# data frame to store timing results
res <- expand.grid(
  device  = c("png","image_draw"), 
  n       = c(1, 10, 20),
  elapsed = NA)

for(i in 1:nrow(res)) {
  n <- res$n[i] # number of plots to draw
  if(res$device[i]=="png") {
    res$elapsed[i] <- system.time(
      graphs <- mk_plot_png(n, tempdir = "./tmp/"))["elapsed"]
  } else {
    res$elapsed[i] <- system.time(
      graphs <- mk_plot_image_draw(n))["elapsed"]
  }
  image_destroy(graphs)
}

# plot (see above)
lattice::xyplot(elapsed ~ n, group=device, data=res, 
  type="b", auto.key=TRUE)

Info:

  • R version 4.4.2
  • magick_2.8.6

`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions