【问题标题】:How to crop the image using UIBezierPath?如何使用 UIBezierPath 裁剪图像?
【发布时间】:2012-10-31 07:33:12
【问题描述】:

我想从UIBezierpath 封闭路径中获取图像(见图)。我使用drawRect 方法在UIView 上绘制图像,并使用drawRect 方法绘制线条。 如何获得特定的封闭路径图像?请帮我。提前致谢。

此代码用于绘制贝塞尔路径。

UIBezierPath *aPath = [UIBezierPath bezierPath];
for (NSString *pointString in pointArray) {
    if ([pointArray indexOfObject:pointString] == 0)
        [aPath moveToPoint:CGPointFromString(pointString)];
    else
        [aPath addLineToPoint:CGPointFromString(pointString)];
}
[aPath closePath];

【问题讨论】:

  • 我们如何在 UIImageView 上画一条线,当我尝试在 UIview 上画一条线时,UIview 工作但在 uiimageview 不工作,你能帮我吗
  • 你的目标实现了吗?
  • 嗨,你能回答你自己的问题吗....
  • @Rajneesh071 Yup.
  • 如果您找到了解决方案,请告诉我。我也在使用类似的功能。 stackoverflow.com/questions/30643161/crop-image-in-swift

标签: iphone objective-c ios uibezierpath


【解决方案1】:

您可以为此使用shapeLayer。类似的,

UIBezierPath *aPath = [UIBezierPath bezierPath];
for (NSString *pointString in pointArray) {
    if ([pointArray indexOfObject:pointString] == 0)
        [aPath moveToPoint:CGPointFromString(pointString)];
    else
        [aPath addLineToPoint:CGPointFromString(pointString)];
}
[aPath closePath];

CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = aPath.CGPath;
[view.layer setMask:shapeLayer];//or make it as [imageview.layer setMask:shapeLayer]; 
//and add imageView as subview of whichever view you want. draw the original image
//on the imageview in that case

要将其作为图像获取,

