• R语言已解决
  • 在 Ubuntu 系统上,当输出是 HTML 时, TikZ 代码渲染报错

报错信息

processing file: tikz-rmd.Rmd
  |...................................                 |  67% [fig-tikz]       Error:
! PDF parsing failure.
Backtrace:
  1. rmarkdown::render("/home/rstudio/Tikz/tikz-rmd.Rmd", encoding = "UTF-8")
  2. knitr::knit(knit_input, knit_output, envir = envir, quiet = quiet)
  3. knitr:::process_file(text, output)
  8. knitr:::process_group.block(group)
  9. knitr:::call_block(x)
 10. knitr:::block_exec(params)
 13. knitr (local) engine(options)
 17. magick::image_read_pdf(fig)
 18. pdftools::pdf_info(path, opw = password)
 19. pdftools:::poppler_pdf_info(loadfile(pdf), opw, upw)
                                                                                                            
PDF error: Couldn't find trailer dictionary
PDF error: Couldn't find trailer dictionary
PDF error: Couldn't read xref table

Quitting from lines 24-34 [fig-tikz] (tikz-rmd.Rmd)
Execution halted

可重复的小例子

---
title: "Rmd with TikZ"
editor: visual
output: 
  html_document:
    toc: yes
  pdf_document: 
    toc: yes
    keep_tex: true
---

## TikZ

```{r}
options(
  tinytex.engine = "xelatex",
  tikzDefaultEngine = "xetex"
)
```

The figure generated by TikZ code is normal when the output is PDF while abnormal when output is HTML.

```{tikz}
#| label: fig-tikz
#| fig-cap: TikZ
#| engine-opts: !expr list(classoption="tikz,border=1mm")
#| fig-width: 3
#| fig-height: 3
#| echo: false

\begin{tikzpicture}
\draw[<->] (6,0) -- (0,0) -- (0,6);
\end{tikzpicture}
```

环境信息

sessionInfo(package = c("pdftools", "magick", "knitr"))
R version 4.3.2 (2023-10-31)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 22.04.3 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so;  LAPACK version 3.10.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8       
 [4] LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
[10] LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

time zone: Etc/UTC
tzcode source: system (glibc)

attached base packages:
character(0)

other attached packages:
[1] pdftools_3.4.0 magick_2.8.1   knitr_1.45    

loaded via a namespace (and not attached):
 [1] compiler_4.3.2    fastmap_1.1.1     cli_3.6.1         graphics_4.3.2    htmltools_0.5.6.1
 [6] tools_4.3.2       rstudioapi_0.15.0 utils_4.3.2       yaml_2.3.7        grDevices_4.3.2  
[11] tinytex_0.48      stats_4.3.2       datasets_4.3.2    rmarkdown_2.25    methods_4.3.2    
[16] digest_0.6.33     xfun_0.41         rlang_1.1.1       base_4.3.2        evaluate_0.23

排错

发现 figure-html/ 目录下的 fig-tikz-1.pdf 文件要比 figure-pdf/ 目录下的文件 fig-tikz-1.pdf 小得多。 (908B vs 2KB)

用函数 pdftools::pdf_info() 检查figure-html/ 目录下的 fig-tikz-1.pdf 文件,发现上述错误来自该 fig-tikz-1.pdf 文件,该文件已被损坏。(说明 pdftools 和 magick 都没问题,问题应该是来自 knitr 或 rmarkdown?)

奇怪的现象发生了,为什么输出格式设定 HTML 时,编译同样的 TikZ 代码得到错误的 PDF 图片文件?

在 MacOS 上,文档输出格式无论是 HTML 还是 PDF ,结果都是正常的,没有报错。

tikz 应该是latex生态的吧,拉进html感觉属于横练武功

yihui 问题找到了。

问题继续简化一下,有如下 tex 文件 tikz-mini.tex

\documentclass[tikz,border=1mm]{standalone}
\begin{document}
\begin{tikzpicture}
\draw[<->] (6,0) -- (0,0) -- (0,6);
\end{tikzpicture}
\end{document}

用函数 tinytex::latexmk 可以编译出 pdf 文件(没有报错),文件大小 908 B,接着用 pdftools::pdf_info 检查 PDF 文件,报错。因此说明 tinytex::latexmk 编译 tex 文件,这一步有问题。

tinytex::latexmk("tikz-mini.tex")
pdftools::pdf_info("tikz-mini.pdf")
PDF error: Couldn't find trailer dictionary
PDF error: Couldn't find trailer dictionary
PDF error: Couldn't read xref table
Error: PDF parsing failure.

