1
votes

I have a function where I fill the image with a color and use a UIBezierPath to erase a point for corners.

CGRect rect = CGRectMake(0.0f, 0.0f, width, height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();

CGContextSetBlendMode(context, kCGBlendModeCopy);

// Fill image
CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
CGContextFillRect(context, rect);

// Round corners
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:15.0];
CGContextSetStrokeColorWithColor(context, [[UIColor clearColor] CGColor]);
[bezierPath stroke];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

With the above, I get an image that does have the Bézier path cut out, and the background filled. Icon with Bézier path cut out

However, how can I remove the corners outside of the path, or get at least some way to reference where they are so I can clear them?

1
Rather than stroking the path, you should mask the image to that path. - Rob
BTW, do really need to create image with rounded corners, because if you just want the rounded corners in the UI, you could just set the cornerRadius of the view's layer. - Rob
@Rob I sadly can't change the view itself with the way I'm doing this, so I have to use the image. Thank you though, I'll check out masking. - Spotlight
@Rob I tried getting the UIImage from the current context, creating a new context, and applying the bezier's path there, but that didn't do anything (in fact, it made the entire image clear). Am I missing something? - Spotlight

1 Answers

2
votes

A couple of options:

  1. Use CoreGraphics, like you have, but clip it to a path:

    CGRect rect = CGRectMake(0.0f, 0.0f, width, height);
    
    UIGraphicsBeginImageContextWithOptions(rect.size, false, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(context, kCGBlendModeCopy);
    
    // Round corners
    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:15.0];
    CGContextAddPath(context, bezierPath.CGPath);
    CGContextClip(context);
    
    // Fill image
    CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
    CGContextFillRect(context, rect);
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
  2. Alternatively, eliminate CoreGraphics and just fill the UIBezierPath:

    UIGraphicsBeginImageContextWithOptions(rect.size, false, 0);
    [[UIColor redColor] setFill];
    [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:15.0] fill];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

Note, in both of those examples, I used UIGraphicsBeginImageContextWithOptions, supplying a scale of 0 (a scale optimized for display on the device in question). If you really want, you can supply a scale of 1, which obviously will be a bit pixelated when rendered on a retina device, but that's up to you.