DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Jpegファイルにあるタグを編集したいです(Adobe社のXMPについて)

環境/言語:[Win7 64bit VB.net Visual Studio 2008]
分類:[.NET]

2014/11/26(Wed) 16:37:57 編集(投稿者)
2014/11/19(Wed) 02:21:25 編集(投稿者)
2014/11/19(Wed) 02:21:16 編集(投稿者)


分類:[VB.NET/VB2005 以降] 

皆様、お世話になります。

現在、JPGファイルについているXMPタグを追加したいと思っています。

以下のXMPメタにhogehogeCISを1つ追加したい(<hogehogeCIS:xxxxx>)のですがどのように行えば宜しいでしょうか?


<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:Description rdf:about=""
xmlns:hogehogeCIS="http://ns.sanyo.com/xmp/1.0/">
<hogehogeCIS:Objective>4</hogehogeCIS:Objective>
<hogehogeCIS:FieldWidth>999</hogehogeCIS:FieldWidth>
<hogehogeCIS:FieldHeight>333</hogehogeCIS:FieldHeight>
<hogehogeCIS:Magnification>333</hogehogeCIS:Magnification>
<hogehogeCIS:ImagingModuleName>hogehoge</hogehogeCIS:ImagingModuleName>
<hogehogeCIS:CameraSerialNo>12345</hogehogeCIS:CameraSerialNo>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>


参考としてSamle.jpgファイルを添付致します。Jpgファイルを秀丸などのエディタで開いていただくと、ヘッダー部に上記と似たコードが表示されます。<hogehogeCIS:Objective>4</hogehogeCIS:Objective>の下に<hogehogeCIS:hogehoge>hoge</hogehogeCIS:hogehoge>を入れたいです。



色々と自分で調査したのですが、以下のことしか解りませんでした。

・JavaやC++だと容易に出来そうだが開発言語がVB.netなので実装できない。
・VB.netでもWindows Imaging Component で出来るようだが、DLLを見つける事が出来ない。

別に他の方法で処理が行えればそれで問題ないのですが、その他方法はございますでしょうか?
例えば、streamReaderでJpgファイルを読み込み、その内容をStreamWriterで書き込むなど。
(恐らくJpgファイルなのでWriteするときに出来ないと思いますが。。。)



お手数ですがよろしくお願い致します。
(この記事にはファイル"sample.jpg"が添付されていましたが、削除されました。)
この投稿はマルチポストです。もし元記事の投稿者にマルチポストの心当たりがない場合は、すぐに返信でお知らせください。

●マルチポストされている場所
http://bbs.wankuma.com/index.cgi?mode=al2&namber=73972

----------
この掲示板ではマルチポストが禁止されています。詳しくは、「書き込みのルールについて」をお読みください。

●書き込みのルールについて
http://dobon.net/vb/bbs/index.html
マルチポストのルールを知らずに申し訳ございませんでした。

早速記事を削除したいと思うのですが、返信がついてるようで削除が行えません。

どうすれば削除が行えますでしょうか?
■No32719に返信(おじゃさんの記事)
> マルチポストのルールを知らずに申し訳ございませんでした。
>
> 早速記事を削除したいと思うのですが、返信がついてるようで削除が行えません。
>
> どうすれば削除が行えますでしょうか?

提示したルールを読まれていないということですか?
http://dobon.net/vb/bbs/index.html#replypost
ルールを確認しました。
すみません、削除そのものがいけないという事ですね。
小生の質問は2つの掲示板で行っていますので、どちらかに回答が着いた際は、至急もう1つの掲示板にも解決済みの回答を記入しようと思います。

お手数をおかけして申し訳ございませんでした、以後気を付けます。

> 提示したルールを読まれていないということですか?
> http://dobon.net/vb/bbs/index.html#replypost
力になって頂ける方いらっしゃいませんでしょうか?

お手数ですがよろしくお願いいたします。
■No32726に返信(おじゃさんの記事)

