画像をUDPで送りそれを受信する側でフォームに貼り付けるプログラムについて
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 5,054
現在質問タイトルのようなプログラムを作っていて一応は動くようになったのですが、理想していたものとはかけ離れた状態に困惑しています。
完成イメージはマウスの動きを認識できるくらいスムーズに画像を変えていきたかったのですが、それ以前に一枚目もロクに表示できずかろうじて画面の上部分1/5くらいがフォームに表示される程度でした。
そして非常に重いです。これでは今後考えている機能追加にも困ります。ネットワークのプログラムを書くのは初めてなのですが、なぜこんなに重くなるのでしょうか。
またスムーズに画像を変えていくにはどんな風にプログラムを改変すればよいのか教えてください。
画像を撮って送るほうのプログラム
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace ControlServer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.SendImage();
}
public async void SendImage()
{
while (true)
{
int cnt = 0;
List<byte> bytelist = new List<byte>();
IPEndPoint remote = new IPEndPoint(IPAddress.Parse("192.168.1.59"), 8000);
byte[] imgbyte = ScreenCapture.CaptureBitmap();
await Task.Delay(1000);
Back : for (; cnt < imgbyte.Length; cnt++)
{
try {
if (imgbyte.Length - cnt < 1300)
{
using (var client = new UdpClient(8001))
{
client.Connect(remote);
byte[] remain = imgbyte.Skip(cnt).Take(imgbyte.Length - cnt).ToArray();
await client.SendAsync(remain, remain.Length);
}
using (var client = new UdpClient(8001))
{
client.Connect(remote);
byte[] end = Encoding.UTF8.GetBytes("end");
await client.SendAsync(end, end.Length);
}
break;
}
if (bytelist.Count == 1300)
{
using (var client = new UdpClient(8001))
{
client.Connect(remote);
await client.SendAsync(bytelist.ToArray(), bytelist.ToArray().Length);
}
bytelist = new List<byte>();
await Task.Delay(10);
}
else
{
bytelist.Add(imgbyte[cnt]);
}
}
catch(Exception)
{
MessageBox.Show("エラー");
goto Back;
}
}
}
}
}
// 画面をとりbyte配列にして返す
static class ScreenCapture
{
public static byte[] CaptureBitmap()
{
byte[] byteimage;
Bitmap bm = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
using (var mms = new MemoryStream())
{
using (var graphics = Graphics.FromImage(bm))
{
graphics.CopyFromScreen(new Point(0, 0), new Point(0, 0), bm.Size);
bm.Save(mms, System.Drawing.Imaging.ImageFormat.Jpeg);
byteimage = mms.GetBuffer();
}
mms.Close();
}
return byteimage;
}
}
}
受け取ってフォームに表示するプログラム
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ControlClient
{
public partial class Form1 : Form
{
private List<byte[]> ImageConnect { get; set; } = new List<byte[]>();
public Form1()
{
InitializeComponent();
this.ListenMessage();
}
public async void ListenMessage()
{
var local = new IPEndPoint(IPAddress.Any, 8000);
var remote = new IPEndPoint(IPAddress.Any, 8000);
var client = new UdpClient(local);
while (true)
{
var recieve = await client.ReceiveAsync();
byte[] result = recieve.Buffer;
if (Encoding.UTF8.GetString(result) == "end") // endが送られてきたらbyte配列を全部送ったことに
{
byte[] linking = null;
for(int i=0; i<this.ImageConnect.Count; i++) // List<byte[]>を1つのbyte[]でつなぎ合わせる
{
if(i == 0)
{
linking = Enumerable.Concat(this.ImageConnect[0], this.ImageConnect[1]).ToArray();
}
else
{
if (i + 1 > this.ImageConnect.Count-1) break;
linking = Enumerable.Concat(linking, this.ImageConnect[i + 1]).ToArray();
}
}
ImageConverter imgconv = new ImageConverter();
Image img = (Image)imgconv.ConvertFrom(linking); // byte配列をImageオブジェクトへ
this.OnRecieve(img);
this.ImageConnect = new List<byte[]>();
}
else
{
this.ImageConnect.Add(result);
}
}
}
private void OnRecieve(Image img) // フォームのバックグラウンドイメージに
{
this.Width = img.Width + 5;
this.Height = img.Height + 20;
this.BackgroundImage = img;
}
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
まずは、データは圧縮しましょう。
次に各処理の時間を測って見ましょう。
ImageConnectはListよりも効率の良いものにしましょう。
毎回全フレームを送るのではなく、変化があった領域だけ送りましょう、
と言ってもまだまだ足りないので、、、
以下のコンポーネントなどの活用を考えましょう。
http://devlights.hatenablog.com/entry/20091120/p1
ところで、ループ処理も例えば以下のように改善が必要です。
for (; cnt < imgbyte.Length; 4096 )
{
sendsize = min( 4096, imagebyte.Length-cnt );
Array.Copy(imagebyte, cnt, sendBuffer, 0, sendsize);
cnt += sendsize;
sendBufferを送る
}
endを送る
udpを使う場合はデータの到達順序やデータが消えることなども考慮が必要です。画像を一枚送るだけでもそこそこコツが必要です、TCPを使った方が良いですね。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.09%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/01/26 00:54
2017/01/26 01:14
高速化については、転送量を少なくすることを考えましょう。