shuhelohelo’s blog

Xamarin.Forms多めです.

iTextSharpでPDFを回転,選択する

使用するライブラリ

公式ではありません. NuGetからインストールします.

PDFファイルの読み込み

まずはPDFファイルを読み込みます.

PdfReader reader = PdfReader(filePath);

PDF情報の取得

このPdfReaderオブジェクトからはいろいろな情報を取得できます.

例えば以下のコードを実行してみましょう.

            //PDFファイルの読み込み
            PdfReader reader = new PdfReader(inputFilePath);

            //PDFファイルの各種情報の取得
            Console.WriteLine("Page count: {0}", reader.NumberOfPages);
            Console.WriteLine("Page rotation: {0}", reader.GetPageRotation(1));
            Console.WriteLine("Page size: {0}", reader.GetPageSize(1));
            Console.WriteLine("Page size with rotation: {0}", reader.GetPageSizeWithRotation(1));

指定したPDFに関する情報が出力されます. 今回指定したPDFは1ページ目を右に90°回転させてあり,用紙サイズはLetterサイズ(612*792)のものです.

Page count: 5
Page rotation: 90
Page size: Rectangle: 612x792 (rot: 0 degrees)
Page size with rotation: Rectangle: 792x612 (rot: 90 degrees)

指定したページの情報が取得できています.

ページ数の取得

int pageCount = reader.NumberOfPages;

指定したページの取得

GetPageNメソッドを使います. int型でページ番号を指定すると,そのページのオブジェクトを取得できます.

PdfDictionary page = _pdfReader.GetPageN(pageNumber);

ページの情報の取得

PdfDictionaryオブジェクトのGetAsNumberメソッドを使います.

PdfDictionaryという名前のとおり,引数にKeyを指定すると,そのKeyに対応するオブジェクトを取得できるようです.

例えば,ページの向きの情報を取得する場合は以下のようにします.

PdfNumber rotation = page.GetAsNumber(PdfName.Rotate);

角度をint型で取得する場合はIntValueプロパティで取得できますが,一つ注意が必要です. そのページが回転されていない,つまり0°の場合はpage.GetAsNumber(PdfName.Rotate)nullを返します.なので,nullチェックを挟む必要があります.

                PdfDictionary page = reader.GetPageN(2);
                //角度
                PdfNumber rotation = page.GetAsNumber(PdfName.Rotate);
                Console.WriteLine("Page rotation: {0}", rotation == null ? 0 : rotation.IntValue);

ページの回転

ページを回転させるには,そのページの角度を表すオブジェクトに新しい角度を表すオブジェクトをセットします.

まず,新しい角度を表すオブジェクトを作成します.

元の向きを基準に指定した角度回転させる,ということなので,以下のように「元の角度に回転させる角度を足して,それを360で割った余り」を計算して引数に与えます.

PdfNumber newRotation = new PdfNumber((元の角度+回転角) % 360);

次に,そのオブジェクトをPdfDictionaryオブジェクトにセットします.これにはPutメソッドを使用します.

Rotateに対してnewRotationをセットします.

page.Put(PdfName.Rotate, newRotation);

上記の2ステップでページを回転させることができます.

例えば,指定したページを右に90°回転させたい場合は以下のようにします.

            //ページの回転(右に90°回転)
            PdfNumber rotation = page.GetAsNumber(PdfName.Rotate);
            PdfNumber newRotation = new PdfNumber(rotation == null ? 90 : (rotation.IntValue + 90) % 360);
            page.Put(PdfName.Rotate, newRotation);

回転前後でページの角度を表示させてみます.

                //改めて角度を表示
                page = reader.GetPageN(1);
                rotation = page.GetAsNumber(PdfName.Rotate);
                Console.WriteLine("Page new rotation: {0}", rotation == null ? 0 : rotation.IntValue);

以下のように,90°回転していることが確認できます.

Page rotation: 90
Page new rotation: 180

編集後のファイル保存

保存は以下のようにPdfStamperクラスを使って別のファイルに書き込みます.

                //別ファイルに保存
                string outputFilePath = inputFilePath + "_output.pdf";//適当
                using (FileStream fs = new FileStream(outputFilePath, FileMode.OpenOrCreate))
                {
                    PdfStamper stamper = new PdfStamper(reader, fs);
                    stamper.Close();
                }

一つ注意が必要ですが,ここで読み込んだファイルに上書きするつもりで以下のようにすると,

                //同じファイルに保存(失敗する)
                using (FileStream fs = new FileStream(inputFilePath, FileMode.OpenOrCreate))
                {
                    PdfStamper stamper = new PdfStamper(reader, fs);
                    stamper.Close();
                }

すでに開かれているという理由でエラーになります.

f:id:shuhelohelo:20201022104743p:plain

今の所,スマートな保存の方法がわからないので,暫定的に以下のように,ファイルを開くときに一時ファイルにコピーしてから開くことで,保存時の上記エラーを回避しています.

            //一時ファイル経由のPDF読み込み
            string tempFilePath = Path.GetTempFileName();
            File.Copy(inputFilePath, tempFilePath, true);
            PdfReader reader = new PdfReader(tempFilePath);

ページの選択

PdfReaderのSelectPagesメソッドを使います.

以下のように選択したいページ番号をカンマ区切りで指定することで,読み込んだPDFファイルが指定したページのみになります.

                //1,3ページだけ選択
                reader.SelectPages("1,3");

また,ページの指定の仕方は以下のように-を使って範囲で指定することもできます.

                //1,2,3,5ページだけ選択
                reader.SelectPages("1-3,5");

ソースコード

https://github.com/shuheydev/iTextSharpLGPLv2CorePractice