如何在 Core Graphics 中绘制任何 PNG 格式

Posted

技术标签:

【中文标题】如何在 Core Graphics 中绘制任何 PNG 格式【英文标题】:How to draw any PNG format in Core Graphics 【发布时间】:2013-02-07 14:39:38 【问题描述】:

我们有从 PNG 数据提供者创建 CGImage 的代码,然后在 CGBitmapContext 上绘制它。大多数 PNG 工作正常,但不支持某些 PNG 格式(请参阅here),因此我们得到一个 NULL 上下文。这就是我们创建它的方式:

CGContextRef imageContext = CGBitmapContextCreate(NULL, width, height, CGImageGetBitsPerComponent(image), 0, CGImageGetColorSpace(image), CGImageGetBitmapInfo(image));

现在,虽然这种方式在 Core Graphics 中不起作用,但使用相同的 PNG 制作 UIImage 是可行的。我们确实手动确认确实不支持给定的 PNG 格式(24 bpp、8 bpc、仅 RGB(无 alpha 通道))。此外,传递 kCGImageAlphaPremultipliedFirst 的 CGBitmapInfo 有效!

所以,似乎有一种方法可以让杂散的 PNG 渲染,而 UIImage 实现了这一点。但是我们真的不能在这里使用 UIImage (我们想在后台线程上预渲染位图),因此问题 - 什么是在 Core Graphics 中渲染所有 PNG 的好启发式方法?或者,我们可以使用哪些其他绘图技术来实现相同的效果(但不使用 Core Graphics)?

【问题讨论】:

【参考方案1】:

首先: UIImage 现在是线程安全的。 From the docs:

这也意味着图像对象本身可以安全地从任何 线程。

第二:您的问题仅在于可用的 CGBitmapContext 像素格式数量有限。

如果您始终使用 32bpp、带有预乘 alpha 的 RGB,一切都应该可以工作。当然,您不会得到 PNG 的原始像素格式(如调色板、黑白或其他),但这通常无关紧要,因为在屏幕上绘制图像是用 RGB 完成的。

【讨论】:

第二:如果您的意思是只提供特定格式,那是最后的解决方案。感觉我们还不必去那里。首先:这很有趣,我正在尝试使用 UIKit 实现预渲染,但至少 [UIImage drawAtPoint:] 的行为不像我预期的那样。我会继续尝试,但 CG 解决方案已经证明了自己。 @VladimirGritsenko 我对第二个建议的意思是:始终使用完整的 RGBA、32bpp CGBitmapContext。然后,您将能够将每个 PNG(ImageIO 理解的)渲染到此上下文中。 ImageIO 是 UIImage 和 CGI​​mage 用于读取图像的底层库。它可以读取我偶然发现的每一个 PNG。您确实遇到的问题是由于您尝试使用 PNG 的像素格式设置图像上下文。这不起作用,因为 CGBitmapContext 在支持的格式方面受到很大限制。 顺便说一下,这里是the list of supported bitmap formats。 @NikolaiRuhe,我刚刚经历了一段时间以来最大的脸掌时刻。我确实尝试使上下文与 PNG 相同,这确实是完全没有必要的。谢谢! :-)

以上是关于如何在 Core Graphics 中绘制任何 PNG 格式的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Core Graphics / Quartz 2D 中绘制圆角矩形?

使用 Core Graphics 绘制 UIImage?

如何使用 Core Graphics 绘制点?

在 iOS 中使用 Core Graphics 绘制 VU 表

如何使用 Core Graphics 绘制箭头?

使用 Core Graphics 绘制带有减去文本的路径