UIGraphicsBeginImageContext(view.bounds.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

image应该有对应的图片。

【讨论】:

  • 谢谢 ACB...如何从 UIBezierpath 获取图像。
  • 谢谢...我试过了,它得到的图像和背景是白色的。我只想要 UIBezierPath 部分的图像(参见图像猫头)。你懂我吗?
  • 为什么不尝试在 UIImageView 中设置原始图像并使用上面的代码。检查这是否给出了正确的图像。而不是代码中的“视图”使用“图像视图”。
  • 我的问题是在裁剪图像之后,然后转换为黑白图像。图像剩余背景为黑色。所以我正在搜索图像的特定路径。
  • @ACB 你能把你的代码示例发给我吗,因为我们没有得到正确的图像
【解决方案2】:

对于 Swift 试试这个:ZImageCropper

ZImageCropper 使用以下内容作为核心部分:

  • UIBezierPath
  • UITouch 事件
  • CAShapeLayer
  • CoreGraphics

【讨论】:

    【解决方案3】:

    嗯,有几件事你必须注意。

    1. 您是否传递了 UIImageView 而不是 UIView?
    2. 如果是,您是否为触摸处理启用了图像视图?
    3. 继承您的 UIImageView 并使用 drawrect() 为您处理这些内容。

    如果您只想要图像的一部分(如猫),则需要根据 UIBezierPath 对图像进行子掩码。

    更新

    以下是一个完整的工作示例,请根据您的要求进行更改。

    ViewController.h:

    @interface ViewController : UIViewController
    {
      UIBezierPath *aPath;
    }
    @property (nonatomic,retain) NSMutableArray *pathArray;
    @property (nonatomic,retain) NSMutableDictionary *dic;
    @property (nonatomic,retain) IBOutlet UIImageView *imgView;
    
    @end
    

    ViewController.m:

    @interface ViewController ()
     - (IBAction)Crop:(id)sender;
    @end
    
    @implementation ViewController
    @synthesize pathArray,dic,imgView;
    - (void)viewDidLoad
     {
       [super viewDidLoad];
    
     }
     - (void) setClippingPath:(UIBezierPath *)clippingPath : (UIImageView *)imgView;
    {
    
        NSLog(@"Mask Paths %@",clippingPath);
    
        CAShapeLayer *maskLayer = [CAShapeLayer layer];
        maskLayer.frame = self.imgView.frame;
        maskLayer.path = [clippingPath CGPath];
        maskLayer.fillColor = [[UIColor whiteColor] CGColor];
        maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
    
    
        self.imgView.layer.mask = maskLayer;
    
    
    
    }
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
     {
    
       UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
       self->aPath = [[UIBezierPath alloc]init];
       [aPath moveToPoint:[mytouch locationInView:imgView]];
    
    }
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
     {
    
      UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
      [aPath addLineToPoint:[mytouch locationInView:imgView
                           ]];
    
     }
    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
     {
    
     }
    - (IBAction)Crop:(id)sender
     {
      [self setClippingPath:aPath :imgView];
     }
    

    【讨论】:

    • 嗨,现在我们如何将此图层保存为背景清晰的uiimage?如stackoverflow.com/questions/3454356/… 中所述,我尝试将 CALayer self.imgView.layer.mask 转换为 UIImage。但这不是我们想要的结果。
    • 嗨,苏菲扬。我如何开始理解 uibezierpath?我试图阅读文档,但由于我只是一个新手,我发现很难掌握。请指导我一些好的 uibezierpath 教程。谢谢。
    • 有点晚了,但你应该在某个地方渲染你的图层并获得所需的 UIImage..
    【解决方案4】:

    使用这个吊舱ios-helpers

    - (UIImage *)imageWithStrokeColor: (UIColor *)stroke_color andFillColor: (UIColor *)fill_color {
    
        // adjust bounds to account for extra space needed for lineWidth
        CGFloat width = self.bounds.size.width + self.lineWidth * 2;
        CGFloat height = self.bounds.size.height + self.lineWidth * 2;
        CGRect bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, width, height);
    
        // create a view to draw the path in
        UIView *view = [[UIView alloc] initWithFrame:bounds];
    
        // begin graphics context for drawing
        UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, [[UIScreen mainScreen] scale]);
    
        // configure the view to render in the graphics context
        [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    
        // get reference to the graphics context
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        // reverse the y-axis to match the opengl coordinate space
        CGContextScaleCTM(context, 1, -1);
        CGContextTranslateCTM(context, 0, -view.bounds.size.height);
    
        // translate matrix so that path will be centered in bounds
        CGContextTranslateCTM(context, -(bounds.origin.x - self.lineWidth), -(bounds.origin.y - self.lineWidth));
    
        // stroke color
        [stroke_color setStroke];
        [self stroke];
    
        //fill color
        [fill_color setFill];
        [self fill];
    
        // get an image of the graphics context
        UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    
        // end the context
        UIGraphicsEndImageContext();
    
        return viewImage;
    }
    

    【讨论】:

    • 您能否在答案中添加更多细节?很高兴您包含指向文档和示例代码的链接,但您能描述一下它的具体作用吗?
    【解决方案5】:

    如果您在代码中绘制所有内容,只需使用 -addClip,即:

    UIBezierPath *aPath = [UIBezierPath bezierPath];
    for (NSString *pointString in pointArray) {
        if ([pointArray indexOfObject:pointString] == 0)
            [aPath moveToPoint:CGPointFromString(pointString)];
        else
            [aPath addLineToPoint:CGPointFromString(pointString)];
    }
    [aPath closePath];
    
    
    CGContextSaveGState(context);
    {
        [aPath addClip];
        // draw image
        [aPath stroke];
    }
    CGContextRestoreGState(context);
    

    【讨论】:

    • 您好 hypercrypt...谢谢您的回复。
    • 如何从特定的 UIBezierPath 获取图像。
    • 创建图像上下文并使用UIGraphicsGetImageFromCurrentImageContext()
    • 谢谢。我想要图像的特定部分(参见图像猫头)。
    【解决方案6】:

    iDev 的回答很好,但是如果你需要透明背景,那么除了 UIGraphicsBeginImageContext(view.bounds.size); 你应该使用

    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 1.0);
    

    默认情况下,图像上下文是使用 opaque == YES 创建的,因此您必须将其更改为 NO。

    【讨论】:

      【解决方案7】:

      这对我有用...

      UIBezierPath *path = ....//your path
      CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
      CGContextRef    context    = CGBitmapContextCreate(nil, frame.size.width, frame.size.height, 8, 4*frame.size.width, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
      
      CGContextAddPath(context, path.CGPath);
      CGContextClip(context);
      CGContextDrawImage(context, frame, image.CGImage);
      
      [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
      

      【讨论】:

        【解决方案8】:
        // This Work 100%
        

        - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

        mouseSwiped = NO;
        UITouch *touch = [touches anyObject];
        lastPoint = [touch locationInView:self.view];
        megView = [[UIImageView alloc]initWithFrame:CGRectMake(lastPoint.x , lastPoint.y , k_POINT_WIDTH , k_POINT_WIDTH )];
        //[megView setImage:[UIImage imageNamed:@"b_image22.png"]];
        [megView setContentMode:UIViewContentModeScaleToFill];
        megView.alpha = 2;
        //megView.layer.backgroundColor = [UIColor whiteColor].CGColor;
        //megView.layer.cornerRadius = megView.frame.size.width / 2;
        megView.clipsToBounds = YES;
        [self.main_uiview addSubview:megView];
        
        
        self.bezierPath = [UIBezierPath bezierPath];
        [self.bezierPath moveToPoint:lastPoint];
        

        }

          // Touchmove method
        
        
         - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
        
        mouseSwiped = YES;
        UITouch *touch = [touches anyObject];
        CGPoint currentPoint = [touch locationInView:self.view];
        UIGraphicsBeginImageContext(self.main_uiview.frame.size);
        [self.bg_imageview.image drawInRect:CGRectMake(0, 0, self.main_uiview.frame.size.width, self.main_uiview.frame.size.height)];
        megView.frame = CGRectMake( currentPoint.x - k_POINT_WIDTH/2 , currentPoint.y - k_POINT_WIDTH/2 , k_POINT_WIDTH , k_POINT_WIDTH );
        CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
        CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
        CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
        CGContextStrokePath(UIGraphicsGetCurrentContext());
        
        
        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red,green ,blue, 0.20);
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
          self.bg_imageview.image = UIGraphicsGetImageFromCurrentImageContext();
          [self.bg_imageview setAlpha:opacity];
        
         UIGraphicsEndImageContext();
        
         lastPoint = currentPoint;
        
        [self.bezierPath addLineToPoint:lastPoint];
        

        }

         // TouchEnd Method
        
        
           - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
        

        {

        [megView removeFromSuperview];
        

        }

              // Image Crop Method
        
        
            -(UIImage *)croppedImage
           {
        UIImage *myImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        [self.bezierPath closePath];
        CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 0.0);
        _b_image = self.bg_imageview.image;
        CGSize imageSize = _b_image.size;
        CGRect imageRect = CGRectMake(0, 0, imageSize.width, imageSize.height);
        UIGraphicsBeginImageContextWithOptions(imageSize, NO, [[UIScreen mainScreen] scale]);
        [self.bezierPath addClip];
        [_b_image drawInRect:imageRect];
        
        UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return croppedImage;
        

        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-02-05
          • 2012-09-22
          • 2017-08-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-18
          • 2019-07-09
          相关资源
          最近更新 更多