0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ゼロから始めるプログラム学習(C#)_008

Posted at

はじめに

プログラミング言語  【C#『シーシャープ』】 を使用して
プログラムを最初から学習するための記載。

   前回:ゼロから始めるプログラム学習(C#)_007
   https://qiita.com/nekoozi/items/c07643603fd0cc92ca53

PDFファイルをグレースケール化して結合する処理

 今回は、複数のPDFファイルをグレースケール化し、  それらを1つにマージを、以下のような流れで処理。

 1.PDFファイルを読み込む。

 2.各ページを画像として抽出し、グレースケール化する。

 3.グレースケール画像を新しいPDFファイルに再保存する。

 4.複数のPDFファイルを1つに結合する。

1・・・ サンプル構成コード(PDFProcessor.cs)

PDFを画像に変換し、グレースケール化した後に再度PDFとして保存し、最終的に結合するコード

using OpenCvSharp;
using PdfiumViewer;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using System.Drawing.Imaging;

public static class PDFProcessor
{
    /// <summary>
    /// 選択された複数のPDFをグレースケール化してマージする
    /// </summary>
    /// <param name="inputFiles">入力PDFファイルのパス配列</param>
    /// <param name="outputFile">出力するマージ済PDFファイル</param>
    public static void ProcessAndMergePDFs(string[] inputFiles, string outputFile)
    {
        // 一時フォルダを作成して、そこで画像変換作業を行う
        string tempDir = Path.Combine(Path.GetTempPath(), "PDFGrayMerge_" + Guid.NewGuid().ToString());
        Directory.CreateDirectory(tempDir);

        List<string> tempPdfList = new();

        try
        {
            // 各PDFファイルに対して処理を行う
            foreach (var pdfPath in inputFiles)
            {
                string tempOutputPath = Path.Combine(tempDir, Path.GetFileNameWithoutExtension(pdfPath) + "_gray.pdf");
                ConvertPdfToGrayscale(pdfPath, tempOutputPath);
                tempPdfList.Add(tempOutputPath);
            }

            // 全ての一時PDFを1つにマージ
            MergePdfs(tempPdfList.ToArray(), outputFile);
        }
        finally
        {
            // 一時ファイルを削除
            Directory.Delete(tempDir, true);
        }
    }

    /// <summary>
    /// PDFをページ単位でグレースケール画像に変換し、再PDF化する
    /// </summary>
    private static void ConvertPdfToGrayscale(string inputPath, string outputPath)
    {
        // PdfiumViewerを使ってPDFを開く
        using var document = PdfDocument.Load(inputPath);
        using var outputDocument = new PdfSharp.Pdf.PdfDocument();

        for (int i = 0; i < document.PageCount; i++)
        {
            // 画像としてPDFページを読み取る
            using var pageImage = document.Render(i, 300, 300, true);

            // 一時的に保存してOpenCvで処理
            string tempImagePath = Path.GetTempFileName();
            pageImage.Save(tempImagePath, ImageFormat.Png);

            // OpenCvSharpで画像を読み込み、グレースケール変換
            using var mat = Cv2.ImRead(tempImagePath);
            using var gray = mat.CvtColor(ColorConversionCodes.BGR2GRAY);

            // グレースケール画像を再保存(PDFSharpが読み込める形式)
            string grayImagePath = Path.GetTempFileName() + ".png";
            Cv2.ImWrite(grayImagePath, gray);

            // 変換した画像をPDFページとして追加
            var pdfPage = outputDocument.AddPage();
            using var gfx = PdfSharp.Drawing.XGraphics.FromPdfPage(pdfPage);
            using var img = PdfSharp.Drawing.XImage.FromFile(grayImagePath);
            gfx.DrawImage(img, 0, 0, pdfPage.Width, pdfPage.Height);

            // 後始末
            File.Delete(tempImagePath);
            File.Delete(grayImagePath);
        }

        outputDocument.Save(outputPath);
    }

    /// <summary>
    /// 複数のPDFファイルを1つにマージする
    /// </summary>
    private static void MergePdfs(string[] pdfFiles, string outputFile)
    {
        using var outputDocument = new PdfDocument();

        foreach (var pdf in pdfFiles)
        {
            using var inputDocument = PdfReader.Open(pdf, PdfDocumentOpenMode.Import);

            // ページごとにコピーしてマージ
            for (int idx = 0; idx < inputDocument.PageCount; idx++)
            {
                var page = inputDocument.Pages[idx];
                outputDocument.AddPage(page);
            }
        }

        outputDocument.Save(outputFile);
    }
}


 説明

ProcessAndMergePDFs:
 複数のPDFファイルをグレースケール化し、それらを1つにマージするメイン処理です。

ConvertPdfToGrayscale:
 PDFをページ単位でグレースケール画像に変換し、それを再PDF化します。

MergePdfs:
 複数のPDFを1つにマージする処理です。

2・・・ フォームから呼び出す処理(Form1.cs)

フォームアプリケーションでPDFファイル選択ダイアログを表示し、ユーザーが選択したPDFをグレースケール化して結合する処理のコード

private void btnConvertAndMerge_Click(object sender, EventArgs e)
{
    // ファイル選択ダイアログを表示して、複数PDFを選択
    using OpenFileDialog ofd = new OpenFileDialog();
    ofd.Filter = "PDFファイル (*.pdf)|*.pdf";
    ofd.Multiselect = true;

    if (ofd.ShowDialog() == DialogResult.OK)
    {
        // 出力ファイル名を選択
        using SaveFileDialog sfd = new SaveFileDialog();
        sfd.Filter = "PDFファイル (*.pdf)|*.pdf";
        sfd.FileName = "Merged_Gray.pdf";

        if (sfd.ShowDialog() == DialogResult.OK)
        {
            try
            {
                // PDFのグレースケール変換 & マージ処理を実行
                PDFProcessor.ProcessAndMergePDFs(ofd.FileNames, sfd.FileName);
                MessageBox.Show("PDFの変換と結合が完了しました!", "完了");
            }
            catch (Exception ex)
            {
                MessageBox.Show("エラーが発生しました: " + ex.Message);
            }
        }
    }
}

 説明
OpenFileDialog:
 ユーザーが選択したPDFファイルを取得するダイアログを表示します。

SaveFileDialog:
 出力先のファイル名を決定するダイアログを表示します。

ProcessAndMergePDFs:
 PDFの変換と結合処理を呼び出します。


   次回:作成中

参考文献

C#関連情報サイト様

OpenCvSharp公式GitHub
https://github.com/shimat/opencvsharp

PDFiumViewerドキュメント
https://pdfiumViewer.github.io

PdfSharp公式サイト
http://www.pdfsharp.net/

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?