2011-07-28 57 views
3

我正在创建一个应用程序,允许用户剪出图像的一部分。为了做到这一点,他们将创建一堆UIBezierPaths来形成剪切路径。我目前的设置如下:iOS:从UIBezierPath创建图像剪切路径

  • UIImageView显示他们正在剪切的图像。
  • 在此之上,UIImageView是UIImageView的一个自定义子类, 执行自定义drawRect:方法来显示/更新用户添加的UIBezierPaths的 。
  • 当用户单击“完成”按钮时,将创建一个新的UIBezierPath对象,该对象通过循环存储在其中的数组并循环调用appendPath:自身来合并用户创建的所有单个路径。这个新的UIBezierPath然后关闭它的路径。

这就像我已经得到。我知道UIBezierPath有一个addClip方法,但我无法从文档中找出如何使用它。

一般来说,我见过的所有用于裁剪的示例都直接使用Core Graphics而不是UIBezierPath包装器。我意识到UIBezierPath有一个CGPath属性。那么我应该在裁剪时使用它而不是完整的UIBezierPath对象吗?

+1

你如何检测你想要剪辑的部分?通过手势? – Shrawan

回答

0

根据UIImageView class reference,苹果表示不要继承UIImageView。感谢@rob mayoff指出了这一点。

但是,如果您正在实现自己的drawRect,请从您自己的UIView子类开始。并且,它在drawRect中使用addClip。您可以使用UIBezierPath做到这一点,而无需将其转换为CGPath。

- (void)drawRect:(CGRect)rect 
{ 
    // This assumes the clippingPath and image may be drawn in the current coordinate space. 
    [[self clippingPath] addClip]; 
    [[self image] drawAtPoint:CGPointZero]; 
} 

如果要向上或向下缩放以填充边界,则需要缩放图形上下文。 (你也可以申请一个CGAffineTransform到clippingPath,但那是永久性的,所以你需要先复制clippingPath。)

- (void)drawRect:(CGRect)rect 
{ 
    // This assumes the clippingPath and image are in the same coordinate space, and scales both to fill the view bounds. 
    if ([self image]) 
    { 
     CGSize imageSize = [[self image] size]; 
     CGRect bounds = [self bounds]; 

     CGContextRef context = UIGraphicsGetCurrentContext(); 
     CGContextScaleCTM(context, bounds.size.width/imageSize.width, bounds.size.height/imageSize.height); 

     [[self clippingPath] addClip]; 
     [[self image] drawAtPoint:CGPointZero]; 
    } 
} 

这将单独缩放图像上的各轴。如果你想保持它的宽高比,你需要计算整体缩放比例,并且可能翻译它,使它居中或者对齐。

最后,如果您的路径被绘制了很多,所有这些相对较慢。您可能会发现将图像存储在CALayer中的速度更快,并且包含路径的CAShapeLayer除测试外,请勿使用以下方法。您需要分别缩放图像图层和蒙版以使其排列整齐。优点是您可以更改蒙版而不渲染底层图像。

- (void) setImage:(UIImage *)image; 
{ 
    // This method should also store the image for later retrieval. 
    // Putting an image directly into a CALayer will stretch the image to fill the layer. 
    [[self layer] setContents:(id) [image CGImage]]; 
} 

- (void) setClippingPath:(UIBezierPath *)clippingPath; 
{ 
    // This method should also store the clippingPath for later retrieval. 
    if (![[self layer] mask]) 
     [[self layer] setMask:[CAShapeLayer layer]]; 

    [(CAShapeLayer*) [[self layer] mask] setPath:[clippingPath CGPath]]; 
} 

如果您使用图层蒙版进行图像剪裁工作,则不再需要drawRect方法。删除它的效率。