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

わんくま同盟

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

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

ツリー一括表示

画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/05(Wed) 14:39) #89567
Re[1]: 画像ファイルのヘッダーに文字列を埋め込む方法 /kiku (18/12/05(Wed) 15:14) #89568
  └ Re[2]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/05(Wed) 15:32) #89569
    ├ Re[3]: 画像ファイルのヘッダーに文字列を埋め込む方法 /リンクス (18/12/05(Wed) 15:56) #89571
    └ Re[3]: 画像ファイルのヘッダーに文字列を埋め込む方法 /kiku (18/12/05(Wed) 15:48) #89570
      ├ Re[4]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/05(Wed) 16:27) #89573
      │└ Re[5]: 画像ファイルのヘッダーに文字列を埋め込む方法 /Hongliang (18/12/05(Wed) 16:57) #89575
      └ Re[4]: 画像ファイルのヘッダーに文字列を埋め込む方法 /PANG2 (18/12/05(Wed) 16:26) #89572
        └ Re[5]: 画像ファイルのヘッダーに文字列を埋め込む方法 /PANG2 (18/12/05(Wed) 16:49) #89574
          └ Re[6]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/05(Wed) 17:04) #89576
            └ Re[7]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/05(Wed) 20:13) #89577
              └ Re[8]: 画像ファイルのヘッダーに文字列を埋め込む方法 /Hongliang (18/12/05(Wed) 21:24) #89578
                └ Re[9]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/05(Wed) 21:36) #89579
                  └ Re[10]: 画像ファイルのヘッダーに文字列を埋め込む方法 /Hongliang (18/12/05(Wed) 22:13) #89580
                    └ Re[11]: 画像ファイルのヘッダーに文字列を埋め込む方法 /リンクス (18/12/06(Thu) 12:33) #89585
                      └ Re[12]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/07(Fri) 19:12) #89602
                        └ Re[13]: 画像ファイルのヘッダーに文字列を埋め込む方法 /魔界の仮面弁士 (18/12/07(Fri) 19:29) #89603
                          └ Re[14]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/07(Fri) 21:01) #89604
                            └ Re[15]: 画像ファイルのヘッダーに文字列を埋め込む方法 /魔界の仮面弁士 (18/12/08(Sat) 13:19) #89605
                              └ Re[16]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/08(Sat) 15:05) #89606
                                ├ Re[17]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/09(Sun) 18:18) #89610
                                └ Re[17]: 画像ファイルのヘッダーに文字列を埋め込む方法 /魔界の仮面弁士 (18/12/10(Mon) 00:58) #89611
                                  └ Re[18]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/10(Mon) 10:38) #89612
                                    └ Re[19]: 画像ファイルのヘッダーに文字列を埋め込む方法 /魔界の仮面弁士 (18/12/10(Mon) 13:35) #89617
                                      └ Re[20]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/10(Mon) 16:04) #89620
                                        └ Re[21]: 画像ファイルのヘッダーに文字列を埋め込む方法 /魔界の仮面弁士 (18/12/10(Mon) 18:12) #89622
                                          └ Re[22]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/10(Mon) 20:00) #89624
                                            └ Re[23]: 画像ファイルのヘッダーに文字列を埋め込む方法 /魔界の仮面弁士 (18/12/10(Mon) 20:36) #89625
                                              └ Re[24]: 画像ファイルのヘッダーに文字列を埋め込む方法 /なり (18/12/11(Tue) 22:22) #89635 解決済み


親記事 / ▼[ 89568 ]
■89567 / 親階層)  画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (1回)-(2018/12/05(Wed) 14:39:34)

分類:[.NET 全般] 

VB.NETを使って、
JPEGやPNG画像を出力するプログラムを作成しているのですが、
出力した画像のヘッダーに文字列を埋め込みたいと考えています。


JPEGやPNGのヘッダーフォーマットは公開されており、
文字列を埋め込むためのセグメントもあることは分かっています。

http://module.jp/blog/comment_in_imagefile.html

一度、ファイルを出力してから、
再度そのファイルをバイナリデータとして開いて解析し
自作プログラムで文字列を埋め込む、ということはできると思うのですが
何となく二度手間のような気がするため、
できれば、VB.NETの機能を使って
文字列を埋め込みたいのですが
VB.NETにそのような機能はございますでしょうか?







