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

使用免费软件库使用C#编程压缩现有PDF,c#,pdf,pdf-generation,C#,Pdf,Pdf Generation,我在谷歌上搜索了很多关于如何压缩现有的pdf(大小)。 我的问题是 我不能使用任何应用程序,因为它需要由C#程序完成 我不能使用任何付费图书馆,因为我的客户不想超出预算。因此,付费图书馆肯定是一种否定 在过去的两天里,我做了我的家庭作业,并使用iTextSharp、BitMiracle找到了一个解决方案,但没有用,因为前者只减少了文件的1%,而后来的一个是付费的 我也遇到了PDFcompressNET和pdftk,但我找不到它们的.dll 实际上,pdf是保险单,有2-3张图片(黑白),大约70

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

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

  • 我不能使用任何付费图书馆,因为我的客户不想超出预算。因此,付费图书馆肯定是一种否定

  • 在过去的两天里,我做了我的家庭作业,并使用iTextSharp、BitMiracle找到了一个解决方案,但没有用,因为前者只减少了文件的1%,而后来的一个是付费的

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

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


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

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

    • iTextSharp是AGPL许可的,所以您必须发布解决方案的源代码或购买商业许可
    • PDFcompressNET是一个商业图书馆
    • pdftk是GPL许可的,所以您必须发布解决方案的源代码或购买商业许可证
    • 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);
        }
    }
    
    还有
    用flate重新压缩
    用group3fax重新压缩
    用jpeg重新压缩
    方法

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

    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工作。

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

    如果您有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的大多数实现都不是免费的
    • 如果你是一个摇滚明星,你想尝试分割图像,并将其分割成真正的黑白和彩色区域
    这就是说,如果你能在无监督的情况下做好所有这些,你就有了一个商业产品

    我要说的是,你可以用(免责声明:这不是免费的;我在那里工作;我写了几乎所有的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);
    
    List pagesToReplace=new List();
    PdfImageCollection pagesToEncode=新的PdfImageCollection();
    使用(文档文档=新文档(源流,密码)){
    对于(int i=0;ipublic 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);
        }
    }