web-dev-qa-db-ja.com

既存の圧縮PDF C#プログラミングを使用してフリーウェアライブラリを使用

既存のpdf(サイズ)を圧縮する方法について、Googleで多くの検索を行っています。私の問題は

  1. C#プログラムで実行する必要があるため、どのアプリケーションも使用できません。

  2. 私のクライアントは予算を使いたくないので、私は有料ライブラリを使用できません。したがって、有料ライブラリは確かに[〜#〜] no [〜#〜]

私は過去2日間家事をしていて、iTextSharp、BitMiracleを使用した解決策に出会いましたが、前者はファイルの1%しか減らなかったので、それは有料です。

私はPDFcompressNETとpdftkにも出会いましたが、それらの.dllを見つけることができませんでした。

実際には、pdfは2〜3枚の画像(白黒)と約70ページのサイズで5 MBの保険証券です。

PDFのみの出力が必要です(他の形式にすることはできません)

19
Luv

これを行う方法を次に示します(これは、使用するツールキットに関係なく機能するはずです)。

24ビットRGBまたは32ビットcmykイメージがある場合は、次の手順を実行します。

  • 画像が実際に何であるかを確認します。 cmykの場合は、rgbに変換します。 rgbで本当に灰色の場合は、灰色に変換します。灰色またはパレット付きで、実際の色が2つしかない場合は、1ビットに変換します。グレーであり、グレーバリエーションが比較的少ない場合は、適切な2値化手法を使用して1ビットに変換することを検討してください。
  • ページへの配置方法に関連して画像の寸法を測定します。300dpi以上の場合は、画像のビット深度に応じて、画像をより小さなサイズにリサンプリングすることを検討してください。たとえば、おそらく300 dpiグレーまたはRGBから200 dpiに移行し、あまり詳細を失わないようにします。
  • 本当にカラーのrgbイメージがある場合は、パレット化することを検討してください。
  • 画像の内容を調べて、圧縮率を高めるのに役立つかどうかを確認します。たとえば、カラー/グレーの画像を実行し、クラスタリングする多くの色を細かくする場合は、それらをスムージングすることを検討してください。灰色または白黒で多数の斑点がある場合は、斑点除去を検討してください。
  • 最終的な圧縮を賢く選択してください。 JPEG2000はJPEGよりも優れています。 JBIG2はG4よりもはるかに優れています。 Flateは、おそらくグレーの非破壊圧縮に最適です。 JPEG2000とJBIG2のほとんどの実装は無料ではありません
  • あなたがロックスターなら、画像をセグメント化して、それを本当に白黒で本当に色のある領域に分割したいと思うでしょう。

そうは言っても、監視なしでこれをすべてうまくやることができれば、それ自体で商品ができあがります。

これのほとんどは Atalasoft dotImage (免責事項:無料ではありません。私はそこで作業します。ほぼすべてのPDFツールを作成しました。以前は作業していたと言えます)アクロバット)。

DotImageを使用する特定の方法の1つは、画像のみのページをすべて取り出し、それらを再圧縮して新しい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);

ここで欠けているのはProcessImage()です。 ProcessImageはページをラスタライズし(画像がPDFに合わせて拡大縮小されている可能性があることを理解する必要はありません)、画像を抽出し(そして画像の変換行列を追跡し)、上記の手順を実行します。これは簡単なことではありませんが、実行可能です。

14
plinth

私はあなたが言及したライブラリのいずれかが完全に無料ではないことをクライアントに知らせたいと思うかもしれません:

  • iTextSharpはAGPLライセンスであるため、ソリューションのソースコードをリリースする必要があるか、商用ライセンスを購入します。
  • PDFcompressNETは商用ライブラリです。
  • pdftkはGPLライセンスなので、ソリューションのソースコードをリリースする必要があるか、商用ライセンスを購入します。
  • Docotic.Pdfは商用ライブラリです。

上記のすべてを考えると、freeware要件をドロップできると思います。

Docotic.Pdfは、破壊的な変更を導入することなく 圧縮された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メソッドもあります。

ライブラリは、必要に応じてカラー画像を2値画像に変換します。 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メソッドの1つを使用して、指定された幅と高さにサイズ変更できます。 ResizeToメソッドは画像のアスペクト比を保持しようとしないことに注意してください。適切な幅と高さを自分で計算する必要があります。

免責事項:私はビットミラクルで働いています。

6
Bobrovsky

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);
    }
}
1
Simon

GhostScript は、PDFを圧縮できるAGPLライセンスソフトウェアです。 AGPLライセンスのC#ラッパーもgithubにあります こちら

そのラッパーからGhostscriptProcessorクラスを使用して、カスタムコマンドをGhostScriptに渡すことができます。たとえば、PDF圧縮について説明している このAskUbuntu回答 にあるようなコマンドです。

1
brismuth