什么是最小的有效PDF?

mes*_*shy 60 pdf optimization pdf-generation

出于简单的好奇心,看过最小的GIF,什么是最小的有效PDF文件?

pli*_*nth 78

这是一个有趣的问题.按照这本书的说法,你可以从这开始:

%PDF-1.0
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Type/Page/MediaBox[0 0 3 3]>>endobj
xref
0 4
0000000000 65535 f
0000000010 00000 n
0000000053 00000 n
0000000102 00000 n
trailer<</Size 4/Root 1 0 R>>
startxref
149
%EOF
Run Code Online (Sandbox Code Playgroud)

这是291字节的PDF欢乐.Acrobat打开它,但它有点抱怨.它有一页,它是3/72"方形,规格允许的最小值.

但是,Acrobat X甚至不再使用交叉引用表,所以我们可以把它拿出来:

%PDF-1.0
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Type/Page/MediaBox[0 0 3 3]>>endobj
trailer<</Size 4/Root 1 0 R>>
Run Code Online (Sandbox Code Playgroud)

Acrobat抱怨,但打开它.现在我们处于178字节.事实证明你在预告片中不需要/ Size.现在我们在172:

%PDF-1.0
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Type/Page/MediaBox[0 0 3 3]>>endobj
trailer<</Root 1 0 R>>
Run Code Online (Sandbox Code Playgroud)

事实证明,你不需要字典中所有那些讨厌的/类型元素:

%PDF-1.0
1 0 obj<</Pages 2 0 R>>endobj 2 0 obj<</Kids[3 0 R]/Count 1>>endobj 3 0 obj<</MediaBox[0 0 3 3]>>endobj
trailer<</Root 1 0 R>>
Run Code Online (Sandbox Code Playgroud)

现在我们是138字节.

事实证明,当规范说"应该是间接引用"并且需要/ Count,并且标题"必须"为%PDF-1.0时,它们会提出宽松的建议.这是我能做到的最小,并且可以在Acrobat X中打开它:

%PDF-1.
trailer<</Root<</Pages<</Kids[<</MediaBox[0 0 3 3]>>]>>>>>>
Run Code Online (Sandbox Code Playgroud)

70个字节.

现在,我的编辑器使用Windows换行规则,但Acrobat接受Windows,Mac或Unix约定,所以通过使用十六进制编辑器,我用\ r \n替换了\ r \n并完全删除了最后一个换行符,这留下了67个字节

25 50 44 46 2D 31 2E 0D 74 72 61 69 6C 65 72 3C 
3C 2F 52 6F 6F 74 3C 3C 2F 50 61 67 65 73 3C 3C 
2F 4B 69 64 73 5B 3C 3C 2F 4D 65 64 69 61 42 6F 
78 5B 30 20 30 20 33 20 33 5D 3E 3E 5D 3E 3E 3E 
3E 3E 3E 
Run Code Online (Sandbox Code Playgroud)

我尝试取消最后一个字典(>>),但Acrobat不会那样.内置于谷歌浏览器(FoxIt)的PDF阅读将无法打开它.

作为一个PostScript(HA!看看我在那里做了什么?),如果你同意Acrobat"修复"该文件,它会碰到高达3550字节,其中大部分是可选的元数据,但它留下了许多明显的规范违规.

  • 我需要一个 PDF 的 base64 表示。所以,如果有人有兴趣,这里是138的基于64位字节的字符串版本:`JVBERi0xLjAKMSAwIG9iajw8L1BhZ2VzIDIgMCBSPj5lbmRvYmogMiAwIG9iajw8L0tpZHNbMyAw \ nIFJdL0NvdW50IDE + PmVuZG9iaiAzIDAgb2JqPDwvTWVkaWFCb3hbMCAwIDMgM10 + PmVuZG9iagp0 \ ncmFpbGVyPDwvUm9vdCAxIDAgUj4 + CG ==` (15认同)
  • ...这里是 67 字节版本的 base64 字符串版本:`JVBERi0xLg10cmFpbGVyPDwvUm9vdDw8L1BhZ2VzPDwvS2lkc1s8PC9NZWRpYUJveFswIDAgMyAzXT4+XT4+Pj4+Pg==` (9认同)
  • *事实证明,当规范说"应该是间接参考"并且需要/ Count,并且标题"必须"是%PDF-1.0时,他们会提出宽松的建议.*不,这些都不是松散的建议,那些是有效性的要求.即使某些PD​​F查看器不强制执行它们,但不遵循它们意味着无效,并且OP要求提供有效的PDF. (5认同)
  • 接受,因为答案以"规格允许的最小值"开始,然后超越.很好的答案,谢谢!:) (5认同)
  • 这就是规格。PDF 中的对象图具有循环。 (2认同)

kol*_*pto 17

