Rob*_*Rob 11 core-graphics objective-c cgcontext ios
我正在尝试使用Core Graphics构建一个橡皮擦工具,我发现制作高性能橡皮擦非常困难 - 这一切都归结为:
CGContextSetBlendMode(context, kCGBlendModeClear)
如果你四处搜索如何使用Core Graphics"擦除",那么几乎每个答案都会带回来.问题是它(仅显然)在位图上下文中起作用.如果你正在尝试实现交互式擦除,我看不出kCGBlendModeClear你有多大帮助 - 据我所知,你或多或少地被锁定在屏幕上和屏幕外擦除UIImage/ CGImage并在着名的非图像中绘制图像高效的[UIView drawRect].
这是我能做的最好的:
-(void)drawRect:(CGRect)rect
{
if (drawingStroke) {
if (eraseModeOn) {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[eraseImage drawAtPoint:CGPointZero];
CGContextAddPath(context, currentPath);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, lineWidth);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextSetLineWidth(context, ERASE_WIDTH);
CGContextStrokePath(context);
curImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[curImage drawAtPoint:CGPointZero];
} else {
[curImage drawAtPoint:CGPointZero];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, currentPath);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, lineWidth);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
CGContextStrokePath(context);
}
} else {
[curImage drawAtPoint:CGPointZero];
}
}
Run Code Online (Sandbox Code Playgroud)
绘制法线(!eraseModeOn)是可以接受的; 我正在将我的屏幕外绘图缓冲区(curImage包含所有先前绘制的笔划)与当前图像进行对比CGContext,并且我正在渲染当前绘制的线条(路径).它并不完美,但嘿,它有效,并且它的性能相当合理.
但是,因为kCGBlendModeNormal显然在位图上下文之外不起作用,我不得不:
UIGraphicsBeginImageContextWithOptions).eraseImage实际上是从curImage打开橡皮擦工具时得到的 - 所以与curImage参数真的非常相似).kCGBlendModeClear用于清除像素).curImage = UIGraphicsGetImageFromCurrentImageContext();)CGContext这很糟糕,表现明智.使用Instrument的Time工具,很明显这个方法的问题在于:
UIGraphicsBeginImageContextWithOptions 太贵了很自然地,代码在真正的iPad上表现得非常糟糕.
我不确定该怎么做.我一直试图弄清楚如何清除非位图上下文中的像素,但据我所知,依赖kCGBlendModeClear是一个死胡同.
有什么想法或建议吗?其他iOS绘图应用程序如何处理擦除?
附加信息
我一直在玩一种CGLayer方法,因为看起来它CGContextSetBlendMode(context, kCGBlendModeClear)会CGLayer基于我已经完成的一些谷歌搜索工作.
但是,我并不希望这种方法能够成功.在drawRect(甚至使用setNeedsDisplayInRect)中绘制图层是非常不具有效果的; 令人窒息的核心图形将渲染图层中的每个路径CGContextDrawLayerAtPoint(根据Instruments).据我所知,使用位图背景是在性能方面绝对是最好在这里-唯一的问题,当然,作为上述问题(kCGBlendModeClear没有工作后,我的blit位图上下文主要CGContext的drawRect).
我通过使用以下代码设法获得了良好的结果:
- (void)drawRect:(CGRect)rect
{
if (drawingStroke) {
if (eraseModeOn) {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginTransparencyLayer(context, NULL);
[eraseImage drawAtPoint:CGPointZero];
CGContextAddPath(context, currentPath);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, ERASE_WIDTH);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextSetStrokeColorWithColor(context, [[UIColor clearColor] CGColor]);
CGContextStrokePath(context);
CGContextEndTransparencyLayer(context);
} else {
[curImage drawAtPoint:CGPointZero];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, currentPath);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextStrokePath(context);
}
} else {
[curImage drawAtPoint:CGPointZero];
}
self.empty = NO;
}
Run Code Online (Sandbox Code Playgroud)
诀窍是将以下内容包含在CGContextBeginTransparencyLayer/ CGContextEndTransparencyLayercalls中:
kCGBlendModeClear由于擦除背景图像的像素数据和擦除路径都在同一层中,因此它具有清除像素的效果.
| 归档时间: |
|
| 查看次数: |
7404 次 |
| 最近记录: |