C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

画像ファイルのヘッダーに文字列を埋め込む方法 [1]

[トピック内 29 記事 (21 - 29 表示)]  << 0 | 1 >>

■89610 / inTopicNo.21)  Re[17]: 画像ファイルのヘッダーに文字列を埋め込む方法
  
□投稿者/ なり (13回)-(2018/12/09(Sun) 18:18:56)
どなたかご回答ありませんでしょうか?
よろしくお願いいたします。

引用返信 編集キー/
■89611 / inTopicNo.22)  Re[17]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ 魔界の仮面弁士 (1979回)-(2018/12/10(Mon) 00:58:36)
No89606 (なり さん) に返信
> png の場合、/tEXt/Comment クエリ文字列で SetQuery メソッドを使って書き込むようです。
> と回答が書かれてありますが
> これは具体的にどのようにしたら良いのでしょうか?

回答にある通り、 meta.SetQuery("/tEXt/Comment", "コメント文章") とするだけなのでは…?



> しかし、この方法だと
> D a t a
> のように、文字と文字の間にスペースが入ってしまいます。

提示頂いた「この方法」というのは、Jpeg への埋め込みのコードではなく、
Png への埋め込みのコードのように見えますが、その方法では埋め込めずに、
エラーになったはずですよね。一体、どういう状況なのでしょうか。


また、「文字と文字の間にスペース」とのことですが、
それはどのようにして確認したものなのでしょうか。
もしかして、UTF-16 として書き込まれている文字列を、
誤って ASCII として読み取っているといったことはないでしょうか。


フォーマットについては、最初に調査頂いているようですし、
まずは出力結果のバイナリの内容を確認してみてください。


そもそも一口にコメントと言っても、たとえば JPEG なら、
・セグメント マーカー FFFE のコメント ( No89567 のサイトで紹介されているもの )
・セグメント マーカー FFE1 (APP1 セグメント) の Exif として
  ・0th IFD の XP Comment タグ 0x9c9c (40092)
  ・0th IFD の User Comment タグ 0x9286 (37510)
・セグメント マーカー FF64 のコメント (JPEG2000)
などのように、いくつもの種類があるわけですよね。

XP Comment (0x9c9c) なら UCS-2 バイナリとして埋め込まれるでしょうし、
User Comment (0x9286) なら、タグデータの最初の 8 バイトによって、
 0x4153434949000000('ASCII') … ITU-T T.50 IA5
 0x4A49530000000000('JIS') … JIS X0208-1990
 0x554E49434F444500('Unicode') … Unicode Standard
 0x0000000000000000('Undefined') … Undefined
のように異なってくるわけで。

http://www.exiv2.org/tags.html
https://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif/usercomment.html
引用返信 編集キー/
■89612 / inTopicNo.23)  Re[18]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (14回)-(2018/12/10(Mon) 10:38:25)
ありがとうございます。

PNG画像の方ですがご提示くださった方法でうまくいきました。

JPEG画像の方ですが、
もちろん、JPEGの場合には以下のように書き直して使用しています。



Dim bitmapStream As New MemoryStream
img.Save(bitmapStream, ImageFormat.Jpeg)
bitmapStream.Position = 0
Dim enc As New JpegBitmapEncoder


Dim outStream As New MemoryStream(bitmapStream.ToArray())
Dim dec As New JpegBitmapDecoder(outStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None)
Dim frm As BitmapFrame = BitmapFrame.Create(dec.Frames(0))
Dim meta As BitmapMetadata = DirectCast(frm.Metadata, BitmapMetadata)
meta.Comment = "Data"
enc.Frames.Add(BitmapFrame.Create(frm, Nothing, meta, Nothing))

Dim StreamOut As FileStream = File.Open(bmpFilename, System.IO.FileMode.CreateNew, System.IO.FileAccess.Write)
enc.Save(StreamOut)

bitmapStream.Dispose()
StreamOut.Dispose()

img.Dispose()

確認の仕方ですが、
テキストエディタで開いてASCIIとして確認しています。


バイナリエディタで確認したところ、
XP Comment タグ 0x9c9c

として埋め込まれていることが分かりました。

普段はテキストエディタで中身を確認するため、
これをASCIIデータとして埋め込みたいのですが
どのようにすれば良いですか?

コードを見ても、それらしい引数オプションが見当たらないのですが・・・。


