文字コードらしきものはどうやらCIDというAdobe固有の文字コードテーブルのようで、計算して復元できるような代物ではないらしい。その変換テーブル情報を CMap と言うらしい。
そこで xpdf というサイトにある xpdf-japanese.tar.gz というのを入手して、そのなかにある Adobe-Japan1-UCS2 というテキストファイル(拡張子なし)がどうも、今回のCMAPとして使えそうだ。
イメージとしては 読み込んだPDFの中にもそういったCMAP情報があって、それを元にコード変換していくのがスマートにも思えるが、PDFファイルの中にCMAP情報があるのか?またどのクラスモジュールで抜き出すのかがいまいち分からない。
PDFによっては他のCMAPファイルで文字コードを復元しなくちゃいけないんだろうが、どの情報を見てどのCMAPを使うかは今後の課題としよう・・・。
とりあえず、コーディングしてみた。
ついでにページ単位にフォント情報を一覧取得できる方法も分かったので、コメントアウトしてあるが掲載してみた。利用方法は不明だけど。。。
とりあえずはテキスト文字を抽出できるようになったみたいだが、どこからどこまでが1行分なのかがよくわからない。
元ネタ:http://yonaizumi.dip.jp/weblog/cappe/2011/01/citextsharp-2.html
そこで xpdf というサイトにある xpdf-japanese.tar.gz というのを入手して、そのなかにある Adobe-Japan1-UCS2 というテキストファイル(拡張子なし)がどうも、今回のCMAPとして使えそうだ。
イメージとしては 読み込んだPDFの中にもそういったCMAP情報があって、それを元にコード変換していくのがスマートにも思えるが、PDFファイルの中にCMAP情報があるのか?またどのクラスモジュールで抜き出すのかがいまいち分からない。
PDFによっては他のCMAPファイルで文字コードを復元しなくちゃいけないんだろうが、どの情報を見てどのCMAPを使うかは今後の課題としよう・・・。
とりあえず、コーディングしてみた。
using System.IO; using iTextSharp.text; using iTextSharp.text.pdf; namespace PDFtoHTML { public partial class Form1 : Form { private string InPDF = @"C:hoge.pdf"; private string InCMAP = @"C:\Adobe-Japan1-UCS2"; private void button1_Click(object sender, EventArgs e) { // CMapの読込み iTextSharp.text.pdf.fonts.cmaps.CMap uCmap = new iTextSharp.text.pdf.fonts.cmaps.CMap(); iTextSharp.text.pdf.fonts.cmaps.CMapParser uCMapParser = new iTextSharp.text.pdf.fonts.cmaps.CMapParser(); StreamReader sr = new StreamReader(InCMAP, Encoding.GetEncoding("Shift-JIS")); uCmap = uCMapParser.Parse(sr.BaseStream); sr.Close(); // iTextSharp::PdfReader PDFの読込み iTextSharp.text.pdf.PdfReader uReader = new iTextSharp.text.pdf.PdfReader(InPDF); Console.Write("□GetPageContent\n"); for (int i = 0; i < uReader.NumberOfPages; i++) { Console.Write(string.Format(" Page No = {0}\n", (i + 1))); byte[] b = uReader.GetPageContent(i + 1); string s = iTextSharp.text.pdf.PdfEncodings.ConvertToString(b, PdfObject.TEXT_PDFDOCENCODING).Replace("\r\n", " "); Console.Write(string.Format("{0}\n", s)); // テキスト部分を抽出 System.Text.RegularExpressions.MatchCollection mc = System.Text.RegularExpressions.Regex.Matches(s, @"<[0-9A-F]*?>|\(.*?\)"); foreach (System.Text.RegularExpressions.Match m in mc) { byte[] bv = new byte[2]; string ss = ""; if (m.Value[0] == '<') { for (int j = 1; j < (m.Value.Length - 1); j = j + 4) { bv[0] = Convert.ToByte(Convert.ToInt32(m.Value.Substring(j, 2), 16)); bv[1] = Convert.ToByte(Convert.ToInt32(m.Value.Substring(j + 2, 2), 16)); ss += uCmap.Lookup(bv, 0, 2); } } else { ss += m.Value.Substring(1, m.Value.Length - 2); } Console.Write(string.Format("{0}\n", ss)); } } // フォント一覧情報 //List<object[]> uLisBaseFont = iTextSharp.text.pdf.BaseFont.GetDocumentFonts(uReader, (i)); // Ending uReader.Close(); Console.Write("■End\n"); } } }これでUnicodeだが文字としてちゃんと取得できるようになった。
ついでにページ単位にフォント情報を一覧取得できる方法も分かったので、コメントアウトしてあるが掲載してみた。利用方法は不明だけど。。。
とりあえずはテキスト文字を抽出できるようになったみたいだが、どこからどこまでが1行分なのかがよくわからない。
元ネタ:http://yonaizumi.dip.jp/weblog/cappe/2011/01/citextsharp-2.html
0 件のコメント:
コメントを投稿