我最近遇到过必须在屏幕上绘制许多2D图像的情况。有时候必须绘制大约200张小图像。我曾经为此目的调用UIImage.draw(in:)方法,但很快就学会了(通过分析)它很慢。我可以通过缩小图像来加快速度,即对图像使用合适的尺寸,而不是尺寸太大而且必须按比例缩小的图像(这是我以后会做的,但是在开发过程中你想快速尝试一下。)这加速了大约400ms到100ms。还是太慢了。我还可以通过仅绘制实际改变的屏幕部分来加快速度。这有帮助,除非我必须绘制大部分屏幕。它仍然缓慢:我的意思是,许多现代3D游戏可以在iPhone SE上绘制每帧10000个三角形,高清纹理和每秒60帧;所以我非常确定有一种方法可以在不到1毫秒的时间内在iPhone 7上将100张图像绘制到屏幕上。
我想过在OpenGL ES,Metal或者使用SpriteKit重写视图,但我想知道这是否有点过分。
对于我正在开发的游戏,我最多需要15个不同的图像,每个图像需要多次绘制。一次最多可以绘制1000张图像。图像的最大分辨率为120 * 120像素。
将图像绘制到屏幕的快速方法是什么?设置阶段可能需要300毫秒,并且可以将所有图像数据复制到图形内存中,或类似的东西。尽管如此,快速取代UIImage将是最方便的。
答案 0 :(得分:3)
正如您已经发现的那样,自己绘制UIImage
个对象并不是很快。我在之前的项目中遇到了类似的要求,并进行了各种测试,试图找到一种足够有效的方法来在屏幕上获得相当小的位图。虽然没有声称知道关于这个主题的全部真相,但我认为我有相同的有趣信息要分享。
CALayer +内容
我发现(正如Palle在他的简短评论中所说),CALayer
位图设置为contents
属性是最快的方法。可能不如金属或OpenGL快,但速度比draw
快。看起来当你向屏幕添加一个图层时,它最终会进入GPU内存,因此在(或关闭)屏幕上重新定位这些图层的速度非常快 。您还可以在这些图层上进行变换(3D),但不会有任何损失。另外,据我所知,对于许多图层使用与contents
相同的位图,实际上也会在GPU上共享内存。
如果您还没有使用图层,那么它是非常直接的。在iOS上,每个UIView
都由CALayer
支持,实际上这意味着只需执行view.layer
即可轻松访问图层。
创建位图支持图层很简单,只需将其实例化并设置contents
,然后将其添加到视图控制器的图层(或任何您想要的位置)。
CALayer *layer = [CALayer layer];
layer.contents = [UIImage imageNamed:@"yourImage"].CGImage;
[self.view.layer addSublayer:layer];
关于使用图层的最后说明。默认情况下,所有CALayer
个对象都会附加动画,以便进行各种属性更改。例如,如果您想要动画对象的移动,这很方便,因为您所要做的就是设置新位置。 然而,如果您正在拍摄自己的风景,可能不可能是您想要的,并且可能使用CADisplayLink
制作动画。在这种情况下,您必须删除这些默认动画,否则它们会干扰您的更新。
从CALayer对象中删除隐式动画
- (void)removeAnimationFromLayer:(CALayer *)layer {
layer.actions = @{ @"contents": [NSNull null], @"position": [NSNull null],
@"frame": [NSNull null], @"opacity": [NSNull null],
@"bounds": [NSNull null], @"affineTransform": [NSNull null],
@"sublayerTransform": [NSNull null], @"transform": [NSNull null],
@"zPosition": [NSNull null], @"anchorPoint": [NSNull null],
@"cornerRadius": [NSNull null], @"sublayers": [NSNull null],
@"onLayout": [NSNull null], };
}
<强>的UIImageView 强>
正确使用时,几乎与图层一样快(可能是令人惊讶的)UIImageView
个对象。它们也似乎是高度优化的,并且非常快速地在屏幕上移动。我的经验是,您应该尝试不在UIImageView
上重新分配图像,而是为不同的图像使用单独的UIImageView
个对象。与图层一样,您应该尝试仅对对象进行定位和变换以保持速度
UIImageView
和CALayer
之间的显着差异在于CALayer
仅用于输出,而UIImageView
则是UIView
和UIResponder
的后代,还处理输入。如果您需要,这可能值得权衡。另一个区别是UIImageView
通常更容易使用。
我建议你做一些自己的测试,看看你有什么表现。 UIImageView
可能会让你一路走来!