文字コードらしきものはどうやら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 件のコメント:
コメントを投稿