如何使用 Ghostscript 和 Ghostscript .NET 通过嵌入 IIC 配置文件生成正确的 PDF/A

Posted

技术标签:

【中文标题】如何使用 Ghostscript 和 Ghostscript .NET 通过嵌入 IIC 配置文件生成正确的 PDF/A【英文标题】:How to generate proper PDF/A with embedding IIC profile using Ghostscript and Ghostscript .NET 【发布时间】:2020-07-28 10:29:35 【问题描述】:

当前情景:

我正在尝试基于普通 PDF 文档生成正确且符合标准的 PDF/A,经过几个小时的调查,我们决定使用 Ghostscript 功能。这个业务需求是为我正在从事的一个更大的 C# 项目设置的,但首先我开始在 Windows 上下文中使用 Ghostscript 命令 进行一些测试,并创建了一个独立的 另一个使用 Ghostscript .NET 的控制台应用程序,以测试此功能的可行性。

我们在第一次测试中集中了 PFD/A-1B 格式,并使用了 VeraPDFPDF-Tools 检查生成文件的一致性。

以下测试已使用几个不同的 PDF 文件完成,其中一些是我们的项目应用程序实际生成的文件。为简单起见,如果有人想检查,我提供了一个简单的 PDF(只有几行文本),它已以相同的方式使用和测试,并且重现了相同的行为。

Download PDF for testing

Ghostscript 命令测试

执行

使用 GhostScript v 9.52,我尝试了以下命令:

gswin32c.exe -dNOSAFER -dPDFA=1 -sColorConversionStrategy=RGB -sDEVICE=pdfwrite -dPDFACompatibilityPolicy=1 -dNOPAUSE -dBATCH -o result.pdf "C:\GS_PDFA\PDFA_def.ps" WriterPDF.pdf

*注意:即使我读到不推荐使用 -dNOSAFER 参数,我也无法在没有它的情况下生成 PDF,因为 /invalidfileaccess 错误。我怀疑访问权限是原因,正如在 *** (GhostScript: Error: /invalidfileaccess in --file--) 上搜索时发现的那样,但仍然没有找到任何适合我的解决方案。

也尝试了以下命令,但同样的错误(将所需的 ICC 配置文件与 .ps 模板文件放在同一文件中):

gswin32c.exe --permit-file-read=c:/GS_PDFA/srgb.icc -dPDFA=1 -sColorConversionStrategy=RGB -sDEVICE=pdfwrite -dPDFACompatibilityPolicy=1 -dNOPAUSE -dBATCH -o result2.pdf C:/GS_PDFA/PDFA_def_FULL.ps WriterPDF.pdf 

对于 PDFA 配置文件,我尝试在 Ghostscript 安装目录中的 /lib 上提供默认 PDFA_def.ps template。之后,尝试使用 PDFA_def.ps 模板文件,更新行:

/ICCProfile (C:/GS_PDFA/srgb.icc)

/OutputConditionIdentifier (sRGB)

结果和验证

结果:Download PDF generated by command line

VeraPDF 说:

PDF 文件符合验证配置文件要求

PDF-Tools 说:

该文档确实符合 PDF/A-1b 标准。

此外,当使用 Adob​​e Reader DC 打开时,一致性选项卡会显示所选格式 (PFD/A-1B) 的所有详细信息,但不显示 OutputIntent,甚至 PDFA_def.ps template 被设置为参数,sRGB ICC 配置文件包含在模板文件中。 Adobe conformance status missed OutputIntend capture

Ghostscript .NET 控制台应用程序:

执行

我尝试根据 Ghostscript 测试期间使用的相同参数编写代码:

string outputFile = @"C:\temp\output.pdf";
string inputFile = @"C:\temp\WriterPDF.pdf";

GhostscriptPipedOutput gsPipedOutput = new GhostscriptPipedOutput();

// pipe handle format: %handle%hexvalue
string outputPipeHandle = "%handle%" + int.Parse(gsPipedOutput.ClientHandle).ToString("X2");