[ □ Tree ] 返信 編集キー/

▲[ 89567 ] / ▼[ 89569 ]
■89568 / 1階層)  Re[1]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ kiku (67回)-(2018/12/05(Wed) 15:14:30)
検索して見てヒットした情報をお知らせします。
内容については検証などしていません。

https://dobon.net/vb/bbs/log3-44/26468.html

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89568 ] / ▼[ 89571 ] ▼[ 89570 ]
■89569 / 2階層)  Re[2]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (3回)-(2018/12/05(Wed) 15:32:13)
ありがとうございます。

コードはまだ試していませんが
この方法は一度画像を出力した後に、バイナリデータとして読み込む方法だと思います。
もし画像出力と同時にヘッダに書き込める方法があれば
教えてください。

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89569 ] / 返信無し
■89571 / 3階層)  Re[3]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ リンクス (8回)-(2018/12/05(Wed) 15:56:23)
kikuさんの提示例は、画像ファイルを読み込んでから、画像データにコメントを書き込み、保存していますので、
ご希望の内容に近いかと思います。
PNGについてはSetQueryを使って対象項目に書き込みできることがkikuさんの提示例にあるますが、
以下の具体例も参考になるかも知れません。

https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/graphics-multimedia/how-to-write-metadata-to-a-bitmap

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89569 ] / ▼[ 89573 ] ▼[ 89572 ]
■89570 / 3階層)  Re[3]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ kiku (68回)-(2018/12/05(Wed) 15:48:09)

tEXtチャンクとExif情報が同一なものかわかりませんが、
同一だと仮定すると、下記の情報が有用かもしれません。

tEXtチャンクが埋め込まれている画像ファイルを
なんとか用意し、下記URLを参考に、読み込めるのか確認し、
読み込めるのであるならば、設定もできように思います。

https://dobon.net/vb/dotnet/graphics/getexifinfo.html#section5

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89570 ] / ▼[ 89575 ]
■89573 / 4階層)  Re[4]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (4回)-(2018/12/05(Wed) 16:27:25)
ありがとうございます。

少し質問内容が伝わっていないようなのですが、
例えば、

Dim img As Bitmap = New Bitmap(Nx, Ny, PixelFormat.Format8bppIndexed)

で定義した画像データがあり、
これをPNGあるいはJPEGとして出力すると同時にヘッダーに文字列を書き込みたいという意味なのですが。
https://dobon.net/vb/bbs/log3-44/26468.html

この方法だと、一度画像を保存してから
再度、そのファイルを読み込んで
更に、保存し直さないといけないと思うのですが。

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89573 ] / 返信無し
■89575 / 5階層)  Re[5]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ Hongliang (725回)-(2018/12/05(Wed) 16:57:05)
System.Drawing.Bitmapの場合、とりあえずjpeg/tiffにおいては
ID=&H9c9c, Type=1, Value=末尾にChrW(0)を付けたUnicodeバイト配列
を格納したPropertyItemをSetPropertyItemすることで行けるようですね。

PropertyItemを確保するためには一旦ダミーのBitmapを作成した上でMemoryStreamにでもtiffやjpegで保存し、それをロードしてPropertyItemsから拾ってくるという面倒な手法が必要ですが。

pngは保存時にはPropertyItemは確か無視していた記憶があるので、多分System.Drawingでは無理じゃないかな。

比較的手軽な方法としては、例えばこんなのとか。
1. MemoryStreamに目的のフォーマットでBitmapをSaveする
2. MemoryStreamからBitmapDecoderで開く
3. CreateInPlaceBitmapMetadataWriterを使ってメタデータをインプレース更新
4. MemoryStreamをファイルに吐き出す
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89570 ] / ▼[ 89574 ]
■89572 / 4階層)  Re[4]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ PANG2 (253回)-(2018/12/05(Wed) 16:26:07)
全く試していないが、

JpegBitmapEncoder
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.media.imaging.jpegbitmapencoder.-ctor?view=netframework-4.7.2

のサンプルで、
encoder.Metadata.Comment = "hello";

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89572 ] / ▼[ 89576 ]
■89574 / 5階層)  Re[5]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ PANG2 (254回)-(2018/12/05(Wed) 16:49:14)
2018/12/06(Thu) 17:27:11 編集(投稿者)

