CGContextDrawImage(CGContextRef、CGRect、CGImageRef)は、UIImageをサポートするCGImageを描画する場合よりも、CoreGraphicsによって(つまり、CGBitmapContextCreateImageを使用して)作成されたCGImageを描画する場合に非常に悪いパフォーマンスを示すようです。このテスト方法を参照してください。
-(void)showStrangePerformanceOfCGContextDrawImage
{
///Setup : Load an image and start a context:
UIImage *theImage = [UIImage imageNamed:@"reallyBigImage.png"];
UIGraphicsBeginImageContext(theImage.size);
CGContextRef ctxt = UIGraphicsGetCurrentContext();
CGRect imgRec = CGRectMake(0, 0, theImage.size.width, theImage.size.height);
///Why is this SO MUCH faster...
NSDate * startingTimeForUIImageDrawing = [NSDate date];
CGContextDrawImage(ctxt, imgRec, theImage.CGImage); //Draw existing image into context Using the UIImage backing
NSLog(@"Time was %f", [[NSDate date] timeIntervalSinceDate:startingTimeForUIImageDrawing]);
/// Create a new image from the context to use this time in CGContextDrawImage:
CGImageRef theImageConverted = CGBitmapContextCreateImage(ctxt);
///This is WAY slower but why?? Using a pure CGImageRef (ass opposed to one behind a UIImage) seems like it should be faster but AT LEAST it should be the same speed!?
NSDate * startingTimeForNakedGImageDrawing = [NSDate date];
CGContextDrawImage(ctxt, imgRec, theImageConverted);
NSLog(@"Time was %f", [[NSDate date] timeIntervalSinceDate:startingTimeForNakedGImageDrawing]);
}
ですから、問題は、#1何がこれを引き起こしているのか、#2はそれを回避する方法、つまり、より高速なCGImageRefを作成する他の方法があるのかということだと思います。最初にすべてをUIImagesに変換できることに気付きましたが、それは非常に醜い解決策です。私はすでにCGContextRefをそこに置いています。
更新:これは小さな画像を描くときに必ずしも当てはまらないようですか?これは、大きな画像(つまりフルサイズのカメラ写真)を使用すると、この問題が増幅されるという手がかりになる可能性があります。640x480は、どちらの方法でも実行時間の点でかなり似ているようです
更新2:わかりました、それで私は何か新しいものを発見しました..それは実際にはパフォーマンスを変えているCGImageの裏付けではありません。2つのステップの順序をフリップフロップして、UIImageメソッドの動作を遅くすることができますが、「裸の」CGImageは超高速になります。あなたが2番目に実行するものはどれでもひどいパフォーマンスに苦しむようです。これは、CGBitmapContextCreateImageで作成した画像に対してCGImageReleaseを呼び出してメモリを解放しない限り、当てはまるようです。その後、UIImageでバックアップされたメソッドは高速になります。逆にそれは真実ではありません。何が得られますか?「混雑した」メモリは、このようなパフォーマンスに影響を与えるべきではありませんか?
更新3:話が早すぎた。以前の更新は、サイズ2048x2048の画像にも当てはまりますが、1936x2592(カメラサイズ)にステップアップすると、操作の順序やメモリの状況に関係なく、ネイキッドCGImageメソッドの速度が大幅に低下します。21MBの画像を効率的に処理できないのに対し、16MBの画像を効率的にするCGの内部制限があるかもしれません。2048x2048よりもカメラサイズの描画が文字通り20倍遅くなります。どういうわけか、UIImageは純粋なCGImageオブジェクトよりもはるかに高速にCGImageデータを提供します。oO
UPDATE 4:これはメモリキャッシュの問題に関係しているのではないかと思いましたが、UIImageが非キャッシュの[UIImage imageWithContentsOfFile]でロードされても、[UIImageimageNamed]が使用されている場合と同じ結果になります。
更新5(2日目):昨日回答されたよりもmroeの質問を作成した後、今日は何かしっかりしたものがあります。私が確かに言えることは次のとおりです。
- UIImageの背後にあるCGImageはアルファを使用しません。(kCGImageAlphaNoneSkipLast)。私のコンテキストはアルファを使用していたので、おそらくそれらはより速く描画されると思いました。そこで、kCGImageAlphaNoneSkipLastを使用するようにコンテキストを変更しました。これにより、次の場合を除いて、描画がはるかに高速になります。
- 最初にUIImageを使用してCGContextRefに描画すると、後続のすべての画像の描画が遅くなります
私はこれを1)最初に非アルファコンテキスト(1936x2592)を作成することによって証明しました。2)ランダムに色付けされた2x2の正方形で塗りつぶしました。3)そのコンテキストにCGImageを描画するフルフレームは高速(.17秒)でした。4)実験を繰り返しましたが、UIImageを裏付ける描画されたCGImageでコンテキストを埋めました。その後のフルフレーム画像の描画は6秒以上でした。SLOWWWWW。
どういうわけか、(大きい)UIImageを使用してコンテキストに描画すると、そのコンテキストへの後続のすべての描画が大幅に遅くなります。