Why does my plot of a raster in R blur in saved file? - r

I'm hoping to export a map with a raster plotted on it as a .pdf or some other vector file. For some reason, when I save it as a .pdf or .ps file, the raster is blurry/fuzzy/smeared and unusable. Any tips for fixing this? A .png saves with the desired resolution, but can't be manipulated layer-by-layer in post-processing.
library(maps)
library(raster)
ra<-raster(nrows=40,ncols=35,xmn=-110,xmx=-75,ymn=7,ymx=47)
ra2 <- rasterize(cbind(runif(1000,min=-109,max=-76),runif(1000,min=8,max=46)), ra,fun=function(x,...)log10(length(x)))
pal <- colorRampPalette(c("grey90","grey40"))
map(database="world",regions=c("US","Mexico","El Salvador","Honduras","Costa Rica","Guatemala","Belize","Nicaragua","Panama"),myborder=0.0000001,xlim=c(-110,-75),ylim=c(0,50))
plot(ra2,add=T,col=pal(7))
Here is a screenshot of the saved .pdf file
Here is a screenshot of the Quartz window with desired resolution

I just found that adding 'useRaster=FALSE' to the plot() function fixes this.

You can use the following code to save high-resolution image as pdf file
pdf(file = "My Plot.pdf",
width = 14, # The width of the plot in inches
height = 8.5) # The height of the plot in inches
pal <- colorRampPalette(c("grey90","grey40"))
map(database="world",regions=c("US","Mexico","El Salvador","Honduras","Costa Rica","Guatemala","Belize","Nicaragua","Panama"),myborder=0.0000001,xlim=c(-110,-75),ylim=c(0,50))
plot(ra2,add=T,col=pal(7))
#Run dev.off() to create the file!
dev.off()

Related

Cropping the top and bottom output of ggsave from grid.arrange of PNG Files

library(grid)
library(gridExtra)
library(png)
library(ggplot2)
library(RCurl)
PNG_1 <- readPNG(getURLContent("https://i.ibb.co/MVx1QsQ/A.png"))
PNG_2 <- readPNG(getURLContent("https://i.ibb.co/kHVGNfQ/B.png"))
PNG_3 <- readPNG(getURLContent("https://i.ibb.co/yVf3Hjg/C.png"))
grid <- grid.arrange(rasterGrob(PNG_1), rasterGrob(PNG_2), rasterGrob(PNG_3), ncol=3)
ggsave(grid,filename="output.png")
Output.png
Tried to set the output dimensions manually, but to no avail.
Simply wish to remove the large top and bottom margins. Thanks.
As plots adapts to device size it's not simple to get part size. I think the easiest way is to compute aspect ratio from dimension of PNGs and provide device size to ggsave.
asp <- (ncol(PNG_1)+ncol(PNG_2)+ncol(PNG_3))/max(nrow(PNG_1),nrow(PNG_2),nrow(PNG_3))
ggsave(grid, filename= ..., width=5, height=5/asp)
to stitch those PNG you can use this code that will keep original pixel count.
We can't use cbind/rbind function as readPNG returns arrays and not matrices. Fortunately the abind package provide a function to do it, abind(
along=2 means cbind, along=1 for rbind)
library(abind)
PNG <- abind(PNG_1,PNG_2,PNG_3,along=2)
writePNG(PNG,"output.png")

Is there a way to read a plot as a matrix of pixels without saving it on disk?

I'd like to have an R plot as a matrix of pixels. I can simply save and read it again as a bitmap. But is there a faster way to do this directly without saving the plot first?
library(readbitmap)
tmp = tempfile()
bmp(tmp)
plot(1)
dev.off()
result = read.bitmap(tmp)

Problems generating gif using raster package and google map images R

I want to generate a gif from raster images using imagemagick convert.
I use as a background a google map so I need to call plot() twice and this generated a flickering in the resulting gif, because a blank image is inserted in each cycle. How can I eliminate this blank image and generate a smooth gif?
An example follows:
require(raster)
require(dismo)
bk<-gmap(c(" DR Congo"))
png(file="Rplot%03d.png", width=500, height=500)
for(i in 1:4){
rnd <-matrix(rnorm(100*100),100,100)
s_rnd<-raster(rnd)
extent(s_rnd)<-extent(bk)/i
crs(s_rnd) <- crs(bk)
plot(bk, legend=FALSE, axes=FALSE, box=FALSE)
plot(s_rnd, legend=FALSE, axes=FALSE, box=FALSE,add=TRUE)
}
dev.off()
system(paste0("convert -delay 40 Rplot*.png ","Test.gif" ))
file.remove(list.files(pattern="^Rplot.*\\.png$"))

