• 服务器上R调用png显示x11报错怎么办?


    太长不读版

    • 治本的方法,服务器安装pango, 之后重新编译R语言
    • 治标的方法,在R的配置文件中增加options(bitmapType='cairo')

    服务器上装完R语言之后,发现自己的PNG函数无法正常调用,始终会出现一个X11连接失败的错误。

    > png('ab.png')
    Error in .External2(C_X11, paste0("png::", filename), g$width, g$height,  :
      unable to start device PNG
    In addition: Warning message:
    In png("ab.png") : unable to open connection to X11 display ''
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用 capabilities查询之后,的确是没有启用X11。

    > capabilities()
           jpeg         png        tiff       tcltk         X11        aqua
           TRUE        TRUE        TRUE        TRUE       FALSE       FALSE
       http/ftp     sockets      libxml        fifo      cledit       iconv
           TRUE        TRUE       FALSE        TRUE        TRUE        TRUE
            NLS       Rprof     profmem       cairo         ICU long.double
           TRUE        TRUE       FALSE        TRUE        TRUE        TRUE
        libcurl
           TRUE
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    回溯到我源代码的配置过程,发现配置项目包括X11的界面支持,Interfaces supported:X11, tcltk. 但是我思索了下,这个X11支持指的应该是Linux的图形界面下的R,而不是终端的R,我的直觉告诉我,这个信息应该是和我们的报错无关了。

    之后,我又去查了下其他资料,谢益辉提到这可能是png函数的type参数选择出现了问题,也就是下面这段函数

        if (missing(type))
            type <- getOption("bitmapType")
    
    • 1
    • 2

    进一步这个bitmapType选项的设置又和 grDevices:::.onLoad函数中的.Call(C_cairoProps, 2L)有关。其中.Call是R语言调用C语言编写函数的一种方式,回溯到对应的C代码(代码位置为src/library/grDevices/src/init.c)

    #ifndef _WIN32
    /* This really belongs with the X11 module, but it is about devices */
    static SEXP cairoProps(SEXP in)
    {
        int which = asInteger(in);
        if(which == 1)
            return ScalarLogical(
    #ifdef HAVE_WORKING_CAIRO
                1
    #else
                0
    #endif
                );
        else if(which == 2)
            return ScalarLogical(
    #ifdef HAVE_PANGOCAIRO
                1
    #else
                0
    #endif
                );
        return R_NilValue;
    }
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    还好,我略懂一些C语言,发现这个输出结果又和变量 HAVE_PANGOCAIRO 有关。 搜索R源代码中所有和HAVE_PANGOCAIRO有关的内容,发现在configure有相关记录,对应的逻辑判断语句如下

    if test "x${r_cv_has_pangocairo}" = xyes; then
    
    printf "%s\n" "#define HAVE_PANGOCAIRO 1" >>confdefs.h
    
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5

    进一步,我们在configure中查找 r_cv_has_pangocairo, 找到如下的判断语句

    else $as_nop
      if "${PKG_CONFIG}" --exists pangocairo; then
             r_cv_has_pangocairo="yes"
           else
             r_cv_has_pangocairo="no"
           fi
    
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    那看来有可能是pangocairo这个库出现了问题。使用下列代码在我的服务器上测试,发现输出是no, 说明的确没有安装。

    /bin/pkg-config --exists pangocairo && echo "yes" || echo "no"
    
    • 1

    我尝试着用下述代码安装pango

    # CentOS
    sudo yum install pango-devel pango libpng-devel
    # ubuntu
    sudo apt install libpango-1.0-0
    
    • 1
    • 2
    • 3
    • 4

    对R进行重新编译安装,发现 getOption("bitmapType") 得到的结果是cairo,符合预期了。

    当然,你可能也不需要那么麻烦的方法,还有一种简单的思路是在 ~/.Rprofile中加入这一行,手动指定cairo。

    options(bitmapType='cairo')
    
    • 1

    注意: 直接用apt/yum安装的R, getOption("bitmapType") 输出直接是 cairo.

    参考资料

    • https://stackoverflow.com/questions/17243648/cant-display-png
  • 相关阅读:
    springboot+英语在线学习系统 毕业设计-附源码211714
    如何用jOOQ将一个嵌套的SQL集合类型安全地映射到一个嵌套的Java地图上
    TDengine 与煤科院五大系统实现兼容性互认,助力煤矿智能化安全体系搭建
    外汇天眼:Patrick Wonsey挪用340万美元!涉嫌外汇和二元期权欺诈
    用好CompletableFuture类,性能起飞
    uView2 LineProgress进度太小时显示不全的一种解决办法
    MYSQL高级(二)---索引
    (微信开发)Laya转发H5网页到微信,带图片
    【数仓设计】企业数仓为什么要进行分层?(六大好处)
    2022年9月19日--9月25日(ue4热更新视频教程为主,)
  • 原文地址:https://blog.csdn.net/u012110870/article/details/125502867