C#尽可能快地通过套接字发送图像
我正在尝试通过试图压缩的套接字发送尽可能快的图像。。。比较图片。。。它仍然工作得很慢。。。 顺便说一句,我试图保存压缩前后的图像,大小是一样的。。。。1或2 kb的内存 查看客户端代码:C#尽可能快地通过套接字发送图像,c#,image,sockets,stream,C#,Image,Sockets,Stream,我正在尝试通过试图压缩的套接字发送尽可能快的图像。。。比较图片。。。它仍然工作得很慢。。。 顺便说一句,我试图保存压缩前后的图像,大小是一样的。。。。1或2 kb的内存 查看客户端代码: Bitmap pre; private void Form2_Load(object sender, EventArgs e) { pre = GetDesktopImage(); prev = Compress(ImageToByte(pre)).Le
Bitmap pre;
private void Form2_Load(object sender, EventArgs e)
{
pre = GetDesktopImage();
prev = Compress(ImageToByte(pre)).Length;
theThread = new Thread(new ThreadStart(startSend));
theThread.Start();
}
Bitmap curr;
byte[] compressed;
private void startSend()
{
sck = client.Client;
s = new NetworkStream(sck);
while (true)
{
curr = GetDesktopImage();
compressed = Compress(ImageToByte(curr));
if (Math.Abs(compressed.Length - prev) > 500)
{
bFormat.Serialize(s, compressed);
prev = compressed.Length;
count++;
}
}
}
压缩方法:
byte[] Compress(byte[] b)
{
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream z = new GZipStream(ms, CompressionMode.Compress, true))
z.Write(b, 0, b.Length);
return ms.ToArray();
}
}
byte[] ImageToByte(Image img)
{
ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(img, typeof(byte[]));
}
这是服务器端:
while (true)
{
try
{
bFormat = new BinaryFormatter();
inBytes = bFormat.Deserialize(stream) as byte[];
inImage = ByteToImage(Decompress(inBytes));
theImage.Image = (Image)inImage;
count++;
label1.Invoke(new Action(() => label1.Text = count.ToString()));
}
catch { }
}
顺便说一句,我见过一些人使用socket.send,但没有将图像保存到流。。。。你们能解释一下区别吗?请告诉我我的代码中有什么错误,以及如何改进我的算法?你的问题真的把“过于宽泛”作为一个接近的理由推向了极限。通过网络发送图像数据的一般问题是一个非常广泛的研究领域,有大量不同的技术,具体的应用程序/用户场景决定了哪种技术实际上是最好的 这就是说,有一个非常明显的变化,你可以对你的代码是必要的,这可能会加快它,这取决于瓶颈在哪里 具体来说,您使用
ImageConverter.ConvertTo()
将位图
对象转换为字节[]
,然后使用gzip流
压缩该字节数组。问题是ConvertTo()
已经在压缩数据;它返回的字节[]
包含以PNG格式表示的原始位图,这是一种相当好的图像无损压缩算法
因此,不仅再次压缩它实际上什么也做不了,而且要花费大量的CPU才能做到这一点。不要那样做。只需按原样发送byte[]
数据,而无需通过gzip流运行它
现在,所有这些都表明
正如我所提到的,这种改变是否真的能起到这么大的作用取决于其他因素,包括位图有多大,以及您使用的网络有多快。如果你已经用你在问题中发布的低效代码使网络饱和,那么加快代码的速度是没有帮助的
用于处理网络带宽瓶颈的技术包括(但不限于):
使用有损压缩(例如JPEG、MPEG等),从而简单地丢弃发送成本过高的信息
使用差分压缩技术(例如,MPEG、MP4、Quicktime等),该技术利用这样一个事实,即当处理运动图像视频时,从一帧到下一帧的大多数像素不变或至少非常相似
发送渲染命令而不是位图数据。这通常用于VNC或Microsoft的远程桌面/终端服务器API,并利用屏幕上的绘图通常使用相对简单的绘图命令(填充/勾勒矩形、绘制文本、绘制小位图等)影响大量像素这一事实
在许多情况下,这些技术以不同的方式组合在一起以实现最大性能
如果您想使用这些技术,您需要做的不仅仅是询问有关堆栈溢出的问题。提供这些技术的广泛文档和教程远远超出了本网站的范围。您需要自己研究它们,或者更好地使用现有的实现来实现您的目标。什么是GetDesktopImage
?图像的文件格式是什么?图像有多大?看起来你想做些VNC?不是真的VNC哈哈但是如果你说。。。我使用了捕获图像算法,它比从屏幕上复制图形要快,而且使用的cpu更少。。。我认为它的屏幕截图格式是内存bmp。。。全屏幕大小既然两个图像都是在客户端生成的,为什么不在那里比较它们并将差异发送到服务器呢?它会卸载服务器,特别是在多客户端应用程序中,您有许多客户端向服务器发送屏幕截图。我比较它们,兄弟,然后我只在它们不同的情况下发送图像。。看看代码@Ron Beyer你上面展示的代码没有做任何比较,所以不确定我应该如何认识到这一点?我不是说只在发生变化时才发送图像,我是说只发送图像的变化,这是一组小得多的数据。非常感谢兄弟,我非常感谢你的解释@Peter Duniho,那么关于你所说的ImageConverter.ConvertTo()
我不应该在gzipstream中使用compress方法吗?所以要发送它,只需使用compressed=(ImageToByte(curr))代码>?但我注意到如果我也使用压缩,它的kb会更少。。不要问我如何保存这两个文件,有一点不同。。。可能是因为屏幕不同,哈哈,只需使用ImageToByte()
的结果即可。PNG有多种压缩选项,ImageConverter
只使用默认值。因此,您可能会看到数据大小的小幅度减少,再次压缩它,因为您尚未优化PNG压缩。但这些减少不太可能很大(我猜尺寸的改善不到5-10%),而且代价高昂。如果你真的需要的话,你最好得到一个PNG实现,它提供了对压缩的更多控制,并且只优化初始PNG压缩。