又发现 pdflatex 编译出来的文件是 OK 的

tinytex::latexmk("tikz-mini.tex", engine = "pdflatex")
pdftools::pdf_info("tikz-mini.pdf")
$version
[1] "1.5"

$pages
[1] 1

$encrypted
[1] FALSE

$linearized
[1] FALSE

$keys
$keys$Producer
[1] "pdfTeX-1.40.25"

$keys$Creator
[1] "TeX"

$keys$Trapped
[1] ""

$keys$PTEX.Fullbanner
[1] "This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023) kpathsea version 6.3.5"


$created
[1] "2023-12-07 00:12:41 UTC"

$modified
[1] "2023-12-07 00:12:41 UTC"

$metadata
[1] ""

$locked
[1] FALSE

$attachments
[1] FALSE

$layout
[1] "no_layout"

应该与 knitr 无关。knitr 包调用 magick 包的函数 image_read_pdf(),函数 image_read_pdf() 调用 pdftools 包的函数 pdf_info() 数 PDF 文件的页数,这个数页数的函数 pdftools::pdf_info() 在 MacOS 和 Ubuntu 上检查同一份 PDF 文件(XeLaTeX 编译出来的文件)结果不同,在 Ubuntu 上报错,在 MacOS 上显示正常。

    Cloud2016 所以问题是两个?一、xelatex 编出来的那个 908B 的 PDF 文件是坏的;二、pdflatex 编出来的 PDF 是好的,但 Ubuntu 下 pdftools::pdf_info() 报错。

      yihui > xelatex 编出来的那个 908B 的 PDF 文件是坏的

      XeLaTeX 编译出来的文件是好的(我之前预先假定 pdftools::pdf_info() 没有问题,它检查报错就是 PDF 文件的问题,而实际上是这个 pdftools::pdf_info() 本身有问题)。不仅 PDF 阅读器可以打开,而且在 Mac 上用 pdftools::pdf_info() 检查是 OK 的。

      不妨将下面内容保存到文件 tikz-mini.tex

      \documentclass[tikz,border=1mm]{standalone}
      \begin{document}
      \begin{tikzpicture}
      \draw[<->] (6,0) -- (0,0) -- (0,6);
      \end{tikzpicture}
      \end{document}

      Ubuntu + xelatex pdftools::pdf_info 检查报错

      在 Ubuntu 上,tinytex::latexmk("tikz-mini.tex", engine = "xelatex") 得到 tikz-mini.pdf 大小是 907 B(当用 XeLaTeX 编译时,生成的 PDF 文件就是小很多,在 Mac 上也一样小),用函数 pdftools::pdf_info("tikz-mini.pdf") 检查,报错信息如下:

      PDF error: Couldn't find trailer dictionary
      PDF error: Couldn't find trailer dictionary
      PDF error: Couldn't read xref table
      Error: PDF parsing failure.

      Ubuntu + pdflatex pdftools::pdf_info 检查正常

      tinytex::latexmk("tikz-mini.tex", engine = "pdflatex")
      pdftools::pdf_info("tikz-mini.pdf")
      $version
      [1] "1.5"
      
      $pages
      [1] 1
      
      $encrypted
      [1] FALSE
      
      $linearized
      [1] FALSE
      
      $keys
      $keys$Producer
      [1] "pdfTeX-1.40.25"
      
      $keys$Creator
      [1] "TeX"
      
      $keys$Trapped
      [1] ""
      
      $keys$PTEX.Fullbanner
      [1] "This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023) kpathsea version 6.3.5"
      
      
      $created
      [1] "2023-12-07 02:21:56 UTC"
      
      $modified
      [1] "2023-12-07 02:21:56 UTC"
      
      $metadata
      [1] ""
      
      $locked
      [1] FALSE
      
      $attachments
      [1] FALSE
      
      $layout
      [1] "no_layout"

      在 Mac 下,用 pdftools::pdf_info 检查 Ubuntu 下 XeLaTeX 编译出来的文件。

      在 Mac 系统上用 pdftools::pdf_info 检查 Ubuntu 下用 tinytex::latexmk("tikz-mini.tex", engine = "xelatex") 得到的文件 tikz-mini.pdf 显示正常。

      文件 tikz-mini.tex 的内容太迷你了,文件太小,多加点东西就好了。比如下面这样

      \documentclass[tikz,border=1mm]{standalone}
      \begin{document}
      \begin{tikzpicture}
      \draw[<->] (6,0) -- (0,0) node[left]{O} -- (0,6);
      \end{tikzpicture}
      \end{document}