http://www.chilkatsoft.com/xmp-dotnet.asp
魔界の仮面弁士様

 途方に暮れていましたので助かります、
 
 教えていただいたURLを確認してみたいと思います。

 どうもありがとうございます。

 結果は追ってご連絡致します!
2014/11/20(Thu) 16:14:37 編集(投稿者)

魔界の仮面弁士様

早速、教えていただいたサイトのDLLをダウンロードして以下コードを書いてうまく良く事を確認しました。

Dim xmp As New Chilkat.Xmp()
Dim success As Boolean

Dim xml As Chilkat.Xml
xml = xmp.NewXmp()
xmp.AddSimpleStr(xml, "photoshop:Headline", "This is the new headline")

success = xmp.LoadAppFile("c:\aaa.jpg")

xmp.Append(xml)
xmp.SaveAppFile("c:\xxx.jpg")

上記コードを書くと、以下の内容がJpegファイルの先頭部に追加される。

<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
<photoshop:Headline>This is the new headline</photoshop:Headline>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>




ただ、無償版だと30日限定みたいなので困っています。
一応、開発会社(米国)にソフト購入したい旨のメールを出しましたが、いくら請求されるか心配です。

他に無償版で何か良さげな物はございませんでしょうか?

お手数ですがよろしくお願い致します。

追記:もう一つのサイトにも同様の内容を記入いたします。
■No32729に返信(おじゃさんの記事)
> いくら請求されるか心配です。
紹介した URL の最初に書かれている [Purchase] のリンク先の金額なのでは。