MemoryStream に保存

MemoryStream bitmapStream = new MemoryStream();
img.Save(bitmapStream, ImageFormat.Bmp);
bitmapStream.Position = 0;
encoder.Frames.Add(BitmapFrame.Create(bitmapStream));

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89574 ] / ▼[ 89577 ]
■89576 / 6階層)  Re[6]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (5回)-(2018/12/05(Wed) 17:04:42)
ありがとうございます。

ID=&H9c9c, Type=1, Value=末尾にChrW(0)を付けたUnicodeバイト配列
を格納したPropertyItemをSetPropertyItemすることで行けるようですね。

というのはどういうコードになりますでしょうか?


あと、できれば、保存してあるPNGやJPEG画像のヘッダー情報から
ASCIIデータを取得する方法もお教えいただけないでしょうか?

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89576 ] / ▼[ 89578 ]
■89577 / 7階層)  Re[7]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (7回)-(2018/12/05(Wed) 20:13:05)
https://dobon.net/vb/bbs/log3-44/26468.html

このコードを試してみたのですが、
PngBitmapDecoder
BitmapCreateOptions

などいろいろな場所でエラーが出てしまいます。
https://dobon.net/vb/dotnet/graphics/selectactiveframe.html

このページを参考に
'Imports System.Windows.Media.Imaging
'Imports System.IO
'Imports System.Drawing
'Imports System.Windows.Forms

をファイルの先頭に入れてみたのですが、
この名前空間が含まれていないというエラーがでます。

文章を読むとこれはWPF用のコードだと思います

いま作成しているのは、普通のフォームアプリケーションですので
これらのコードを使用することはできないのではないでしょうか?


[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89577 ] / ▼[ 89579 ]
■89578 / 8階層)  Re[8]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ Hongliang (726回)-(2018/12/05(Wed) 21:24:19)
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.media.imaging.pngbitmapdecoder
Docsの該当クラスを見れば、Assemblyのところに参照が必要なDLLが書かれています。
もしそのDLLが更に他のDLLの参照を必要としてる場合、ビルドした時に「〜〜も参照しろ」的なエラーメッセージを出してくれるはずです。
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89578 ] / ▼[ 89580 ]
■89579 / 9階層)  Re[9]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (8回)-(2018/12/05(Wed) 21:36:06)
ありがとうございます。

VBコードに翻訳してみたのですが



<System.Security.SecurityCritical>
Public Sub New(ByVal bitmapStream As System.IO.Stream, ByVal createOptions As System.Windows.Media.Imaging.BitmapCreateOptions, ByVal cacheOption As System.Windows.Media.Imaging.BitmapCacheOption)
End Sub


やはり、エラーが出ます
というか、正常に翻訳できていないように見えるのですが
http://www.carlosag.net/Tools/CodeTranslator/
http://converter.telerik.com/

二つ翻訳サイトを試してみましたが駄目でした。
どのようにしたら良いですか?

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89579 ] / ▼[ 89585 ]
■89580 / 10階層)  Re[10]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ Hongliang (727回)-(2018/12/05(Wed) 22:13:58)
Docsへのリンクを張ったのは参照に追加するAssemblyをご確認いただくためだけだったのですが、ひょっとして「参照」というのが何なのか分からないということでしょうか。

Visual Studioのソリューションエクスプローラを見れば、「参照」というのがあります。
これを右クリックして「参照の追加」を選ぶと、「参照マネージャ」というダイアログが開きます。
手元のVisual Studio 2015だと、.NETが標準で提供しているライブラリの場合は左の「アセンブリ」-「フレームワーク」のを選ぶと真ん中にDLLの一覧が表示されるので、その中から必要なAssemblyにチェックを入れ([名前]の左側に出るチェックボックスをチェックする)、OKボタンをクリックします。
この辺はご使用のVisual Studioのバージョンによって多少差異があるかも知れませんが、おおよその操作は同じはずです。

あと、「エラーが出る」だけではなく、エラーメッセージも記載していただかないと、適切な回答が困難になります。
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89580 ] / ▼[ 89602 ]
■89585 / 11階層)  Re[11]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ リンクス (9回)-(2018/12/06(Thu) 12:33:26)
2018/12/06(Thu) 12:37:00 編集(投稿者)

