質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

3回答

1971閲覧

VB.NETで制御している装置(オシロ)から画像データを取得したい(解決しました)

退会済みユーザー

退会済みユーザー

総合スコア0

VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2021/04/08 12:17

編集2021/04/11 22:27

前提・実現したいこと

オシロの画像データをVB.NETで取得しようとしています。
オシロメーカーからバイナリデータの出力の仕方は教わったのですが、肝心なその後の画像ファイルにする方法までは教えてくれませんでした。

画像データの拡張子はPNGです。
画像データを扱うのは初めてなので、やり方がさっぱり分からないです。
装置メーカーに画像ファイルの生成方法を聞くのも違うかなと思って、こちらに質問を出させていただきました。

発生している問題

バイナリデータもちゃんと取得できているか分かりませんが、ほかのコマンドで測定値は読めるので、出力されている前提でお願いします。 バイナリデータの取り込み方はいろいろと調べて、「試したこと」に記載したコードは見つけました。 ですが、これをどう使うのかが分かりません。

該当のソースコード

VB.NET

1Private Sub hard_copy_Click(sender As Object, e As EventArgs) Handles hard_cpopy.Click 2 3 SerialPort1.Open() 4 5 SerialPort1.WriteLine("HARDCOPY:PORT RS232") 6 SerialPort1.WriteLine("HARDCOPY:FORMAT PNG") 7 SerialPort1.WriteLine("HARDCOPY START") 'ここからバイナリデータが出力されるとメーカーから教わった 8 9    'ここに下記コードでデータは取得できそうですが、そこからPNGファイルに変換したいです 10    '画像ファイルに変換できるのなら、別の方法でも可です 11 12    SerialPort1.Close() 13 14 End Sub

解決したコード

バイト配列をImageオブジェクトに変換するFunctionを追加しています。
(Web上から見つけました)

VB.NET

1 Private Sub hard_cpopy_Click(sender As Object, e As EventArgs) Handles hard_cpopy.Click 2 SerialPort1.Open() 3 SerialPort1.WriteLine("HARDCOPY:PORT RS232") 4 SerialPort1.WriteLine("HARDCOPY:LAYOUT PORTRAIT") 5 SerialPort1.WriteLine("HARDCOPY:INKS ON") 6 SerialPort1.WriteLine("HARDCOPY:FORMAT TIF") 7 SerialPort1.WriteLine("HARDCOPY START") 8 9 Dim img As Byte() 10 img = ReadBinaryData(SerialPort1) 11 12 Dim img2 As Image = ByteArrayToImage(img) 13 14 img2.Save("hard.tif", System.Drawing.Imaging.ImageFormat.Tiff) 15 16 SerialPort1.Close() 17 18 End Sub 19 20 ' バイト配列をImageオブジェクトに変換 21 Public Shared Function ByteArrayToImage(ByVal b As Byte()) As Image 22 Dim img As Image = CType(imgconv.ConvertFrom(b), Image) 23 Return img 24 End Function 25 26 Public Function ReadBinaryData(st As SerialPort) As Byte() 27 Dim buf(32768) As Byte ' 一時バッファ 28 '無限に待たれても困るので、ReadTimeoutがInfiniteTimeoutならとりあえず10秒に設定 29 If st.ReadTimeout = SerialPort.InfiniteTimeout Then 30 st.ReadTimeout = 10000 31 End If 32 Using ms As New MemoryStream() 33 While (True) 34 Try 35 ' シリアルポートから一時バッファに読み込む 36 Dim read As Integer = st.Read(buf, 0, buf.Length) 37 If read > 0 Then 38 ' 一時バッファの内容をメモリ・ストリームに書き込む 39 ms.Write(buf, 0, read) 40 Else 41 Exit While 42 End If 43 Catch ex As TimeoutException 44 'タイムアウト処理も入れておく 45 Exit While 46 End Try 47 End While 48 ' メモリ・ストリームの内容をバイト配列に格納 49 Return ms.ToArray() 50 End Using 51 End Function

上記のコードで期待するTIFF画像を得ることができました。
課題は10秒待たないとTIFFが得られないこと。
オシロからのTIFFデータの転送終了を知ることが出来れば完璧ですが、とりあえず及第点です。

回答いただいた方、ありがとうございました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YAmaGNZ

2021/04/09 00:22

このプロトコルって画像データの終わりはどうやって知るんですかね?
退会済みユーザー

退会済みユーザー

2021/04/09 00:30

