检查两个 tex 源是否生成相同的 pdf

检查两个 tex 源是否生成相同的 pdf

我有一个我认为相当合理和常见的问题,但我仍然无法在任何地方找到答案。

我有两个 .tex 文件,我只是想检查是否pdflatex会生成完全相同的 pdf。

很容易生成两个不同的 .tex 文件,据我所知,它们会给出完全相同的 pdf。试想一下 - 两个具有不同换行符的 .tex 文件 - 一个 .tex 文件执行\newcommand{c1}{c}并调用 c1,另一个直接调用 c - 一个 .tex 文件执行\input{blabla.tex}并包含与 c1 完全相同的内容blabla.tex

背景是我有一个包含 tex 文件的存储库。很多时候,我发现自己所做的更改根本不应该更改输出的 pdf(例如上述示例中的更改),但我无法检查。

我已经想到的事情:

  • 使用工具直接比较 pdf:理想情况下,我希望事情更加自动化和彻底。
  • 使用 latexdiff:我不能使用 perl,而且我再次想要一些更自动化和更彻底的东西。
  • 使用 latexand、flatex、flatten 等工具:不行,因为这只会扩展输入/包含。

我发现的一个有趣的线索是 如何防止不同排版的校验和不同 但我无法让它工作。

当然,我不是计算机专家,所以我不太清楚如何准确定义“两个 pdf 完全相同”。我会这样定义:“如果你把它们一个叠在另一个上面,放在明亮的窗户上,它们看起来就像是其中的一个。”

如果重要的话,我正在使用 Win7 和 pdflatex(通过 TeXnicCenter)。

答案1

本着“将纸张举到光线下”的精神,我们可以使用 Python 脚本精确复制此效果。阅读 PDF,然后叠加页面以查看每个像素是否相同。

import wand.image as w
import itertools
import functools
import sys

def load_pages(filename):
    """ Load the PDF file into a sequence of bytes, with dimensions """
    pdf = w.Image(filename=filename)
    for page in pdf.sequence:
        image = w.Image(page)
        width, height = image.width, image.height
        # Copy raw image data into blob string
        blob = image.make_blob(format='RGB')
        yield (blob, width, height)


def pages_identical(blob1, blob2, width, height):
    """ Check (pixel by pixel) if the pages (blobs) are identical """
    for c in range(0, width*height*3, 3):
        px1 = (blob1[c], blob1[c+1], blob1[c+2])
        px2 = (blob2[c], blob2[c+1], blob2[c+2])
        if px1 != px2:
            return False
    return True


def files_identical(filename1, filename2):
    """ Check if the two PDF files 'look' the same """
    pages1, pages2 = load_pages(filename1), load_pages(filename2)
    for pageno, (page1, page2) in enumerate(itertools.zip_longest(pages1, pages2, fillvalue=None)):
        if None in {page1, page2}:
            print("Files have a different number of pages")
            yield False
            return  # Break out now
        (blob1, width1, height1) = page1
        (blob2, width2, height2) = page2
        if (width1, height1) != (width2, height2):
            print("Pages are different sizes!")
            yield False
            return  # Break out now
        if pages_identical(blob1, blob2, width1, height1):
            yield True
        else:
            print("Page {} differs".format(pageno))
            yield False


fn1 = sys.argv[1]
fn2 = sys.argv[2]

match = functools.reduce(lambda a, b: a and b, files_identical(fn1, fn2), True)
# print(match)

请注意,这需要 ImageMagick 及其 Python 绑定(wand)。

答案2

您可以使用它\tracingoutput来获取有关 LaTeX 发送给 pdf 的框的信息。这应该可以让您识别出无法通过测试的差异,“如果您将它们一个放在明亮的窗口上,它们看起来就像其中之一”,尽管对边距/纸张大小的更改可能会悄悄地出现。

\documentclass{article}

\tracingoutput=1
\showboxbreadth=1000
\showboxdepth=1000