今回追加の参照設定が必要なアセンブリは、多分PresentationCoreですね。
対象の名前空間System.Windows.Mediaとアセンブリ名がイマイチ合致しないヤツだったので、覚えています。
あとは、Hongliangさん提示の手順で参照の追加をすれば良いです。
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89585 ] / ▼[ 89603 ]
■89602 / 12階層)  Re[12]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (9回)-(2018/12/07(Fri) 19:12:32)
ありがとうございます。

とりあえず、掲示板に書かれた通りのまま、
既に保存してある画像がイメージを読み込む方法を試してみました。


        Using StreamIn As New MemoryStream(File.ReadAllBytes(bmpFilename))
            Dim dec As New PngBitmapDecoder(StreamIn, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None)

            Using StreamOut As FileStream = File.Open(bmpFilename, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite)
                Dim enc As New BitmapEncoder
                Dim frm As BitmapFrame = BitmapFrame.Create(dec.Frames(0))
                enc.Frames.Add(frm)
                Dim meta As BitmapMetadata = DirectCast(frm.Metadata, BitmapMetadata)
                meta.Comment = "Data"
                enc.Frames.Add(BitmapFrame.Create(frm, Nothing, meta, Nothing))
                enc.Save(StreamOut)
            End Using

        End Using

しかし、
Dim enc As New BitmapEncoder
のところで、
'MustInherit' として宣言されたクラスでは、'New' を使用することはできません。

というエラーが出ます。

仕方なく、

        Using StreamIn As New MemoryStream(File.ReadAllBytes(bmpFilename))
            Dim dec As New PngBitmapDecoder(StreamIn, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None)

            Using StreamOut As FileStream = File.Open(bmpFilename, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite)
                Dim enc As BitmapEncoder = Nothing
                Dim frm As BitmapFrame = BitmapFrame.Create(dec.Frames(0))
                enc.Frames.Add(frm)
                Dim meta As BitmapMetadata = DirectCast(frm.Metadata, BitmapMetadata)
                meta.Comment = "Data"
                enc.Frames.Add(BitmapFrame.Create(frm, Nothing, meta, Nothing))
                enc.Save(StreamOut)
            End Using

        End Using

のようにすると、

enc.Frames.Add(frm)
のところでインスタンスが設定されていない、というエラーが出ます。

一体、どうすれば良いですか?



更に、画像をファイルではなく、イメージから読み込む方法も試してみたのですが、



        Dim bitmapStream As MemoryStream = New MemoryStream
        img.Save(bitmapStream, ImageFormat.Png)
        bitmapStream.Position = 0
        Dim enc As BitmapEncoder = Nothing

        Dim dec As New PngBitmapDecoder(StreamIn, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None)

        Dim frm As BitmapFrame = BitmapFrame.Create(dec.Frames(0))
        enc.Frames.Add(BitmapFrame.Create(bitmapStream))


        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.Open, System.IO.FileAccess.ReadWrite)
        enc.Save(StreamOut)



        Dim dec As New PngBitmapDecoder(StreamIn, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None)


のところで、画像ファイルのパスを指定する必要があります。

どのようにすれば、一度も画像ファイルを書き出さずに
文字列を書き込んだ画像ファイルを保存することができますか?



[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89602 ] / ▼[ 89604 ]
■89603 / 13階層)  Re[13]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ 魔界の仮面弁士 (1977回)-(2018/12/07(Fri) 19:29:53)
No89602 (なり さん) に返信
> Dim enc As New BitmapEncoder
> のところで、
> 'MustInherit' として宣言されたクラスでは、'New' を使用することはできません。

エラーメッセージに書かれた文字通りの意味なので、
画像形式に合わせた派生クラスを生成してみてください。

New BmpBitmapEncoder()
New PngBitmapEncoder()
New JpegBitmapEncoder()
New GifBitmapEncoder()
New TiffBitmapEncoder()
New WmpBitmapEncoder()


> enc.Frames.Add(frm)
> のところでインスタンスが設定されていない、というエラーが出ます。
enc が Nothing だからでしょう。