メーカーからは下記の回答を得ています。 「また、RS232のようなインターフェースでは転送の終了を確認する方法がないので ご注意ください。転送されるデータがASCIIであれば、CRやLFをもって転送終了と する事もできますが、バイナリデータではそれができません。複数回読み込みを 行っていただき、データがある程度(10秒程度)来ない事を確認して転送の終了と するのが確実です。」 この文言も理解できていないです。。。 まずは出来るところからと思っています。
退会済みユーザー

退会済みユーザー

2021/04/09 01:20

タイムアウト処理が必要であれば、ReadTimeout既定値では無限に待ち続けるので適切な値を設定してください。(10秒なら10000)
退会済みユーザー

退会済みユーザー

2021/04/10 03:40

昨日、保管している装置を確認したのですが、画像保存の形式がPNGに対応していないものもありました。 TIFFなら全部対応していたので、こちらに変更するしかなさそうです。 PNG対応とTIFF対応の2つのコードを書くのは大変そうなので。。。
退会済みユーザー

退会済みユーザー

2021/04/11 23:12 編集

解決したコードが私の修正したサンプルのコードと同じようですが、ベストアンサーではない理由をお聞かせ願えますか?自力では到達出来なかったコードなのに、及第点とか言われてるのもイラっとするんですが。
退会済みユーザー

退会済みユーザー

2021/04/12 03:02

不快な思いさせて、すみませんでした。 ベストアンサーにしなかったのは、当初はPNGを想定していたので、その解決法を示してくださった方を選んだためです。 ベストアンサーは一つしか選べなかったので、高評価を付けさせていただきました。
guest

回答3

0

~~試したことに提示されているReadBinaryDataに、SerialPortのBaseStreamを渡し、~~戻ってきたバイト配列を、File.WriteAllBytesでファイルに出力すればよいのではないでしょうか。

BaseStreamはReadTimeoutを考慮してくれないようなので、SerialPortオブジェクトをそのまま使用した方がよいかもしれません。サンプルソースを少し弄ってみました。(デバッグはしてないです)

vbnet

1Public Function ReadBinaryData(st As SerialPort) As Byte() 2 3 Dim buf(32768) As Byte ' 一時バッファ 4 5 '無限に待たれても困るので、ReadTimeoutがInfiniteTimeoutならとりあえず10秒に設定 6 If st.ReadTimeout = SerialPort.InfiniteTimeout Then 7 st.ReadTimeout = 10000 8 End If 9 10 Using ms As New MemoryStream() 11 12 While (True) 13 Try 14 ' シリアルポートから一時バッファに読み込む 15 Dim read As Integer = st.Read(buf, 0, buf.Length) 16 17 If read > 0 Then 18 ' 一時バッファの内容をメモリ・ストリームに書き込む 19 ms.Write(buf, 0, read) 20 Else 21 Exit While 22 End If 23 24 Catch ex As TimeoutException 25 'タイムアウト処理も入れておく 26 Exit While 27 End Try 28 End While 29 30 ' メモリ・ストリームの内容をバイト配列に格納 31 Return ms.ToArray() 32 33 End Using 34End Function

投稿2021/04/08 23:56

編集2021/04/09 01:37
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/04/09 03:58

今日は実機を使ってデバックできないので、来週確認したいと思います。 複数の回答をいただいているので、いろいろと試してみたいと思います。
退会済みユーザー

退会済みユーザー

2021/04/10 08:52

TIFFに保存形式を変更することにしましたので、いったんクローズします。 TIFFだと総バイト数が最初のほうのヘッダーから計算できるようなので、ちょっと頑張ってみます。 また質問させていただくときは、よろしくお願いします。
退会済みユーザー

退会済みユーザー

2021/04/11 08:22 編集

結局、戻ってきたバイトデータをファイルに書き出すだけなので、送信コマンドが変わるくらいだと思いますけどね。通信が途中で切れたりする場合を想定するなら、いずれにしてもタイムアウト例外の処理は必要不可欠です。
guest

0

「また、RS232のようなインターフェースでは転送の終了を確認する方法がないので

ご注意ください。転送されるデータがASCIIであれば、CRやLFをもって転送終了と
する事もできますが、バイナリデータではそれができません。複数回読み込みを
行っていただき、データがある程度(10秒程度)来ない事を確認して転送の終了と
するのが確実です。」

とのことですので、最終データ受信から10秒データの受信がなかったら画像データ終了とみなすしかないかと思います。(10秒間未受信というのも長いような気もしますが)
ただし、10秒間データを受信しなかったから正常に画像データを受信できたかの保障はありません。

VBNET