> 他に無償版で何か良さげな物はございませんでしょうか?
自分で調査・開発する場合の人件費は考慮しなくて良いのでしょうか。(^^;

人件費を無視してよいのなら、仕様は公開されているようなので、
自前でバイナリを直接解析・編集するとか…?


それは冗談としても、私自身は全く検証していないので、
お勧めできるようなものは特に何もありません。済みません。

とはいえ、数分間ネット検索してみるだけでも、いろいろな情報に
簡単に行き当たりました。……これらは既に訪問済みのサイトでしょうか?
http://www.antenna.co.jp/XML/xmllist/XMP/AboutXMP.htm
http://sourceforge.net/projects/csxmptk/
http://msdn.microsoft.com/ja-jp/library/windows/apps/xaml/jj709941.aspx
http://8thway.blogspot.jp/2014/05/exif-edit.html
回答とはいえないコメント止まりですが…。

■No32716に返信(おじゃさんの記事)
> ・VB.netでもWindows Imaging Component で出来るようだが、DLLを見つける事が出来ない。

WIC でいうこの辺の話なんですよね?
http://msdn.microsoft.com/en-us/library/windows/desktop/ee719653(v=vs.85).aspx

WIC は COM として公開されているほか、WPF 側のアセンブリ(System.Windows.Media.Imaging 名前空間)を参照していただければマネージクラス経由で操作することもできます。
たとえば、BitmapMetadata クラスは WIC のメタデータ読み書きに中継してくれるクラスのはず。

http://msdn.microsoft.com/ja-jp/library/system.windows.media.imaging.bitmapmetadata.setquery(v=vs.110).aspx


Windows Forms で主流となる GDI+ とは使い勝手が異なるので取っつきづらいとは思いますが、無料の範囲内でできることでしょうね。
(外部支払いよりも調査の人件費の方が安いと判断している、あるいは学習・スキルアップ目的ならよいかもしれません)

// 魔界の仮面弁士さん紹介のリンクの4つ目相当の焼き直しかも orz
魔界の仮面弁士さん

ご連絡ありがとうございます。
昨晩、ご指摘の4つのリンクを確認してみましたが、まだ実装まで行えておりません。
今日一日確認した後、それでも難しそうでしたら他の方法を考慮したいと思います。
(C++などでしたら出来そうですね。どうもVB.net情報があまりなさそうです。。)

12月で忙しい時期にご回答いただきありがとうございます。
Azuleanさん

ご連絡ありがとうございます。

さっそくご指摘のサイトを確認いたしました。
現在、実装中なのですが以下をImportしようとすると

Imports System.Windows.Media.Imaging

指定された名前空間または方が、パブリックメンバを含んでないか、または見つかりません・・・ と表示されてしまいます。

何か見当違いな事をやっていますでしょうか?

なお、以下のCOMとして公開されているとは、VisualStudio2008のCOMにあるという事でしょうか?

>WIC は COM として公開されているほか

お手数ですが宜しくお願い致します。
■No32734に返信(おじゃさんの記事)
> 指定された名前空間または方が、パブリックメンバを含んでないか、または見つかりません・・・ と表示されてしまいます。

今回使うのは、(System.Windows.Media.Imaging 名前空間の)BitmapMetadata クラスで
あるということまでは、Azulean さんの回答から分かりますよね。

であれば、まず見るべきは BitmapMetadata クラスの仕様。
No32732 で Azulean さんが投稿された URL はご覧になられましたか?

その URL には、
  名前空間: System.Windows.Media.Imaging
  アセンブリ: PresentationCore (PresentationCore.dll 内)
という記述が書かれていたはずです。


すなわち、この名前空間を含んでいるアセンブリである
PresentationCore を『参照設定』する必要がある、ということです。
(参照設定の手順はわかりますよね?)


なお、WCF は .NET Framework 3.0 以降の機能ですので、現在のプロジェクトを
.NET Framework 2.0 用プロジェクトとして作成している場合、
PresentationCore を参照設定することができません。
(VS2008 は、既定で .NET 3.5 が使われるので大丈夫だとは思いますが念のため)
魔界の仮面弁士さん

アドバイスありがとうございます。
アセンブリの意味をよく理解していませんでした。
以下のURLを見て理解いたしました。

http://www.sophia-it.com/content/%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%AA

さっそく、PresentationCore と WindowsBase を参照の追加したら
System.Windows.Media.Imaging のImportが行えました。

さっそく、ご指示いただいたコードを試してみたいと思います。


>
> その URL には、
>   名前空間: System.Windows.Media.Imaging
>   アセンブリ: (PresentationCore.dll 内)
> という記述が書かれていたはずです。
>
>
> すなわち、この名前空間を含んでいるアセンブリである
> PresentationCore を『参照設定』する必要がある、ということです。
> (参照設定の手順はわかりますよね?)
>
>
> なお、WCF は .NET Framework 3.0 以降の機能ですので、現在のプロジェクトを
> .NET Framework 2.0 用プロジェクトとして作成している場合、
> PresentationCore を参照設定することができません。
> (VS2008 は、既定で .NET 3.5 が使われるので大丈夫だとは思いますが念のため)
■No32733に返信(おじゃさんの記事)
> 12月で忙しい時期にご回答いただきありがとうございます。

いったん落ち着きましょう。今は11月です!! (^_^;)



ちょうど昼休みになったので、No32730 の最後の URL にある内容を
VB で書き直してみました。

そのソースコードと、加工前後の画像ファイルを置いておきます。
http://www.vb-user.net/junk/replySamples/2014.11.21.12.59/sample.zip


なお私自身は、コードの内容をまったく理解していません。あしからず。

そもそも書き込んだ XMP を見る方法を持ち合わせていない上に、
XMP という用語自体が初耳だったため、内容については保証できかねます。


# 加工前の画像はネットからの拾い物。どこから流れてきたものかは失念。
# 問題があるようなら差し替えます。
■No32727に追記(魔界の仮面弁士の記事)

XMP の公式解説
http://www.adobe.com/jp/devnet/xmp.html

XMP を .NET から操作するためのラッパーライブラリ
http://sourceforge.net/projects/csxmptk/

上記を試してみました。
すべての機能がラップされているわけではないので、
今回の要件にあうかどうかは保証できませんケド。


(1) 上記から、C# XMP Toolkit をダウンロード。

(2) CsXmpToolkit.dll を参照設定した上で、プロジェクト内に
 XmpToolkit.dll を含める(参照設定では無く、ファイルとして追加)。
 ※XmpToolkitは参照設定できませんが、実行には必要。

(3) ソリューションエクスプローラーで、XmlToolkit.dll を選択し、
 プロパティ ウィンドウで[出力ディレクトリにコピー]の欄を
 "コピーしない" 以外の選択肢に変更する。


Imports SE.Halligang.CsXmpToolkit
Imports SE.Halligang.CsXmpToolkit.Schemas

Using oXmp As Xmp = Xmp.FromFile(jpegFilePath1, XmpFileMode.ReadWrite)
 TextBox1.Text = oXmp.Dump().Replace(vbLf, vbNewLine)

 Dim xBasic As New XmpBasic(oXmp)
 xBasic.Identifier.Clear()
 xBasic.Identifier.Add(New XmpBasic.QualifiedIdentifier("Identifier A", Nothing))
 xBasic.Identifier.Add(New XmpBasic.QualifiedIdentifier("Identifier B", "Scheme B"))
 xBasic.MetadataDate = Now
 xBasic.Rating = 5
 xBasic.Thumbnails.Clear()

 Dim dc As New DublinCore(oXmp)
 dc.Subject.Clear()
 dc.Subject.Add("あいうえお")
 dc.Subject.Add("かきくけこ")
 oXmp.Save()
End Using


'If XmpCore.Initialize() Then
' If XmpFiles.Initialize() Then
'  Dim xfFlags = OpenFlags.OpenForRead Or OpenFlags.OpenForUpdate Or OpenFlags.OpenOnlyXmp
'  Using files As New XmpFiles(jpegFilePath, FileFormat.Jpeg, xfFlags)
'   Using core As New XmpCore()
'    If files.GetXmp(core) Then
'     Dim dcNS1 As String = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
'     Dim dcNS2 As String = "http://purl.org/dc/elements/1.1/"
'     Dim dnNS3 As String = "http://ns.sanyo.com/xmp/1.0/"
'     '
'     'If core.GetProperty(…
'     'Using iter As New XmpIterator(core, …
'     '
'    End If
'   End Using
'  End Using
'  XmpFiles.Terminate()
' End If
' XmpCore.Terminate()
'End If
魔界の仮面弁士さん

 ご連絡ありがとうございます。
 教えていただきまいた手順の通り、VS2008で実施しましたが、
 
 sing oXmp As Xmp = Xmp.FromFile(jpegFilePath1, XmpFileMode.ReadWrite) 
 
 上記行で以下のエラーが出てしまいます。


 間違ったフォーマットのプログラムを読み込もうとしました。

 読み込ませるファイルはJpgファイルで、特に変わった画像ファイルではありません。何か間違ったことを行っていますでしょうか?

 大変申し訳ございませんが、何かわかりましたらご教示お願いいたします。
2014/11/25(Tue) 14:49:33 編集(投稿者)

■No32743に返信(おじゃさんの記事)
>  sing oXmp As Xmp = Xmp.FromFile(jpegFilePath1, XmpFileMode.ReadWrite) 
sing → Using ですね。


>  間違ったフォーマットのプログラムを読み込もうとしました。
XMP Toolkit が、画像形式の異常を報告している…というよりは、
XMP のライブラリのロードに失敗したという意図のエラーのようですね。

コンパイルされた EXE と同じフォルダに、
CsXmpToolkit.dll と XmpToolkit.dll の両方が
配置されているかどうかを確認してみて下さい。

また、ビルドを x86/x64/AnyCPU とで変更してみた場合はどうでしょうか?
(付属のサンプルでは AnyCPU ビルドになっているようです)


なお、このライブラリで目的を果たせるかどうかは保証できかねますし、
ライブラリの詳細な使い方を尋ねられても、こちらとしては分かりかねます。m(_ _)m
魔界の仮面弁士さん

ご回答ありがとうございます。

 
>ビルドを x86/x64/AnyCPU とで変更してみた場合はどうでしょうか?

 ⇒ありがとうございました。今まで行ってた AnyCPUをx86に変更したら無事にプログラムが動作しました。


>なお、このライブラリで目的を果たせるかどうかは保証できかねますし、
>ライブラリの詳細な使い方を尋ねられても、こちらとしては分かりかねます 

 ⇒了解いたしました。こちらで色々と調査した所、<xxxCIS:hogehoge>hoge</xxxCIS:hogehoge>などのタグをXMPに入れる場合は、どうやら一度Jpgファイルを読み込み、メタタグ上にタグを追加して再度、元に戻す方法が妥当なようです。その方法で対応可能か検証したいと思います。(こちらの方法で行う際に不明な点が出た際にはまた別トピックを立てたいと思います)

 魔界の仮面弁士さん、お忙しいところ、色々調査して頂きどうもありがとうございました。
2014/11/26(Wed) 12:48:59 編集(投稿者)

現在は、FreeImageというDLLを使用して実装を試しています。

http://sourceforge.net/projects/freeimage/ からDLLやサンプルソースをダウンロードして以下のコードを書いていますが、まだうまく反映されません。どなたか間違っている個所が解りますでしょうか? 以下のソースはサンプルを真似をして書きました。


' Load the image
Dim dib As FIBITMAP = New FIBITMAP()
dib = FreeImage.LoadEx("c:\111.jpg")

If (dib.IsNull) Then
MessageBox.Show("Failed to load image.")
Else

'Dim tag As FreeImageAPI.Metadata.MetadataTag = New MetadataTag(FREE_IMAGE_MDMODEL.FIMD_COMMENTS)
'tag.SetValue(System.Text.Encoding.ASCII.GetBytes("hogeo"))
'tag.Key = 270
'tag.AddToImage(dib)
'FreeImage.SetMetadata(FREE_IMAGE_MDMODEL.FIMD_XMP, dib, "FIMD_XMP", tag)


Dim FTag As New Metadata.MetadataTag(FREE_IMAGE_MDMODEL.FIMD_COMMENTS)
FTag.Key = "HogeDescription"
FTag.ID = 270
FTag.Value = System.Text.Encoding.ASCII.GetBytes("hogeo")
FTag.AddToImage(dib)


FreeImage.Save(FREE_IMAGE_FORMAT.FIF_JPEG, dib, "c:\222.jpg", FREE_IMAGE_SAVE_FLAGS.JPEG_QUALITYNORMAL)


End If
進展がありました。

あまり納得していないのですが、以下のような方法をとり、やりたいことは出来ました。

・System.IO.StreamReader  でJpgファイルを読み込み、一行一行をString型の変数に入れる。
・行を読み続け、キーとなるタグになった時点で挿入したいタグを変数に入れる。
。また行を読み続け、終了のキーとなるタグが出てきたら変数に入れるのをやめる。

・上記変数を以下のソースに流し込む。

Dim dib As FIBITMAP = New FIBITMAP()
dib = FreeImage.LoadEx(strImageFileFullPath)

If (dib.IsNull) Then
LogWrite("Failed to load image.", True)
Else

Dim FTag As New Metadata.MetadataTag(FREE_IMAGE_MDMODEL.FIMD_XMP)

FTag.Key = "hoge"
FTag.ID = 7
FTag.Value = System.Text.Encoding.ASCII.GetBytes(str1Line & strHeadMetaData & " <hogeCIS:shikichi>hoge</sanyoCIS:shikichi>" & vbLf & strTailMetaData)
FTag.AddToImage(dib)


FreeImage.Save(FREE_IMAGE_FORMAT.FIF_JPEG, dib, "c:\hoge.jpg", FREE_IMAGE_SAVE_FLAGS.JPEG_QUALITYNORMAL)

End If


 あまり納得いかないプログラムになりましたが、他の方法などございますでしょうか? 数日待ってないようでしたら、解決済みにチェックいたします。


 以上、よろしくお願い致します。
魔界の仮面弁士さん、Azuleanさん

アドバイスどうもありがとうございました。
他に良い案がなさそうなのでクローズしたいと思います。

この版を見て、考えて下さった皆様
どうもありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板