LuaLaTeX 解析 PDF 中未编码的小字符串 DeviceCMYK 吗?

LuaLaTeX 解析 PDF 中未编码的小字符串 DeviceCMYK 吗?

编辑:事实证明 Lua 是不需要的。由于我从脚本调用 TeX,因此可以直接使用findstrWindows 批处理或 BASH 中的等效方法进行必要的调查。但这是在运行 TeX 文件之前使用脚本。下面提供的答案将在 TeX 文件中执行此操作。

问题:

我只使用 LuaLaTeX、Windows 和 Linux。出于跨平台兼容性考虑,对于非管理员用户,我无法sed从 TeX 内部调用或大多数其他 shell 转义程序,即使可用。我可以使用非管理员批处理或 BASH 脚本从 TeX 外部调用。

我的文档类生成 PDF/X-1a。因此,任何包含的图像都必须是 DeviceGray 或 DeviceCMYK。目前,我通过严格限制包含图像或其他 PDF 的 TeX 命令来避免潜在问题。如果可能的话,我想取消这些限制。

得益于此非常有帮助的答案相关问题,\includepdf如果包含的文件包含字体,我可以阻止使用。现在,我想阻止使用,\includepdf除非文件包含DeviceGrayDeviceCMYK写入。

在所有情况下,包含的 PDF 都只有一页、一张图片。

如果我在十六进制编辑器中打开合适的 PDF,我会看到如下内容:

10 0 obj
/DeviceCMYK
endobj

实际图像作为另一个对象(使用 FlateDecode)跟随。

因此,重新表述我的问题:LuaLaTeX 有没有什么方法可以筛选 PDF 文件,也许使用类似于sed或的方法grep,并对字符串DeviceCMYK或是否DeviceGray出现提供是/否答案?

我自己可以简单地使用 Adob​​e 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}

相关内容