根据这里的所有答案,这是带有文本的最小 PDF:

SMALL_PDF = (
    b"%PDF-1.2 \n"
    b"9 0 obj\n<<\n>>\nstream\nBT/ 32 Tf(  YOUR TEXT HERE   )' ET\nendstream\nendobj\n"
    b"4 0 obj\n<<\n/Type /Page\n/Parent 5 0 R\n/Contents 9 0 R\n>>\nendobj\n"
    b"5 0 obj\n<<\n/Kids [4 0 R ]\n/Count 1\n/Type /Pages\n/MediaBox [ 0 0 250 50 ]\n>>\nendobj\n"
    b"3 0 obj\n<<\n/Pages 5 0 R\n/Type /Catalog\n>>\nendobj\n"
    b"trailer\n<<\n/Root 3 0 R\n>>\n"
    b"%%EOF"
)
Run Code Online (Sandbox Code Playgroud)

作为base64。复制此内容并在 Chrome 中测试:

数据:应用程序/pdf;base64,JVBERi0xLjIgCjkgMCBvYmoKPDwKPj4Kc3RyZWFtCkJULyAzMiBUZiggIFlPVVIgVEVYVCBIRVJFICAgKScgRVQKZW5kc3RyZWFtCmVuZG9iago0IDAgb2JqCjw8Ci9UeXBlIC9QYWdlCi9 QYXJlbnQgNSAwiFIKL0NvbnRlbnRzIDkgMCBSCj4+CmVuZG9iago1IDAgb2JqCjw8Ci9LaWRzIFs0IDAgUiBdCi9Db3VudCAxCi9UeXBlIC9QYWdlcwovTWVkaWFCb3ggWyAwIDAgMjUwiIDUwIF0KPj4KZW5kb 2JqCjMgMCBvYmoKPDwKL1BhZ2VzIDUgMCBSCi9UeXBlIC9DYXRhbG9nCj4+CmVuZG9iagp0cmFpbGVyCjw8Ci9Sb290IDMgMCBSCj4+CiUlRU9G

要使页面更大,请调整 MediaBox 尺寸:)

/媒体框 [ 0 0 250 50 ]

  • 当我尝试使用 PyPDF2 阅读此内容时:“PyPDF2.errors.PdfReadError:未找到 startxref” (2认同)

Ala*_*ell 11

我无法打开hello world示例.

对于包含文本内容的小型文件:

%PDF-1.2 
9 0 obj
<<
>>
stream
BT/ 9 Tf(Test)' ET
endstream
endobj
4 0 obj
<<
/Type /Page
/Parent 5 0 R
/Contents 9 0 R
>>
endobj
5 0 obj
<<
/Kids [4 0 R ]
/Count 1
/Type /Pages
/MediaBox [ 0 0 99 9 ]
>>
endobj
3 0 obj
<<
/Pages 5 0 R
/Type /Catalog
>>
endobj
trailer
<<
/Root 3 0 R
>>
%%EOF
Run Code Online (Sandbox Code Playgroud)

  • 此外,根据铬,数据打开:应用/ PDF; BASE64,JVBERi0xLjIgCjkgMCBvYmoKPDwKPj4Kc3RyZWFtCkJULyA5IFRmKFRlc3QpJyBFVAplbmRzdHJlYW0KZW5kb2JqCjQgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL1BhcmVudCA1IDAgUgovQ29udGVudHMgOSAwIFIKPj4KZW5kb2JqCjUgMCBvYmoKPDwKL0tpZHMgWzQgMCBSIF0KL0NvdW50IDEKL1R5cGUgL1BhZ2VzCi9NZWRpYUJveCBbIDAgMCA5OSA5IF0KPj4KZW5kb2JqCjMgMCBvYmoKPDwKL1BhZ2VzIDUgMCBSCi9UeXBlIC9DYXRhbG9nCj4 + CmVuZG9iagp0cmFpbGVyCjw8Ci9Sb290IDMgMCBSCj4 + CiUlRU9G (6认同)
  • 这不起作用,您需要定义一个字体资源并在页面内容中选择它以显示文本。 (2认同)
  • 该文件实际上是在 Mac OS X El Capitan 下打开的,而 PDF1.0 中评分最高的答案却没有。 (2认同)

Hug*_*len 7

我以为我会制作一个显示"Hello World"的最小pdf.文字位于左下角.对于9磅字体感到抱歉,任何更大的字体都会花费额外的字节:)

用于Adobe Reader X的172个字节(如果使用仅换行换行符保存,并且没有尾随换行符或空字节):

%PDF-1.
1 0 obj<</Kids[<</Parent 1 0 R/Resources<<>>/Contents 2 0 R>>]>>endobj 2 0 obj<<>>stream
BT/ 9 Tf(Hello World)' ET
endstream
endobj trailer<</Root<</Pages 1 0 R>>>>
Run Code Online (Sandbox Code Playgroud)

