我们应该使用哪种CGImageAlphaInfo?

12

Quartz 2D编程指南定义了各种Alpha存储模式的可用性:

enter image description here

对于RGB上下文,应该使用哪些模式?为什么

对于非不透明上下文,使用kCGImageAlphaPremultipliedFirstkCGImageAlphaPremultipliedLast

对于不透明上下文,使用kCGImageAlphaNoneSkipFirstkCGImageAlphaNoneSkipLast

选择值是否会影响性能?

通常,我看到非不透明情况下使用kCGImageAlphaPremultipliedFirst和不透明情况下使用kCGImageAlphaNoneSkipFirst。有些人表示这些方式的表现更好,但我没有看到任何硬证据或文档支持这个说法。

快速搜索GitHub显示,开发者们更喜欢kCGImageAlphaPremultipliedFirst而不是kCGImageAlphaPremultipliedLast,而且更喜欢kCGImageAlphaNoneSkipLast而不是kCGImageAlphaNoneSkipFirst。不幸的是,这只是一些经验性的证据。


我敢打赌,“最佳”选项取决于可用的GPU硬件是不同的。由于我个人没有接触过苹果在过去几年中发货的约50种不同的GPU,所以我无法为您提供任何关于什么是最好的数据。编写一个应用程序来进行性能测试,并对每种方法的精确颜色输出进行分析,然后在您可用的任何硬件上运行它。 - Abhi Beckert
各种选项定义了像素数据如何计算和在内部表示...例如,当从原始像素数据构建图像时(输入C数组),如果选择错误的alpha表示方式,将会产生巨大的影响。 - Volker
@AbhiBeckert 这也是我的直觉,但最好能够得到一些确认或共识。我打赌大多数开发人员只是复制 CGBitmapContextCreate 代码,而不会考虑是否使用了正确的位图信息。 - hpique
@Volker,让位图信息与原始数据格式匹配是有道理的,但是位图信息是否也会影响绘制性能呢?也许在创建时(可以在后台完成)获得的优势在绘制时(主线程)会丧失。 - hpique
我的猜测是它会影响性能和准确性。视频卡,特别是消费级视频卡,并不总是输出准确的颜色。这就是它们比在CPU上执行相同操作要快得多的原因之一。它们只需要足够好,用户不会注意到任何不准确之处。如果你关心的话,那么你需要进行测试。 - Abhi Beckert
永远不要过早地进行优化 - 如果您发现任何性能问题,请使用其中一种版本构建并进行测试。我已经尝试了各种格式,并没有发现最终用户会遇到的问题... - Volker
4个回答

10

在2014年的WWDC上,一位Apple工程师确认我们应该使用kCGImageAlphaPremultipliedFirstkCGImageAlphaNoneSkipFirst,并且它确实会影响性能。


4
如果你是从未来阅读这篇文章,请保持警觉,不要完全相信其中的内容,因为它可能已经发生了变化! - hpique

4
最常用的是RGBA格式(真彩色格式),其中Alpha字节位于描述像素的最后一个字节。- kCGImageAlphaPremultipliedLast(32位)。并非所有设备都支持所有格式。只是一个观察结果,但我处理从Web下载的所有png和jpeg图像都是RGBA(或在将PNG转换为UIImage时变成这样) - 我从未遇到过ARGB格式的文件,尽管我知道这是可能的。
不同的格式会影响图像的文件大小和颜色质量(如果您不知道),以及图像质量,8位格式是黑白(灰度),有关所有这些的讨论在此处找到:http://en.wikipedia.org/wiki/Color_depth

1
还有一件事 - 如果您使用核心图像滤镜,您会发现很多滤镜特别是CIColorMatrix期望RGBA(真彩色)格式,而不是其他格式。您仍然可以使用其他格式,但需要先进行转换... - Paulo
嗨,保罗。ARGB在iOS资源中常用,尽管我不确定为什么。我认为你的回答应该是一个评论,因为它更像是对颜色格式的解释,而不是试图回答我的问题。 - hpique
事实上,你关于核心图像滤镜的评论比你实际的答案更与问题相关。 - hpique
UIColor通常是RGBA格式,除了黑色或白色的UIColor是单色。我有一个处理大量图像的应用程序,大多数函数都需要RGBA格式。在这个大型应用程序中,我从未涉及过任何ARBG对象。无论如何,我参考了这篇文章,因为真彩色32位RGBA是普遍认可的,并且是Photoshop和其他常用图像软件的典型输出。使用RGBA可以确保与广泛的其他应用程序兼容,特别是如果您生成的图像要在其他平台上交换使用。 - Paulo

0

我正在使用 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big,它运行得非常好。


0

为了获得最佳性能,每行字节和数据应该对齐到16字节的倍数。

每个颜色分量使用的位数:每个颜色分量使用的位数。对于16位RGBA,16/4个分量=4。

每像素位数:至少每个分量的位数*分量数

每行字节数:((每个分量的位数*分量数+7)/8)*宽度

来自CGBitmapContext.h:

每个像素组成中每个分量的位数由'bitsPerComponent'指定。每个像素的字节数等于'(bitsPerComponent * number of components + 7)/8'。位图的每一行由'bytesPerRow'字节组成,其必须至少为'width * bytes per pixel'字节;此外,'bytesPerRow'必须是每个像素的字节数的整数倍。

如果你已经知道了所需的像素格式和色彩空间的每行字节数,如果它是16的倍数,那么就可以了。如果没有正确对齐,Quartz会为您执行一些优化,这将产生开销。为了额外加分,您还可以尝试优化每行的字节数,以适应目标架构上的L2缓存线。

这在Quartz 2D编程指南以及CGImage的文档中有很好的介绍。也有一个相关的问题

总之,最好尝试不同的方法并在Instruments中进行分析。


每行的字节数为(每像素的字节数)* 宽度,而不是(每组件的位数)(组件数量)宽度:像素不能跨越多个单位。如果您使用16位RGB,则一个像素为16位,无论剩下的1位如何未使用。此外,我认为Quartz仅支持超过16位(5 bpc)的RGB,而不支持RGBA。 - zneak
从CGBitmapContext.h文件中:每像素的字节数等于(bitsPerComponent * number of components + 7)/8。将其乘以每行像素数(宽度)。kCGImageAlphaLast是RGBA没有预乘的一个例子。kCGImageAlphaPremultipliedLast则是预乘的RGBA。 - quellish

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