UIImage 和 CALayer 的遮罩

1. UIImage 遮罩

 

- (void)yourMaskFunction()

{

UIImage *originalImage = [UIImage xxx];

UIImage *maskImage = [UIImage xxx];

UIImage *maskedImage = [self maskImage: originalImage withMask: maskImage];

}


- (CGImageRef)CopyImageAndAddAlphaChannel:(CGImageRef)sourceImage

{

CGImageRef retVal = NULL;

 

size_t width = CGImageGetWidth(sourceImage);

size_t height = CGImageGetHeight(sourceImage);

 

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

 

CGContextRef offscreenContext = CGBitmapContextCreate(NULL, width, height,

  80, colorSpace, kCGImageAlphaPremultipliedFirst);

 

if (offscreenContext != NULL)

{

CGContextDrawImage(offscreenContext, CGRectMake(00, width, height), sourceImage);

retVal = CGBitmapContextCreateImage(offscreenContext);

CGContextRelease(offscreenContext);

}

 

CGColorSpaceRelease(colorSpace);

 

return retVal;

}


- (UIImage*)maskImage:(UIImage *)image withMask:(UIImage *)maskImage

{

CGImageRef maskRef = maskImage.CGImage;

CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),

CGImageGetHeight(maskRef),

CGImageGetBitsPerComponent(maskRef),

CGImageGetBitsPerPixel(maskRef),

CGImageGetBytesPerRow(maskRef),

CGImageGetDataProvider(maskRef), NULLfalse);

 

CGImageRef sourceImage = [image CGImage];

CGImageRef imageWithAlpha = sourceImage;

//add alpha channel for images that don't have one (ie GIF, JPEG, etc...)

//this however has a computational cost

if (CGImageGetAlphaInfo(sourceImage) == kCGImageAlphaNone)

{

imageWithAlpha = [self CopyImageAndAddAlphaChannel:sourceImage];

}

 

CGImageRef masked = CGImageCreateWithMask(imageWithAlpha, mask);

CGImageRelease(mask);

 

//release imageWithAlpha if it was created by CopyImageAndAddAlphaChannel

if (sourceImage != imageWithAlpha)

{

CGImageRelease(imageWithAlpha);

}

 

UIImage* retImage = [UIImage imageWithCGImage:masked];

CGImageRelease(masked);

 

return retImage;

}


 

+ (CGImageRef)maskableImageRefConvertFrom:(CGImageRef)sourceImage

{

    CGImageRef retVal = NULL;

    

    size_t width = CGImageGetWidth(sourceImage);

    size_t height = CGImageGetHeight(sourceImage);

    

    //CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();

    

    CGContextRef offscreenContext = CGBitmapContextCreate(NULL,

  width,

  height,

                                                          8,

  0,

  colorSpace,

  kCGBitmapByteOrderDefaul| kCGImageAlphaNone);

    

    if (offscreenContext != NULL)

    {

 

CGContextSetFillColorWithColor(offscreenContext, [UIColor whiteColor].CGColor);

CGContextFillRect(offscreenContext, CGRectMake(00, width, height));

 

        CGContextDrawImage(offscreenContext, CGRectMake(00, width, height), sourceImage);

        retVal = CGBitmapContextCreateImage(offscreenContext);

        CGContextRelease(offscreenContext);

    }

    

    CGColorSpaceRelease(colorSpace);

    

    return retVal;

}

注意事项:被遮罩的图片理论上是需要有透明通道的图片,这样遮罩之后才会达到一部分透明一部分不透明的效果,上述方法已经做了此项工作,所以不用担心。

最重要的部分,作为遮罩的图片,在这种使用方法下必须没有透明通道,无论是png,jpg或者其他格式,有了透明通道,将达不到想要的效果,可能会出现完全透明的情况。如果有透明通道,则可以通过maskableImageRefConvertFrom方法稍加修正,对于一般情况都没有问题外纯白色表示被遮罩区域将完全透明,纯黑色表示被遮罩区域将会原封不动保留下来,灰色部分(0x000000~0xFFFFFF)表示被遮罩区域将会处理成半透明的效果。


 

2. CALayer 遮罩 (MaskLayer 的内容从UIImage生成)

- (void)yourMaskFunction()


{

 

UIView *originalView = [UIView xxx];

 

UIImage *imageForMask = [UIImage xxx];

 

CALayer *maskLayer = [CALayer layer];

 

maskLayer.frame = originalView.frame;

 

maskLayer.contents = (id)[imageForMask CGImage];

 

[[originalView layersetMask:maskLayer];

 

}

这里讲的只是CALayer遮罩的一类情况,就是从UIImage生成CALayer 来进行对UIView的遮罩,也可以直接由程序生成某种颜色某种透明度的遮罩。

注意事项,一般imageForMask,maskLayer的尺寸要和originalView的尺寸保持一致,不然将出现拉伸。如果maskLayer的frame的尺寸为0,那么遮罩出来的效果将会完全透明,这个容易忽视。

这种方法生成的maskLayer对imageForMask有一个要求,就是imageForMask必须要有透明通道,否则被遮罩出来的效果将会完全透明,达不到想要的效果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值