RemoveDuplicateImages.cs
//
// This code is part of Document Solutions for PDF demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Pdf.Annotations;
using System.Collections.Generic;

namespace DsPdfWeb.Demos
{
    // When merging PDFs that contain identical images, by default the resulting PDF
    // will end up containing several copies of the same image.
    // To ensure that the PDF is not larger than necessary, DsPdf provides the method
    // GcPdfDocument.RemoveDuplicateImages() that scans the PDF, finds and removes duplicates.
    // The MergeDocumentOptions class also has the property RemoveDuplicateImages,
    // which allows you to scan for/remove duplicates at once when merging PDFs,
    // but by default it is false. This is because the occurrence of duplicate images
    // in merged PDFs is not a very common scenario, while scanning for duplicates
    // may affect the performance of the merge. Also, if you are merging multiple PDFs
    // that contain duplicate images, it is better to merge all PDFs first, and then
    // remove all duplicates from the final PDF at once with a single call to
    // GcPdfDocument.RemoveDuplicateImages(), as demonstrated by this demo.
    //
    // In this demo we merge several sample invoices that include the same company logo,
    // and then call GcPdfDocument.RemoveDuplicateImages() and compare the sizes of the
    // resulting PDF before and after that call.
    // 
    // See also OptimizeFonts.
    public class RemoveDuplicateImages
    {
        static FileStream MergePDFs(GcPdfDocument dest, string fpath)
        {
            GcPdfDocument d = new GcPdfDocument();
            var fs = File.OpenRead(fpath);
            d.Load(fs);
            dest.MergeWithDocument(d);
            return fs;
        }

        public int CreatePDF(Stream stream)
        {
            // Input file names:
            const int N = 7;
            var fpaths = new List<string>(N);
            for (int i = 1; i <= 7; i++)
                fpaths.Add(Path.Combine("Resources", "PDFs", $"DsDemoInvoice{i}.pdf"));
            // Facilitate clean up:
            var fss = new List<FileStream>();
            string tempPdfBefore = null, tempPdfAfter = null;
            try
            {
                var doc = new GcPdfDocument();
                // Merge the invoices into a single PDF:
                for (int i = 0; i < N; i++)
                    fss.Add(MergePDFs(doc, fpaths[i]));

                // Compare the merged PDF size before and after removing duplicates:
                tempPdfBefore = Path.GetTempFileName();
                doc.Save(tempPdfBefore);
                var sizeBefore = new FileInfo(tempPdfBefore).Length;
                doc.RemoveDuplicateImages();
                tempPdfAfter = Path.GetTempFileName();
                doc.Save(tempPdfAfter);
                var sizeAfter = new FileInfo(tempPdfAfter).Length;
                Common.Util.AddNote(String.Format(
                    "Using the GcPdfDocument.RemoveDuplicateImages() method on this document (which was produced by merging " +
                    "several demo invoices with the same company logo) reduced the size of the merged PDF from {0:N0} to {1:N0} bytes.",
                    sizeBefore, sizeAfter),
                    doc.Pages.Insert(0));
                doc.Save(stream);
                return doc.Pages.Count;
            }
            finally
            {
                if (tempPdfBefore != null)
                    File.Delete(tempPdfBefore);
                if (tempPdfAfter != null)
                    File.Delete(tempPdfAfter);
                fss.ForEach(fs_ => fs_.Dispose());
            }
        }
    }
}