OptimizePDF.cs
// 
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// © MESCIUS inc. All rights reserved.
// 
using System;
using System.IO;
using System.IO.Compression;
using System.Drawing;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Common;

namespace DsPdfWeb.Demos
{
    // GcPdfDocument.Optimize() メソッドを使用して、
    // PDF のサイズを削減する方法を示します。
    // 最適化手法の詳細については、OptimizeDocumentOptions クラスを参照してください。
    //
    // このサンプルでは、 最初に最適化を行っていない PDF の先頭 5 ページを
    // 新しいドキュメントに結合し、そのサイズを記録します。
    // 次に、その PDF に対して Optimize() を実行して最適化を行い、
    // 再度 PDF のサイズを記録します。
    // 最後に、最適化前と最適化後のPDFサイズを、
    // このサンプルが生成する PDF 内に出力します。

    // 「埋め込みフォントの削除」は、環境によってはドキュメントが正しく
    // 表示されなくなる可能性があるため、
    // RemoveEmbeddedFonts = false に設定して無効化しています。
    //
    // 最適化に関しては、 OptimizeFontsRemoveDuplicateImagesも併せてご覧ください。
    public class OptimizePDF
    {
        public int CreatePDF(Stream stream)
        {
            // 最適化をしていないPDFを読み込みます。
            var srcFn = Path.Combine("Resources", "PDFs", "CompleteJavaScriptBook.pdf");
            // テスト用に、上記のPDFの最初の5ページだけを使ったPDFを作成します。
            var tmpInput = MakeInputFile(srcFn);
            var fiInput = new FileInfo(tmpInput);

            // 最適化用に、さらに新しいPDFを作成し、上記PDFを読み込みます。
            // このPDFに対して最適化を実行します。
            var tmpOutput = Path.GetTempFileName();
            var tmpDoc = new GcPdfDocument();
            using (var fs = File.OpenRead(tmpInput))
            {
                tmpDoc.Load(fs);
                var odo = new OptimizeDocumentOptions();

                // ファイルサイズが一番小さくなるよう、全ての処理を実行します。
                odo.SetForMinimumSize();

                // 埋め込みフォントは削除しないよう設定します。
                odo.RemoveEmbeddedFonts = false;
                tmpDoc.Optimize(tmpOutput, odo);
            }
            var fiOutput = new FileInfo(tmpOutput);

            // 結果のPDFに入力ファイルと出力ファイルのサイズを記録しています。
            var doc = new GcPdfDocument();
            Common.Util.AddNote(String.Format(
                "GcPdfDocument.Optimize() メソッドを使用することで、PDFサイズを {0:N0}バイト から {1:N0}バイト に削減できました。" +
                "これは、SetForMinimumSizeメソッドを利用して、複数の最適化手法を適用したためです。\n" +
                "同じ結果をローカル環境で再現したい場合は、このサンプルをダウンロードして実行してください。" +
                "ローカル環境では最適化前と最適化後の両PDFファイルを、エクスプローラなどで比較できます。"
                , fiInput.Length, fiOutput.Length),
                doc.NewPage());
            doc.Save(stream);

            // クリーンアップ処理を行います。
            // (デバッグしたい場合は、一時ファイルを削除せず、拡張子を .pdf に変更することで中身を確認できます。
            // 以下の ChangeExtension を使った 2 行を有効にし、クリーンアップを無効にしてください。)
            // File.Move(tmpInput, Path.ChangeExtension(tmpInput, ".pdf"), true);
            // File.Move(tmpOutput, Path.ChangeExtension(tmpOutput, ".pdf"), true);
            File.Delete(tmpInput);
            File.Delete(tmpOutput);

            return doc.Pages.Count;
        }

        static string MakeInputFile(string inFn)
        {
            var indoc = new GcPdfDocument();
            using var fs = File.OpenRead(inFn);
            indoc.Load(fs);

            // 読み込んだPDFの最初の5ページを、新しいPDFに追加します。
            var pageCount = 5;
            var docs = new List<GcPdfDocument>(pageCount);
            for (int i = 0; i < pageCount; ++i)
            {
                var outdoc = new GcPdfDocument();
                outdoc.MergeWithDocument(indoc, new MergeDocumentOptions() { PagesRange = new OutputRange(i + 1, i + 1) });
                docs.Add(outdoc);
            }

            var doc = new GcPdfDocument();
            foreach (var d in docs)
                doc.MergeWithDocument(d);

            // 新しく作成したPDFを一時ファイルに保存して、そのファイル名を返します。
            var outFn = Path.GetTempFileName();
            doc.Save(outFn);
            return outFn;
        }
    }
}