2

Is there a straightforward way to get the RGB composition of a plot in R?

Right now what I am doing is writing the plot to an external file, then reading it with readPNG from the png package. I haven't found anything yet but surely there must be a better way to do this.

[EDIT] the codes:

INPUT <- c("3
            0 1 3 3
            2 2 6 4
            1 0 3 5")

require(png)

 # This is the pixel precision, 1e4 recommended for optimal results
PRECISION <- 1e4  

 # Just parsing the initial input and the vectors
sdata <- strsplit(gsub("\n", " ", INPUT), split=c(" "))[[1]] 
data  <- as.numeric(sdata)

 # Some usefull matrices for the plot points
Rm  <- matrix(data[-1], data[1],4,T)
Rmx <- cbind(Rm[,c(1,1)], Rm[,c(3,3)], Rm[,1])
Rmy <- cbind(Rm[,c(2,4)], Rm[,c(4,2)], Rm[,2])
 # and for the overall big rectangle
B  <- c(min(Rm[,1]), min(Rm[,2]), max(Rm[,3]), max(Rm[,4]))
Bx <- c(B[c(1,1)],B[c(3,3)],B[1])
By <- c(B[c(2,4)],B[c(4,2)],B[2])
A  <- B[3:4]-B[1:2]

 # Biggest number of digits given, not perfect but it works
D <- max(nchar(gsub("(.*\\.)|([0]*$)", "", sdata[-1])))

 # Create the plot and save it in the working directory, 
 #  then read it back to get the RGB information
png("rgb1.png", bg="black", width=PRECISION, height=PRECISION)
plot(x=Rmx, y=Rmy,'n', xaxt='n', yaxt='n', xlab="", ylab="", bty='n', 
     xlim=B[c(1,3)], ylim=B[c(2,4)])
polygon(Bx, By, col="blue", border=NA)
sapply(1:nrow(Rm), function(v){ polygon(Rmx[v,], Rmy[v,], 
                                        col="red", border=NA)})
dev.off()
plot.rgb <- readPNG("rgb1.png")

 # Compute area
Re <- sum(plot.rgb[,,1])
Bl <- sum(plot.rgb[,,3])
round( (Re/(Bl+Re))*prod(A), digits=D+1 )
gung - Reinstate Monica
  • 11,583
  • 7
  • 60
  • 79
Pane
  • 555
  • 2
  • 7
  • 20
  • Perhaps delving into the R Internals for [graphics devices](http://cran.r-project.org/doc/manuals/r-release/R-ints.html#Graphics-devices) would be a good place to start, along with the [graphics devices intro](https://www.stat.auckland.ac.nz/~paul/RGraphics/chapter1.pdf). – hrbrmstr Apr 20 '14 at 03:04
  • 4
    See `grid.cap()` to capture the contents of the current graphics device, `col2rgb()` to convert the colors into R, G, and B components, `array()` and `aperm()` to get those in the format you want (which you haven't specified). That could at least get you started. – Josh O'Brien Apr 20 '14 at 03:14
  • What sort of plot are you creating? Getting the color from a scatterplot is rather different from retrieving the colors of a raster image, for example. – Carl Witthoft Apr 20 '14 at 12:04
  • Josh, I'll look into that, right now when I use `grid.cap()` with Rstudio it always returns `NULL`. I had this issue before in my run-ins with `grid-cap` and need to remember what was the problem. – Pane Apr 20 '14 at 13:59
  • Carl, I've added the code. It is my solution to a programming challenge on a popular website. You can see I'm filling the plot with color in order to calculate the total area of the intersecting rectangles defined in the `INPUT`. It works almost perfectly when exporting the png with a large number of pixels (`1e4`) but the numbers are still off a bit. For example, the precise area in the above input is `18` and I'm getting `18.00054` , bummer. Anyway, I thought the problem might be when exporting to png and maybe the solution was to get a more "faithful" pixel representation. – Pane Apr 20 '14 at 14:24
  • maybe turn aliasing off for this rounding error? – baptiste Apr 20 '14 at 14:39
  • baptise, I tried the anti-aliasing options changing the type as well to no avail. – Pane Apr 20 '14 at 15:12
  • OK, then back to what I *should* have asked: What is the problem you are trying to solve? There may be simpler or quicker ways to get the actual information you're after. – Carl Witthoft Apr 20 '14 at 15:19
  • Sorry if I'm confusing. The bottom problem, given an R plot, is to determine the percentage of the plot displayed in a given color. In my example, [this](http://imgur.com/5FE1Ku3,HbYXiuv#0) is the plot and with the png method I find that the red color represents 60.00182% of the plot. I suspected there might be a simpler, perhaps more precise way of obtaining this percentage than writing/reading an external png. – Pane Apr 20 '14 at 15:49
  • So basically like [this question and my answer to it](http://stackoverflow.com/questions/21073587/measure-ink-of-a-plot/21079294#21079294), except that RStudio cripples your ability to take advantage or R's full functionality ;) – Josh O'Brien Apr 21 '14 at 02:28
  • That seems to be exactly what I was looking for. Definitely not working on Rstudio even with `options(device="windows")`. I suppose I'll give it a try on Emacs. Thank you – Pane Apr 21 '14 at 05:31
  • 1
    Cool. Glad that looks like it accomplishes what you're after. I'm an Emacs user and can confirm that it'll work for you there. – Josh O'Brien Apr 21 '14 at 05:59

0 Answers0