How to crop the image using UIBezierPath?

后端 未结 8 1616
我在风中等你
我在风中等你 2020-11-30 23:16

I want to get the image from the UIBezierpath closed path(See the image). I draw the image on the UIView using drawRect method and als

相关标签:
8条回答
  • 2020-11-30 23:34

    You can use a shapeLayer for that. Something like,

    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
    

    To get it as an image,

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

    image should have the corresponding image.

    0 讨论(0)
  • 2020-11-30 23:37

    If you're drawing everything in code just use -addClip, i.e.:

    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);
    
    0 讨论(0)
  • 2020-11-30 23:38

    this works for me...

    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)];
    
    0 讨论(0)
  • 2020-11-30 23:41

    iDev's answer is excellent, but if you need transparent background, then except UIGraphicsBeginImageContext(view.bounds.size); you should use

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

    By default image context is created with opaque == YES, so you have to change it to NO.

    0 讨论(0)
  • 2020-11-30 23:41
    // 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;
    

    }

    0 讨论(0)
  • 2020-11-30 23:47

    Well, there are a couple of things that you have to take in notice.

    1. Are you passing your UIImageView instead of your UIView?
    2. If you are, did you enable your image view for touch handling?
    3. Subclass your UIImageView and use drawrect() for handling that stuff for you.

    If you want only a portion of the image (like the cat), then you need to submask your image according to UIBezierPath.

    Updated

    The following is a complete working example, change it to your requirements.

    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];
     }
    
    0 讨论(0)
提交回复
热议问题