Chrome内置PDF查看器的120字节:

%PDF 1 0 obj<</Pages<</Kids[<</Contents<<>>stream
BT 9 Tf(Hello World)' ET endstream>>]>>>>endobj trailer<</Root 1 0 R>>
Run Code Online (Sandbox Code Playgroud)

要在Chrome中轻松看到此内容,请将此URI粘贴到地址栏中(因此我不会将其链接到该地址栏,并且在其他浏览器中根本无法使用):

data:application/pdf,%25PDF%201%200%20obj%3C%3C%2FPages%3C%3C%2FKids%5B%3C%3C%2FContents%3C%3C%3E%3Estream%0ABT%209%20Tf(Hello%20World)'%20ET%20endstream%3E%3E%5D%3E%3E%3E%3Eendobj%20trailer%3C%3C%2FRoot%201%200%20R%3E%3E
Run Code Online (Sandbox Code Playgroud)

  • 不会在我的Chrome下打开. (4认同)
  • 很小.;)根据规范,无效. (2认同)

K J*_*K J 7

我发现最近的 Acrobat(几乎没有其他读者)可以毫无怨言地接受最短的纯文本,因此“可读”和“可写”,因为 line.pdf 是毫无意义的 38 字节(接近 Pancakes 较短的 36 字节版本,使用 null )。

\n
%PDF-1.\ntrailer <</Root<</Pages<<>>>>>>\n
Run Code Online (Sandbox Code Playgroud)\n

为了被 chrome 接受,它需要更像 76 字节,但随后被 acrobat 等拒绝......

\n
%PDF-1.\n1 0 obj<</Pages<</Kids<<>>/Count 1>>>>endobj\ntrailer <</Root 1 0 R>>\n
Run Code Online (Sandbox Code Playgroud)\n

我将举一个我认为的最小有效“通用”PDF 的例子。直到我注意到使用 PDF 的整个精神是确保它在所有设备及其 PDF 阅读器上呈现完全相同。然而,在交叉检查我的“完美的小结构良好的 PDF”时,我发现了这一点。TL;DR 这已在我个人的最小文本模板中修复(在最后)

\n

在此输入图像描述

\n

所以基本规则是“尽可能小的有效 PDF”,但我认为这种短缺应该算作无效 PDF,因为它不符合“适合目的”的概念,因此最小 PDF 本身必须至少包含一个修复工作字体的方法。

\n

为了解释我提出的解决方案以及为什么它不够完美,由于剪切和粘贴,它的形式很粗糙。

\n
%PDF-1.0\n%\xc2\xb5\xc2\xb6\n\n1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n\n2 0 obj\n<</Kids[3 0 R]/Count 1/Type/Pages/MediaBox[0 0 595 792]>>\nendobj\n\n3 0 obj\n<</Type/Page/Parent 2 0 R/Contents 4 0 R/Resources<<>>>>\nendobj\n\n4 0 obj\n<</Length 58>>\nstream\nq\nBT\n/ 96 Tf\n1 0 0 1 36 684 Tm\n(Hello World!) Tj\nET\nQ\n\nendstream\nendobj\n\nxref\n0 5\n0000000000 65536 f \n0000000016 00000 n \n0000000062 00000 n \n0000000136 00000 n \n0000000209 00000 n \n\ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n316\n%%EOF\n
Run Code Online (Sandbox Code Playgroud)\n

虽然问题规则没有定义我已经包含了一些过去的用户问题经验。

\n

您可能注意到的第一个区别是第二个对象中的媒体框是混合体MediaBox[0 0 595 792],它是最小最大 A4 宽度和最小最大 US Letter 高度,否则大多数国家/地区的“通用页面”将强制以 100% 比例打印第二张纸对于语言环境默认值来说页面定义太宽或太高。

\n

当前的问题在第三个 obj 中得到了证实,因为没有为资源设置字体,因此目标是最小化PDF,我在没有定义字体的情况下进行竞争,将是无效的。

\n

因此,到目前为止,包括我自己的答案在内,似乎都没有生成一个 PDF,该 PDF 作为"WORK"“有效”意味着生成相同的打印输出,无论平台或查看器如何。

\n

转向库,我发现了一个 3MB 的 zip 文件,其中包含一个非常通用的 windows.exe(一个文件,可以执行大多数 pdf 功能,如拆分、合并、导入、邮票、导出附件等),它可以在命令行中输入“Hello World!”并生成一个良好的结果。工作文件,这是页面中心放大的\n在此输入图像描述

\n

它使用流来表示文本及其定位,并且具有其他符合数据(例如生成器)的数据,因此我将其作为潜在的良好最小化削减提供,请注意,由于从二进制到文本的流损坏,该文件将显示为空白。

