1

不确定我正在尝试做的事情是否会奏效,甚至可能。基本上我正在创建一个远程桌面类型的应用程序,它将屏幕捕获为 jpeg 图像并将其发送到客户端应用程序进行显示。
我想通过将图像与旧图像进行比较并仅发送差异来减少每次发送的数据量。例如:

var bitmap = new Bitmap(1024, 720);

string oldBase = "";

using (var stream = new MemoryStream())
using (var graphics = Graphics.FromImage(bitmap))
{
    graphics.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size);
    bitmap.Save(stream, ImageFormat.Jpeg);
    string newBase = Convert.ToBase64String(stream.ToArray());

    // ! Do compare/replace stuff here with newBase and oldBase !

    // Store the old image as a base64 string.
    oldBase = newBase;
}

使用类似这样的东西,我可以比较两个 base64 字符串并替换任何匹配项。匹配的文本可以替换为:

[替换的字符数]

这样,在客户端我知道在哪里替换旧数据并添加新数据。同样,我不确定这是否会起作用,因此非常感谢任何人对此的想法。:) 如果可能的话,你能指出我正确的方向吗?谢谢。

4

3 回答 3

1

我们目前正在研究非常相似的东西 - 基本上,您尝试实现的是视频编解码器(非常简单的运动 jpeg)。有一些简单的方法和一些非常复杂的方法。

  1. 最简单的方法是比较连续帧并仅发送差异。您可以尝试比较 RGB 空间或 YCbCr 空间中帧之间的颜色差异,并仅发送随某些元数据发生变化的像素。
  2. 更复杂的解决方案是比较DCT变换后熵编码前的图片。这将为您提供更好的比较并删除一些丑陋的伪影。
  3. 查看有关 JPEG、Motion JPEG、H.264 的更多信息 - 您可以使用这些编解码器正在使用的某些方法,或者尽可能简单地使用现有编解码器。
于 2012-09-04T19:59:01.657 回答
1

您可以通过直接比较位图位来做到这一点。查看Bitmap.LockBits,它将为您提供一个BitmapData指针,您可以从中获取像素数据。然后,您可以比较每条扫描线的像素并将它们编码为您想要用于传输的任何格式。

请注意,以字节为单位的扫描线长度始终是 4 的倍数。因此,除非您使用 32 位颜色,否则您必须考虑可能位于扫描线末尾的填充。这就是该Stride属性在BitmapData结构中的用途。

在每条扫描线的基础上做事更容易,但可能不如将位图视为一个连续的数据块那样有效(在减少发送的数据量方面)。您的传输格式应类似于:

<start marker>
// for each scan line
<scan line marker><scan line number>
<pixel position><number of pixels><pixel data>
<pixel position><number of pixels><pixel data>
...
// next scan line
<scan line marker><scan line number>
...
<end marker>

每个<pixel position><number of pixels><pixel data>条目都是一系列变化的像素。如果一条扫描线没有变化的像素,您可以选择不发送。或者您可以只发送扫描线标记和编号,然后立即发送下一条扫描线。

<pixel position>对于字段和字段,两个字节就足够了<number of pixels>。因此,每个块都有四个字节的开销。在您拥有最简单的版本后,您可能会感兴趣的优化是在小运行时组合更改/未更改的像素块。例如,如果您有uucucuc,其中u是一个未更改的像素并且c是一个更改的像素,您可能希望将 编码cucuc为五个更改像素的运行。这将减少您必须传输的数据量。

请注意,这不是做事的最佳方式,但它简单、有效且相对容易实现。

在任何情况下,一旦你编码了东西,你就可以通过内置的GZip压缩​​器运行数据(尽管这样做可能没有多大帮助),然后将它向下推送到客户端,它会解压缩并解释结果.

在一台机器上构建它是最简单的,使用两个窗口来验证结果。一旦工作正常,您就可以连接网络传输部分。通过在中间放置传输步骤来调试初始剪辑可能会非常令人沮丧。

于 2012-09-04T20:32:16.717 回答
0

这不适用于JPEG。您需要使用 BMP,或者可能是未压缩的 TIFF。

我想如果是我,我会使用 BMP,扫描像素以查找更改并构建一个 PNG,其中除了更改之外的所有内容都是透明的。

首先,这会减少您的传输大小,因为 PNG 压缩非常好,尤其是对于重复像素。

其次,它使接收端的显示变得非常容易,因为您可以简单地将新图像绘制在旧图像之上。

于 2012-09-04T19:53:41.297 回答