gpt4 book ai didi

c# - 需要更快地实现 Image.FromStream 以实时显示图像

转载 作者:太空宇宙 更新时间:2023-11-03 20:34:14 25 4
gpt4 key购买 nike

我正在创建一个远程桌面程序,因此我开发了一个类,用于拍摄客户端计算机的快照并将每个图像以字节数组格式发送到服务器。然后服务器读取这些字节并将流转换为 System.Drawing.Image 类型。但是 Image.FromStream 花费的时间太长。每次我断点下面的这条线时,它都会卡住。没有异常被抛出,在那行代码之后什么也没有发生。

导致问题的线路:

StreamingData(client, new DataEventArgs(Image.FromStream(stream, false, false)));

完整代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
using System.Drawing;
namespace Simply_Remote_Desktop_Library
{
public sealed class RemoteDesktopListener
{
private TcpListener listner;
private TcpClient client;
public delegate void ConnectedEventHandler(TcpClient sender, EventArgs e);
public event ConnectedEventHandler Connected;
public delegate void IncommingDataEventHandler(TcpClient sender, DataEventArgs e);
public event IncommingDataEventHandler StreamingData;
public delegate void ConnectionEndedEventHandler(RemoteDesktopListener sender, EventArgs e);
public event ConnectionEndedEventHandler ConnectionEnded;
/// <summary>
/// Constructor (+1 Overloads)
/// </summary>
/// <param name="port">The port to listen for incoming connections.</param>
/// <param name="host_ip">The IP address of the client computer.</param>
public RemoteDesktopListener(int port, string host_ip)
{
IPAddress addr;
if (IPAddress.TryParse(host_ip, out addr))
{
if (port > 0 || port < 65535)
{
listner = new TcpListener(addr, port);
}
else if (port < 0 || port > 65535)
{
throw new RemoteDesktopException(new ArgumentOutOfRangeException("port"));
}
}
else
{
throw new RemoteDesktopException("Error: Invalid IP address in string format. Make sure it is in the right format.");
}
}
/// <summary>
/// Constructor (+1 Overloads)
/// </summary>
/// <param name="port">Port for server to listen for incoming connections.</param>
/// <param name="host_ip">Ip address of client.</param>
public RemoteDesktopListener(int port, IPAddress host_ip)
{
if (port > 0 && port < 65535)
{
listner = new TcpListener(host_ip, port);
}
else if (port < 0 && port > 65535)
{
throw new RemoteDesktopException("Error: Port number invalid! Range is from 0 - 65535.");
}
}
/// <summary>
/// Starts the listening process and establishes a connection to a client.
/// </summary>
public void BeginListening()
{
if (listner == null)
{
throw new RemoteDesktopException(new NullReferenceException());
}
else if (listner != null)
{
byte[] bytes = new byte[204800];
bool connected = false;
listner.Start();
//int i;
while (true)
{
client = listner.AcceptTcpClient();
if (connected == false)
{
Connected(client, new EventArgs());
connected = true;
}
NetworkStream stream = client.GetStream();
while (stream.DataAvailable == true)
{

StreamingData(client, new DataEventArgs(Image.FromStream(stream, false, false)));
}
client.Close();
ConnectionEnded(this, new EventArgs());
}

}
return;
}
/// <summary>
/// Starts listening for incoming connection requests.
/// </summary>
/// <param name="backlog">Maximum number of pending connection</param>
public void BeginListening(int backlog)
{
if (listner == null)
{
throw new RemoteDesktopException(new NullReferenceException());
}
else if (listner != null)
{
//byte[] bytes = new byte[204800];
bool connected = false;
listner.Start(backlog);
//int i;
while (true)
{
client = listner.AcceptTcpClient();
if (connected == false)
{
Connected(client, new EventArgs());
connected = true;
}
NetworkStream stream = client.GetStream();
while (stream.DataAvailable == true)
{

StreamingData(client, new DataEventArgs(Image.FromStream(stream, false, false)));
}
client.Close();
ConnectionEnded(this, new EventArgs());
}

}
return;
}
public void StopListening()
{
client.Close();
listner.Stop();
}
/// <summary>
/// Returns the System.Net.Sockets.Socket of the current session.
/// </summary>
public Socket Socket
{
get
{
return listner.Server;
}
}
~RemoteDesktopListener()
{
client.Close();
listner.Stop();
ConnectionEnded(this, new EventArgs());
}

}
public sealed class RemoteDesktopClient
{
private TcpClient client;
private Timer timer;
private Bitmap bitmap;
private System.Drawing.Imaging.PixelFormat format;
private Graphics g;
private NetworkStream stream;
public delegate void ConnectionCloseEventHandler(RemoteDesktopClient sender, EventArgs e);
public event ConnectionCloseEventHandler ConnectionClosed;
/// <summary>
/// Constructor (1 Overload)
/// </summary>
/// <param name="pixel_format">The bitmap's pixel format that will be used for every frame that is sent across the network.</param>
public RemoteDesktopClient(System.Drawing.Imaging.PixelFormat pixel_format)
{
format = pixel_format;
}
public void BeginConnection(int port, string host_ip)
{
IPAddress addr;
if (IPAddress.TryParse(host_ip, out addr))
{
if (port > 0 && port < 65535)
{
client = new TcpClient(host_ip, port);
timer = new Timer();
timer.Interval = Convert.ToInt32(Math.Pow(24, -1) * 1000); // 24 frames per second.
timer.Tick += new EventHandler(timer_Tick);
stream = client.GetStream();
timer.Enabled = true;

}
else if (port > 0 && port > 65535)
{
throw new RemoteDesktopException(new ArgumentOutOfRangeException("port"));
}
}
else
{
throw new RemoteDesktopException("Error: Invalid IP address in string format. Make sure it is in the right format.");
}
}

void timer_Tick(object sender, EventArgs e)
{
bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

g = Graphics.FromImage(bitmap);
g.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
Cursors.Default.Draw(g, new Rectangle(Cursor.Position, Cursors.Default.Size));
byte[] buffer = imageToByteArray(bitmap);
stream.Write(buffer, 0, buffer.Length);

}
public void EndConnection()
{
g.Dispose();
stream.Close();
stream.Dispose();
bitmap.Dispose();
timer.Enabled = false;
client.Close();
ConnectionClosed(this, new EventArgs());
return;
}
public Socket Socket
{
get
{
return client.Client;
}
}
byte[] imageToByteArray(System.Drawing.Image imageIn)
{
System.IO.MemoryStream ms = new System.IO.MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
}
/// <summary>
/// Represents all remote desktop runtime errors. Inherits from System.Exception.
/// </summary>
public class RemoteDesktopException : Exception
{
private string message;
private Exception ex;
/// <summary>
/// Constructor (+1 Overloads)
/// </summary>
/// <param name="error">The error message in string format.</param>
public RemoteDesktopException(string error)
{
message = error;
}
/// <summary>
/// Constructor (+1 Overloads)
/// </summary>
/// <param name="error">The error in System.Exception format.</param>
public RemoteDesktopException(Exception error)
{
ex = error;
}
public override string StackTrace
{
get
{
return base.StackTrace;
}
}
public override string HelpLink
{
get
{
return base.HelpLink;
}
set
{
base.HelpLink = value;
}
}
public override string Message
{
get
{
if (message != null)
{
return message;
}
else
{
return ex.Message;
}
}
}
}
public class DataEventArgs : EventArgs
{
private Image image;
public DataEventArgs(Image img)
{
image = img;
}
public System.Drawing.Image CurrentFrame
{
get
{

return image;
}
}

}
}

我这里加了flush

