24

pdf私は既存の(サイズ)を圧縮する方法についてグーグルでたくさん探してきました。私の問題は

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

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

私は過去2日間宿題をし、iTextSharp、BitMiracleを使用して解決策を見つけましたが、前者はファイルの1%しか減少せず、後者は有料であるため、役に立ちませんでした。

PDFcompressNETとpdftkにも出くわしましたが、.dllが見つかりませんでした。

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

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

4

4 に答える 4

15

これを行うためのアプローチは次のとおりです(これは、使用するツールキットに関係なく機能するはずです)。

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

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

とは言うものの、教師なしの方法でこれらすべてをうまく行うことができれば、それ自体が商用製品になります。

このほとんどはAtalasoftdotImageで実行できます(免責事項:無料ではありません。そこで作業しています。ほぼすべてのPDFツールを作成しました。以前はAcrobatで作業していました)。

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上に拡大縮小されている可能性があることを理解する必要はありません)、画像を抽出し(そして、画像上の変換行列を追跡し)、上記の手順を実行します。これは自明ではありませんが、実行可能です。

于 2012-12-07T16:21:27.027 に答える
7

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

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

上記のすべてを考えると、私はフリーウェアの要件を削除できると思います。

Docotic.Pdfは、破壊的な変更を加えることなく、圧縮および非圧縮のPDFのサイズをさまざまな程度に縮小できます。

ゲインはPDFのサイズと構造によって異なります。小さなファイルやほとんどがスキャンされた画像であるファイルの場合、削減はそれほど大きくない可能性があるため、ファイルを使用してライブラリを試してみてください。

サイズが最も気になり、ファイル多くの画像があり、それらの画像の品質の一部を失うことに問題がない場合は、Docotic.Pdfを使用して既存の画像を簡単に再圧縮できます。

すべての画像を2レベルにし、FAX圧縮で圧縮するコードは次のとおりです。

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

        doc.Save(outputName);
    }
}

RecompressWithFlate、、メソッドもRecompressWithGroup3FaxありRecompressWithJpegます。

ライブラリは、必要に応じてカラー画像を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);
    }
}

いずれかの方法を使用して、画像を指定した幅と高さにサイズ変更できますResizeToResizeToこの方法では、画像のアスペクト比を維持しようとはしませんのでご注意ください。適切な幅と高さは自分で計算する必要があります。

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

于 2012-12-07T05:30:41.750 に答える
3

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

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

于 2015-10-12T02:55:45.853 に答える
2

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);
    }
}
于 2019-08-07T02:58:07.803 に答える