- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我目前正在开发一个应用程序,它可以一个接一个地显示许多图像。不幸的是,我没有为此使用视频的奢侈,但是,我可以选择正在使用的图像编解码器。数据从服务器发送到应用程序,已经编码。
例如,如果我使用 PNG 或 JPEG,我可以使用 [[UIImage alloc] initWithData:some_data]
将接收到的数据转换为 UIImage。当我使用原始字节数组或另一个必须首先解码为原始字节数组的自定义编解码器时,我必须创建一个位图上下文,然后使用 CGBitmapContextCreateImage(bitmapContext)
给出一个 CGImageRef,它然后被送入[[UIImage alloc] initWithImage:cg_image]
。这要慢得多。
上图(时间以秒为单位)是执行从NSData到UIImage的转换所花费的时间。 PNG、JPEG、BMP 和 GIF 都大致相同。 Null 根本不关心转换并返回 nil 。 Raw 是使用位图上下文方法转换的原始 RGBA 字节数组。自定义的解压缩成 Raw 格式,然后做同样的事情。 LZ4 是原始数据,使用 LZ4 算法压缩,因此它也通过位图上下文方法运行。
例如,PNG 图像只是经过压缩的位图图像。这种解压缩然后渲染比我渲染 Raw 图像花费的时间更少。 iOS 必须在幕后做一些事情来加快速度。
如果我们查看转换每种类型需要多长时间以及绘制(到图形上下文)需要多长时间的图表,我们会得到以下信息:
我们可以看到大多数图像的转换时间非常不同,但绘制时间非常相似。这排除了 UIImage 的任何性能提升是惰性和仅在需要时才转换的。
我的问题本质上是:我可以利用众所周知的编解码器的更快速度吗?或者,如果没有,是否有另一种方法可以更快地渲染原始数据?
编辑:为了记录,每当我得到一个新图像时,我都会在另一个 UIImage 之上绘制这些图像。可能有一个我愿意研究的更快的替代方案。然而,不幸的是,OpenGL 不是一个选项。
进一步编辑:这个问题相当重要,我想要最好的答案。在时间到期之前不会授予赏金,以确保给出最佳答案。
最终编辑:我的问题是为什么解压缩和绘制原始 RGBA 数组的速度不比绘制 PNG 快,因为 PNG 必须解压缩为 RGBA 数组然后绘制。结果是它实际上更快。但是,这似乎只出现在发布版本中。调试构建没有为此进行优化,但在幕后运行的 UIImage 代码显然是。通过编译为发布版本,RGBA 阵列图像比其他编解码器快得多。
最佳答案
在衡量性能时,衡量整个管道以找出瓶颈非常重要。
在您的情况下,这意味着您无法隔离 UIImage
创建。您将必须包括图像显示——否则您将陷入只测量您感兴趣的部分内容的陷阱。
UIImage 不是位图数据的薄包装,而是一个相当复杂和优化的系统。例如,底层 CGImage
可以只是对磁盘上某些压缩数据的引用。这就是为什么使用 initWithContentsOfFile:
或 initWithData:
快速初始化 UIImage
的原因。 iOS 中的 ImageIO 和 Quartz 框架中还有更多隐藏的性能优化,这些都将添加到您的测量中。
获得可靠测量值的唯一可靠方法是做您真正想做的事情(从网络或磁盘获取数据,以某种方式创建 UIImage,并在屏幕上至少显示一帧)。
以下是您应该注意的一些注意事项:
Apple 的图形框架竭尽全力执行最少的必要工作。如果图像未显示,则可能永远不会解压缩。
如果图像以低于其原始像素的分辨率显示,则可能仅部分解压缩(对于 JPEG 尤其如此)。这对于帮助优化可能是一件好事,但当然不能在从全图像分辨率的 CGBitmapContext
创建图像时使用。因此,除非必要,否则不要这样做。
使用 Instruments 进行测量时,您可能看不到所有相关的 CPU 周期。图片的解压缩可以在 backboardd
(iOS 中使用的那种窗口服务器)中进行。
使用未压缩的图像似乎是最快的想法。但这确实忽略了一个事实,即内存可能是瓶颈,而更少的数据(压缩图像)可以帮助解决这个问题。
结论:
您的目标应该是找到您的真实场景的瓶颈。所以不要使用虚构的测试数据和人为的代码进行测试。您最终可能会优化应用中未采用的代码路径的性能。
当您更改测试代码以测量整个管道时,如果您可以用结果更新您的问题,那就太好了。
关于ios - 为什么 CGBitmapContextCreateImage 比 [UIImage initWithData :]? 慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25207819/
我有一个应用程序,它将在 SQLDatabase 中保存一组图像,然后用户将拍摄一张照片,我希望能够将它与数据库中的图像相匹配。 我不知道从哪里开始,有人可以帮忙吗?指出我正确的方向? 谢谢 最佳答案
在我的项目中,我有两个 UIViewController。在我的第一个 ViewController 上,我有一个 UIImageView,并且有一个来自 url 的图像。在第二个 ViewContr
如何从上下文创建 UIImage 以便我可以返回它?我只希望它有透明像素。我有一种不同的方法,可以将较小的 UIImage 添加到较大的 UIImage,但我需要从头开始。 + (UIImage *)
我想知道如何将 UIImage 居中到 UIButton。我正在使用 UIButton 的 setImage 方法来放置 UIImage .. 最佳答案 您可以使用 contentMode 属性: b
我从相机获取 UIimages 并将它们分配给要显示的 UIImageViews。当我这样做时,相机会给我一个 1200 x 1600 像素的图像,然后我将其分配给我的应用程序中的 UIImageVi
Swift 4 有 Codable这太棒了。但是UIImage默认情况下不符合它。我们怎么能做到这一点? 我试过 singleValueContainer和 unkeyedContainer exte
我的代码在普通设备上运行良好,但在视网膜设备上创建模糊图像。 有人知道我的问题的解决方案吗? + (UIImage *) imageWithView:(UIView *)view { UIGr
我总是得到:CGImageCreate:无效的图像大小:0 x 0。 ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; // En
我有一张图片,想创建一张如下所示的黑色图片: 我有一个 View 和一个 ImageView ,因为它是 subview 。 ImageView 的 alpha 为 0.5,其色调颜色为黑色。 Vie
几天来我一直被困在一些必须非常简单的事情上,我已经搜索了几天,但我似乎无法找到正确的代码来工作。 我有两张图片,一张是背景图片,另一张会遮盖第一张图片。我可以用手势移动蒙版图像。我可以缩放、旋转和移动
我正在尝试拍摄类似背景透明的三角形图像,并根据用户偏好在三角形部分或背景部分上应用圆点图像。例如,我如何将圆点应用于三角形部分,然后将条纹应用于图像的透明部分。有针对这种事情的屏蔽技术吗? 非常感谢,
给出下面的图片,百分比为 25%。如何生成另一个代表给定图像径向部分 25% 的 UIImage?非常感谢任何帮助。 输入 输出 - (UIImage *)radialPortion:(float)p
这是我的代码: - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { // at this point the
我正在使用扩展程序对我的图像进行像素化处理,如下所示: func pixellated(scale: Int = 8) -> UIImage? { guard let ciImage = CI
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 6 年前。 Improve t
我有两个 UIImage 实例。我怎样才能创建第三个 UIImage 这只是拼接在一起的两个原始图像?我想要第一张图片在顶部,第二张图片在底部,这样顶部图片的底部边缘与底部图像的顶部边缘齐平。 最佳答
我有一个 UIImage 和一个 CGPoint,它们告诉我应该朝哪个方向移动它以创建另一个图像。背景可以是任何东西。 提供初始 UIImage 我如何创建新的?最有效的方法是什么? 这是我正在做的:
我有一个 UIImage,显示在 UIImageView 中。我在 UIImageView 中还有另一张图片,它位于第一张图片上方。我希望能够仅在第一张图片的边界内拖动第二张图片。为了让我的目标更清楚
我看过这个问题:UIImage Shadow Trouble 但接受的答案对我不起作用。 我想做的是获取一个 UIImage 并向其添加阴影,然后返回一个全新的 UIImage、阴影和所有内容。 这就
我有两张图片:第一张是用户个人图片,第二张是图标(角标(Badge))。 我想在第一个 uiimage(用户图像)的左下角添加第二个 uiimage(图标),并将它们保存到一个新的 Uiimage 中
我是一名优秀的程序员,十分优秀!