iTextSharp というオープンソースライブラリを使うことで PDF ファイルを操作する事ができます。
PDFファイルに埋め込まれている画像を取り出してみようと思います。
iTextSharpのインストール
先ずは iTextSharp をインストールします。
インストール方法は「C#でPDFファイルを操作する 準備編 (iTextSharp)」を参照してください。
サンプルコード
using System; using System.Collections.Generic; using System.IO; using System.Drawing; using System.Drawing.Imaging; using iTextSharp.text.pdf; namespace ConsoleApplication1 { class Program { static void Main() { PDFtoImage(@"C:\test.pdf", @"C:\images\"); } static void PDFtoImage(string pdfName, string imgFolder) { var imgName = Path.GetFileNameWithoutExtension(pdfName); var pdf = new PdfReader(pdfName); var images = new List<PdfObject>(); int n = pdf.NumberOfPages; for (int i = 1; i <= n; i++) { PdfDictionary pg = pdf.GetPageN(i); CollectImage(pg, images); } for (int i = 0; i < images.Count; ++i) { var obj = (PRIndirectReference)images[i]; var pfdStream = (PRStream)pdf.GetPdfObject(obj.Number); byte[] bytes = PdfReader.GetStreamBytesRaw(pfdStream); var name = string.Format("{0}{1}_{2}.jpg", imgFolder, imgName, i); File.WriteAllBytes(name, bytes); } } static void CollectImage(PdfDictionary dic, List<PdfObject> images) { var res = (PdfDictionary)PdfReader.GetPdfObject(dic.Get(PdfName.RESOURCES)); var xobj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT)); if (null != xobj) { foreach (PdfName name in xobj.Keys) { PdfObject obj = xobj.Get(name); if (obj.IsIndirect()) { var tg = (PdfDictionary)PdfReader.GetPdfObject(obj); var type = (PdfName)PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE)); if (PdfName.IMAGE.Equals(type)) { images.Add(obj); } else if (PdfName.FORM.Equals(type)) { CollectImage(tg, images); } else if (PdfName.GROUP.Equals(type)) { CollectImage(tg, images); } } } } } } }
PDFを開く (22行目)
PdfReaderクラスのインスタンスを作成してPDFファイルを開きます。
PDF内の画像オブジェクトを収集する (23~29行目、42~70行目)
PDF内の様々な要素は PdfObject オブジェクトとして管理されています。
画像タイプの PdfObject オブジェクトを収集する為に「CollectImageメソッド」を作成しました。
PDF内の要素は階層構造となっている場合があるので、CollectImageメソッドは再帰的に呼び出されるようになっています。
データをbyte配列で取得して保存する (33~38行目)
GetStreamBytesRawメソッドで画像タイプの PdfObject からデータを byte配列で取得します。
取得したByte配列をそのままファイルへ書き出しています。
※残念ながらこれだけでは、一部の画像しか正しく取得する事は出来ません
※もう少し工夫が必要なようです
コメントをお書きください