加载中…
正文 字体大小:

UIImage 和 CALayer 的遮罩

(2012-11-30 15:47:51)
分类: iPhone开发
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,

  8, 0, colorSpace, kCGImageAlphaPremultipliedFirst);

 

if (offscreenContext != NULL)

{

CGContextDrawImage(offscreenContext, CGRectMake(0, 0, 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), NULL, false);

 

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,

  kCGBitmapByteOrderDefault | kCGImageAlphaNone);

    

    if (offscreenContext != NULL)

    {

 

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

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

 

        CGContextDrawImage(offscreenContext, CGRectMake(0, 0, 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 layer] setMask:maskLayer];

 

}

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

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

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

0

阅读 评论 收藏 转载 喜欢 打印举报
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有