Image CGI with R

March 24, 2014
By

(This article was first published on BioStatMatt » R, and kindly contributed to R-bloggers)

I received an email recently with a question about using R in the common gateway interface (CGI) framework to create and pass image data to the web browser. I posted to stackoverflow about this some time ago, but had forgotten the details. The trouble is that R's graphics devices only write image data to file, rather than to a buffer or R connection. Hence, when passing image data via CGI, it is necessary to write an intermediary image file, read the file, and then output the data to STDOUT. Unfortunately, R will not allow you to write binary data to STDOUT (for example, try writeBin(as.raw("0xFF"), stdout()). So, this becomes even more complicated! One solution is to open a (binary) pipe connection to the Linux cat command, which sends it's output to STDOUT, and write the image data to the pipe connection. Of course, this is a platform dependent solution. Below is a CGI script that implements this:

#!/bin/sh
REXEC="/usr/local/bin/R --vanilla --slave"
$REXEC <<EOF

# create a random file name
pngfile <- paste0(format(Sys.time(), "%Y%m%d%H%M%S"),
  paste(sample(letters,10), collapse=""), ".png")

# create temporary graphic file
png(pngfile, type = "cairo")
x <- seq(-10, 10, length= 30)
y <- x
f <- function(x, y) { r <- sqrt(x^2+y^2); 10 * sin(r)/r }
z <- outer(x, y, f)
z[is.na(z)] <- 1
op <- par(bg = rgb(1,1,1,0))
persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue")
persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue",
  ltheta = 120, shade = 0.75, ticktype = "detailed",
  xlab = "X", ylab = "Y", zlab = "Sinc( r )")
invisible(dev.off())

# write headers
pngsize <- file.info(pngfile)[["size"]]
cat("Content-type: image/png\n")
cat(paste("Content-length: ", pngsize, "\n\n", sep=""))

# open pipe to stdout and pass image data
con <- pipe("cat", "wb")
writeBin(readBin(pngfile, 'raw', n=pngsize), con)
flush(con)
close(con)

# remove intermediate graphic
invisible(file.remove(pngfile))

EOF
###

To leave a comment for the author, please follow the link and comment on his blog: BioStatMatt » R.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.