MB.
MB.

Reputation: 4211

iOS UIImage clip to paths

I'm working with an image where the user has selected part of it using UIBezierPath. How can I delete/clear out/make transparent everything that is not part of that selection?

Upvotes: 11

Views: 10015

Answers (2)

FreeTymeKiyan
FreeTymeKiyan

Reputation: 307

I tried the code of union multiple paths, and it doesn't work.

Actually, if the union of paths don't overlap with each other, we append one path to another and crop with the final path.

UIGraphicsBeginImageContextWithOptions(originalImg.size, NO, 0);
[path1 appendPath:path2]; // append path2 to path1
[path1 addClip];

[originalImg drawAtPoint:CGPointZero];
result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Upvotes: 0

rob mayoff
rob mayoff

Reputation: 385750

With one path it's very easy. Just set the path as the clipping path:

- (UIImage *)maskImage:(UIImage *)originalImage toPath:(UIBezierPath *)path {
    UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, 0);
    [path addClip];
    [originalImage drawAtPoint:CGPointZero];
    UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return maskedImage;
}

If you want to use the union of multiple paths, it's harder, because Quartz doesn't have any functions that directly compute the union of two paths. One way is to fill each path one by one into a mask, and then draw the image through the mask:

- (UIImage *)maskedImage
{
    CGRect rect = CGRectZero;
    rect.size = self.originalImage.size;
    UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0); {
        [[UIColor blackColor] setFill];
        UIRectFill(rect);
        [[UIColor whiteColor] setFill];
        for (UIBezierPath *path in self.paths)
            [path fill];
    }
    UIImage *mask = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0); {
        CGContextClipToMask(UIGraphicsGetCurrentContext(), rect, mask.CGImage);
        [self.originalImage drawAtPoint:CGPointZero];
    }
    UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return maskedImage;
}

Upvotes: 20

Related Questions