编辑:事实证明 Lua 是不需要的。由于我从脚本调用 TeX,因此可以直接使用findstr
Windows 批处理或 BASH 中的等效方法进行必要的调查。但这是在运行 TeX 文件之前使用脚本。下面提供的答案将在 TeX 文件中执行此操作。
问题:
我只使用 LuaLaTeX、Windows 和 Linux。出于跨平台兼容性考虑,对于非管理员用户,我无法sed
从 TeX 内部调用或大多数其他 shell 转义程序,即使可用。我可以使用非管理员批处理或 BASH 脚本从 TeX 外部调用。
我的文档类生成 PDF/X-1a。因此,任何包含的图像都必须是 DeviceGray 或 DeviceCMYK。目前,我通过严格限制包含图像或其他 PDF 的 TeX 命令来避免潜在问题。如果可能的话,我想取消这些限制。
得益于此非常有帮助的答案相关问题,\includepdf
如果包含的文件包含字体,我可以阻止使用。现在,我想阻止使用,\includepdf
除非文件包含DeviceGray
或DeviceCMYK
写入。
在所有情况下,包含的 PDF 都只有一页、一张图片。
如果我在十六进制编辑器中打开合适的 PDF,我会看到如下内容:
10 0 obj
/DeviceCMYK
endobj
实际图像作为另一个对象(使用 FlateDecode)跟随。
因此,重新表述我的问题:LuaLaTeX 有没有什么方法可以筛选 PDF 文件,也许使用类似于sed
或的方法grep
,并对字符串DeviceCMYK
或是否DeviceGray
出现提供是/否答案?
我自己可以简单地使用 Adobe Acrobat Pro,或者 ImageMagick。这是为了更多普通用户的利益,而不必脱离 LuaLaTeX。
答案1
解决方案如下epdf
:
\documentclass{scrartcl}
\usepackage{luacode,pdfpages}
\begin{luacode*}
function check_colorspaces(allowed_colorspace, name)
local doc = epdf.open(name);
if doc == nil then
tex.sprint(luatexbase.catcodetables['latex-package'],
"\\errmessage{Could not open " .. name .. "}{}{}\\@gobbletwo")
return;
else
for pageno=1,doc:getNumPages() do
local xobjs= doc:getCatalog():getPage(pageno):getResourceDict():lookup("XObject");
if not xobjs:isNull() then
for i=1,xobjs:dictGetLength() do
xobjDict = xobjs:dictGetVal(i):streamGetDict()
if xobjDict:lookup('Subtype'):getName() == 'Image' then
if not allowed_colorspace[xobjDict:lookup('ColorSpace'):getName()] then
tex.sprint(luatexbase.catcodetables['latex-package'], '\\@firstoftwo')
return
end
end
end
end
end
end
tex.sprint(luatexbase.catcodetables['latex-package'], '\\@secondoftwo')
return;
end
\end{luacode*}
\newcommand\PDFHasDisallowedColorspaceTF[1]{%
\directlua{check_colorspaces({DeviceCMYK=true, DeviceGray=true},"\luaescapestring{#1}")}%
}
\begin{document}
\PDFHasDisallowedColorspaceTF{image.pdf}{%
\errmessage{image.pdf contains invalid colorspace!}%
}{%
\includepdf[pages=-]{image.pdf}%
}
\end{document}
这不会检查文件是否包含允许的色彩空间之一,而是检查 PDF 中没有图像具有不允许的色彩空间。如果您只有一个图像,这应该会导致相同的结果,但如果包含多个图像,则检查每个图像。如果没有找到图像,则不视为错误,并且文本中的色彩空间将被忽略。
该答案也可以处理压缩的PDF文件。
答案2
由于颜色空间将以纯 ASCII 格式保存在文件中,因此您只需搜索字符串即可。与 相比,这可能会带来一些性能损失epdf
。
\documentclass{article}
\pagestyle{empty}
\begin{document}
\directlua{
local filename = "test.pdf"
local color_space_found = false
%
for line in io.lines(filename) do
if string.find(line,"/DeviceGray") or string.find(line,"/DeviceCMYK") then
color_space_found = true
break
end
end
%
if not color_space_found then
error(filename .. " does not specify the correct color space")
end
}
\end{document}