\def\foo{Hello World}
\def\bar{World Hello}

\begin{document}
%Hello World
%\foo
\bar
\end{document}

运行后,您需要比较日志文件并查找以下方面的差异:

Completed box being shipped out [1]
\vbox(633.0+0.0)x407.0
.\glue 16.0
.\vbox(617.0+0.0)x345.0, shifted 62.0
..\vbox(12.0+0.0)x345.0, glue set 12.0fil
...\glue 0.0 plus 1.0fil
...\hbox(0.0+0.0)x345.0
..\glue 25.0
..\glue(\lineskip) 0.0
..\vbox(550.0+0.0)x345.0, glue set 539.94232fil
...\write-{}
...\glue(\topskip) 3.05556
...\hbox(6.94444+0.0)x345.0, glue set 277.47212fil
....\hbox(0.0+0.0)x15.0
....\OT1/cmr/m/n/10 H
....\OT1/cmr/m/n/10 e
....\OT1/cmr/m/n/10 l
....\OT1/cmr/m/n/10 l
....\OT1/cmr/m/n/10 o
....\glue 3.33333 plus 1.66666 minus 1.11111
....\OT1/cmr/m/n/10 W
....\kern-0.83334
....\OT1/cmr/m/n/10 o
....\OT1/cmr/m/n/10 r
....\OT1/cmr/m/n/10 l
....\OT1/cmr/m/n/10 d
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\glue 0.0 plus 1.0fil
...\glue 0.0
...\glue 0.0 plus 0.0001fil
..\glue(\baselineskip) 23.55556
..\hbox(6.44444+0.0)x345.0, glue set 170.0fil
...\glue 0.0 plus 1.0fil
...\OT1/cmr/m/n/10 1
...\glue 0.0 plus 1.0fil

Completed box being shipped out [1]
\vbox(633.0+0.0)x407.0
.\glue 16.0
.\vbox(617.0+0.0)x345.0, shifted 62.0
..\vbox(12.0+0.0)x345.0, glue set 12.0fil
...\glue 0.0 plus 1.0fil
...\hbox(0.0+0.0)x345.0
..\glue 25.0
..\glue(\lineskip) 0.0
..\vbox(550.0+0.0)x345.0, glue set 539.94232fil
...\write-{}
...\glue(\topskip) 3.05556
...\hbox(6.94444+0.0)x345.0, glue set 277.47212fil
....\hbox(0.0+0.0)x15.0
....\OT1/cmr/m/n/10 W
....\kern-0.83334
....\OT1/cmr/m/n/10 o
....\OT1/cmr/m/n/10 r
....\OT1/cmr/m/n/10 l
....\OT1/cmr/m/n/10 d
....\glue 3.33333 plus 1.66666 minus 1.11111
....\OT1/cmr/m/n/10 H
....\OT1/cmr/m/n/10 e
....\OT1/cmr/m/n/10 l
....\OT1/cmr/m/n/10 l
....\OT1/cmr/m/n/10 o
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\glue 0.0 plus 1.0fil
...\glue 0.0
...\glue 0.0 plus 0.0001fil
..\glue(\baselineskip) 23.55556
..\hbox(6.44444+0.0)x345.0, glue set 170.0fil
...\glue 0.0 plus 1.0fil
...\OT1/cmr/m/n/10 1
...\glue 0.0 plus 1.0fil

您可以使用简单的方法diff来查找差异。

答案3

您可以使用程序比较两个 PDF,以显示这些文件之间的差异。我建议使用 DiffPDF(Mark Summerfield 的 2.1.3 版),它有一个“便携”版本(PortableApps.com)。

答案4

对于 reledmac/reledpar 开发工具,我编写了一个 python 脚本,调用 conver 工具来

  1. 将 pdf 导出为 png
  2. 比较 png。

它比tracebox方法慢,但我们不能排除一些框具有相同的大小,但内容不同。

脚本在这里https://github.com/maieul/ledmac/blob/master/examples/check-example.py

相关内容