I'm having a problem when it comes to clipping a photo to a custom UIBezierPath. Instead of displaying the area within the path, as it should, it displays another part of the photo instead (of different size and position than where it should be, but still the same shape as was drawn). Note I'd also like to keep the full quality of the original photo.

I've included photos and captions below to explain my problem in more depth. If anyone could give me another way to do such a thing I'll gladly start over.

The user draws a UIBezierPath with his finger Above is an illustration of the UIImage within a UIImageView, all within a UIView of which the CAShapeLayer that displays the UIBezierPath is a sublayer. For this example assume that the path in red was drawn by the user.

Visualization In this diagram is the CAShapeLayer and a graphics context created with the original image's size. How would I clip the context so that the result below is produced (please excuse the messiness of it)?

The result This is the result I'd like to be produced when all is said and done. Note I'd like it to still be the same size/quality as the original.

Here are some relevant portions of my code:

This clips an image to a path

-(UIImage *)maskImageToPath:(UIBezierPath *)path {
    // Precondition: the path exists and is closed
    assert(path != nil);


    // Mask the image, keeping original size
    UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);

    [path addClip];
    [self drawAtPoint:CGPointZero];

    // Extract the image
    UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return maskedImage;
}

This adds points to the UIBezierPath

 - (void)drawClippingLine:(UIPanGestureRecognizer *)sender {
    CGPoint nextPoint = [sender locationInView:self];

    // If UIBezierPath *clippingPath is nil, initialize it.
    // Otherwise, add another point to it.
    if(!clippingPath) {
        clippingPath = [UIBezierPath bezierPath];
        [clippingPath moveToPoint:nextPoint];
    }
    else {
        [clippingPath addLineToPoint:nextPoint];
    }

    UIGraphicsBeginImageContext(_image.size);
    [clippingPath stroke];
    UIGraphicsEndImageContext();


}
有帮助吗?

解决方案

You are getting an incorrect crop because the UIImage is scaled to fit inside the UIImageView. Basically this means you have to translate the UIBezierPath coordinates to the correct coordinates within the UIImage. The easiest way to do this is to use a UIImageView category which will convert the points from one view (in this case the UIBezierPath, even though it's not really a view) to the correct points within the UIImageView. You can see an example of such a category here. More specifically you will need to use the convertPointFromView: method within that category to convert each point in your UIBezierPath. (Sorry for not writing the complete code, I'm typing on my phone)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top