\n
%PDF-1.7\n%\xc3\x82\xc2\xb5\xc3\x82\xc2\xb6\n\n1 0 obj\n<</Pages 2 0 R/Type/Catalog>>\nendobj\n\n2 0 obj\n<</Count 1/Kids[5 0 R]/MediaBox[0 0 595 792]/Type/Pages>>\nendobj\n\n3 0 obj\n<</BaseFont/Helvetica/Encoding/WinAnsiEncoding/Subtype/Type1/Type/Font>>\nendobj\n\n4 0 obj\n<</Filter/FlateDecode/Length 101>>\nstream\nx\xc5\x93*Tp\nQ\xc3\x90w3P04\xc3\x9230PISp\nQ01\n\xc3\xa0\xcb\x9ckdf\xc2\xa2ga\xc2\xac`bh\xc3\xa2%\xc3\xa7\xe2\x80\x9a\xc3\xb4(\xe2\x80\x9e\xe2\x80\x9d#\xc2\xa9A\xc3\xae\xc3\xa8"E\xc3\xa9\xc3\x9alA\nHW\xe2\x80\x98\xe2\x80\x9a\xe2\x80\xa0GjNN\xc2\xbeBx~QN\xc5\xa0\xc2\xa2\xc2\xa6BH\xc3\x88\xc3\x9e@@   \xc3\xbf\xc3\xbfF\xc3\xa5\nendstream\nendobj\n\n5 0 obj\n<</Contents 4 0 R/CropBox[0 0 595 792]/MediaBox[0 0 595 792]/Parent 2 0 R/Resources<</Font<</F0 3 0 R>>>>/Type/Page>>\nendobj\n\n6 0 obj\n<</CreationDate(D:20220600600709+01\'00\')/ModDate(D:20220600600709+01\'00\')/Producer(me 2)>>\nendobj\n\nxref\n0 7\n0000000000 65536 f \n0000000016 00000 n \n0000000062 00000 n \n0000000136 00000 n \n0000000225 00000 n \n0000000395 00000 n \n0000000529 00000 n \n\ntrailer\n<</Size 7/Info 6 0 R/Root 1 0 R/ID[<A2A0CE5CCD9D0DABD5845AD574BF0A5C><09BF9D281BE12CB5B5933BB2B62B0D4D>]>>\nstartxref\n636\n%%EOF\n
Run Code Online (Sandbox Code Playgroud)\n

PS我故意添加了一个无效的项目,所以故意不是最低的工作答案,看看你是否能找出明显错误的地方:-)

\n

我的个人产品\n因此,我经常被问到如何编写纯文本模板 PDF,因此需要静态字体(Helvetica 或 Courier 应该这样做)以及易于使用 Windows CMD 行修改的结构,所以这适合我现在的目的如图所示,698 字节,带有两个占位符以显示多行,因此如果需要,可以查找并替换HelveticaCourier (注意后面故意留有 2 个空格以保持字节数)

\n
%PDF-1.1\n%\xc3\xa2\xc3\xa3\n1 0 obj\n<</Type/Catalog/Pages<</Type/Pages/Count 1/Kids[2 0 R]>>>>\nendobj\n2 0 obj\n<</Type/Page/Parent 1 0 R/MediaBox[0 0 594 792]/Resources<</Font<</F1 3 0 R>>/ProcSet[/PDF/Text]>>/Contents 4 0 R>>\nendobj\n3 0 obj\n<</Type/Font/Subtype/Type1/Name/F1/BaseFont/Helvetica>>\nendobj\n4 0 obj\n<</Length 5 0 R>>\nstream\nBT\n/F1 36 Tf\n1 0 0 1 255 752 Tm\n48 TL\n( Hello)\'\n(World!)\'\nET\nendstream\nendobj\n5 0 obj\n78\nendobj\nxref\n0 6\n0000000000 65536 f\n0000000017 00000 n\n0000000094 00000 n\n0000000228 00000 n\n0000000302 00000 n\n0000000425 00000 n\ntrailer\n<</Size 6/Info <</CreationDate(D:2023)/Producer(cmd2pdf)/Title(mini.pdf)>>/Root 1 0 R>>\nstartxref\n446\n%%EOF\n
Run Code Online (Sandbox Code Playgroud)\n

要了解此方法在 Windows 命令行中的工作原理,请右键单击并下载为文本https://github.com/GitHubRulesOK/MyNotes/raw/master/MAKE-PDF.cmd(现在有 200 行长!)注意浏览器安全可能会询问您要信任 cmd 作为下载,请使用 .txt 扩展名,一旦您满意,运行它应该不会有什么害处,您仍然需要将属性更改为 UNBLOCK!

\n

@mkl 你准备好拍出最好的照片了吗?

\n