什么是最小的有效PDF?

时间:2013-06-24 15:52:06

标签: pdf optimization pdf-generation

出于简单的好奇心,看过the smallest GIF,可能的最小PDF文件是什么?

6 个答案:

答案 0 :(得分:76)

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

%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

这是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>>

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>>

原来你不需要字典中所有那些讨厌的/类型元素:

%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>>

现在我们只有138个字节。

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

%PDF-1.
trailer<</Root<</Pages<</Kids[<</MediaBox[0 0 3 3]>>]>>>>>>

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 

我尝试取消最后一个字典(&gt;&gt;),但Acrobat没有。内置于谷歌浏览器(FoxIt)的PDF阅读将无法打开它。

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

答案 1 :(得分:9)

我以为我会制作一个最小的pdf来显示&#34; Hello World&#34;。文字位于左下角。对于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>>>>

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

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

要在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

答案 2 :(得分:6)

我无法打开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

答案 3 :(得分:4)

根据这里的所有答案,这里是最小的带文本的 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"
)

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

<块引用>

数据:应用/ PDF; BASE64,JVBERi0xLjIgCjkgMCBvYmoKPDwKPj4Kc3RyZWFtCkJULyAzMiBUZiggIFlPVVIgVEVYVCBIRVJFICAgKScgRVQKZW5kc3RyZWFtCmVuZG9iago0IDAgb2JqCjw8Ci9UeXBlIC9QYWdlCi9QYXJlbnQgNSAwIFIKL0NvbnRlbnRzIDkgMCBSCj4 + CmVuZG9iago1IDAgb2JqCjw8Ci9LaWRzIFs0IDAgUiBdCi9Db3VudCAxCi9UeXBlIC9QYWdlcwovTWVkaWFCb3ggWyAwIDAgMjUwIDUwIF0KPj4KZW5kb2JqCjMgMCBvYmoKPDwKL1BhZ2VzIDUgMCBSCi9UeXBlIC9DYXRhbG9nCj4 + CmVuZG9iagp0cmFpbGVyCjw8Ci9Sb290IDMgMCBSCj4 + CiUlRU9G

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

<块引用>

/MediaBox [ 0 0 250 50 ]

答案 4 :(得分:2)

根据此Ange Albertini lecture,最小可能的有效 PDF 为 36 字节:

%PDF-(NULL)trailer<>>>>>

其中 (NULL) 是不可打印的 ASCII 0 字符。

然而,正如 Ange 所指出的,虽然此 PDF 在技术上是有效的,但大多数 PDF 阅读器应用程序仅根据大小将其视为无效,因此无法打开它。

答案 5 :(得分:0)

在Java中,使用此:

 private static String samplepdf = "255044462D312E0D747261696C65723C3C2F526F6F743C3C2F50616765733C3C2F4B6964735B3C3C2F4D65646961426F785B302030203320335D3E3E5D3E3E3E3E3E3E";

然后

byte[] bytes = hexStringToByteArray(samplepdf);

...

public byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                + Character.digit(s.charAt(i + 1), 16));
    }
    return data;
}