CoreGraphics 在大 UIImage 上绘图

Posted

技术标签:

【中文标题】CoreGraphics 在大 UIImage 上绘图【英文标题】:CoreGraphics drawing on a large UIImage 【发布时间】:2011-08-08 23:21:34 【问题描述】:

我有一个 UIImage,我在它上面画出跟随用户手指的线条。这就像一个绘图板。这在 UIImage 很小(比如 500 x 600)时非常有效,但如果它像 1600 x 1200 一样,它会变得非常粗糙和滞后。有没有办法可以优化这个?这是我在 touchesModed 中的绘图代码:

UIGraphicsBeginImageContext(self.frame.size);
[drawImageView.image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 15.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
//CGContextSetAlpha(UIGraphicsGetCurrentContext(), 0.5f);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

谢谢。

【问题讨论】:

【参考方案1】:

与其一次性绘制整个 1600X1200 帧,不如根据需要绘制它。我的意思是,由于您正在绘制整个帧(驻留在内存中),因此您的性能参差不齐。

试试CATiledLayer。基本上,您只需要绘制您的设备能够绘制的屏幕尺寸,除此之外,当用户滚动时,您需要动态绘制它。

这是在 iPad 或 iPhone 上的 Google 地图中使用的。希望这会有所帮助...

【讨论】:

【参考方案2】:

不是每次触摸移动时都创建一个新上下文并将当前图像绘制到其中,而是使用CGBitmapContextCreate 创建一个上下文并重用该上下文。之前的所有绘图都已经在上下文中,并且您不必在每次触摸移动时都创建新的上下文。

- (CGContextRef)drawingContext 
    if(!context)  // context is an instance variable of type CGContextRef
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        if(!colorSpace) return nil;
        context = CGBitmapContextCreate(NULL, contextSize.width, contextSize.height,
                                        8, contextSize.width * 32, colorSpace,
                                        kCGImageAlphaPremultipliedFirst);
        CGColorSpaceRelease(colorSpace);
        if(!context) return nil;
        CGContextConcatCTM(context, CGAffineTransformMake(1,0,0,-1,0,contextSize.height));
        CGContextDrawImage(context, (CGRect)CGPointZero,contextSize, drawImageView.image.CGImage);
        CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
        CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 15.0);
        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
    
    return context;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
    CGContextRef ctxt = [self drawingContext];
    CGContextBeginPath(ctxt);
    CGContextMoveToPoint(ctxt, lastPoint.x, lastPoint.y);
    CGContextAddLineToPoint(ctxt, currentPoint.x, currentPoint.y);
    CGContextStrokePath(ctxt);
    CGImageRef img = CGBitmapContextCreateImage(ctxt);
    drawImageView.image = [UIImage imageWithCGImage:img];
    CGImageRelease(img);

此代码需要实例变量CGContextRef contextCGSize contextSize。上下文需要在 dealloc 中释放,并且每当您更改其大小时。

【讨论】:

以上是关于CoreGraphics 在大 UIImage 上绘图的主要内容,如果未能解决你的问题,请参考以下文章

用于视网膜显示的 CoreGraphics

使用 Core Graphics 绘制 UIImage?

如何从 UIImage (Cocoa Touch) 或 CGImage (Core Graphics) 获取像素数据?

如何在 UIImage 中屏蔽 XOR [重复]

UIImage 将原始像素从白色更改为清晰?

iOS 图像处理 - 图像拼接