> Dim dec As New PngBitmapDecoder(StreamIn, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None)
> のところで、画像ファイルのパスを指定する必要があります。
第一引数のことでしょうか。Byte 配列からの MemoryStream 等では駄目でしたか?
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89603 ] / ▼[ 89605 ]
■89604 / 14階層)  Re[14]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (11回)-(2018/12/07(Fri) 21:01:44)
ありがとうございます。

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

Dim dec As New JpegBitmapDecoder(bitmapStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None)

Dim frm As BitmapFrame = BitmapFrame.Create(dec.Frames(0))
enc.Frames.Add(BitmapFrame.Create(bitmapStream))


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.Open, System.IO.FileAccess.ReadWrite)
enc.Save(StreamOut)




とやるとエラーは出なくなったのですが
実行しようとすると、


enc.Frames.Add(BitmapFrame.Create(bitmapStream))


で、

型 'System.NotSupportedException' のハンドルされていない例外が PresentationCore.dll で発生しました

追加情報:この処理を完了するために必要なイメージング コンポーネントが見つかりませんでした。


というエラーが発生します

一体なぜでしょうか?





[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89604 ] / ▼[ 89606 ]
■89605 / 15階層)  Re[15]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ 魔界の仮面弁士 (1978回)-(2018/12/08(Sat) 13:19:41)
No89604 (なり さん) に返信
> とやるとエラーは出なくなったのですが
> enc.Frames.Add(BitmapFrame.Create(bitmapStream))
> 型 'System.NotSupportedException' のハンドルされていない例外が PresentationCore.dll で発生しました

エンコーダーとデコーダーとで、共に同一の MemoryStream を
使いまわしているからでは?

同じデータが必要なら、先に書いたように
「Byte 配列からの MemoryStream 等」を渡してみてください。
元の MemoryStream を CopyTo しても OK です。

たとえば、
 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))
とか。
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89605 ] / ▼[ 89610 ] ▼[ 89611 ]
■89606 / 16階層)  Re[16]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (12回)-(2018/12/08(Sat) 15:05:15)

ありがとうございます。

        Dim outStream As New MemoryStream(bitmapStream.ToArray())
        Dim dec As New PngBitmapDecoder(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()



これで文字列を埋め込むことができました。

しかし、この方法だと

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

これは一体どうすれば良いでしょうか?

後、同様にPNG画像にも文字列を埋め込もうとしてみたのですが、

https://dobon.net/vb/bbs/log3-44/26468.html

このページにも書かれてあるように
「このコーデックは、指定されたプロパティをサポートしていません。」という例外が発生してしまいます。


png の場合、/tEXt/Comment クエリ文字列で SetQuery メソッドを使って書き込むようです。

と回答が書かれてありますが
これは具体的にどのようにしたら良いのでしょうか?


[ 親 89567 / □ Tree ] 返信 編集キー/

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

[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89606 ] / ▼[ 89612 ]
■89611 / 17階層)  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
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89611 ] / ▼[ 89617 ]
■89612 / 18階層)  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データとして埋め込みたいのですが
どのようにすれば良いですか?

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


[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89612 ] / ▼[ 89620 ]
■89617 / 19階層)  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 名前空間)ではなく、
オープンソースのライブラリ等に頼ることになるかもしれません。
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89617 ] / ▼[ 89622 ]
■89620 / 20階層)  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に変換するにはどうしたら良いですか?








[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89620 ] / ▼[ 89624 ]
■89622 / 21階層)  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
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89622 ] / ▼[ 89625 ]
■89624 / 22階層)  Re[22]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (16回)-(2018/12/10(Mon) 20:00:05)
> それは「手段」ですよね。『何のために』埋め込むのかを訊ねています。
> また、何故それが ASCII で無ければならないのかの説明も欲しいです…。

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


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

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

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

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


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



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

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


[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89624 ] / ▼[ 89635 ]
■89625 / 23階層)  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 )であるはず。
[ 親 89567 / □ Tree ] 返信 編集キー/

▲[ 89625 ] / 返信無し
■89635 / 24階層)  Re[24]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (17回)-(2018/12/11(Tue) 22:22:39)
どうもありがとうございます。

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

勉強になりました。

解決済み
[ 親 89567 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -