- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
我正在尝试使用 Core Graphics 构建橡皮擦工具,但我发现制作高性能橡皮擦非常困难 - 这一切都归结为:
CGContextSetBlendMode(上下文, 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];
}
}
绘制一条普通线 (!eraseModeOn
) 是可以接受的性能;我正在将我的屏幕外绘图缓冲区(curImage
,其中包含所有以前绘制的笔画)blit 到当前的 CGContext
,并且我正在渲染线(路径)当前绘制。它并不完美,但是嘿,它可以工作,而且性能相当不错。
但是,因为 kCGBlendModeNormal
显然不能在位图上下文之外工作,所以我不得不:
UIGraphicsBeginImageContextWithOptions
)。eraseImage
,当橡皮擦工具打开时,它实际上是从 curImage
派生的 - 所以实际上与 curImage
为了论证)。kCGBlendModeClear
清除像素)。curImage = UIGraphicsGetImageFromCurrentImageContext();
)CGContext
从性能方面来说,这太糟糕了。使用 Instrument 的时间工具,很明显这种方法的问题在于:
UIGraphicsBeginImageContextWithOptions
很昂贵很自然地,代码在真实 iPad 上的表现非常糟糕。
我不太确定在这里做什么。我一直在尝试弄清楚如何在非位图上下文中清除像素,但据我所知,依赖 kCGBlendModeClear
是死路一条。
有什么想法或建议吗?其他 iOS 绘图应用如何处理删除?
附加信息
我一直在尝试使用 CGLayer
方法,因为看起来 CGContextSetBlendMode(context, kCGBlendModeClear)
将在 CGLayer
基于我所做的一些谷歌搜索。
但是,我不太希望这种方法能够成功。在 drawRect
中绘制图层(即使使用 setNeedsDisplayInRect
)性能非常差; Core Graphics 将在 CGContextDrawLayerAtPoint
中渲染图层中的每个路径(根据 Instruments)。据我所知,就性能而言,这里使用位图上下文绝对更可取 - 当然,唯一的问题是上述问题(kCGBlendModeClear
在我将位图上下文 blit 到drawRect
中的主要 CGContext
。
最佳答案
我已经通过使用以下代码获得了良好的结果:
- (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;
}
诀窍是将以下内容包装到 CGContextBeginTransparencyLayer
/CGContextEndTransparencyLayer
调用中:
kCGBlendModeClear
由于删除背景图的像素数据和删除路径在同一层,所以起到清除像素的作用。
关于ios - CGContext:如何删除位图上下文之外的像素(例如 kCGBlendModeClear)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19876856/
我正在尝试使用 Core Graphics 构建橡皮擦工具,但我发现制作高性能橡皮擦非常困难 - 这一切都归结为: CGContextSetBlendMode(上下文, kCGBlendModeCle
我使用 kCGBlendModeClear 混合模式来实现橡皮擦工具。它在 ios 中工作正常,但在 OS X 中不起作用。它在 OS X 中使用 kCGBlendModeClear 混合模式创建黑色
我是一名优秀的程序员,十分优秀!