Thanks to jlhoward for pointing me in the right direction. There are a few more missing ingredients -- for instance, without labs(x=NULL, y=NULL)
, the output PNG will have white borders on the bottom and left.
I decided my solution should have two parts:
- Craft a ggplot object to visualize my data. (This step is the same as usual.)
- Call a general-purpose function to take care of all the annoying details which are necessary to output that plot as a pixel-perfect PNG.
Here is one such function.
BorderlessPlotPng <- function(plot, ...) {
# Write a ggplot2 plot to an image file with no borders.
#
# Args:
# plot: A ggplot2 plot object.
# ...: Arguments passed to the png() function.
require(grid)
png(type='cairo', antialias=NULL, units='px', ...)
print(plot
+ theme(plot.margin=unit(c(0, 0, -0.5, -0.5), 'line'),
axis.text=element_blank(),
axis.ticks=element_blank(),
axis.title=element_blank(),
legend.position='none')
+ scale_x_continuous(expand=c(0, 0))
+ scale_y_continuous(expand=c(0, 0))
+ labs(x=NULL, y=NULL)
)
dev.off()
}
To see it in action, here's a plot of some synthetic data. (I made each output pixel 10 pixels wide for demonstration purposes.)
# Synthetic data.
width <- 64
height <- 48
d <- data.frame(row=rep(1:height, each=width),
col=rep(1:width, height),
x=rnorm(n=width * height))
# Construct and print the plot.
library(ggplot2)
plot <- (ggplot(data=d, aes(x=col, y=height + 1 - row, fill=x))
+ geom_raster()
+ scale_fill_gradient2()
)
pixel_size <- 10
BorderlessPlotPng(plot,
filename='test.png',
width=width * pixel_size,
height=height * pixel_size)
Output:

Of course, running with pixel_size <- 1
would give you a 1:1 image, which you could compare to the original image by flipping back and forth.