【发布时间】:2012-08-05 07:29:24
【问题描述】:
我正在开发一个名为“远程桌面控制”的客户端-服务器应用程序。我需要做的是截取客户端计算机的屏幕截图并将此屏幕截图发送到服务器计算机。我可能需要每秒发送 3 到 5 张图像。但是考虑到直接发送BufferedImage 的过程成本太高,我需要减小图像的大小。画质损失不必少。
如何减小图像的字节大小?有什么建议吗?
【问题讨论】:
标签: java image screenshot screen-capture
我正在开发一个名为“远程桌面控制”的客户端-服务器应用程序。我需要做的是截取客户端计算机的屏幕截图并将此屏幕截图发送到服务器计算机。我可能需要每秒发送 3 到 5 张图像。但是考虑到直接发送BufferedImage 的过程成本太高,我需要减小图像的大小。画质损失不必少。
如何减小图像的字节大小?有什么建议吗?
【问题讨论】:
标签: java image screenshot screen-capture
您可以通过使用GZIPInputStream 及其在套接字另一端的输出副本非常轻松地使用 ZIP 压缩它。
编辑:
还请注意,您可以创建 delta 图像进行传输,例如,您可以使用“透明颜色”(神奇粉色#FF00FF)来表示屏幕的该部分没有进行任何更改.另一方面,您可以在最后一张上绘制新图像,忽略这些魔术像素。
请注意,如果图片已经包含此颜色,您可以将真正的粉红色像素更改为例如#FF00FE。这是不明显的。
另一种选择是为每个图像传输一个1位掩码(在将不变像素绘制为任意颜色之后。为此,您可以更改主要用于图片以产生最佳压缩比(最佳霍夫曼编码)。
【讨论】:
一种方法是使用 ImageIO API
ImageIO.write(buffimg, "jpg", new File("buffimg.jpg"));
至于质量和其他参数-我不确定,但应该可以,只需深入挖掘即可。
【讨论】:
请参阅this thread,了解如何以可控的压缩/质量编码为 JPG。左边的滑块是用来控制关卡的。
最终最好将图像直接编码为可以流式传输的视频编解码器,但我对细节有点模糊。
【讨论】:
Vbence 使用GZIPInputStream 的解决方案是一个很好的建议。在大多数商业软件(Windows 远程桌面、VNC 等)中执行此操作的方式是仅发送对屏幕缓冲区的更改。因此,您在服务器上保留客户端“看到”的内容的副本,并且每次连续捕获时,您都会计算屏幕区域的不同之处。然后,您只需将这些屏幕区域连同它们的左上角坐标、宽度、高度一起发送给客户端。并使用这些新区域更新客户端“视图”的服务器副本。
这将大大减少您使用的网络数据量,虽然我一直在输入这个答案,但每次击键只有 400 左右像素 (20x20) 发生变化。这在 1920x1080 的屏幕上只是屏幕的 1/10,000,显然值得考虑。
唯一昂贵的部分是如何计算一帧和下一帧之间的“差异”。有很多库可以很便宜地做到这一点,其中大多数都非常数学化(离散余弦变换类型的东西,超出我的想象),但它可以相对便宜地完成。
【讨论】: