使用免费软件库使用C#编程压缩现有PDF

我一直在谷歌上搜索如何压缩现有的pdf (大小)。 我的问题是

  1. 我不能使用任何应用程序,因为它需要由C#程序完成。

  2. 我不能使用任何付费图书馆,因为我的客户不想退出预算。 因此PAID库肯定是NO

我做了最近2天的家庭工作,并使用iTextSharp,BitMiracle找到了一个解决方案,但没有用,因为前者只减少了1%的文件,后来一个是付费的。

我也遇到了PDFcompressNET和pdftk,但我找不到他们的.dll。

实际上,pdf是保险单,有2-3张图片(黑白),大约70页,大小为5 MB。

我只需要pdf的输出(不能是任何其他格式)

这是一种执行此操作的方法(这应该在不考虑您使用的工具包的情况下工作):

如果您有24位rgb或32位cmyk映像,请执行以下操作:

  • 确定图像是否真的如此。 如果是cmyk,请转换为rgb。 如果它是rgb并且真的是灰色的,则转换为灰色。 如果它是灰色或调色板并且只有2种真实颜色,则转换为1位。 如果它是灰色的并且灰度变化的方式相对较少,请考虑使用合适的二值化技术转换为1位。
  • 测量与页面放置方式相关的图像尺寸 – 如果图像尺寸为300 dpi或更高,请考虑根据图像的位深度将图像重新采样为较小的尺寸 – 例如,您可以从300 dpi开始灰色或rgb到200 dpi并且不会丢失太多细节。
  • 如果你有一个真正颜色的rgb图像,请考虑将其调色。
  • 检查图像的内容,看看是否可以帮助使其更具可压缩性。 例如,如果您运行彩色/灰色图像并对要聚集的许多颜色进行细化,请考虑对其进行平滑处理。 如果它是灰色或黑白并且包含许多斑点,请考虑去斑点。
  • 明智地选择你的最终压缩。 JPEG2000可以比JPEG做得更好。 JBIG2比G4好得多。 Flate可能是灰色的最佳非破坏性压缩。 JPEG2000和JBIG2的大多数实现都不是免费的。
  • 如果你是一个摇滚明星,你想要尝试将图像分割并将其分解为非常黑白和真正颜色的区域。

也就是说,如果你能以无人监督的方式做到这一切,那么你就拥有了自己的商业产品。

我会说你可以用Atalasoft dotImage完成大部分工作(免责声明:它不是免费的;我在那里工作;我写过几乎所有的PDF工具;我曾经在Acrobat上工作)。

使用dotImage的一个特殊方法是拉出所有只有图像的页面,重新压缩它们并将它们保存到新的PDF然后通过从原始文档中取出所有页面并将它们替换为重新压缩的页面来构建新的PDF,然后再次储蓄。 这并不难。

 List pagesToReplace = new List(); PdfImageCollection pagesToEncode = new PdfImageCollection(); using (Document doc = new Document(sourceStream, password)) { for (int i=0; i < doc.Pages.Count; i++) { Page page = doc.Pages[i]; if (page.SingleImageOnly) { pagesToReplace.Add(i); // a PDF image encapsulates an image an compression parameters PdfImage image = ProcessImage(sourceStream, doc, page, i); pagesToEncode.Add(i); } } PdfEncoder encoder = new PdfEncoder(); encoder.Save(tempOutStream, pagesToEncode, null); // re-encoded pages tempOutStream.Seek(0, SeekOrigin.Begin); sourceStream.Seek(0, SeekOrigin.Begin); PdfDocument finalDoc = new PdfDocument(sourceStream, password); PdfDocument replacementPages = new PdfDocument(tempOutStream); for (int i=0; i < pagesToReplace.Count; i++) { finalDoc.Pages[pagesToReplace[i]] = replacementPages.Pages[i]; } finalDoc.Save(finalOutputStream); 

这里缺少的是ProcessImage()。 ProcessImage将栅格化页面(您无需了解图像可能已缩放到PDF上)或提取图像(并跟踪图像上的变换矩阵),并完成上面列出的步骤。 这是非平凡的,但它是可行的。

我想您可能想让您的客户意识到您提到的任何库都不是完全免费的:

  • iTextSharp是AGPL许可的,因此您必须发布解决方案的源代码或购买商业许可证。
  • PDFcompressNET是一个商业图书馆。
  • pdftk是GPL许可的,因此您必须发布解决方案的源代码或购买商业许可证。
  • Docotic.Pdf是一个商业图书馆。

鉴于以上所有,我认为我可以放弃免费软件要求。

Docotic.Pdf可以在不引入任何破坏性更改的情况下将压缩和未压缩PDF的大小减小到不同程度。

增益取决于PDF的大小和结构:对于大多数扫描图像的小文件或文件,缩小可能不是那么好,因此您应该尝试使用文件库并亲自查看。

如果您最关心大小并且文件中有许多图像, 并且您可以放弃这些图像的某些质量,那么您可以使用Docotic.Pdf轻松地重新压缩现有图像。

以下代码使所有图像通过传真压缩进行双层和压缩:

 static void RecompressExistingImages(string fileName, string outputName) { using (PdfDocument doc = new PdfDocument(fileName)) { foreach (PdfImage image in doc.Images) image.RecompressWithGroup4Fax(); doc.Save(outputName); } } 

还有RecompressWithFlateRecompressWithGroup3FaxRecompressWithJpeg方法。

如果需要,库将把彩色图像转换为双层图像。 您可以指定deflate压缩级别,JPEG质量等。

Docotic.Pdf还可以在PDF中调整大图像(并同时重新压缩)。 如果文档中的图像实际上比需要的更大或者图像质量不那么重要,这可能很有用。

下面是一个代码,可以对所有宽度或高度大于或等于256的图像进行缩放。然后使用JPEG压缩对缩放后的图像进行编码。

 public static void RecompressToJpeg(string path, string outputPath) { using (PdfDocument doc = new PdfDocument(path)) { foreach (PdfImage image in doc.Images) { // image that is used as mask or image with attached mask are // not good candidates for recompression if (!image.IsMask && image.Mask == null && (image.Width >= 256 || image.Height >= 256)) image.Scale(0.5, PdfImageCompression.Jpeg, 65); } doc.Save(outputPath); } } 

可以使用ResizeTo方法之一将图像调整为指定的宽度和高度。 请注意, ResizeTo方法不会尝试保留图像的宽高比。 你应该自己计算适当的宽度和高度。

免责声明:我为Bit Miracle工作。

GhostScript是AGPL许可软件,可以压缩PDF。 在github上还有一个AGPL许可的C#包装器。

您可以使用该包装器中的GhostscriptProcessor类将自定义命令传递给GhostScript,就像在这个描述PDF压缩的AskUbuntu答案中找到的那样。