我有一个从CGImage中绘制图像的应用程序。
使用CGImageSourceCreateImageAtIndex加载CImage本身,以便从PNG文件创建图像。
这是精灵引擎的一部分 - 在一个PNG文件中有多个精灵图像,因此每个精灵都有一个CGRect,用于定义在CGImage上找到它的位置。
问题是,CGContextDraw只接受目标rect - 并拉伸源CGImage来填充它。
因此,要绘制每个精灵图像,我们需要使用CGImageCreateWithImageInRect()从原始源创建多个CGImages。
我起初认为这将是一个“便宜”的操作 - 似乎每个CGImage都不需要包含它自己的图像位副本 - 但是,分析表明使用CGImageCreateWithImageInRect()是相当昂贵的操作
是否有更优化的方法将CGImage的子部分绘制到CGContext上,所以我不需要经常使用CGImageCreateWithImageInRect()?
由于缺少源矩形,以及在CGImage上从矩形制作CGImage的容易性,我开始怀疑CGImage可能实现了写入时复制语义,其中由CGImage制作的CGImage将引用与父节点相同的物理位的子矩形。 分析似乎证明这是错误的:/
答案 0 :(得分:2)
我和你在同一条船上。 CGImageCreateWithImageInRect()
更好地满足了我的需求,但之前我曾试图转换为NSImage
,在此之前我正在剪切我正在绘制的上下文,并进行翻译以便CGContextDrawImage()
绘制正确的数据进入裁剪区域。
在我尝试的所有解决方案中:
剪辑和翻译对CPU造成了极大的负担。太慢了。似乎增加位图数据的数量只会略微产生重大的性能影响,这表明这种方法缺乏任何可扩展性。
转换为NSImage
相对有效,至少对于我们使用的数据而言。似乎没有任何重复的位图数据,我可以看到,这主要是我害怕从一个图像对象到另一个图像对象。
有一次我转换为CIImage
,因为这个类也允许绘制图像的子区域。这似乎比转换为NSImage
慢,但确实让我有机会通过一些核心图像过滤器来摆弄位图。
使用CGImageCreateWithImageInRect()
是最快的;也许这已经被优化,因为你上次使用它。 documentation for this function表示生成的图像保留了对原始图像的引用,这似乎与您对写时复制语义的假设一致。在我的基准测试中,似乎没有重复的数据,但也许我读错了结果。我们采用这种方法是因为它不仅速度最快,而且似乎是一种更“干净”的方法,将整个过程保持在一个框架中。
答案 1 :(得分:0)
Create an NSImage with the CGImage。 NSImage对象使draw only some section of it to a destination rectangle变得容易。
答案 2 :(得分:0)
我认为建议使用裁剪区域。
答案 3 :(得分:0)
在编写简单的基于2D图块的游戏时,我遇到了类似的问题。
我获得不错表现的唯一方法是:
1)使用CGContextDrawImage()将图块CGImage预呈现到CGBitmapContext中
2)创建另一个CGBitmapContext作为屏幕外渲染缓冲区,其大小与我正在绘制的UIView相同,并且像素格式与(1)中的上下文相同。
3)编写我自己的快速blit例程,该例程会将像素的区域(CGRect)从(1)中创建的位图上下文复制到(2)中创建的位图上下文。这非常简单:只需简单的内存复制(如果需要,还可以进行一些额外的每像素操作来进行alpha混合),请记住,栅格在缓冲区中的排列顺序相反(图像的最后一行像素位于缓冲区的开头)。
4)绘制框架后,使用CGContextDrawImage()在视图中绘制屏幕外缓冲区。
据我所知,每次调用CGImageCreateWithImageInRect()时,它都会将整个PNG文件解码为原始位图,然后将位图的所需区域复制到目标上下文中。