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

Luv*_*Luv 19 c# pdf pdf-generation

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

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

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

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

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

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

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

pli*_*nth 14

这是一种方法(这应该工作而不考虑您使用的工具包):

如果您有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<int> pagesToReplace = new List<int>();
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);
Run Code Online (Sandbox Code Playgroud)

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

  • 伟大的答案,"如果你是一个摇滚明星"让我大声笑 (2认同)

Bob*_*sky 6

我想你可能想让你的客户知道你提到的任何库都不是完全免费的:

  • 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

还有RecompressWithFlate,RecompressWithGroup3FaxRecompressWithJpeg方法.

如果需要,库将把彩色图像转换为双层图像.您可以指定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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 使用 JPEG 缩放/重新压缩并更改 jpeg 质量时要格外小心。我认识一位程序员,他被分配了这项任务,负责归档法律文件,结果是许多法庭案件不得不放弃,因为文件的唯一副本现在无法阅读。 (3认同)

Sim*_*mon 6

使用PdfSharp

public static void CompressPdf(string targetPath)
{
    using (var stream = new MemoryStream(File.ReadAllBytes(targetPath)) {Position = 0})
    using (var source = PdfReader.Open(stream, PdfDocumentOpenMode.Import))
    using (var document = new PdfDocument())
    {
        var options = document.Options;
        options.FlateEncodeMode = PdfFlateEncodeMode.BestCompression;
        options.UseFlateDecoderForJpegImages = PdfUseFlateDecoderForJpegImages.Automatic;
        options.CompressContentStreams = true;
        options.NoCompression = false;
        foreach (var page in source.Pages)
        {
            document.AddPage(page);
        }

        document.Save(targetPath);
    }
}
Run Code Online (Sandbox Code Playgroud)