4

Hi iam trying to make a custom crop tool which enables user to create a custom closed region using bezier path.

enter image description here

The code i am using to clip imageView with path is

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = clippingPath.CGPath;
[imgView.layer setMask:maskLayer];

but the result is

enter image description here

Can any one point me in right direction, what i need to do?

-(void)longPressAddPoint:(UITapGestureRecognizer*)gesture
{   ctr++;
    CGPoint  touchpoint=[gesture locationInView:self];
    [ptsNew addObject:[NSValue valueWithCGPoint:[gesture locationInView:self] ]];
    if(ctr>1)
    {
      if(CGRectContainsPoint([self viewWithTag:1].frame, [gesture locationInView:self]))
      {
          pathClosed=YES;
          touchpoint=[self viewWithTag:1].center;

      }

    UIView *greenCircle=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 20, 20)];
    greenCircle.center=touchpoint;
    greenCircle.backgroundColor=[UIColor greenColor];
        [greenCircle setTag:ctr];
    [greenCircle.layer setCornerRadius:10];
    [self addSubview:greenCircle];
        [pathMain appendPath:[pathCurrent bezierPathByReversingPath]];
        pathMain.usesEvenOddFillRule=YES;
        [pathCurrent moveToPoint:[[ptsNew objectAtIndex:ptsNew.count-2] CGPointValue]];
        [pathCurrent addCurveToPoint:[[ptsNew objectAtIndex:ptsNew.count-1] CGPointValue] controlPoint1:firstControllPoint.center controlPoint2:[[ptsNew objectAtIndex:ptsNew.count-1] CGPointValue]]; // this is how a Bezier curve is appended to a path
        [self setNeedsDisplay];


    }
    else {

        UIView *greenCircle=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 20, 20)];
        greenCircle.center=touchpoint;
        greenCircle.backgroundColor=[UIColor greenColor];
        [greenCircle setTag:ctr];
        [greenCircle.layer setCornerRadius:10];
        [self addSubview:greenCircle];
    }
}
- (void)drawRect:(CGRect)rect
{   
    [pathCurrent stroke];
    [pathMain stroke];

}


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

    UITouch *touch = [touches anyObject];
    if(CGRectContainsPoint(firstControllPoint.frame,[touch locationInView:self] )&&(ptsNew.count>=2))
    {
       flagForTouch=YES;
    }
    else {
        flagForTouch=NO;
    }

}

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

    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
       if (flagForTouch) // 4th point
    {
        [pathCurrent removeAllPoints];
        [self setNeedsDisplay];
        [pathCurrent moveToPoint:[[ptsNew objectAtIndex:ptsNew.count-2] CGPointValue]];
        [pathCurrent addCurveToPoint:[[ptsNew objectAtIndex:ptsNew.count-1] CGPointValue] controlPoint1:firstControllPoint.center controlPoint2:[[ptsNew objectAtIndex:ptsNew.count-1] CGPointValue]]; // this is how a Bezier curve is appended to a path
        [self setNeedsDisplay];

    }
    if(flagForTouch)
    firstControllPoint.center=[[touches anyObject] locationInView:self];
}

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

}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesEnded:touches withEvent:event];
}

#pragma mark:- clipping image based on path
- (void) setClippingPath:(UIBezierPath *)clippingPath imageViewObj: (UIImageView *)imgView;
{
//    if (![[imgView layer] mask])
//        [[imgView layer] setMask:[CAShapeLayer layer]];
//    
//    [(CAShapeLayer*) [[imgView layer] mask] setPath:[clippingPath CGPath]];


    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = self.bounds;
    clippingPath.usesEvenOddFillRule=YES;
    maskLayer.path = clippingPath.CGPath;
    [imgView.layer setMask:maskLayer];
    UIGraphicsBeginImageContext(self.frame.size);
}

-(void)getCroppedImage:(sendImageBlock)Image
{
    sendImageToBase=Image;
}
-(void)cropIt
{
    if (pathClosed) {
        NSLog(@"path closed crop now");
        [pathMain appendPath:[pathCurrent bezierPathByReversingPath]];
        pathMain.usesEvenOddFillRule=YES;
        [self setClippingPath:[pathMain bezierPathByReversingPath] imageViewObj:self.imageToBeCropped];
        sendImageToBase(self.imageToBeCropped);
    }

}

I have a Path main (which is passed as clipping path) i create current path which user can add curve to.When user adds a new path current path is appended to main path.

amar
  • 4,285
  • 8
  • 40
  • 52
  • http://stackoverflow.com/questions/13153223/how-to-crop-the-image-using-uibezierpath – Rushabh Apr 03 '13 at 12:41
  • Thanku but iam already doing the same thing my problem ios iam not getting the correct region – amar Apr 03 '13 at 13:17
  • Could you post the code that creates `clippingPath` – Elliott Apr 03 '13 at 14:02
  • Solved it the issue was i was appending curves. I saved both points and control points and used them to make path now its working fine – amar Apr 04 '13 at 11:07

1 Answers1

1

Here is a good library to match your requirement, it is given below:

For Swift try this : ZImageCropper

ZImageCropper is using following things as core part:

UIBezierPath, UITouch Events, CAShapeLayer, CoreGraphics

Kindly check and revert me back.

SmarterSusheel
  • 169
  • 2
  • 15
  • It was long time back... and any ways i was making pen tool free draw is not perfect . – amar May 28 '18 at 03:51