我想在使用 LaTeX 生成的 PDF 文件中添加某种水印。我想到的是图形元素(线条、圆圈等),它们会部分遮挡页面上的文本。元素的排列(以及形状和数量)在每一页上都应该不同,最好能从文档中给出的伪随机种子中得出,这样不同的编译就会产生相同的元素排列。
作为额外奖励,我想保护文本的某些部分不被那些随机的线条和波浪线遮挡 - 水印不会遮挡这些部分,而是会穿过白色矩形的“下方”,水印位于上方,或者只是不会出现在受保护的文本所在的位置。在 LaTeX 文档中标记这些部分不是问题。
我的用例是用于文档跟踪的可见水印,具有非常基本的反 OCR 功能(因为文本中的某些字母会被遮挡)。我先声明一下,我很清楚从 PDF 复制文本的能力、重新输入文档的可能性等。
现在的问题是,从哪里开始寻找解决方案 - TikZ 能够很好地绘制几何形状,但我不知道如何使它们在每一页上随机且不同,也不知道如何保护部分文本......任何指针都会受到赞赏。
答案1
这是一个快速但肮脏的解决方案:
\documentclass{article}
\makeatletter
\usepackage{tikz}
\usepackage{everypage}
\pgfmathsetseed{314}
\newlength{\obfobjectsize}
\setlength{\obfobjectsize}{36pt}
\newcommand{\obftext}{obfuscated}
\newcommand{\dontobfuscate}[1]{%
\ifmmode\let\@dollar=$\else\let\@dollar=\relax\fi
\vphantom{#1}\smash{\fboxsep=0pt\colorbox{white}{\@dollar #1\@dollar}}%
}
\newcommand{\setrandomcoordinates}{% Places random coordinates (in pt)
\pgfmathrnd % in \a and \b.
\let\a=\pgfmathresult
\pgfmathmultiply{\a}{\paperwidth}%
\let\a=\pgfmathresult
%
\pgfmathrnd
\let\b=\pgfmathresult
\pgfmathmultiply{\b}{\paperheight}%
\let\b=\pgfmathresult
}
\newcommand{\tkzplacerandomline}{
\setrandomcoordinates
%
\pgfmathrand
\let\c=\pgfmathresult
\pgfmathmultiply{\c}{\obfobjectsize}%
\let\c=\pgfmathresult
%
\pgfmathrand
\let\d=\pgfmathresult
\pgfmathmultiply{\d}{\obfobjectsize}%
\let\d=\pgfmathresult
%
\coordinate[xshift=\a,yshift=\b] (a) at (current page.south west);
\coordinate[xshift=\c,yshift=\d] (b) at (a);
\draw[ultra thick] (a) -- (b);
}
\newcommand{\tkzplacerandomcircle}{
\setrandomcoordinates
%
\pgfmathrnd
\let\c=\pgfmathresult
\pgfmathmultiply{\c}{\obfobjectsize}%
\let\c=\pgfmathresult
%
\coordinate[xshift=\a,yshift=\b] (a) at (current page.south west);
\draw[ultra thick] (a) circle (\c pt);
}
\newcommand{\tkzplacerandomnode}{%
\setrandomcoordinates
%
\pgfmathrandominteger{\c}{30}{330}
%
\coordinate[xshift=\a,yshift=\b] (a) at (current page.south west);
\node[rotate=\c] at (a) {\obftext};
}
\newcommand{\placerandomobjects}[2]{%
\begin{tikzpicture}[overlay,remember picture]
\foreach \n in {1,2,...,#2} { #1 }
\end{tikzpicture}%
}
\AddEverypageHook{
\placerandomobjects{\tkzplacerandomline}{100}
\placerandomobjects{\tkzplacerandomcircle}{100}
\placerandomobjects{\tkzplacerandomnode}{100}
}
\makeatother
\begin{document}
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus
elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur
dictum gravida mauris. Nam arcu libero, nonummy eget, consectetuer id,
vulputate a, magna. Donec vehicula augue eu neque. Pellentesque
habitant morbi tristique senectus et netus et malesuada fames ac
turpis egestas. Mauris ut leo. Cras viverra metus rhoncus sem. Nulla
et lectus vestibulum urna fringilla ultrices. Phasellus eu tellus sit
amet tortor gravida placerat. Integer sapien est, iaculis in, pretium
quis, viverra ac, nunc. \dontobfuscate{Praesent eget sem vel leo ultrices
bibendum}. Aenean faucibus. Morbi dolor nulla, malesuada eu, pulvinar
at, mollis ac, nulla. Cur- abitur auctor semper nulla. Donec varius
orci eget risus. Duis nibh mi, congue eu, accumsan eleifend, sagittis
quis, diam. Duis eget orci sit amet orci dignissim rutrum.
Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel,
wisi. Morbi auctor lorem non justo. Nam lacus libero, pretium at,
lobortis vitae, ultricies et, tellus. Donec aliquet, tortor sed
accumsan bibendum, erat ligula aliquet magna, vitae ornare odio metus
a mi. Morbi ac orci et nisl hendrerit mollis. Suspendisse ut
massa. Cras nec ante. Pellentesque a nulla. Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus
mus. Aliquam tincidunt urna.
Nulla ullamcorper vestibulum turpis. Pellentesque cursus luctus
mauris. Nulla malesuada porttitor diam. Donec felis erat, congue non,
volutpat at, tincidunt tristique, libero. Vivamus viverra fermentum
felis. \dontobfuscate{$E=m(a^2+b^2)$} Donec nonummy pellentesque
ante. Phasellus adipiscing semper elit. Proin fermentum massa ac
quam. Sed diam turpis, molestie vitae, placerat a, molestie nec,
leo. Mae- cenas lacinia. Nam ipsum ligula, eleifend at, accumsan nec,
suscipit a, ipsum. Morbi blandit ligula feugiat magna. Nunc eleifend
consequat lorem. Sed lacinia nulla vitae enim. Pellentesque tincidunt
purus vel magna. Integer non enim. Praesent euismod nunc eu
purus. Donec bibendum quam in tellus. Nullam cur- sus pulvinar
lectus. Donec et mi. Nam vulputate metus eu enim. Vestibulum
pellentesque felis eu massa.
Quisque ullamcorper placerat ipsum. Cras nibh. Morbi vel justo vitae
lacus tincidunt ultrices. Lorem ipsum dolor sit amet, consectetuer
adipiscing elit. In hac habitasse platea dictumst. Integer tempus
convallis augue. Etiam facilisis.
\begin{displaymath}
\dontobfuscate{E=m(a^2+b^2)}
\end{displaymath}
Nunc elementum fermentum
wisi. Aenean placerat. Ut imperdiet, enim sed gravida sollicitudin,
felis odio placerat quam, ac pulvinar elit purus eget enim. Nunc
vitae tortor. Proin tempus nibh sit amet nisl. Vivamus quis tortor
vitae risus porta vehicula.
\end{document}
它不是很优雅,尤其是 \dontobfuscate 命令真的非常简单;它将在水平模式下工作(并生成一个框,因此它将不会被破坏,并且空格将具有其自然宽度,这看起来很丑陋,除非(a)只放入单个单词或(b)文本设置为右边参差不齐或类似的东西;它也将在数学模式下工作,但以非常原始的方式(例如适用于简单的符号)。但它可以作为概念证明,并且使其更加通用现在是一个进行一些调整的问题。玩得开心!
附言:更不用说“drm”标签可能会被这个社区的某些人认为有点冒犯;)。
编辑:正如 cjorssen 在评论中提到的,这需要两遍编译,因为它使用了 tikz 的记忆图片机制。
答案2
这是一种可能性TikZ
everyshi
,使用@Jake 的回答中使用的反转剪辑技巧:如何在 TikZ 中反转“剪辑”选择?
这是最终的代码:
\documentclass{article}
\usepackage{everyshi}
\usepackage{tikz}
\usetikzlibrary{calc}
\def\nodrmstart{\tikz[remember picture, overlay]\coordinate(nodrms);}
\def\nodrmend{\tikz[remember picture, overlay]\coordinate(nodrme);}
\EveryShipout{%
\begin{tikzpicture}[overlay, remember picture]
\tikzstyle{reverseclip}=[insert path={(0,0) --
++(\textwidth,0) --
++(0,-\textheight) --
++(-\textwidth,0) --
(0,0)}
]
\begin{pgfinterruptboundingbox}
\path[clip] let \p1=(nodrms), \p2=(nodrme) in (\textwidth,\y1) -- (0,\y1) -- (0,\y2) -- (\textwidth,\y2) -- cycle [reverseclip];
\end{pgfinterruptboundingbox}
\pgfmathsetseed{2}
\foreach \i in {1,2,...,200}{
\pgfmathsetlengthmacro{\yloc}{random(0,int(\the\textheight))}
\pgfmathsetlengthmacro{\xloc}{random(0,int(\the\textwidth))}
\pgfmathsetlengthmacro{\rad}{random(5,30)}
\draw (\xloc, -\yloc) circle[radius=\rad];
}%
\end{tikzpicture}
}
\begin{document}
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida
mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra
metus rhoncus sem. Nulla et lectus vestibulum urna fringilla ultrices. Phasellus
eu tellus sit amet tortor gravida placerat. Integer sapien est, iaculis in, pretium
quis, viverra ac, nunc. Praesent eget sem vel leo ultrices bibendum. Aenean
faucibus. Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac, nulla. Cur-
abitur auctor semper nulla. Donec varius orci eget risus. Duis nibh mi, congue
eu, accumsan eleifend, sagittis quis, diam. Duis eget orci sit amet orci dignissim
rutrum.
Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi
auctor lorem non justo. Nam lacus libero, pretium at, lobortis vitae, ultricies et,
tellus. Donec aliquet, tortor sed accumsan bibendum, erat ligula aliquet magna,
vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mollis. Suspendisse
ut massa. Cras nec ante. Pellentesque a nulla. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Aliquam tincidunt urna.
Nulla ullamcorper vestibulum turpis. Pellentesque cursus luctus mauris.
Nulla malesuada porttitor diam. Donec felis erat, congue non, volutpat at,
tincidunt tristique, libero. Vivamus viverra fermentum felis. Donec nonummy
pellentesque ante. Phasellus adipiscing semper elit. Proin fermentum massa
ac quam. Sed diam turpis, molestie vitae, placerat a, molestie nec, leo. Mae-
cenas lacinia. Nam ipsum ligula, eleifend at, accumsan nec, suscipit a, ipsum.
Morbi blandit ligula feugiat magna. Nunc eleifend consequat lorem. Sed lacinia
nulla vitae enim. Pellentesque tincidunt purus vel magna. Integer non enim.
Praesent euismod nunc eu purus. Donec bibendum quam in tellus. Nullam cur-
sus pulvinar lectus. Donec et mi. Nam vulputate metus eu enim. Vestibulum
pellentesque felis eu massa.
Quisque ullamcorper placerat ipsum. Cras nibh. Morbi vel justo vitae lacus
tincidunt ultrices. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In
hac habitasse platea dictumst. Integer tempus convallis augue. Etiam facilisis.
Nunc elementum fermentum wisi. Aenean placerat. Ut imperdiet, enim sed
gravida sollicitudin, felis odio placerat quam, ac pulvinar elit purus eget enim.
Nunc vitae tortor. Proin tempus nibh sit amet nisl. Vivamus quis tortor vitae
risus porta vehicula.
Fusce mauris. Vestibulum luctus nibh at lectus. Sed bibendum, nulla a fau-
cibus semper, leo velit ultricies tellus, ac venenatis arcu wisi vel nisl. Vestibulum
diam. Aliquam pellentesque, augue quis sagittis posuere, turpis lacus congue
quam, in hendrerit risus eros eget felis. Maecenas eget erat in sapien mattis
porttitor. Vestibulum porttitor. Nulla facilisi. Sed a turpis eu lacus commodo
facilisis. Morbi fringilla, wisi in dignissim interdum, justo lectus sagittis dui, et
vehicula libero dui cursus dui. Mauris tempor ligula sed lacus. Duis cursus enim
ut augue. Cras ac magna. Cras nulla. Nulla egestas. Curabitur a leo. Quisque
egestas wisi eget nunc. Nam feugiat lacus vel est. Curabitur consectetuer.
Suspendisse vel felis. Ut lorem lorem, interdum eu, tincidunt sit amet,
laoreet vitae, arcu. Aenean faucibus pede eu ante. Praesent enim elit, rutrum
at, molestie non, nonummy vel, nisl. Ut lectus eros, malesuada sit amet, fer-
mentum eu, sodales cursus, magna. Donec eu purus. Quisque vehicula, urna sed
ultricies auctor, pede lorem egestas dui, et convallis elit erat sed nulla. Donec
luctus. Curabitur et nunc. Aliquam dolor odio, commodo pretium, ultricies
non, pharetra in, velit. Integer arcu est, nonummy in, fermentum faucibus,
egestas vel, odio.
Sed commodo posuere pede. Mauris ut est. Ut quis purus. Sed ac odio. Sed
vehicula hendrerit sem. Duis non odio. Morbi ut dui. Sed accumsan risus eget
odio. In hac habitasse platea dictumst. Pellentesque non elit. Fusce sed justo
eu urna porta tincidunt. Mauris felis odio, sollicitudin sed, volutpat a, ornare
ac, erat. Morbi quis dolor. Donec pellentesque, erat ac sagittis semper, nunc
dui lobortis purus, quis congue purus metus ultricies tellus. Proin et quam.
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
hymenaeos. Praesent sapien turpis, fermentum vel, eleifend faucibus, vehicula
eu, lacus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames
ac turpis egestas. Donec odio elit, dictum in, hendrerit sit amet, egestas sed, leo.
Praesent feugiat sapien aliquet odio. Integer vitae justo. Aliquam vestibulum
fringilla lorem. Sed neque lectus, consectetuer at, consectetuer sed, eleifend ac,
lectus. Nulla facilisi. Pellentesque eget lectus. Proin eu metus. Sed porttitor.
In hac habitasse platea dictumst. Suspendisse eu lectus. Ut mi mi, lacinia sit
amet, placerat et, mollis vitae, dui. Sed ante tellus, tristique ut, iaculis eu,
malesuada ac, dui. Mauris nibh leo, facilisis non, adipiscing quis, ultrices a, dui.
\nodrmstart Morbi luctus, wisi viverra faucibus pretium, nibh est placerat odio, nec com-
modo wisi enim eget quam. Quisque libero justo, consectetuer a, feugiat vitae,
porttitor eu, libero. Suspendisse sed mauris vitae elit sollicitudin malesuada.
Maecenas ultricies eros sit amet ante. Ut venenatis velit. Maecenas sed mi eget
dui varius euismod. Phasellus aliquet volutpat odio. Vestibulum ante ipsum \nodrmend
primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque sit
amet pede ac sem eleifend consectetuer. Nullam elementum, urna vel imperdiet
sodales, elit ipsum pharetra ligula, ac pretium ante justo a nulla. Curabitur
tristique arcu eu metus. Vestibulum lectus. Proin mauris. Proin eu nunc eu
urna hendrerit faucibus. Aliquam auctor, pede consequat laoreet varius, eros
tellus scelerisque quam, pellentesque hendrerit ipsum dolor sed augue. Nulla
nec lacus.
Suspendisse vitae elit. Aliquam arcu neque, ornare in, ullamcorper quis,
commodo eu, libero. Fusce sagittis erat at erat tristique mollis. Maecenas
sapien libero, molestie et, lobortis in, sodales eget, dui. Morbi ultrices rutrum
lorem. Nam elementum ullamcorper leo. Morbi dui. Aliquam sagittis. Nunc
placerat. Pellentesque tristique sodales est. Maecenas imperdiet lacinia velit.
Cras non urna. Morbi eros pede, suscipit ac, varius vel, egestas non, eros.
Praesent malesuada, diam id pretium elementum, eros sem dictum tortor, vel
consectetuer odio sem sed wisi.
\end{document}
当同一页上有多个需要排除的矩形,并且由于某种原因\EveryShipout
在第一页上不起作用时,就会出现问题。但它可以在后续页面上工作。绘制的随机圆圈只是一个例子,您可以在 for 循环中添加任何类型的随机形状,种子确保不同编译的一致性。代码使用和y
设置的坐标创建剪切矩形。同一页面上有多个矩形的问题可以通过创建一个对列表并迭代剪切路径中的矩形来解决。但这并非易事。生成的第二页如下所示:\nodrmstart
\nodrmend
请注意,圆圈一直画到页面的底部,因为是\textheight
用绘制它们的。