saving rotate images in R - avoiding background and maintaining size -


i have below code based upon earlier question. when save image savethisplot.png, creates unwanted background , image size changes (it reduces). how can save image such rotated part of same size earlier (77 rows , 101 columns) , there no background?

library(raster) r1 <- brick(system.file("external/rlogo.grd", package="raster")) r1 x <- crop(r1, extent(0,ncol(r1),0,nrow(r1))) plotrgb(x)  x1 <- 0:ncol(x) y1 <- 0:nrow(x) z <- matrix(1, nrow=length(x1), ncol=length(y1))  col.mat <- t(apply(matrix(rgb(getvalues(x)/255), nrow=nrow(x), byrow=true), 2, rev))  # rotate 45 degrees persp(x1, y1, z, zlim=c(0,2), theta = 20, phi = 90,        col = col.mat, scale=false, border=na, box=false) png("savethisplot.png") persp(x1, y1, z, zlim=c(0,2), theta = 20, phi = 90,        col = col.mat, scale=false, border=na, box=false) dev.off() 

enter image description here

you can use transparent background, rotating plot require re-sizing.

when save plot can set png("savethisplot.png", bg="transparent") prevent background showing. try:

png("savethisplot.png", width=101 height=77, units="px", pointsize=1, bg="transparent") 

notice if try rotated version of logo, logo re-sized fit within 101 x 77 pixel png. if want rotate , maintain logo size, you'll have resize png, ass @romanluštrik mentioned in comment. re-sizing, if option you, matter of trigonometry find appropriate height , width parameters.

you can try setting new heights , widths save png using trigonometry. here example 35 degrees of rotation:

# hypotenuse hypot <- sqrt((nrow(x)/2)^2 + (ncol(x)/2)^2)  # angle angle <- asin((nrow(x)/2)/ hypot)/(pi/180)  width <- 2 * max(abs(hypot * cos((angle + 35) * pi/180)),                   abs(hypot * cos((- angle + 35) * pi/180)))  height <- 2 * max(abs(hypot * sin((angle + 35) * pi/180)),                   abs(hypot * sin((- angle + 35) * pi/180)))   png("savethisplot.png", height=height, width=width, units="px", pointsize=1,     bg="transparent") par(mar=c(0,0,0,0), xaxs = "i", yaxs = "i") persp(x1, y1, z, zlim=c(0,2), theta = 35, phi = 90,        col = col.mat, scale=false, border=na, box=false) dev.off() 

enter image description here

the overall image not 77 x 101 pixels, logo should same size, though bit rugged. smoother image, see rgl answer below, note transparent background isn't available rgl

alternative approach using rgl package:

a different approach producing image might better if end goal maintain size , smoothness of image. can try rgl (r-to-opengl) package , persp3d function, can rotate plot within window without re-sizing window or altering proportions of logo. can use you've got, color matrix needs modified work persp3d:

col.mat2 <- cbind(rbind(1, col.mat), 1) 

then, set scene, call persp3d, rotate it, , save.

open3d()  rgl.pop("lights")  light3d(specular="black") # reduce reflection persp3d(x1,y1,z, col=col.mat2, ylab="", xlab="", zlab="",         axes=false, smooth=false, aspect="iso")  # rotate defining usermatrix, save     par3d(usermatrix = rotationmatrix(0*pi/180, 0, 0, 1)) rgl.snapshot("rlogo_0.png") # save  par3d(usermatrix = rotationmatrix(45*pi/180, 0, 0, 1)) rgl.snapshot("rlogo_45.png")  par3d(usermatrix = rotationmatrix(135*pi/180, 0, 0, 1)) rgl.snapshot("rlogo_135.png") 

rlogorlogo_45degreesrlog_135degrees

to force image smaller window, can manipulate size of rgl display window , amount of background using combination of windowrect , zoom parameters (see question , answer, example). however, transparent background isn't option rgl currently.

open3d() bg3d(color="#ff00ff") # pink background (some color not in actual image) rgl.pop("lights")  light3d(specular="black")  persp3d(x1,y1,z, col=col.mat2, axes=false,      ylab="", xlab="", zlab="", smooth=false, aspect="iso") rgl.viewpoint(zoom=0.52) par3d(usermatrix = rotationmatrix(0*pi/180, 0, 0, 1), windowrect=c(0,0, 101, 77)) rgl.snapshot("rlogo_77h124w.png") par3d(usermatrix = rotationmatrix(45*pi/180, 0, 0, 1), windowrect=c(0,0, 101, 77)) rgl.snapshot("rlogo45_77h124w.png") 

i wasn't able make window less 124 pixels wide. seems there minimum width of 124 pixels rgl window on computer, can't make window smaller (i.e. can't collapse minimize, restore, , close buttons on top of window).

enter image description here enter image description here

to transparent background, import these saved pngs, , assign alpha values of 1 background color ("#ff69b4"):

library(png) add.alpha <- readpng("rlogo_77h124w.png") #try rotate version,  library(abind) add.alpha <- abind(add.alpha, matrix(1, nrow=nrow(add.alpha), ncol=ncol(add.alpha)))  add.alpha[,,4][which(rgb(add.alpha[,,1],add.alpha[,,2],add.alpha[,,3]) == "#ff00ff")] <- 0 writepng(add.alpha, "rlogo_77h124w_alpha.png") 

it turns out method isn't perfect, , may end slight border on rotated images color isn't "#ff00ff". can address border 1 way or another, if problem you, may not make difference depending on end goals. try using add.alpha[,,4][which(add.alpha[,,1] > .9 & add.alpha[,,3] > .9 & add.alpha[,,2] < .85 )] <- 0 before writepng

enter image description hereenter image description hereenter image description here

if don't want image corners cut off above, use trigonometry earlier size window within par3d:

open3d(); bg3d(color="#ff69b4"); rgl.pop("lights"); light3d(specular="black")  persp3d(x1,y1,z, col=col.mat2, axes=false,      ylab="", xlab="", zlab="", smooth=false, aspect="iso") view3d(zoom=.862) par3d(usermatrix = rotationmatrix(-45*pi/180, 0, 0, 1), windowrect=c(0,0, width, height)) # width , height trigonometry above rgl.snapshot("rlogo45_77h124w.png") #library(png) add.alpha <- readpng("rlogo45_77h124w.png") # try "rlogo_77h124w.png", #library(abind) add.alpha <- abind(add.alpha, matrix(1, nrow=nrow(add.alpha), ncol=ncol(add.alpha)))  add.alpha[,,4][which(add.alpha[,,1] > .9 & add.alpha[,,3] > .9 & add.alpha[,,2] < .85 )] <- 0 # not perfect solution writepng(add.alpha, "rlogo45_77h124w_alpha.png") 

enter image description here


Comments

Popular posts from this blog

powershell Start-Process exit code -1073741502 when used with Credential from a windows service environment -

twig - Using Twigbridge in a Laravel 5.1 Package -

c# - LINQ join Entities from HashSet's, Join vs Dictionary vs HashSet performance -