SeaGate Blog
本館 別館 ブログ
プロフィール
スポンサーサイト
SeaGateコレクション



アーカイブ
ブックマーク
検索


カウンター
合計: 1440633
本日: 228
昨日: 331
コントロールパネル
BROACHのアカウントをお持ちの場合、こちらからログインして下さい

RSS



Powered By
プロバイダーぷらら | Broach v1.3.2 (1522)

JPEGファイルのXMPメタデータ取得

下の記事のように、PDFファイルのXMPメタデータは何とか取得できるようになったので、今度はJPEGファイルです。JPEGファイルのXMPメタデータは、以前Meta Data Extractor in C#というライブラリを利用すると書いたのですが、結局日本語をうまく処理することができず、同じ記事で力技として紹介した方法を採用しました。(その時の情報源となったASPAllianceのページはなくなってしまいましたが...)

JPEGファイルを読み込み、XMPメタデータの開始・終了タグを頼りにXMLで記述されたXMPメタデータを抜き出し、XmlDocumentクラスを利用して読み込みと解析を行っています。ファイルを丸ごと読み込むと重いので、XMPメタデータがありそうな先頭20,000bytes程度読み込み、見つからないときだけすべて読み込むようにしました。リアルタイム処理をしているわけではないのでまぁいいかと...また、XMPメタデータの開始・終了タグがPhotoshop (Elements)のバージョンによって"<x:xmpmeta>"と"<x:xapmeta>"の2種類あるようで、処理を分ける必要がありました。

確かに力技ではありますが、.NET FrameworkがXMLのパーシングやら文字コードなどの面倒を一手に引き受けてくれるので、今のところこんな感じでも特に問題なく読み取れています。こんな感じで多量の画像ファイルに埋め込まれたXMPメタデータをインデックス化し、データベースにインポートしようというわけです。

ちょっと不細工ですけど、ソースコードは以下のような感じ...

・XMPメタデータ抽出部分

const int MAX_BUFFER = 17000; // 13000
// Photoshop Elements 3.0
const string BEGIN_CAPTURE1 = "<x:xmpmeta";
const string END_CAPTURE1 = "</x:xmpmeta>";
// Photoshop Elements 2.0, Photoshop 7.0
const string BEGIN_CAPTURE2 = "<x:xapmeta";
const string END_CAPTURE2 = "</x:xapmeta>";

System.IO.StreamReader sr = new System.IO.StreamReader(filename, Encoding.GetEncoding("utf-8"));
string xmp = "";

char[] buf1 = new char[MAX_BUFFER];
sr.Read(buf1, 0, buf1.Length);
string buf2 = new String(buf1);

int bpos1 = buf2.IndexOf(BEGIN_CAPTURE1, StringComparison.CurrentCultureIgnoreCase);
int epos1 = buf2.IndexOf(END_CAPTURE1, StringComparison.CurrentCultureIgnoreCase);

int bpos2 = buf2.IndexOf(BEGIN_CAPTURE2, StringComparison.CurrentCultureIgnoreCase);
int epos2 = buf2.IndexOf(END_CAPTURE2, StringComparison.CurrentCultureIgnoreCase);

if (bpos1 >= 0 & epos1 >= 0)
{
  // <x:xmpmeta </x:xmpmeta>
  xmp = buf2.Substring(bpos1, (epos1 - bpos1) + END_CAPTURE1.Length);
}
else if (bpos2 >= 0 & epos2 >= 0)
{
  // <x:xapmeta </x:xapmeta>
  xmp = buf2.Substring(bpos2, (epos2 - bpos2) + END_CAPTURE2.Length);
}
else
{
  sr.Close();
  sr = new System.IO.StreamReader(fi.FullName, Encoding.GetEncoding("utf-8"));
  buf2 = sr.ReadToEnd();

  bpos1 = buf2.IndexOf(BEGIN_CAPTURE1, StringComparison.CurrentCultureIgnoreCase);
  epos1 = buf2.IndexOf(END_CAPTURE1, StringComparison.CurrentCultureIgnoreCase);

  bpos2 = buf2.IndexOf(BEGIN_CAPTURE2, StringComparison.CurrentCultureIgnoreCase);
  epos2 = buf2.IndexOf(END_CAPTURE2, StringComparison.CurrentCultureIgnoreCase);

  if (bpos1 >= 0 & epos1 >= 0)
  {
    // <x:xmpmeta </x:xmpmeta>
    xmp = buf2.Substring(bpos1, (epos1 - bpos1) + END_CAPTURE1.Length);
  }
  else if (bpos2 >= 0 & epos2 >= 0)
  {
    // <x:xapmeta </x:xapmeta>
    xmp = buf2.Substring(bpos2, (epos2 - bpos2) + END_CAPTURE2.Length);
  }
  else
  {
    xmp = "";
  }
}

sr.Close();

・XMPメタデータ解析部分

XmlDocument xd = new XmlDocument();
xd.LoadXml(xml);

XmlNodeList xn = xd.GetElementsByTagName("dc:title");
string title = xn.Item(0).ChildNodes[0].InnerText;
xn = xd.GetElementsByTagName("dc:description");
string description = xn.Item(0).ChildNodes[0].InnerText;

このエントリーをはてなブックマークに追加  Clip to Evernote  Spring it! 
SeaGate: 2006.11.12 | コメント (0) | トラックバック (0) | リンク (0) | ▲TOP

Trackback:

このエントリーのトラックバックURL:
http://pub.ne.jp/tb.php/405181
inserted by FC2 system