菜鸟教程小白 发表于 2022-12-12 14:32:28

ios - 如何加快 UIImage 的绘制速度?


                                            <p><p>我最近遇到了一种情况,我必须在屏幕上绘制许多 2D 图像。有时必须绘制大约 200 个小图像。我曾经调用<a href="https://developer.apple.com/documentation/uikit/uiimage/1624092-draw" rel="noreferrer noopener nofollow">UIImage.draw(in:)</a>为此目的的方法,但很快(通过分析)了解到它相当慢。我可以通过缩小图像来加快速度,即为图像使用正确的尺寸,而不是太大而必须缩小的图像(这是我以后会做的事情,但在开发过程中你想快速尝试一下。)这将它从大约 400 毫秒加快到 100 毫秒。还是太慢了。我还可以通过仅绘制实际变化的屏幕部分来使其更快。这会有所帮助,除非我必须绘制大部分屏幕。速度仍然很慢:我的意思是,许多现代 3D 游戏在 iPhone SE 上每帧可以绘制超过 10000 个三角形,具有高清纹理和每秒 60 帧;所以我很确定有一种方法可以在不到 1 毫秒的时间内在 iPhone 7 的屏幕上绘制 100 张图像。</p>

<p>我曾想过用 OpenGL ES、Metal 或可能使用 SpriteKit 重写 View ,但我想知道这是否有点矫枉过正。</p>

<p>对于我正在开发的游戏,我最多有 15 个不同的图像,每个图像需要绘制多次。一次最多绘制 1000 张图像。图像的最大分辨率为 120*120 像素。</p>

<p>将图像绘制到屏幕上的速度足够快的方法是什么?可以有一个可能需要 300 毫秒的设置阶段,并将所有图像数据复制到图形内存中,或类似的东西。不过,快速替换 UIImage 将是最方便的。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>您已经发现自己绘制 <code>UIImage</code> 对象并不是很快。我在之前的项目中也有类似的要求,并进行了各种测试以尝试找到一种足够有效的方法来在屏幕上显示相当小的位图。虽然绝不会声称知道有关该主题的全部真相,但我认为我有同样有趣的信息要分享。</p>

<p><strong>CALayer + 内容</strong><br/>
我发现(正如 Palle 在他的简短评论中所说)将位图设置为其 <code>contents</code> 属性的 <code>CALayer</code> 是最快的方法。可能不如金属或 OpenGL 快,但比 <code>draw</code> 快很多。似乎当您向屏幕添加层时,它最终会出现在 GPU 内存中,因此在屏幕上(或关闭)重新定位这些层<em>非常</em>快。您还可以在这些图层上进行转换(3D)而不会受到任何影响。此外,据我了解,对许多层使用与 <code>contents</code> 相同的位图实际上也会在 GPU 上共享内存。<br/>
如果您之前没有使用过图层,那么它相当简单。在 iOS 上,每个 <code>UIView</code> 都由 <code>CALayer</code> 支持,实际上这意味着您只需执行 <code>view.layer</code> 即可轻松进入图层。 </p>

<p>创建位图支持层很容易,只需实例化它并设置 <code>contents</code>,然后将其添加到 ViewController 的层(或任何您想要的位置)。</p>

<pre><code>CALayer *layer = ;
layer.contents = .CGImage;
;
</code></pre>

<p>关于使用图层的最后说明。默认情况下,所有 <code>CALayer</code> 对象都附有动画以进行各种属性更改。例如,如果您想为对象的移动设置动画,这很方便,因为您所要做的就是设置新位置。 <em>但是</em>,如果您正在制作自己的风景,并且可能使用 <code>CADisplayLink</code> 制作动画,这可能<strong>不是</strong>您想要的。在这种情况下,您必须删除这些默认动画,否则它们会干扰您的更新。</p>

<p>从 CALayer 对象中移除隐式动画<br/></p>

<pre><code>- (void)removeAnimationFromLayer:(CALayer *)layer {
layer.actions = @{ @&#34;contents&#34;: , @&#34;position&#34;: ,
@&#34;frame&#34;: , @&#34;opacity&#34;: ,
@&#34;bounds&#34;: , @&#34;affineTransform&#34;: ,
@&#34;sublayerTransform&#34;: , @&#34;transform&#34;: ,
@&#34;zPosition&#34;: , @&#34;anchorPoint&#34;: ,
@&#34;cornerRadius&#34;: , @&#34;sublayers&#34;: ,
@&#34;onLayout&#34;: , };
}
</code></pre>

<p><strong>UIImageView</strong><br/>
正确使用时,几乎与层一样快(也许令人惊讶)<code>UIImageView</code> 对象。它们也似乎经过了高度优化,并且在屏幕上移动速度非常快。我的经验是,您应该尽量不要在 <code>UIImageView</code> 上重新分配图像,而是为不同的图像使用单独的 <code>UIImageView</code> 对象。与图层一样,您应该尽量只对对象进行定位和变换以保持速度。<br/>
<code>UIImageView</code> 和 <code>CALayer</code> 之间的一个显着区别是 <code>CALayer</code> 仅用于输出,而 <code>UIImageView</code> 作为后代<code>UIView</code> 和 <code>UIResponder</code> 也处理输入。如果您需要,这可能是值得的权衡。另一个区别是 <code>UIImageView</code> 通常更容易使用。</p>

<p>我建议您自己进行一些测试,看看您能获得什么性能。 <code>UIImageView</code> 可能会让你一路走好!</p>

<p> <a href="https://developer.apple.com/documentation/quartzcore/calayer/1410773-contents?language=objc" rel="noreferrer noopener nofollow">CALayer contents property</a> </p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 如何加快 UIImage 的绘制速度?,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/48845856/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/48845856/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 如何加快 UIImage 的绘制速度?