using (GhostscriptProcessor processor = new GhostscriptProcessor())

    List<string> switches = new List<string>();
    switches.Add("-empty");
    switches.Add("-dPDFA=1");
    switches.Add("-sColorConversionStrategy=RGB");
    switches.Add("-dPDFACompatibilityPolicy=1");
    switches.Add("-dBATCH");
    switches.Add("-dNOPAUSE");
    switches.Add("-sDEVICE=pdfwrite");
    switches.Add("-o" + outputPipeHandle);
    //switches.Add("c:/GS_PDFA/PDFA_def.ps");
    switches.Add(inputFile);

    try
    
        processor.StartProcessing(switches.ToArray(), null);

        byte[] rawDocumentData = gsPipedOutput.Data;
        
        File.WriteAllBytes(outputFile, rawDocumentData);

    
    catch (Exception ex)
    
        Console.WriteLine(ex.Message);

        Console.ReadLine();
    
    finally
    
        gsPipedOutput.Dispose();
        gsPipedOutput = null;
    

*注意:请注意,这次没有使用 -dNOSAFER 参数。 如果包含,结果相同,没有额外信息或详细错误如果注释行 (switches.Add("c:/GS_PDFA/PDFA_def.ps");) 包含,则应用程序会引发错误

调用“gsapi_init_with_args”时出错:-100

我试图防止错误使用模板文件的另一个位置,但没有成功。还在顶部添加了代码行:switches.Add("-Ic:/GS_PDFA/"); 但同样的错误。

结果和验证

结果:Download PDF generated by GS .NET DLL

VeraPDF 说:

如果没有设置 PDFA_def.ps 模板文件,则生成的文件不会通过验证检查。

PDF 文件不符合验证配置文件要求

PDF-Tools 说:

该文档确实符合 PDF/A-1b 标准。

此外,当使用 Adob​​e Reader DC 打开时,一致性选项卡会显示所选格式 (PFD/A-1B) 的所有详细信息,现在 OutputIntent 存在,但详细信息不完整,因为未显示标识符和信息值。 Adobe conformance status OutputIntend incomplete capture

问题

根据 Ghostscript 命令,有没有办法生成带有正确 ICC 信息的 PDF/A?就我所见,没有一个结果真正令人满意,那么我应该怎么做才能成功地将这些信息嵌入到 PDF/A 生成的文件中? 猜测 Ghostscript 命令可以实现包含正确 ICC 配置文件的符合标准的 PDF/A 文件,并且由于我们计划使用 Ghostscript .NET,如何将 PDF/A 模板文件作为参数包含在 C# 代码中?

非常感谢。

[编辑]

我无法使用 --permit-file-read 更改权限。我通常在 C:\GS_PDFA 中有 ps 和 icc 文件,但在 GS 本地安装文件夹中尝试使用它们,但总是出现相同的错误:

错误:/invalidfileaccess in --file-- 操作数栈: --nostringval-- --nostringval-- (C:/GS_PDFA/srgb.icc) (r) 执行栈: %interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1990 1 3 %oparray_pop 1989 1 3 % oparray_pop 1977 1 3 %oparray_pop 1833 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- 字典栈: --dict:741/1123(ro)(G)-- --dict:0/20(G)-- --dict:76/200(L)-- 当前分配模式是本地的 最后一个操作系统错误:权限被拒绝 当前文件位置是 2118

使用 Ghostscript .NET 对控制台应用程序进行了大量测试,甚至将 PDFA_def.ps 和 srgb.icc 文件放在解决方案文件夹中,同样的错误。尝试在 C:\GS_PDFA 中找到主要的 GS 安装文件,包括 ICC 配置文件 (srgb.icc),打开命令提示符并再次使用 Ghostscript 命令进行测试,但均不成功。

以下是我尝试过的一些命令示例:

