导入 PDF 文件中的指定目的地

导入 PDF 文件中的指定目的地

\href{myfile.pdf#page.42}{link text}我知道我们可以在 Linux 中使用命令行导出指定的 PDF 目标(外部链接的超级目标,就像我们可以在 LaTeX 中引用它们一样) pdfinfo -dests

但是,我们如何使用命令行工具在从某处收到的现成 PDF 文件中添加/创建这样的命名目标链接呢?

答案1

根据 @meuh 的提示,指向 Adob​​e 的 PDFpdfmark\hypertarget{}功能,我发现从文件导入(可能是手工制作的)pdfmarks(用于使用命名目的地之类的东西,就像它们将由 LaTeX 等创建的那样)的工作可以通过 Ghostscript 完成,例如:

gs -q -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -dPDFDontUseFontObjectNum -dPrinted=false -sOutputFile=FILE_NEW.pdf FILE_ORIGINAL.PDF PDFMARKS_TO_BE_ADDED_TO.ps

...程序的手册页建议extractpdfmark包含在许多 Linux 发行版中,源代码位于https://github.com/trueroad/extractpdfmark),它的作用是将一个 PDF 文件的所有 pdfmarks(导航链接、命名目的地等)显示/导出为 postscript PS 文件,然后可以通过上述ghostscript命令行将其重新导入到其他文件中 – 例如使用原始文件包含目的地的情况,然后在进程之间的某些过程中丢失,并且必须重新导入(就像在我的完整用例中一样,我没有详细描述,因为该部分在这里似乎不相关)。
导入之后,就可以(再次)从 LaTeX 成功链接到该文件的特定 PDF 页面。

以下代码片段可能会简化所描述用例的过程:

#!/bin/bash
# copy pdfmarks from a SOURCE_FILE .pdf to the existing TARGET_FILE .pdf

SOURCE_FILE=$1
TARGET_FILE=$2
PDFMARKS=$(mktemp)
TMPFILE=$(mktemp)

extractpdfmark "${SOURCE_FILE}" > "${PDFMARKS}"

cp "${TARGET_FILE}" ${TMPFILE}

# combine exported PDFMARKS with the content of the TARGET_FILE into the TMPFILE copy of the target file
gs -q -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -dPDFDontUseFontObjectNum -dPrinted=false \
    -sOutputFile=${TMPFILE} "${TARGET_FILE}" "${PDFMARKS}"

cp ${TMPFILE} "${TARGET_FILE}"


(只是添加这个,因为在我的经验的许多转换过程中出现了不需要的副作用:此外,通过 Xournal 或 Okular 完成的注释之类的事情在添加 pdfmarks 后仍然像以前一样,但书签/目录似乎没有被接管,也许为此使用pdftk的功能。)dump_data


另请注意:要为 PDF 生成一些简单的目标,只需创建一个文件,例如pdfmarks.ps

% manually crafted
[ /PageMode /UseOutlines /DOCVIEW pdfmark

然后运行命令行片段:

for i in $(seq 1 999); do 
    echo  "[ /Dest (page.$i) /Page $i /View [/Fit] /DEST pdfmark" >> pdfmarks.ps
done

生成超级目标作为 999 个页面的指定目的地,您可以将其与上面的 Ghostscript 命令一起使用,将其添加到另一个 PDF。 (请注意,对于 PS,一行中的第一个方括号在末尾不闭合。)

答案2

这也许不是最好的方法,但您可以使用 LaTeX 本身来做到这一点,使用pdfpageshyperref包的组合。

假设您有一个名为 inputfile.pdf 的 PDF。您可以通过像这样创建一个包装器来添加一些命名目的地,并使用\includepdf包含picturecommand=命令的选项\hypertarget

\documentclass{article}
\usepackage{pdfpages,hyperref}
\pagestyle{empty}
\begin{document}

% put two named destinations on page 1
\includepdf[pages=1,
    picturecommand={
        \put(100,100){\hypertarget{mydestination2}{}}
        \put(200,250){\hypertarget{anotherdestination3}{}}
    }
]{inputfile}
% put a named destination on page 2
\includepdf[pages=2,
    picturecommand={
        \put(200,100){\hypertarget{yetanother}{}}
    }
]{inputfile}
% put rest of pages as is with only page number targets
\includepdf[pages=3-]{inputfile}

\end{document}

这些\put(x,y)命令会将目标放置在页面上相对于左下角的特定位置。这些与您使用时看到的数字相同或至少非常接近pdfinfo -dests

表单的目标page.###将自动插入,因此您可以“免费”获得这些目标。

如果您想从命令行执行此操作而不创建中间 LaTeX 文件,则该pdfjam实用程序基本上只是带有pdfpages包的 LaTeX 的包装器。所以你可以使用这样的东西:

pdfjam --preamble '\usepackage{hyperref}' --picturecommand'*' '{\put(300,300){\hypertarget{destname}{}}}' inputfile.pdf --outfile outputfile.pdf

将指定的目标位置放置在 300x300 的首页中inputfile.pdf。请参阅 参考资料 来了解pdfjam --help有关执行更高级操作的更多信息。

这些方法的真正缺点是它们不保留任何可能已经存在的目的地。然而,我认为这对于还没有这些 PDF 的 PDF 很有用,您也许可以使用pdfinfo -dests和 此方法的组合来编写重新插入旧 PDF 的脚本。

相关内容