How to draw a shape on top of a UIImage while respecting the image's alpha mask

若如初见. 提交于 2019-12-02 17:20:39

To draw a shape while respecting an image's alpha mask, just add one line before you draw:

 CGContextClipToMask(context, self.bounds, image.CGImage);

 // example usage
  - (void)drawRect:(CGRect)rect {

    if (isGrey) {
            CGContextRef context = UIGraphicsGetCurrentContext();

            // flip orientation
            CGContextTranslateCTM(context, 0.0, self.bounds.size.height);
            CGContextScaleCTM(context, 1.0, -1.0);

            // draw the image
            CGContextDrawImage(context, self.bounds, self.image.CGImage);

            // set the blend mode and draw rectangle on top of image
            CGContextSetBlendMode(context, kCGBlendModeColor);
            CGContextClipToMask(context, self.bounds, image.CGImage); // respect alpha mask
            CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0);
            CGContextFillRect(context, rect);               
    } else {
            [self.image drawInRect:rect];
    }

}

Although it doesn't directly answer your question, you may be able to get the effect you are looking for by using the kCGBlendModeLuminosity blend mode:

- (void)drawRect:(CGRect)rect {
    CGSize imageSize = [image size];
    CGContextRef c = UIGraphicsGetCurrentContext();
    if (isGrey)
        CGContextSetBlendMode(c, kCGBlendModeLuminosity);
    CGContextScaleCTM(c, 1.0, -1.0);
    CGContextDrawImage(c, CGRectMake(0.0f, 0.0f, imageSize.width, -imageSize.height), [image CGImage]);
}

Also, the rect passed to drawRect: is the invalid area, not the entire area. You should be using the bounds instead

I'd take the easy way out and draw a black circle with the same size as the round image you have. Probably not what you are asking for.

You could try to add a mask to the view's Core Animation layer.

CALayer *maskLayer = [CALayer layer];
[maskLayer setBounds:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)];

// Center the layer
[maskLayer setPosition:CGPointMake([self view].bounds.size.width/2, 
                          [self view].bounds.size.height/2)];

// Set the cornerRadius to half the width/height to get a circle.
[maskLayer setCornerRadius:50.f];
[maskLayer setMasksToBounds:YES];

// Any solid color will do. Just using black here.
[maskLayer setBackgroundColor:[[UIColor blackColor] CGColor]];

// Set the mask which will only allow that which is in the
// circle show through
[[[self view] layer] setMask:maskLayer];

One other thought. Why can't you just create a b&w version of the image and swap that out depending on your flag?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!