--permit-file-read=c:/GS_PDFA/srgb.icc
 --permit-file-read="c:/GS_PDFA/srgb.icc"
 --permit-file-read="c:/GS_PDFA/srgb.icc"
 --permit-file-read=srgb.icc
 --permit-file-read="c:\GS_PDFA\srgb.icc"
 --permit-file-read="/srgb.icc"
 --permit-file-read=/srgb.icc
 --permit-file-read="\srgb.icc"
 --permit-file-read=\srgb.icc
 --permit-file-read=c:/GS_PDFA/
 --permit-file-read="c:/GS_PDFA/"
 --permit-file-read=c:\GS_PDFA\
 --permit-file-read=c:/GS_PDFA/****.icc
 --permit-file-read=c:/GS_PDFA/*.icc
 --permit-file-read=c:/GS_PDFA/*

我尝试移动文件、更改位置、文件夹等。我尝试更改文件夹安装方式,即使使用 Ghostscriptx64 也是如此...安装时我有什么遗漏吗?

请问,有人有可以帮助我的 windows 工作示例吗?

【问题讨论】:

【参考方案1】:

您不应使用-dNOSAFER,而应使用 --permit-file-read 开关将文件/目录添加到允许的文件阅读列表中。需要读取的文件是 OutputIntent 配置文件,它是 pdfa_def.ps 文件的主要成分之一。见下文。

如果您不包含 pdfa_def.ps 文件,那么您将不会在最终的 PDF/A 文件中获得 OutputIntent,并且它将不符合 PDF/A(除非您将 UseDeviceIndependentColor 指定为 ColorConversionStrategy)。这就是为什么您的代码示例不起作用的原因。注意到 PDF-Tools 仍然说该文件是有效的,我会停止使用它作为验证器,它显然不可靠。我个人发现 VeraPDF 是最好的验证器(比 Acrobat 内置的验证器要好)。

我很惊讶您在问题顶部显示的命令行会生成有效的 PDF/A 文件,除非您修改了 pdfa_def.ps 文件?您应该,特别是您必须修改与 /ICCProfile 键关联的值。该值(括号内的字符串)需要是 ICC 配置文件的完全限定路径,并且需要将 ICC 配置文件文件或其所在的目录添加到允许读取的文件列表中,请参阅文档here 下-dSAFER.

假设您已经这样做了,那么生成的 PDF 文件应该是符合 PDF/A-1b 的文件。事实上,根据你的问题,VeraPDF 说它是一致的,所以我不清楚你的问题是什么。共享输入和输出 PDF 文件比共享 Acrobat 显示的(部分)图片更有用。

所以回答你的问题:

    是的,有一种方法可以生成带有 ICC 信息的 PDF/A 文件(如果它没有 OutputIntent,则它无效)并且您的命令行会这样做。如果您没有适当地修改 pdfa_def.ps 文件,您可能仍然会遇到问题。

    据我所知,您使用 Ghostscript.NET 以与在命令行上完全相同的方式运行 pdfa_def.ps 文件,只需将其放在参数列表中即可。因此,您只需要取消注释您已评论的行。当然,您没有包含 -dNOSAFER,也没有将 ICC 配置文件添加到允许读取的文件列表中,因此您收到错误消息。我很惊讶你得到了一个致命的错误,我期待一个无效的访问,但显而易见的事情是将 -dNOSAFER 添加到参数中。反向通道输出可能有用,它可能包含更多信息,而您没有包含这些信息。

哦,我也不会写信给管道。 pdfwrite 设备期望写入文件,它可能会在写入文件时尝试在文件中查找。如果确实如此,并且您已写入管道(或其他不可搜索的输出),那么它将失败。

您不需要将 -f 添加到参数列表中,并且:

switches.Add("-dNOPAUSEgsArgs");

在我看来很可疑,看起来应该是 -dNOPAUSE。

最后,如果您打算分发此应用程序,您应该检查 AGPL 的条款,我相信 Artifex 会将 Ghostscript.NET 和 Ghostscript DLL 的使用视为“衍生作品”,您可能需要商业许可证。

编辑

output_gscommand.pdf 有这个:

1 0 obj
<</Type /Catalog /Pages 3 0 R
/OutputIntents [ 5 0 R ]
/Metadata 27 0 R
>>

5 0 obj
<</OutputConditionIdentifier(sRGB)
/DestOutputProfile  4 0 R 
/S/GTS_PDFA1
/Type/OutputIntent>>
endobj

所以这是 Catalog 中指定的 OutputIntent,唯一的 OutputIntent 具有 PDFA1 标识符、有效的 OutputConditionIdentifier(仅用于人类可读信息)和 ICC 配置文件。据我所知,这是完全有效的。

VeraPDF 和 Adob​​e Acrobat X (Pro) 中的印前检查工具都会验证 PDF 文件是否符合要求。所以我认为该文件是符合标准的 PDF/A 文件(Acrobat X 预检工具还将 OutputIntent 列为 sRGB(Custom) ICC OutputProfile: "Artifex Software sRGB ICC Profile")。

我不知道为什么 DC 没有显示 OutputIntent,我看不出文件有任何问题。

【讨论】:

非常感谢您的全面深入审查,我注意到您的答案中可能包含有关某些提示的其他信息,因此我更新了问题。我会尝试 UseIndependentColor 选项,但尝试包含 --permit-file-read 命令但没有成功(有问题更新)。我很抱歉 PDF/A 模板已经在某些测试用例中进行了修改,但我的问题中没有提到这一事实,所以我更新了它。如果您愿意,请再次查看以检查修改的行。 感谢您建议包含在生成的文件中,认为包含多个文件附件是不建议的。 Acrobat 捕获仅假装描述在一种情况下遗漏了 OutputIntent 而在另一种情况下不完整。正如您所说,由于 IIC 并未真正包括在内,因此似乎与此行为有关。关于一致性,PDF-tools 指出文件不符合标准。另一方面,VeraPDF 指出该文件是符合标准的,即使它不包含 ICC 配置文件,PDF 文件是否有可能在不包含 ICC 的情况下符合 PDF/A 格式? 写入管道被认为是 byte[] 生成 (***.com/questions/25240436/…) 的工作解决方案。是否有替代解决方案或最佳实践?我更新了你评论的代码行。关于 AGPL,我已经与 Artifex 取得联系,因为我们的项目仅针对内部企业,并且他们已经确认我们使用 DLL(或者即使您向客户提供和生成的文件)不需要商业许可,甚至发布你的源代码。我们将再次检查 GS.NET。感谢您的建议。 恐怕回复慢,这对我来说是兼职练习。感谢您澄清许可证,只是想确保您没有浪费时间或有一个令人讨厌的惊喜。拥有没有 OutputIntent 的有效 PDF/A 的唯一方法是将所有颜色都放在与设备无关的空间中(srgb、ICCBased、Lab,我可能错过了一些)。通常 pdfwrite 不会产生那些,除非你说 UseDeviceIndependentColor。 --permit-file-read 应该可以工作,它已经过测试,但是要使咒语正确可能会很棘手。是的,我猜 pdfa_def.ps 被修改了,很高兴听到它确实如此。 写入管道“通常”会起作用,直到有一天它不起作用。只有当 pdfwrite 设备需要回溯生成的 PDF 文件并更新一些数据时,它才会失败。 目前在生成线性化文件时就是这种情况,但将来无法保证。我不会依赖它。 Ghostscript.NET(与 Ghostscript 本身相反)可能通过写入文件然后将文件读回内存来处理此问题,我不知道,抱歉。如果是我,除非你确定 Ghostscript.NET 正在做什么,否则我会自己编写代码。

以上是关于如何使用 Ghostscript 和 Ghostscript .NET 通过嵌入 IIC 配置文件生成正确的 PDF/A的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Ghostscript 和 Ghostscript .NET 通过嵌入 IIC 配置文件生成正确的 PDF/A

Michael jackson歌曲Ghosts和Jam的歌词(要中文注解)

LC 789. Escape The Ghosts

LeetCode 789. Escape The Ghosts

[LeetCode] Escape The Ghosts 逃离鬼魂

LWC 73: 789. Escape The Ghosts