引用返信 編集キー/
■89617 / inTopicNo.24)  Re[19]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ 魔界の仮面弁士 (1980回)-(2018/12/10(Mon) 13:35:22)
No89612 (なり さん) に返信
> もちろん、JPEGの場合には以下のように書き直して使用しています。
先の No89606 の投稿では、
dec を PngBitmapDecoder にしておいたうえで
『これで (Jpeg に)文字列を埋め込むことができました』
と書かれていたことに、ちぐはぐさを感じました…。(^^;
(しかも enc の宣言が漏れている)

PngBitmapDecoder 版の不具合コードを示すなら、
Jpeg の話を述べた後の、Png 画像への追質問となる
> これは一体どうすれば良いでしょうか?
> 後、同様にPNG画像にも文字列を埋め込もうとしてみたのですが、
のあたりに記した方が良かったですね。



> テキストエディタで開いてASCIIとして確認しています。
せめてバイナリエディタや EXIF ビューワーの類を使うべきかと。

JPEG は ASCII ファイルでは無いですし、文字列部分だけを見るにしても、
非 ASCII 文字列の場合、開始位置が 1 バイトずれただけで
正しく読めなくなります。たとえば Shift_JIS における
 0x8181 =
 0x8182 ≠
 0x8281 a
 0x8282 b
などのように。


> バイナリエディタで確認したところ、
> XP Comment タグ 0x9c9c
> として埋め込まれていることが分かりました。

XP Comment は UCS-2 を前提としているので、"Data" という 4 文字は、
44,00,61,00,74,00,61,00,00,00
として格納されるはずです。
恐らくは、この NULL 文字(0x00) を空白(0x20) と誤読されたのでしょう。


> これをASCIIデータとして埋め込みたいのですが
> どのようにすれば良いですか?

UserComment であれば ASCII にも対応していますが、
XPComment は Unicode 前提のタグなわけですから、
そこに ASCII を埋め込むべきではないですよね。
それに、何故 ASCII で無ければならないのかも分からないです。


最初の質問を見る限りでは、文字列を COM 拡張セグメント (0xFF,0xFE) に
埋め込む話だったように見えましたが、途中から EXIF タグに埋め込む話に
変わっているようです。そもそも今回、文字列を埋め込む目的は何でしょうか。
埋め込んだ値を、どのようなアプリから利用しようとしているのでしょうか?


このまま当初の「目的」が明かされないまま「手段」を論じ続けると、迷走してしまいそうなので、
まずは、どういう目的で ASCII として埋め込もうとしているのかを明確にしてみてください。
内容次第では、何か代替案を出せる方が居るかもしれません。


本来は、利用側の使用目的に合わせて、格納先の領域を決めるべきとは思いますが、
たとえば ASCII 前提のエントリならどこでも良いというのなら、
EXIF で データタイプ 2 (ASCII) なタグ (たとえば 0x010E の ID) を使うこともできますし、
0x9286 の ID (User Comment) で ASCII モードを指定することもできますよね。
あるいは、未使用の 最初の質問通りに「セグメント」を用いて、
当初の COM (0xFFFE) セグメントや未使用の APP# (0xFFE#) セグメントを使うとか。

もちろん、そのために必要な記述はそれぞれ異なってくるでしょうし、格納先によっては、
GDI+ ライブラリ (System.Drawing 名前空間)や
WPF(Avalon) ライブラリ (System.Windows 名前空間)ではなく、
オープンソースのライブラリ等に頼ることになるかもしれません。
引用返信 編集キー/
■89620 / inTopicNo.25)  Re[20]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (15回)-(2018/12/10(Mon) 16:04:32)
目的は
文字列を COM 拡張セグメント (0xFF,0xFE) に埋め込むことです。

提示してくださった方法
https://dobon.net/vb/bbs/log3-44/26468.html
が、ExIFによるものだったため、
これを使用しました。

ExIFである必要はなく、ASCIIで埋め込めるのなら
COMセグメントで全く問題ありません。

ASCIIなら1バイトずれるという問題はないはずです。

あと、気になっているのですが
JPEGにしてもPNGにしても
埋め込んだ文字列を読み込むにはどうしたら良いのでしょうか?

保存してある画像ファイルをFile.Openで開いて
FileStreamを取得し、
これをBitmapMetadataに変換できれば、
埋め込んだテキストも読み込めると思うのですが、

