iTextSharp 是否处理 PDF 压缩?

Does iTextSharp Handle PDF Compression?

iTextSharp 可以压缩 PDF 文件吗?我正在寻找可在开发中用于压缩 PDF 文件的 PDF 库。本质上,我有一个文件夹列表,其中包含许多大小从 1MB 到 10MB 不等的 PDF 文件,并且这些文件夹的数量每天都在增加,所以为了节省磁盘 space 我希望能够读入处理后的PDF文件,压缩,然后保存到指定的文件夹位置。

如果 iTextSharp 不支持压缩,有人对其他可以支持的 .NET PDF 库有建议吗?购买图书馆不会有问题。我看了很多免费的,比如 PDFSharp,我认为它在制作 PDF 方面非常好,但不能渲染或压缩它们。

我在 Chris Haas 的 Whosebug 上读到了一个很好的答案:

PdfStamper is a helper class that ultimately uses another class called PdfStamperImp to do most of the work. PdfStamperImp is derived from PdfWriter and when you use stamper.Writer you are actually getting back this implementation class. Many of the properties on PdfStamper also pass directly through to the implementation class. So these two calls actually do the same thing.

stamper.SetFullCompression();
stamper.Writer.SetFullCompression();

Another point of confusion is that SetFullCompression and the CompressionLevel aren't actually related at all. "Full compression" represents a feature that was added in PDF 1.5 called "Object Streams" that allows grouping PDF objects together to potentially allow for greater compression. There's actually no requirement that what we think of as "compression" actually occurs but in reality I think it would always happen. (Possibly a super simple document might get larger with this enabled, not sure and don't feel like testing.)

The CompressionLevel is actually what you normally think of as compression, a number from 0 to 9 or -1 to mean default (which currently equals six I think). This property is actually part of the PdfStream class which many classes ultimately derive from. This setting doesn't "trickle down", however. Since you are importing a stream from another location via GetPageContent() and SetPageContent() that specific stream has its own compression settings unrelated to the Writer's compression settings. There's actually a third parameter that you can pass to SetPageContent() to set your specific compression level if you want.

reader.SetPageContent(1, reader.GetPageContent(1), PdfStream.BEST_COMPRESSION);

如有任何帮助或建议,我们将不胜感激。

谢谢。

是的,iText 和 iTextSharp 支持压缩。

  • 从 PDF 1.0 (1993) 到 PDF 1.1 (1994),存储在内容流中的 PDF 语法没有被压缩。
  • 从 PDF 1.2 (1996) 开始,可以压缩存储在内容流中的 PDF 语法。标准过滤器是 /FlateDecode。该算法类似于 ZIP 算法,您可以设置不同的压缩级别(从 0 到 9;其中选择 -1 将使用您的编程语言认为是默认值的任何内容)。
  • 从 PDF 1.5 (2003) 开始,间接对象可以存储在压缩对象流中。此外,交叉引用 table 可以压缩并存储在流中。在 PDF 1.5 之前,这是不可能的(仅支持 PDF 1.4 及更早版本的查看器无法打开 "fully compressed" 个 PDF)。

iText 支持以上所有内容,Chris 的回答已经完全回答了您的问题。由于 PDF 1.1 可以追溯到很久以前(1994 年),我不会担心更改内容流的压缩级别,因此您可以安全地忘记:

reader.SetPageContent(1, reader.GetPageContent(1), PdfStream.BEST_COMPRESSION);

使用这一行不会减少文件大小。

使用 "full compression"(这将导致交叉引用 table 被压缩)应该会影响具有许多间接对象的 PDF 的文件大小。当您使用 "full compression".

时,最小 "Hello World" 文件的文件大小可能会增加

以上所有内容对您帮助不大,因为优秀的 PDF 创建者已经压缩了可以压缩的内容。然而,糟糕的 PDF 创建者(或错误使用好的 PDF 创建者的人)可能包含多余的对象。例如:有些人不知道如何使用 iTextSharp 将徽标作为图像添加到 PDF 的每个页面。由于他们的无知,他们添加图像的次数与页数一样多。在这种情况下,PDF 压缩对您没有帮助,但是如果您通过 iTextSharp 的 PdfSmartCopy 传递这样的 "bad" PDF,那么 PdfSmartCopy 将检测冗余对象并重新组织文件,以便对象在文件中一遍又一遍地重复(例如:每个页面都引用具有相同图像字节的不同对象),被重用(例如:每个页面都引用具有图像字节的相同对象)。

根据您使用的 iTextSharp 版本,reader.RemoveUnusedObjects(); 也可以帮助您(最新版本默认删除未使用的对象)。

ITextSharp 允许您浏览 PDF 页面并编辑其中的对象(以及许多其他功能)。流对象(主要是图像)的压缩可以帮助您减小 PDF 的整体大小。

我对 PDF 文件(主要是其中的图像)的压缩进行了足够深入的研究,并完成了轻量级库,它可以用作您特定压缩案例的父级。

https://github.com/rock-walker/PdfCompression