如何缩小 BufferedImage 的尺寸和质量?

3
我正在开发一个名为“远程桌面控制”的客户端-服务器应用程序。我的任务是对客户端电脑进行屏幕截图,并将此屏幕截图发送到服务器电脑。我可能需要每秒发送3至5张图片。但考虑到直接发送BufferedImage会过于耗费资源,我需要缩小图片的尺寸。图片质量不必完全保留。

如何减小图片的字节数?有什么建议吗?

4个回答

6
你可以使用GZIPInputStream和它的输出对象在套接字的另一端非常容易地将其压缩成ZIP格式。
编辑:
还要注意,您可以创建用于传输的增量图像,例如使用“透明颜色”(魔法粉红色#FF00FF)来指示该部分屏幕没有更改。在另一侧,您可以在忽略这些魔术像素的情况下绘制新图像在上一个图像之上。
请注意,如果图片已经包含此颜色,则可以将真正的粉色像素更改为#FF00FE。这是不可察觉的。
另一种选择是在每个图像中传输1位掩码(在将未更改的像素绘制到任意颜色后)。为此,您可以更改图片中最常用的颜色以获得最佳压缩比(最优哈夫曼编码)。

哇,谢谢!我想我需要再多努力一点,但是我已经理解了主题。 - Jisan Mahmud

4
Vbence的解决方案使用了GZIPInputStream,是一个不错的建议。在大多数商业软件(如Windows远程桌面、VNC等)中,只有屏幕缓冲区的更改才会被发送。因此,您在服务器上保留客户端“看到”的副本,并且每次捕获时计算屏幕区域的差异。然后,您仅向客户端发送这些屏幕区域以及它们的左上角坐标、宽度和高度。并更新客户端“视图”的服务器副本仅包含这些新区域。
这将极大地减少您使用的网络数据量,而当我打字时,每次按键只有400个像素左右(20x20)会发生变化。在1920x1080的屏幕上,这仅占屏幕的1/10,000,因此值得考虑。
唯一昂贵的部分是如何计算一帧与下一帧之间的“差异”。有很多库可以以相对较低的成本进行计算,其中大多数都非常数学化(离散余弦变换之类的东西,超出了我的理解范围)。

唯一昂贵的部分是如何计算一个帧和下一个帧之间的“差异”。有很多库可以便宜地完成这项工作,其中大部分都非常数学化(离散余弦变换等),超出了我的理解范围,但可以相对便宜地完成。你能告诉我一些这方面的库名称吗? - Jisan Mahmud
实际上,你自己做起来并不是很难。可以参考安防摄像头的运动检测算法的想法 http://www.codeproject.com/Articles/10248/Motion-Detection-Algorithms ,因为你知道帧缓存没有“噪声”,所以你可以进行大幅优化。 - lynks
这是一个不错的方法,但需要付出努力来实现。通常情况下,您不希望传输单个矩形,而是计算最佳矩形组合。例如,使用单个矩形时,动画托盘图标可能会导致每次传输几乎整个屏幕。 - vbence

3

请查看此线程,了解如何使用可控压缩/质量将图像编码为JPG。左侧的滑块用于控制级别。

最好直接将图像编码为可以流式传输的视频编解码器,但我有些模糊细节。


谢谢提供链接。我会研究一下的。 你能告诉我更多关于将图像编码到视频编解码器中的信息吗?我该如何做呢?如果有任何链接,也会很有帮助。 - Jisan Mahmud
虽然我已经使用JMF将JPEG图像转换为MOV,但我并没有深入研究生成用于流传输的数据。换句话说,“不是”。除此之外,我认为lynks提供了一种更好的策略(仅传输与上一帧的变化)。 - Andrew Thompson

2

一种方法是使用ImageIO API

ImageIO.write(buffimg, "jpg", new File("buffimg.jpg"));  

关于质量和其他参数 - 我不确定,但应该是可能的,只需要深入挖掘。


"只需深入挖掘" 或者查看我回答中链接的代码。 ;) - Andrew Thompson
我已经尝试过了。我的屏幕分辨率是1366*768,截图产生的图像大约为135KB。所以,仍然太昂贵了! - Jisan Mahmud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接