FileStreamをBitmapMetadataに変換するにはどうしたら良いですか?








引用返信 編集キー/
■89622 / inTopicNo.26)  Re[21]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ 魔界の仮面弁士 (1982回)-(2018/12/10(Mon) 18:12:35)
No89620 (なり さん) に返信
> 目的は
> 文字列を COM 拡張セグメント (0xFF,0xFE) に埋め込むことです。

それは「手段」ですよね。『何のために』埋め込むのかを訊ねています。
また、何故それが ASCII で無ければならないのかの説明も欲しいです…。

本来はまず目的があって、その実現のために手段を選択するはずですが、
目的が不明のため、COM セグメントだったり XP Comment タグだったりと
回答が揺れてしまい、回り道をしているように見受けられます。


で。そもそも Exif を出力した JPEG フォーマットの場合、
SOI,APP1,DQT,DHT,SOF0,SOS,EOI (オプションでAPP2,DRI)
のマーカーセグメントを使うことになっていて、
それ以外の APP や COM は含めないという仕様らしいです。

ただし JPEG 規定では、EOI (0xFFD9) のセグメントは
JPEG ファイルの終わりを表すマーカーであり、それ以降には
何を記録しても良い事になっています。(なので EOI がファイル終端であるとは限らない)
なので、EOI の後にコメントのセグメントが付与されているファイルもあるようで。


> ASCIIなら1バイトずれるという問題はないはずです。
ずれることが無かったとしても、JPEG ファイル自体が ASCII では無いことは自明なわけですから、
いずれにせよテキストエディタで開くのは、結果の確認方法としては不十分かと思います。

下記の本によれば、そもそも COM セグメントの Character Set は
未定義だそうなので、ASCII 前提という仕様が正しいとも言い切れず…。
https://books.google.co.jp/books?id=AepB_PZ_WMkC&pg=PA107


> ExIFである必要はなく、ASCIIで埋め込めるのなら
> COMセグメントで全く問題ありません。
COM セグメントへの出力だとしたら、.NET Framework 標準の
GDI+ ライブラリ (System.Drawing 名前空間)や
WPF(Avalon) ライブラリ (System.Windows 名前空間)では
扱えないかもしれません。

Exif であっても構わないけれど、ASCII が前提(マルチバイト文字は使用不可)という点は
崩せないというのなら、0x8298 (Copyright) タグを使うのはどうでしょう。
本来は撮影者もしくは加工者を記録するためのタグですが、先に使っていた
BitmapMetadata クラスの Copyright プロパティを使えるので、修正量も軽微かと思います。


> あと、気になっているのですが
> JPEGにしてもPNGにしても
> 埋め込んだ文字列を読み込むにはどうしたら良いのでしょうか?

読み出し方法すら決まってないのなら、ASCII に拘る必要も無いような。

具体的なコードはあえて記載せずにおきますが、JPEG で用いた
BitmapMetadata.Comment については、そのまま読み書きできるので
エンコーダーをデコーダーに変えるだけでいけるはずです。
ちなみに System.Drawing.Bitmap からなら、PropertyItem クラスでも OK。
https://dobon.net/vb/dotnet/graphics/getexifinfo.html

SetQuery した PNG についても同様で、エンコーダーをデコーダーに変えた上で、
GetQuery メソッドを使えば取り出せるはずです。
渡すべきクエリ文字列は、SetQuery/GetQuery 共に同じ。
メタデータの存在チェックが必要な場合は ContainsQuery メソッド、
インプレース更新なら InPlaceBitmapMetadataWriter クラスについて調べてみてください。

ちなみに、BitmapMetadata を For Each することで
メタデータのクエリ文字列を String として列挙できます。
それによって画像ファイル内のすべての情報を得られるわけでは無いですけれど。


あるいは、画像がいったんファイル化されているのなら、
エクスプローラーで ファイルのプロパティの「詳細」タブで視認できますし、
プログラムからは ShellFolderItem.ExtendedProperty メソッドで読みだせそうです。
http://bbs.wankuma.com/index.cgi?mode=al2&namber=15019&KLOG=31

ShellFolderItem だと書き込めないので、編集には別の方法が必要そうですが。
https://ja.stackoverflow.com/questions/17098/
http://eternalwindows.jp/shell/shellex/shellex11.html


> 提示してくださった方法
> https://dobon.net/vb/bbs/log3-44/26468.html
> が、ExIFによるものだったため、
> これを使用しました。

その代替案で十分だったのかどうかが分からないので、
目的が知りたかったのですけれどね。

仮に、ASCII バイナリしか認めないという前提という点が
先に来るなら、XPComment での代用は望めないでしょう。
埋め込んだ文字列を、どのアプリで使うのかにもよるわけですから。

読み書きできれば方法も文字コードも問わない場合、
下記のように色々な実装パターンがあるようです。
(VB から扱いやすいかどうかは考慮せず)
https://www.kanzaki.com/docs/sw/photo-rdf.html
引用返信 編集キー/
■89624 / inTopicNo.27)  Re[22]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (16回)-(2018/12/10(Mon) 20:00:05)
> それは「手段」ですよね。『何のために』埋め込むのかを訊ねています。
> また、何故それが ASCII で無ければならないのかの説明も欲しいです…。

既にお答えしてあるように、
テキストエディタで開いて確認するためです。
なぜテキストエディタではなく、他のソフトを使わないのですか?
という質問なのであれば、
まあ、いろいろあるということにしていただけますでしょうか?


> Exif であっても構わないけれど、ASCII が前提(マルチバイト文字は使用不可)という点は
> 崩せないというのなら、0x8298 (Copyright) タグを使うのはどうでしょう。

Copyrightタグは著作権情報を書き込む場所なので
できれば避けたいと考えています。

上でご回答いただいたように、
UserComment やデータタイプ 2
であれば、ASCII形式で記録できるのではないでしょうか?

これらのタグにテキストを書き込む方法をお教えいただけないでしょうか?


> 具体的なコードはあえて記載せずにおきますが、JPEG で用いた
> BitmapMetadata.Comment については、そのまま読み書きできるので
> エンコーダーをデコーダーに変えるだけでいけるはずです。



デコーダーを使えば良いことは分かりますが、
FileStreamをBitmapMetadataに変換しないと読み込めないと思います

一体どうやってこの変換を行えば良いですか?


引用返信 編集キー/
■89625 / inTopicNo.28)  Re[23]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ 魔界の仮面弁士 (1983回)-(2018/12/10(Mon) 20:36:25)
No89624 (なり さん) に返信
> なぜテキストエディタではなく、他のソフトを使わないのですか?
> という質問なのであれば、
> まあ、いろいろあるということにしていただけますでしょうか?

UCS-2 ならメモ帳でも読めますが、それでも駄目ですか?


> Copyrightタグは著作権情報を書き込む場所なので
> できれば避けたいと考えています。

利用目的がわかれば、それに対する対応策も立てられるのですが、
今のままだと

『こういう方法を使うのはどうですか?』
→「コードを教えてください」
→『たとえばこうです』
→「試してみたけど、要件を満たせませんでした」
→『じゃあ、これならどうですか?』

の繰り返しで「後出しジャンケン」になってしまっているんですよ。(疲
解決のためのヒントはそれなりに挙がっていると思うのですけれど…。


> UserComment やデータタイプ 2
> であれば、ASCII形式で記録できるのではないでしょうか?

VB & C# 向けの具体的なサンプルコードのある URL を、既に紹介していますよね? (^_^;)


> デコーダーを使えば良いことは分かりますが、
> FileStreamをBitmapMetadataに変換しないと読み込めないと思います

…何故ですか? FileStream は必須では無いはずですよね。

先のコードでもデコーダーはすでに利用していましたし、
取得した画像もオンメモリで扱うための手法も既に何度か回答されており、
実際にデコーダーに FileStream を渡すことなく、オンメモリの画像データから
BitmapMetadata を取り出していたように思うのですが…。

デコーダーの生成に必要となる引数情報についても、
クラスのリファレンスを見る限り、必要となるのは FileStream ではなく、
Stream または Uri (あるいは Guid )であるはず。
引用返信 編集キー/
■89635 / inTopicNo.29)  Re[24]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (17回)-(2018/12/11(Tue) 22:22:39)
どうもありがとうございます。

自分でもいろいろ調べてみましたが
.NETの機能でスマートに編集するのは難しそうなので
自分でヘッダーを編集するプログラムを作成することにしました。

勉強になりました。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示

<前の20件
トピック内ページ移動 / << 0 | 1 >>

このトピックに書きこむ