Output Stem and Leaf Plot to Image

I'm trying to output a Stem and Leaf plot in R as an image. I'm not sure if there's a nice library which can accomplish this but below is some of the code I've tried.
jpeg(filename="stem.jpeg",width=480,height=480, units="px",pointsize=12)
plot.new()
tmp <- capture.output(stem(men, scale = 1, width = 40))
text( 0,1, paste(tmp, collapse='\n'), adj=c(0,1), family='mono' )
dev.off()
This above code resulted in the data being saved, but it looks very blurry and the plot gets cut off pretty badly. When adding a histogram to an image, R seems to do a good job to scale everything to fit in the size of the image.
jpeg(filename="stem.jpeg",width=480,height=480,
units="px",pointsize=12)
stem(men, scale = 1, width = 40)
dev.off()
This created the image but had no content within it.
Any ideas? Thanks!
That's because stem and leaf plots produce text not images. You can save the text as follows using the sink command: http://stat.ethz.ch/R-manual/R-devel/library/base/html/sink.html
sink(file=“Stem.txt”)
stem(men, scale = 1, width = 40)
sink(file=NULL)
unlink("stem.txt")
To export a stemplot as graphics, you can use a vector graphics format, such
as .eps, .pdf, or .emf. For example, a windows metafile:
win.metafile("stem.wmf", pointsize = 10)
plot.new()
tmp <- capture.output(stem(mtcars$mpg))
text(0,1,paste(tmp,collapse='\n'),family='mono',adj=c(0,1))
dev.off()

fast way to read in png, add grid & coords, and output

I have a lot of png files of a floor plan (mapping) layout that I want to:
read into R
Add grid lines
Add coordinates per cell in grid
Output
There are 1000 of these files so I'm looking for a speedy method. What would be a fast way to accomplish this task. These don't need to be publication quality as I'm looking for certain behavior clusters within cells and want recording the coordinated for these events for each of the 100 frames (pngs).
Here is a MWE that produces 10 png files:
x <- y <- seq(-4*pi, 4*pi, len = 27)
r <- sqrt(outer(x^2, y^2, "+"))
dir.create("delete_me")
wd <- getwd()
setwd("delete_me")
lapply(1:10, function(x){
png(sprintf("file_%s.png", x))
image(z = z <- cos(r^2)*exp(-r/x))
dev.off()
})
setwd(wd)
The final output will look like this for each png (with all the coords filled in).
I assume grid will be the way to create the gridlines quickly but am not sure about reading the png in quickly or plotting the coordinates (assume we'll use a 10 x 10 grid on each png).
How about using ggplot() and annotation_custom() to plot the image across the entire plot area, then manually overplot the grid lines.
(In the image, I trimmed the excess whitespace and axis from the png file in advance)
# pre-req libraries
require(ggplot2)
require(grid) # rasterGrob function
require(png) # to read the PNG file
width<-10
height<-10
# generate the points and labels for the grid
points<-data.frame(expand.grid(w=1:width,h=1:height))
points$labs<-paste0("(",points$w,",",points$h,")")
points$x<-points$w-0.5 # center
points$y<-points$h-0.5
# make the gridline co-ordinates
gridx<-data.frame(x=0:width,xend=0:width,y=rep(0,width+1),yend=rep(height,width+1))
gridy<-data.frame(x=rep(0,height+1),xend=rep(width,height+1),y=0:height,yend=0:height)
grids<-rbind(gridx,gridy)
# function to plot using ggplot with annotation_custom for the image
plotgrid<-function(file){
g<-ggplot(points)+theme_bw()+
annotation_custom(rasterGrob(readPNG(file),0,0,1,1,just=c("left","bottom")),0,width,0,height)+
geom_text(aes(x=x,y=y,label=labs))+
geom_segment(aes(x=x,xend=xend,y=y,yend=yend),data=grids) +
coord_cartesian(c(0,width),c(0,height))
return(g)
}
# run the function for each file in the folder
setwd("delete_me")
lapply(list.files(),function(x)plotgrid(x))
setwd(wd)

Resources