首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用免费软件库使用C#编程压缩现有PDF

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

Stack Overflow用户
提问于 2012-12-05 09:05:35
回答 4查看 41.2K关注 0票数 25

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

  1. 我不能使用任何应用程序,因为它需要通过C#程序来完成。
  2. 我不能使用任何付费图书馆,因为我的客户不想退出预算。因此,付费库当然是一个NO

我在家工作了两天,想出了一个使用iTextSharp,BitMiracle的解决方案,但是没有用,因为前者只减少了一个文件的1%,而后来的一个是付费的。

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

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

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-12-07 16:21:27

这里有一种方法可以做到这一点(这应该可以不考虑您使用的工具包):

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

  • 确定图像是否真的是真实的。如果是cmyk,则转换为rgb。如果它是rgb和真正的灰色,转换为灰色。如果它是灰色或苍白的,只有两个真实的颜色,转换为1位.如果它是灰色的,并且灰色变化的方式相对较少,请考虑使用适当的二值化技术将其转换为1位。
  • 测量图像尺寸与其在页面上的放置方式有关--如果图像为300 dpi或更高,考虑根据图像的位深将图像重采样到更小的大小--例如,您可能会从300 dpi灰色或rgb降到200 dpi,而不会丢失太多细节。
  • 如果您有一个rgb图像是真正的颜色,考虑姑息它。
  • 检查图像的内容,看看是否可以帮助使其更可压缩。例如,如果您浏览了一幅彩色/灰色图像,并细化了许多聚在一起的颜色,请考虑将它们平滑。如果它是灰色或黑色和白色,并包含一些斑点,考虑鄙视。
  • 明智地选择最后的压缩。JPEG2000可以比JPEG做得更好。JBIG2比G4做得好得多。平底可能是最好的无损压缩灰色。JPEG2000和JBIG2的大多数实现都不是免费的。
  • 如果你是一个摇滚明星,你想要分割图像,并把它分割成真正的黑白和真正的颜色。

也就是说,如果你能在没有监督的情况下做好所有这一切,你就有了自己的商业产品。

我要说,您可以使用Atalasoft dotImage完成大部分工作(免责声明:它不是免费的;我在那里工作;我编写了几乎所有的PDF工具;我以前在Acrobat上工作)。

使用dotImage的一种特殊方法是提取所有仅为图像的页面,重新压缩它们并将它们保存到一个新的PDF中,然后通过从原始文档中提取所有页面并将它们替换为重新压缩的页面来构建一个新的PDF,然后再次保存。没那么难。

代码语言:javascript
复制
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);

这里缺少的是ProcessImage()。ProcessImage将对页面进行栅格化(您不需要理解图像可能已经缩放到PDF上)或提取图像(并跟踪图像上的转换矩阵),并完成上面列出的步骤。这不是小事,但它是可行的。

票数 16
EN

Stack Overflow用户

发布于 2012-12-07 05:30:41

我认为您可能希望让您的客户意识到,您提到的任何库都不是完全免费的:

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

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

Docotic.Pdf可以在不同程度上缩小压缩和未压缩PDF的大小而不引入任何破坏性的更改。

增益取决于PDF的大小和结构:对于大多数是扫描图像的小文件或文件,减少可能不是很大,所以您应该尝试使用文件库并亲自查看。

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

下面是将所有图像进行两层压缩并使用传真压缩压缩的代码:

代码语言:javascript
复制
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方法。

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

Docotic.Pdf还可以在PDF中调整大图像的大小(同时对它们进行重新压缩)。如果文档中的图像实际上更大,那么就需要这样做,或者如果图像的质量不是那么重要的话,这可能是有用的。

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

代码语言:javascript
复制
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方法不会尝试保留图像的高宽比。你应该自己算出合适的宽度和高度。

免责声明:我为比特奇迹工作。

票数 7
EN

Stack Overflow用户

发布于 2019-08-07 02:58:07

使用PdfSharp

代码语言:javascript
复制
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);
    }
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13719553

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档