嗨,我正在为 iPhone 开发 VNC 客户端应用程序(用于学校项目),我正在使用 RFB 协议。
我正在接收像素矩阵(每像素 32 位)并且我需要显示它们,但我需要它快速并且作为 VNC 客户端我需要在发生更改时快速更新图像。
我试过了CGBitmapContextCreate
,我可以创建图像并显示它,但每次我需要更新它时,我都必须创建一个新图像,所以这不是一个很好的解决方案。
我想知道是否有更有用或更好的方法来显示我的像素矩阵。
我假设您的服务器发送部分更新,并且不会在每次更新时发送全屏快照。
简单的技术是创建一个CGBitmapContext
并保留它。当您获得新像素时直接更新其数据(使用CGContextFillRect
会慢得多),然后使用它创建图像CGBitmapContextCreateImage
并将该图像分配给view.layer.contents
. (不要忘记将图像存储在该属性中后释放它!)
但是,正如您所发现的,您必须每次都创建一个新图像。为什么?ACGImage
是不可变的。为了强制执行不变性,Core Graphics 在创建CGImage
. 然后,当您在图层中显示图像时,iOS 必须再次将像素数据复制到窗口服务器(这是一个单独的过程)。复制整个屏幕的像素数据很慢:根据设备,您要复制的大小从 614 KB(iPhone 3GS 及更早版本)到 12.6 MB(Retina iPad)不等。
在仍然停留在 UIKit 和 Core Animation 的世界中的同时,您可以加快速度的一种方法是使用图层网格平铺屏幕。假设您使用每个 64x64 像素的图层平铺它。您为每个图层创建一个CGBitmapContext
。然后,当您从服务器接收到像素数据时,您会更新相应CGBitmapContext
s 的数据,然后仅更新需要它的图层的内容。当屏幕的一小部分区域发生变化时,您只会更新一个或几个图块,因此您将复制更少的数据。在 64x64 像素时,您将复制每个图块 16 KiB。您可能想尝试几种不同的尺寸,以找出最适合的尺寸。
如果这还不够快,您将需要离开 UIKit 和 Core Animation 的世界并使用 OpenGL ES。在 iOS 上,OpenGL ES 提供了对视频卡的最直接访问,除非您的电子邮件地址以@apple.com
. 您可以使用像素数据创建纹理,并使用该纹理绘制两个三角形(排列形成一个矩形),覆盖CAEAGLLayer
. glTexSubImage2D
当您获得新的像素数据时,您可以使用并重新绘制三角形将其写入纹理。如果你没有做过太多的 OpenGL 编程,这将是一个相当大的努力。