绘制CGImage的一部分

时间:2010-08-25 13:19:23

标签: cocoa core-graphics cgimage

我有一个从CGImage中绘制图像的应用程序。

使用CGImageSourceCreateImageAtIndex加载CImage本身,以便从PNG文件创建图像。

这是精灵引擎的一部分 - 在一个PNG文件中有多个精灵图像,因此每个精灵都有一个CGRect,用于定义在CGImage上找到它的位置。

问题是,CGContextDraw只接受目标rect - 并拉伸源CGImage来填充它。

因此,要绘制每个精灵图像,我们需要使用CGImageCreateWithImageInRect()从原始源创建多个CGImages。

我起初认为这将是一个“便宜”的操作 - 似乎每个CGImage都不需要包含它自己的图像位副本 - 但是,分析表明使用CGImageCreateWithImageInRect()是相当昂贵的操作

是否有更优化的方法将CGImage的子部分绘制到CGContext上,所以我不需要经常使用CGImageCreateWithImageInRect()?


由于缺少源矩形,以及在CGImage上从矩形制作CGImage的容易性,我开始怀疑CGImage可能实现了写入时复制语义,其中由CGImage制作的CGImage将引用与父节点相同的物理位的子矩形。 分析似乎证明这是错误的:/

4 个答案:

答案 0 :(得分:2)

我和你在同一条船上。 CGImageCreateWithImageInRect()更好地满足了我的需求,但之前我曾试图转换为NSImage,在此之前我正在剪切我正在绘制的上下文,并进行翻译以便CGContextDrawImage()绘制正确的数据进入裁剪区域。

在我尝试的所有解决方案中:

  1. 剪辑和翻译对CPU造成了极大的负担。太慢了。似乎增加位图数据的数量只会略微产生重大的性能影响,这表明这种方法缺乏任何可扩展性。

  2. 转换为NSImage相对有效,至少对于我们使用的数据而言。似乎没有任何重复的位图数据,我可以看到,这主要是我害怕从一个图像对象到另一个图像对象。

  3. 有一次我转换为CIImage,因为这个类也允许绘制图像的子区域。这似乎比转换为NSImage慢,但确实让我有机会通过一些核心图像过滤器来摆弄位图。

  4. 使用CGImageCreateWithImageInRect()是最快的;也许这已经被优化,因为你上次使用它。 documentation for this function表示生成的图像保留了对原始图像的引用,这似乎与您对写时复制语义的假设一致。在我的基准测试中,似乎没有重复的数据,但也许我读错了结果。我们采用这种方法是因为它不仅速度最快,而且似乎是一种更“干净”的方法,将整个过程保持在一个框架中。

答案 1 :(得分:0)

答案 2 :(得分:0)

我认为建议使用裁剪区域。

答案 3 :(得分:0)

在编写简单的基于2D图块的游戏时,我遇到了类似的问题。

我获得不错表现的唯一方法是:

1)使用CGContextDrawImage()将图块CGImage预呈现到CGBitmapContext中

2)创建另一个CGBitmapContext作为屏幕外渲染缓冲区,其大小与我正在绘制的UIView相同,并且像素格式与(1)中的上下文相同。

3)编写我自己的快速blit例程,该例程会将像素的区域(CGRect)从(1)中创建的位图上下文复制到(2)中创建的位图上下文。这非常简单:只需简单的内存复制(如果需要,还可以进行一些额外的每像素操作来进行alpha混合),请记住,栅格在缓冲区中的排列顺序相反(图像的最后一行像素位于缓冲区的开头)。

4)绘制框架后,使用CGContextDrawImage()在视图中绘制屏幕外缓冲区。

据我所知,每次调用CGImageCreateWithImageInRect()时,它都会将整个PNG文件解码为原始位图,然后将位图的所需区域复制到目标上下文中。