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

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

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

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

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

■89567 / inTopicNo.1)  画像ファイルのヘッダーに文字列を埋め込む方法
  
□投稿者/ なり (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にそのような機能はございますでしょうか?







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

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

引用返信 編集キー/
■89569 / inTopicNo.3)  Re[2]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (3回)-(2018/12/05(Wed) 15:32:13)
ありがとうございます。

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

引用返信 編集キー/
■89570 / inTopicNo.4)  Re[3]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ kiku (68回)-(2018/12/05(Wed) 15:48:09)

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

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

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

引用返信 編集キー/
■89571 / inTopicNo.5)  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

引用返信 編集キー/
■89572 / inTopicNo.6)  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";

引用返信 編集キー/
■89573 / inTopicNo.7)  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

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

引用返信 編集キー/
■89574 / inTopicNo.8)  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));

引用返信 編集キー/
■89575 / inTopicNo.9)  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をファイルに吐き出す
引用返信 編集キー/
■89576 / inTopicNo.10)  Re[6]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ なり (5回)-(2018/12/05(Wed) 17:04:42)
ありがとうございます。

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

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


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

引用返信 編集キー/
■89577 / inTopicNo.11)  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用のコードだと思います

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


引用返信 編集キー/
■89578 / inTopicNo.12)  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の参照を必要としてる場合、ビルドした時に「〜〜も参照しろ」的なエラーメッセージを出してくれるはずです。
引用返信 編集キー/
■89579 / inTopicNo.13)  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/

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

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

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

あと、「エラーが出る」だけではなく、エラーメッセージも記載していただかないと、適切な回答が困難になります。
引用返信 編集キー/
■89585 / inTopicNo.15)  Re[11]: 画像ファイルのヘッダーに文字列を埋め込む方法
□投稿者/ リンクス (9回)-(2018/12/06(Thu) 12:33:26)
2018/12/06(Thu) 12:37:00 編集(投稿者)

今回追加の参照設定が必要なアセンブリは、多分PresentationCoreですね。
対象の名前空間System.Windows.Mediaとアセンブリ名がイマイチ合致しないヤツだったので、覚えています。
あとは、Hongliangさん提示の手順で参照の追加をすれば良いです。
引用返信 編集キー/
■89602 / inTopicNo.16)  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)


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

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



引用返信 編集キー/
■89603 / inTopicNo.17)  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 等では駄目でしたか?
引用返信 編集キー/
■89604 / inTopicNo.18)  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 で発生しました

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


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

一体なぜでしょうか?





引用返信 編集キー/
■89605 / inTopicNo.19)  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))
とか。
引用返信 編集キー/
■89606 / inTopicNo.20)  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 メソッドを使って書き込むようです。

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


引用返信 編集キー/

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

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

管理者用

- Child Tree -