 void timer_Tick(object sender, EventArgs e)
{
bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

g = Graphics.FromImage(bitmap);
g.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
Cursors.Default.Draw(g, new Rectangle(Cursor.Position, Cursors.Default.Size));
byte[] buffer = imageToByteArray(bitmap);
stream.Write(buffer, 0, buffer.Length);
stream.Flush();


}

那是您要我放置 stream.Flush() 子例程的地方吗?*因为它仍然不起作用。我还尝试将 NoDelay 属性设置为 true。*

最佳答案

Image.FromStream 的速度不太可能是您的问题。您的代码试图每秒发送 24 帧。假设您的屏幕设置为 1024 x 768,即 786,432 像素。对于 24 位颜色,这大约是 2.25 兆字节。每秒 24 帧将是每秒 54 兆字节。

您的 imageToByteArray 方法创建一个 GIF,它将压缩一些。你得到的字节数组有多大?也就是说,在您的 timer_tick 方法中,您有:

byte[] buffer = imageToByteArray(bitmap);
stream.Write(buffer, 0, buffer.Length);

buffer.Length 的值是多少?

由于 TCP 开销,千兆位网络每秒可为您提供不到 100 兆字节的数据。我怀疑您在这里遇到了网络限制。

通常,传输视频的应用程序(这实际上是您正在做的事情)进行差分压缩。他们找出哪些像素发生了变化,并且只发送这些像素。这大大减少了网络带宽。如果您真的想要在任何尺寸的屏幕上达到 24 FPS,您可能必须执行类似的操作。

关于c# - 需要更快地实现 Image.FromStream 以实时显示图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5843181/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com