【问题标题】:Painting on UIImageView with better performance在 UIImageView 上绘画具有更好的性能
【发布时间】:2010-07-03 05:56:27
【问题描述】:

我有一个视图,当用户在 iPad/iPhone 的屏幕上移动手指时,我绘制了一条虚线。我在存储为 LastLocation 的点和作为 CurrentLocation 的点之间画了一条线。图纸要在屏幕上永久显示。 每次触发 touchMoved 事件时都会发生这种情况,并最终让我绘制一条虚线来跟踪人们拖动手指的位置......就像绘画应用程序一样。

我有一个在触发触摸事件时被调用的函数,它执行以下操作。 该视图包含一个名为 drawImage 的 UIImageView。我使用 UIImageView 作为持久绘制线条的一种方式。这显然不是人们通常做油漆应用的方式,因为它很慢。 任何有关使用 CGContextRef 调用进行持久绘制的更好方法的见解将不胜感激。

/* Enter bitmap graphics drawing context */
UIGraphicsBeginImageContext(frame.size);
/* Draw the previous frame back in to the bitmap graphics context */
[drawImage.image drawInRect:CGRectMake(0, 0, drawImage.frame.size.width, drawImage.frame.size.height)]; //originally self.frame.size.width, self.frame.size.height)];       
/* Draw the new line */
CGContextRef ctx = UIGraphicsGetCurrentContext();
/* Set line draw color to green, rounded cap end and width of 5 */
CGContextSetLineDash(ctx, 0, dashPattern, 2);
CGContextSetStrokeColorWithColor(ctx, color);
CGContextSetLineCap(ctx, kCGLineCapRound); //kCGLineCapSquare, kCGLineCapButt, kCGLineCapRound
CGContextSetLineWidth(ctx, 5.0); // for size
/* Start the new path point */
CGContextMoveToPoint(ctx, LastLocation.x, LastLocation.y);
CGContextAddLineToPoint(ctx, Current.x, Current.y);
CGContextStrokePath(ctx);
/* Push the updated graphics back to the image */
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

“drawImage.image drawInRect”调用非常慢,本质上是重绘整个图像。

有更快的方法吗?我在绘画博客的几个地方看到过这样的绘图代码,但它有点慢。 很想听听关于这个话题的一些想法。

【问题讨论】:

  • Fuzz,你搞定了吗?我试图找出一个非常相似的问题。我很想听听你的想法。谢谢 - fxshot

标签: iphone cocoa-touch uiimageview core-graphics cgcontext


【解决方案1】:

无需手动合成图像和线条。拥有在另一个绘制图像的 UIImageView 上方绘制线条的视图。让系统进行合成并绘制图像。

在您的代码中,只需在画线视图的 drawRect: 方法中的两条 drawImage 线之间进行操作即可。

-(void) drawRect:(CGRect)dirty {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    /* Set line draw color to green, rounded cap end and width of 5 */
    CGContextSetLineDash(ctx, 0, dashPattern, 2);
    CGContextSetStrokeColorWithColor(ctx, color);
    CGContextSetLineCap(ctx, kCGLineCapRound); //kCGLineCapSquare, kCGLineCapButt, kCGLineCapRound
    CGContextSetLineWidth(ctx, 5.0); // for size
    /* Start the new path point */
    CGContextMoveToPoint(ctx, LastLocation.x, LastLocation.y);
    CGContextAddLineToPoint(ctx, Current.x, Current.y);
    CGContextStrokePath(ctx);
}

当线条的一端移动时,保存新的点并将线条图视图标记为需要显示。所以 Current 和 LastLocation 都应该是 line drawing view 的成员,并且在每个的 setter 方法中,调用 setNeedsDisplay。

确保线条图视图的 clearsContextBeforeDrawing 为 YES 且 opaque 为 NO。

【讨论】:

  • drawnonward,我已经考虑过您的解决方案,但我不确定我是否正确解释了自己,所以我会更新这个问题。 UIImageView 仅保留用户在屏幕上绘制的线条,因为上下文总是会刷新。我实际上想要的效果就像用户手指的“画笔”式运动,所有的绘画都保持不变。我正在使用 UIImageView 来保持这种持久性。那有意义吗? :-)
  • 您当前的代码在每次调用时使用 UIGraphicsBeginImageContext 创建一个新的 CGBitmapContext,然后使用 UIGraphicsGetImageFromCurrentImageContext 将该上下文的内容复制到一个新图像中。那是很多不必要的数据被复制。相反,您应该创建一个用于绘制的持久 CGBitmapContext,以及一个引用相同像素的 CGImage。然后在 drawRect: 中绘制该图像或将其粘贴在 UIImageView 中。每当位图发生变化时,在视图上调用 setNeedsDisplay。
  • 啊,太棒了。说得通。我花了一些时间试图解决这个问题,但是我到底如何创建一个与 CGBitmapContext 具有相同内存的 CGImage。我已经创建了上下文,并且有一个足够大的 void* 来存储我的数据......但我不确定如何制作 CGImage。使用 CGBitmapContextCreate 实际上做了一个副本,所以没有帮助:-(
  • 啊,我在 CGDataProviderCreateWithData 中找到了一个朋友,并将其传递给 CGImageCreate。
  • 是的,CGDataProviderCreateWithData 是 CGImage 和 CGBitmapContext 之间缺失的环节。很高兴你得到它。
猜你喜欢
  • 2012-08-15
  • 2013-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多