I am trying to save my filled.contour plots as a high resolution(>600dpi) piture(png, jpeg....) in Rstudio.
However, when I use the "export" function in the interface of Rstudio, the resolution is very low(the figure is only around 20kb).
Then I tried to use "PNG" command to save my plots, but I failed.
May I ask is there anyone knows how to achieve this?
Really appreciate for your kind help!
I assume you want to do this to maintain resolution when the image is rendered at a very large scale. To achieve that using the png(...) function, you have to set the size (height and width parameters) and also the resolution in ppi (res parameter). So the code below creates a png file of an 11 X 8.5 inch image at 600 ppi, or 6600 X 5100 pixels. The file is 435KB.
# open the png graphics device
png("volcano.png",res=600,height=8.5,width=11,units="in")
## the following is taken verbatim from the filled.contour(...) documentation
x <- 10*1:nrow(volcano)
y <- 10*1:ncol(volcano)
filled.contour(x, y, volcano, color=terrain.colors,
plot.title = title(main = "The Topography of Maunga Whau",
xlab = "Meters North", ylab = "Meters West"),
plot.axes = { axis(1, seq(100, 800, by = 100))
axis(2, seq(100, 600, by = 100)) },
key.title = title(main = "Height\n(meters)"),
key.axes = axis(4, seq(90, 190, by = 10))) # maybe also asp = 1
mtext(paste("filled.contour(.) from", R.version.string),
side = 1, line = 4, adj = 1, cex = .66)
##
# close the graphic device
dev.off()
If you expect to render this at a physical size greater than 11 X 8.5, you would need to generate the png at the appropriate size.
Related
height <- dim(img)[1]
width <- dim(img)[2]
screen_resolution <<- (width/height)
points_df <<- data.frame(x = as.numeric(xy_new$x), y = as.numeric(xy_new$y))
coordinates <- c(as.numeric(xy_new$x),as.numeric(xy_new$y))
point <- rbind(point, coordinates)
plot(coord$x, coord$y, xlim=c(0, dim(img)[2]), ylim=c(dim(img)[1],0), xlab="X", ylab="Y", xaxt = "n")
axis(1, at = seq(0, dim(img)[2], by = 50))
axis(2, at = seq(dim(img)[1],0, by = -50))
rasterImage(img, 0, dim(img)[2], dim(img)[1], 0)
First of all, thanks in advance to everyone trying to help.
In this code block, the image placed on the plot is compressed from the top. Is there a way to plot and dynamically align it without breaking the resolution of the image?
For a book, I want to show two rgl images side-by-side, as in the image below. But the publisher wants images with at least 300 dpi resolution.
I created this using the code below to produce two separate images with rgl.snapshot() and then combined them into a single image with some other software.
How can I amend the code below to save each image with higher
resolution? The images I get are ~ 256 x 256 pixels, I think with 72 dpi resolution.
Is there a different device driver I could use with rgl.snapshot?
Is there some way to compose these into a single image using R?
data(randu)
# Figure 9.15 - 3D plots
library(rgl)
with(randu, plot3d(x, y, z, size=6, axes=FALSE,
xlab = "", ylab = "", zlab = ""))
box3d(col="gray")
# left panel
rgl.snapshot("randu0.png")
# right panel
rgl.viewpoint(theta = -3.8, phi = 3.8, fov = 0, zoom = 0.7)
rgl.snapshot("randu.png")
Save in eps format with rgl.postscript. Then convert to png with GhostScript (gs).
data(randu)
library(rgl)
with(randu, plot3d(x, y, z, size=6, axes=FALSE,
xlab = "", ylab = "", zlab = ""))
box3d(col="gray")
# save in eps format
rgl.postscript("randu.eps")
# convert to png
cmd <-
"gs -dSAFER -dBATCH -dNOPAUSE -dEPSCrop -sDEVICE=png16m -r600 -sOutputFile=randu.png randu.eps"
system(cmd)
You can use ImageMagick to append two images.
Not the problem:
There are lots of folks who ask variations on "how do I save a figure" where the figure has borders, annotations, and style; I'm not looking for any of that because I can do it in base, lattice, or ggsave. If you need me to, then I can make a list of 20 SO questions this isn't the same as.
tl;dr
I want to have a bitmap file where my matrix is the values. In python, using OpenCV I can read a matrix, and the pixel [1,1] is going to have a particular value. If I change it, and save it, then that intensity value has changed. How do I get that?
Details:
When I run this code:
set.seed(1)
img_data <- matrix(sample(x = 0:255, size = 228*228,replace = T),nrow = 228,ncol = 228)
image(img_data)
I get this image:
You can see the default annotation. Annotation can be removed.
set.seed(1)
img_data <- matrix(sample(x = 0:255, size = 228*228,replace = T),nrow = 228,ncol = 228)
image(img_data, xaxt='n',yaxt='n')
And this looks less bad.
but opened in mspaint, it shows the problem.
Problems:
White border around actual information
image size is 789x503
I want an image that is 228x228, and the value [1,1] of the image is value [1,1] of the matrix.
How in base, lattice, ggplot, or something else R, does one make that?
Update:
This almost works.
set.seed(1)
img_data <- matrix(sample(x = 0:255, size = 228*228,replace = T),nrow = 228,ncol = 228)
mar_old <- par("mar") #lets not permanently change values
xpd_old <- par("xpd") #lets not permanently change values
bmp(filename = "mytest.bmp", width = 227, height = 228, units = "px")
par(mar=rep(0, 4), xpd = NA)
image(img_data, bty ="n",axes=F,frame.plot=F, xaxt='n', ann=FALSE, yaxt='n', asp=1)
dev.off()
par(mar=mar_old, xpd=xpd_old)
It makes this image
It still leaves a white line on the right and lower edges when viewed in mspaint.
Perhaps bitmaps start their counting at zero??
Update2:
This almost works, and might be what I have to go with.
library(magick)
set.seed(1)
img_data <- array(sample(x = 0:255, size = 228*228*3,replace = T),dim = c(228,228,3))
img <- magick::image_read(img_data/255)
image_write(img, path = "mystes3.bmp", format = "bmp")
It gives this:
And in mspaint:
It has to have 3 layers, RGB (rgba?), to get converted. This means it is a 3d array and not a 2d matrix. It gets the size right in that it doesn't add padding.
You need to set the useRaster parameter to TRUE in image():
set.seed(1)
img_data <- matrix(sample(x = 0:255, size = 228*228,replace = T),nrow = 228,ncol = 228)
mar_old <- par("mar") #lets not permanently change values
xpd_old <- par("xpd") #lets not permanently change values
bmp(filename = "mytest.bmp", width = 228, height = 228, units = "px")
par(mar=rep(0, 4), xpd = NA)
image(img_data, bty ="n",axes=F,frame.plot=F, xaxt='n', ann=FALSE, yaxt='n', asp=1, useRaster = T)
dev.off()
par(mar=mar_old, xpd=xpd_old)
I also corrected the height to 228 instead of 227.
Did a smaller image:
With useRaster = T
Without useRaster:
Without useRaster you even lose a row and a column.
I've created a choropleth of Brazil. When saving the plot in .png, the upper and the lower part of the plot are lost (covered). Here are the lines to save the plot.
plot.new()
par(omi=c(0,0,0,0), mgp=c(0,0,0),mar=c(0,0,0,0) , family = "D")
par(mfrow=c(1,1),cex=1,cex.lab = 0.75,cex.main=0.2,cex.axis=0.2)
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
plot(c(-75,-35),c(0,-30),type="n",axes=FALSE,xlab="",ylab="",asp=1.2)
plot(Brazil,col=cols[Brazil$Cons.g_ri],add=TRUE,border="black",lwd=0.5)
dev.off()
For saving the plot without losing the upper and the lower part of the map, I must change the coordinates to add white space at the bottom and at the top (i.e. replace c(0,-30) by c(5,-33)):
plot.new()
par(omi=c(0,0,0,0), mgp=c(0,0,0),mar=c(0,0,0,0) , family = "D")
par(mfrow=c(1,1),cex=1,cex.lab = 0.75,cex.main=0.2,cex.axis=0.2)
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
plot(c(-75,-35),c(5,-33),type="n",axes=FALSE,xlab="",ylab="",asp=1.2)
plot(Brazil,col=cols[Brazil$Cons.g_ri],add=TRUE,border="black",lwd=0.5)
dev.off()
This works in the sense that I can see the full map but the map then does not use all the available area in the figure. It seems that there are some margin in the upper and the lower part of the figure when saving the plot. I've never had that problem with other types of plot.
Sorry, I don't have enough "reputation" to post images to show you how the maps look like.
Any idea of how to fix this?
Edit:
The comments below got me searching more into the problem and I finally found a fix. I apologize as I now realized that I did not understand the source of the problem and thus did not explain as best as I could have,
It seems that png resets the outer margin of the plot. Thus, even though I had set omi=c(0,0,0,0), those were not the value used by the png command in saving the plot. The solution was to set the plot parameters after calling png so save the figure.
plot.new()
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
par(omi=c(0,0,0,0), mgp=c(0,0,0),mar=c(0,0,0,0) , family = "D")
par(mfrow=c(1,1),cex=1,cex.lab = 0.75,cex.main=0.2,cex.axis=0.2)
plot(c(-75,-35),c(5,-33),type="n",axes=FALSE,xlab="",ylab="",asp=1.2)
plot(Brazil,col=cols[Brazil$Cons.g_ri],add=TRUE,border="black",lwd=0.5)
dev.off()
From Details in ?par:
Each device has its own set of graphical parameters.
Thus, even though I had set the outer margin of the plot in par (omi = c(0,0,0,0)), those value were overwritten by the parameters in png when saving the plot.
The solution was to set the margin parameters in par after calling png
plot.new()
# first open png device...
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
# ...then set par
par(omi = c(0,0,0,0), mgp = c(0,0,0), mar = c(0,0,0,0), family = "D")
par(mfrow = c(1, 1), cex = 1, cex.lab = 0.75, cex.main = 0.2, cex.axis = 0.2)
plot(c(-75, -35), c(5, -33), type = "n", axes = FALSE, xlab = "", ylab = "", asp = 1.2)
plot(Brazil, col = cols[Brazil$Cons.g_ri], add = TRUE, border = "black", lwd = 0.5)
dev.off()
I have stacked into the question: I need to plot the image with DPI=1200 and specific print size.
By default the png looks ok...
png("test.png",width=3.25,height=3.25,units="in",res=1200)
par(mar=c(5,5,2,2),xaxs = "i",yaxs = "i",cex.axis=1.3,cex.lab=1.4)
plot(perf,avg="vertical",spread.estimate="stddev",col="black",lty=3, lwd=3)
dev.off()
But when I apply this code, the image became really terrible it's not scaling (fit) to the size that is needed. What did I miss? How to "fit" the image to the plot?
,
A reproducible example:
the_plot <- function()
{
x <- seq(0, 1, length.out = 100)
y <- pbeta(x, 1, 10)
plot(
x,
y,
xlab = "False Positive Rate",
ylab = "Average true positive rate",
type = "l"
)
}
James's suggestion of using pointsize, in combination with the various cex parameters, can produce reasonable results.
png(
"test.png",
width = 3.25,
height = 3.25,
units = "in",
res = 1200,
pointsize = 4
)
par(
mar = c(5, 5, 2, 2),
xaxs = "i",
yaxs = "i",
cex.axis = 2,
cex.lab = 2
)
the_plot()
dev.off()
Of course the better solution is to abandon this fiddling with base graphics and use a system that will handle the resolution scaling for you. For example,
library(ggplot2)
ggplot_alternative <- function()
{
the_data <- data.frame(
x <- seq(0, 1, length.out = 100),
y = pbeta(x, 1, 10)
)
ggplot(the_data, aes(x, y)) +
geom_line() +
xlab("False Positive Rate") +
ylab("Average true positive rate") +
coord_cartesian(0:1, 0:1)
}
ggsave(
"ggtest.png",
ggplot_alternative(),
width = 3.25,
height = 3.25,
dpi = 1200
)
If you'd like to use base graphics, you may have a look at this. An extract:
You can correct this with the res= argument to png, which specifies the number of pixels per inch. The smaller this number, the larger the plot area in inches, and the smaller the text relative to the graph itself.
An alternate solution to lowering the size of the various components with pointsize and the cex functions is to increase the size of the graph to compensate. This maintains the scale by increasing the size of everything instead of only some components. Your graph will be larger when exported, but will retain the improved resolution if manually decreased in size should you wish to retain the original smaller size.
The png default settings are dpi=72, height=480, width=480. So to maintain the same scale, you need to multiply height and width by the resolution/72. Using your example of width = height = 3.25 inches and a desired resolution dpi of 1200, we will adjust by 1200/72 (equal to 50/3):
reso <- 1200
length <- 3.25*reso/72
png("test.png",units="in",res=reso,height=length,width=length)
par(mar=c(5,5,2,2),xaxs = "i",yaxs = "i",cex.axis=1.3,cex.lab=1.4)
plot(perf,avg="vertical",spread.estimate="stddev",col="black",lty=3, lwd=3)
dev.off()