在R中将绘图保存为GIF格式

11

在R中,我使用函数savePlot将图形保存为图像文件。但是,我的同事只能打开.jpg和.gif文件(可能因为他正在度假,在手机上阅读电子邮件)。我不想创建jpeg,因为箱线图看起来非常丑陋(触须模糊等)。但是savePlot函数仅支持以下类型:

type = c("wmf", "emf", "png", "jpg", "jpeg", "bmp",
                  "tif", "tiff", "ps", "eps", "pdf")

如何在R中将绘图保存为GIF文件?

编辑:如果可能的话,理想的解决方案应该在不安装ImageMagick的情况下工作(这样R脚本就可以轻松移植)。


2
animationcaTools都有保存gif的函数:请参见http://cran.r-project.org/web/packages/animation/animation.pdf和http://svitsrv25.epfl.ch/R-doc/library/caTools/html/GIF.html。此外,还可以在这里查看:http://tolstoy.newcastle.edu.au/R/help/05/02/12809.html。 - user1981275
3
如果您可以安装ImageMagick(http://www.imagemagick.org),您可以在命令行中将图像保存为PNG并执行“convert myPlot.png myPlot.gif”,或者在R中执行“system("convert myPlot.png myPlot.gif")”。请注意,此方法需要安装ImageMagick软件。 - Ben Bolker
1
你确定你的同事只能读取 GIF 格式而不能读取 PNG 格式吗?也许你可以尝试将文件保存为 PNG 格式并发送一个测试样例给他们。 - Ben Bolker
是的@Ben,我确定 - 我给他发送PNG后,他抱怨了 :) 谢谢,你的评论可能就是答案..唯一需要调整的是PNG应该保存为临时文件并在之后删除。 - Tomas
1个回答

14
R没有原生的GIF图形驱动程序,这可能(完全?)是由于GIF格式的专利限制所致:请参见http://tolstoy.newcastle.edu.au/R/help/05/02/12809.html。在caTools包中有一个函数(write.gif()),但它是专门用于编写图像的。如果您想使用它,您需要先将绘图转换为图像(例如,保存为PNG,然后将其作为图像读回到R中)。例如:
png("myPlot.png")
plot(rnorm(1000),rnorm(1000))
dev.off()
library(png)
P1 <- readPNG("myPlot.png")
library(caTools)
write.gif(P1,"myPlot.gif")
showGIF <- function(fn) system(paste("display",fn))
showGIF("myPlot.gif")
unlink("myPlot.gif")  ## clean up

?write.gif()中包含很多关于颜色索引的内容,我没有读过,但对于更复杂的图形可能很重要。

animation包中有一个saveGIF()函数来保存GIFs,但是(1)它设计用于保存多帧动画(而不是一般的图形),(2)它通过调用ImageMagick完成。

最简单的方法就是自己构造该函数。

例如:

png("myPlot.png")
plot(rnorm(1000),rnorm(1000))
dev.off()
system("convert myPlot.png myPlot.gif")
unlink("myPlot.png") ## clean up
showGIF("myPlot.gif")
unlink("myPlot.gif") ## clean up

当然,如果你想经常使用它们,你可以将它们放在一个函数中。

更新: 我花了更长时间来尝试得到一个纯R的解决方案,但是还没有找到一个可行的解决方案。欢迎提出建议或编辑...

## needs ImageMagick: just for testing ...
showGIF <- function(fn) system(paste("display",fn))

主要功能:

saveGIF <- function(fn,verbose=FALSE,debug=FALSE) {
    require(png)
    require(caTools)
    tmpfn <- tempfile()
    on.exit(unlink(tmpfn))
    savePlot(tmpfn,type="png")
    P1 <- readPNG(tmpfn)
    dd <- dim(P1)
    P1 <- aperm(P1,c(3,1,2),resize=TRUE)  ## P1[,1,15]
    dim(P1) <- c(dd[3],prod(dd[1:2]))
    P1 <- t(P1)
    if (verbose) cat("finding unique colours ...\n")
    P1u <- unique(P1)
    rgbMat <- function(x) {
        rgb(x[,1],x[,2],x[,3])
    }
    if (verbose) cat("creating colour index ...\n")
    pp <- paste(P1[,1],P1[,2],P1[,3],sep=".")
    ## make sure factor is correctly ordered
    ind <- as.numeric(factor(pp,levels=unique(pp))) 
    if (verbose) cat("finding colour palette ...\n")
    if (nrow(P1u)>256) {
        if (verbose) cat("kmeans clustering ...\n")
        kk <- kmeans(P1u,centers=256)
        ind <- kk$cluster[ind]
        pal <- rgbMat(kk$centers)
    } else {
        pal <- rgbMat(P1u)
    }
    ## test:
    if (debug) {
        dev.new()
        par(mar=rep(0,4))
        image(t(matrix(ind-1,nrow=dd[1])),col=pal,axes=FALSE,ann=FALSE)
    }
    if (verbose) cat("writing GIF ...\n")
    indmat <- matrix(ind-1,nrow=dd[1])
    storage.mode(indmat) <- "integer"
    write.gif(indmat,fn,col=as.list(pal),scale="never")
}


X11.options(antialias="none")
image(matrix(1:64,nrow=8),col=rainbow(10))
saveGIF("tmp.gif",verbose=TRUE,debug=TRUE)
showGIF("tmp.gif")

谢谢Ben!我想要一个不需要安装ImageMagick的解决方案(这样R脚本就更易于移植),但第一个使用write.gif的解决方案不起作用。它生成了动画灰度(!) gif。似乎write.gif函数无法生成最佳调色板(即没有颜色聚类算法来创建最佳的256色调色板)。 - Tomas
1
看起来 write.gif 可能有更多的选项 -- 你试过 scale="never" 吗?它似乎并没有颜色聚类算法,但是一个相对简单的图形可能不需要这个... - Ben Bolker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接