使用CGBitmapContext绘制得太慢了

Eag*_*gic 4 iphone objective-c drawrect ipad ios

所以我在这个过程中有一个基本的绘图应用程序,允许我绘制线条.我绘制到屏幕外的位图,然后显示图像drawRect.它工作但速度太慢,用你的手指画出来后更新大约半秒钟.我从本教程中获取了代码并对其进行了调整,http://www.youtube.com/watch?v = UFWeMIL-Nu8&feature = relmfu,正如您在评论中所看到的那样,人们也说它太慢但是那个家伙没有'回答.

那么我怎样才能加快速度呢?或者有更好的方法吗?任何指针将不胜感激.

继承了我的代码DrawView.m.

-(id)initWithCoder:(NSCoder *)aDecoder {
     if ((self=[super initWithCoder:aDecoder])) {
         [self setUpBuffer];
     }

     return self;
}

-(void)setUpBuffer {
     CGContextRelease(offscreenBuffer);

     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

     offscreenBuffer = CGBitmapContextCreate(NULL, self.bounds.size.width, self.bounds.size.height, 8, self.bounds.size.width*4, colorSpace, kCGImageAlphaPremultipliedLast);
     CGColorSpaceRelease(colorSpace);

     CGContextTranslateCTM(offscreenBuffer, 0, self.bounds.size.height);
     CGContextScaleCTM(offscreenBuffer, 1.0, -1.0);
}


-(void)drawToBuffer:(CGPoint)coordA :(CGPoint)coordB :(UIColor *)penColor :(int)thickness {

     CGContextBeginPath(offscreenBuffer);
     CGContextMoveToPoint(offscreenBuffer, coordA.x,coordA.y);
     CGContextAddLineToPoint(offscreenBuffer, coordB.x,coordB.y);
     CGContextSetLineWidth(offscreenBuffer, thickness);
     CGContextSetLineCap(offscreenBuffer, kCGLineCapRound);
     CGContextSetStrokeColorWithColor(offscreenBuffer, [penColor CGColor]);
     CGContextStrokePath(offscreenBuffer);

}

- (void)drawRect:(CGRect)rect {
    CGImageRef cgImage = CGBitmapContextCreateImage(offscreenBuffer);
    UIImage *image =[[UIImage alloc] initWithCGImage:cgImage];
    CGImageRelease(cgImage);
    [image drawInRect:self.bounds];

}
Run Code Online (Sandbox Code Playgroud)

在模拟器上完美运行但不是设备,我想这与处理器速度有关.

我正在使用ARC.

Kyl*_*lls 7

我试图修复你的代码,但是因为你似乎只发布了一半的代码我无法使它工作(复制+粘贴代码会导致很多错误,更不用说启动性能调优了).

但是,您可以使用一些提示来大幅提高性能.

第一个,也可能是最引人注目的是-setNeedsDisplayInRect:而不是-setNeedsDisplay.这意味着它只会重绘已更改的小矩形.对于具有1024*768*4像素的iPad 3来说,这是一项很多工作.每帧减少到约20*20或更低将大大提高性能.

CGRect rect;
rect.origin.x = minimum(coordA.x, coordB.x) - (thickness * 0.5);
rect.size.width = (maximum(coordA.x, coordB.x) + (thickness * 0.5)) - rect.origin.x;
rect.origin.y = minimum(coordA.y, coordB.y) - (thickness * 0.5);
rect.size.height = (maximum(coordA.y, coordB.y) + (thickness * 0.5)) - rect.origin.y;
[self setNeedsDisplayInRect:rect];
Run Code Online (Sandbox Code Playgroud)

你可以做的另一个重大改进是只绘制当前触摸的CGPath(你这样做).但是,然后您在绘制rect中绘制已保存/缓存的图像.所以,再次,每帧重绘一次.更好的方法是使绘图视图透明,然后使用后面的UIImageView.UIImageView是在iOS上显示图像的最佳方式.

- DrawView (1 finger)
   -drawRect:
- BackgroundView (the image of the old touches)
   -self.image
Run Code Online (Sandbox Code Playgroud)

然后,绘制视图本身只会绘制当前触摸仅每次更改的部分.当用户抬起手指时,您可以将其缓存到UIImage,在当前背景/缓存UIImageView的图像上绘制,并将imageView.image设置为新图像.

组合图像时的最后一点涉及将2个全屏图像绘制到屏幕外CGContext中,因此如果在主线程上完成则会导致延迟,而这应该在后台线程中完成,然后将结果推回到主线程.

* touch starts *
- DrawView : draw current touch
* touch ends *
- 'background thread' : combine backgroundView.image and DrawView.drawRect
    * thread finished *
    send resulting UIImage to main queue and set backgroundView.image to it;
    Clear DrawView's current path that is now in the cache;
Run Code Online (Sandbox Code Playgroud)

所有这些结合起来可以制作一个非常流畅的60fps绘图应用程序.但是,视图不会像我们想的那样快速更新,因此在更快地移动图形时的绘图看起来是锯齿状的.这可以通过使用UIBezierPath而不是CGPath来改进.

CGPoint lastPoint = [touch previousLocationInView:self];
CGPoint mid = midPoint(currentPoint, lastPoint);
-[UIBezierPath addQuadCurveToPoint:mid controlPoint:lastPoint];
Run Code Online (Sandbox Code Playgroud)


Pau*_*nge 5

它很慢的原因是因为每个帧都在创建一个位图并试图绘制它.

你问过更好的方法吗?你有没有看过iOS上的绘图应用程序的苹果示例代码?如果你不喜欢它,那么你总是可以使用cocos2d,它提供了一个CCRenderTexture类(和示例代码).

目前,您使用的方法已经知道效率不高.