1 Public Sub ReadBinaryData(st As Stream, filename As String) 2 3 Dim buf(32768) As Byte ' 一時バッファ 4 Dim lastRecive As DateTime = Now 5 6 Using fs As New FileStream(filename, FileMode.Create, FileAccess.Write) 7 8 While (True) 9 ' ストリームから一時バッファに読み込む 10 Dim read As Integer = st.Read(buf, 0, buf.Length) 11 12 If read > 0 Then 13 ' 一時バッファの内容をメモリ・ストリームに書き込む 14 fs.Write(buf, 0, read) 15 lastRecive = Now 16 Else 17 if (Now - lastRecive).TotalSeconds > 10 Then 18 Exit While 19 End If 20 End If 21 End While 22 23 End Using 24 End Sub

上記ソースはイメージです(コンパイルも動作確認もしていません)

投稿2021/04/09 00:50

YAmaGNZ

総合スコア10489

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/04/09 04:00

10秒待ちのソース追加ありがとうございます。 今日は実機を使ってデバックできないので、来週確認したいと思います。
退会済みユーザー

退会済みユーザー

2021/04/10 08:51

TIFFに画像形式を変更するので、いったんクローズとします。 TIFFの構造は勉強開始したばかりですが、また質問させていただくときは、よろしくお願いします。
guest

0

ベストアンサー

おそらく、pngなのかjpegなのかは問題ではなく、読んだByte配列をファイルに書けば良いので、

vbnet

1    'ここに下記コードでデータは取得できそうですが、そこからPNGファイルに変換したいです 2    '画像ファイルに変換できるのなら、別の方法でも可です 3 Dim buf(SerialPort1.BytesToRead) As Byte 4 SerialPort1.Read(buf, 0, SerialPort1.BytesToRead) 5 File.WriteAllBytes("aaa.png", buf)

これで良い気がします。

(追記)

pngデータの終わりはIENDチャンクというのを認識すれば良いみたいです。
上記を削除して、下記参考にデバッグしてみてください。

vbnet

1 Dim fs As FileStream 2 Dim last12Bytes(12) As Byte 3 Dim allBytes As Byte() = {} 4 5 fs = File.Create("aaa.png") 6 While Not isIEND(last12Bytes) 7 Dim buf(SerialPort1.BytesToRead) As Byte 8 SerialPort1.Read(buf, 0, SerialPort1.BytesToRead) 9 allBytes = allBytes.Concat(buf) 10 last12Bytes = allBytes.Skip(allBytes.Length - 12).Take(12) 11 End While 12 fs.Write(allBytes, 0, allBytes.Length) 13 End Sub 14 15 'IENDチャンクが来たらファイル終わり 16 '00 00 00 00 "IEND" AE 42 60 82 17 Private Function isIEND(last12Bytes() As Byte) As Boolean 18 Dim iend() As Byte = 19 New Byte() {&H0, &H0, &H0, &H0} _ 20 .Concat("IEND".Select(Of Byte)( 21 Function(c) 22 Return Byte.Parse(c) 23 End Function)) _ 24 .Concat({&HAE, &H42, &H60, &H82}) 25 26 Return last12Bytes.SequenceEqual(iend) 27 28 End Function 29

ソースの先頭にこれが要るかも。

Imports System.IO

投稿2021/04/08 18:14

編集2021/04/09 04:22
neuromancer

総合スコア72

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/04/08 23:36

コードに追加して実行してみたところ、ファイルサイズ1バイトのaaa.pngが作成されました。 aaa.pngが作成された後も装置はBUSY状態だったので、すべてのデータは取り込めていないようです。 もう少しデバックを続けます。
neuromancer

2021/04/09 03:37

実行してないので、細部が正しいかわかりません。 途中で止めたりして変数の内容を見てみてください。 fs は閉じてあげるほうがお行儀が良い、とか、いろいろあると思います。
neuromancer

2021/04/09 03:38

12:18のコメントは削除依頼してます
neuromancer

2021/04/09 03:40

isIENDが成立しないと無限ループするので、対策必要かもです。
退会済みユーザー

退会済みユーザー

2021/04/09 03:54

いろいろと情報ありがとうございます。 今日は実機を使ってデバックできないので、来週確認したいと思います。
退会済みユーザー

退会済みユーザー

2021/04/10 03:42

PNGについて調べていただいたところ、申し訳ないのですが、一部非対応の機種がありました。 なので、TIFFで保存することに変更します。 TIFFについては仕様書がWeb上に公開されていたので、自分で勉強してみます。
退会済みユーザー

退会済みユーザー

2021/04/10 08:49

保存形式をTIFFに変更するので、この問いはいったんクローズします。 TIFFの構造の勉強を開始しましたが、また質問させていただくかもしれません。 その際はまた、よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問