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];
}
}
法線の描画 ( !eraseModeOn
) は許容できるパフォーマンスです。オフスクリーン描画バッファー (curImage
以前に描画されたすべてのストロークを含む) を現在の にブリットし、現在CGContext
描画されている線 (パス) をレンダリングしています。完璧ではありませんが、動作し、適度なパフォーマンスを発揮します。
ただし、kCGBlendModeNormal
明らかにビットマップコンテキストの外では機能しないため、次のことを余儀なくされています。
- ビットマップ コンテキストを作成します (
UIGraphicsBeginImageContextWithOptions
)。 - オフスクリーン バッファを描画します (
eraseImage
これは、消しゴム ツールがオンになっているときに実際に派生するため、引数の目的curImage
とほとんど同じです)。curImage
- 現在描画されている「消去線」(パス) をビットマップ コンテキストにレンダリングします (
kCGBlendModeClear
ピクセルをクリアするために使用します)。 - 画像全体をオフスクリーン バッファに抽出します (
curImage = UIGraphicsGetImageFromCurrentImageContext();
) - そして最後に、オフスクリーン バッファをビューの
CGContext
パフォーマンス的には恐ろしいことです。Instrument の Time ツールを使用すると、この方法のどこに問題があるかが痛々しいほど明白になります。
UIGraphicsBeginImageContextWithOptions
高いです- オフスクリーン バッファを 2 回描画するとコストがかかる
- 画像全体をオフスクリーン バッファに抽出するのはコストがかかる
当然のことながら、このコードは実際の iPad ではひどいパフォーマンスを示します。
ここで何をすべきかよくわかりません。ビットマップ以外のコンテキストでピクセルをクリアする方法を見つけようとしていますが、私が知る限り、に依存することkCGBlendModeClear
は行き止まりです。
何か考えや提案はありますか?他の iOS 描画アプリはどのように消去を処理しますか?
追加情報
私が行った少しのグーグル検索に基づいて 動作CGLayer
するように見えるので、私はアプローチで遊んでいます。CGContextSetBlendMode(context, kCGBlendModeClear)
CGLayer
ただし、このアプローチがうまくいくとはあまり期待していません。drawRect
レイヤーを( を使用しても)描画するsetNeedsDisplayInRect
と、非常にパフォーマンスが低下します。CGContextDrawLayerAtPoint
Core Graphics は、 (Instruments によると)レイヤー内の各パスをレンダリングします。私が知る限り、ビットマップ コンテキストを使用することは、パフォーマンスの点でここでは間違いなく望ましいです。もちろん、唯一の問題は上記の質問です (ビットマップ コンテキストをメインにkCGBlendModeClear
ブリットした後は動作しません)。CGContext
drawRect