无需逐像素处理,如何结合NSBitmapImageRep主图与蒙版生成带Alpha图?
无需逐像素遍历的蒙版合并方案
可以通过CoreGraphics或CoreImage实现批量合并,完全不需要手动遍历像素。以下是两种可行的实现方式:
方法一:CoreGraphics上下文混合模式
利用kCGBlendModeDestinationIn混合模式,将蒙版的亮度信息映射为主图像的Alpha通道(黑色对应不透明,白色对应透明):
代码实现(Objective-C)
// 你的主图像与蒙版 NSBitmapImageRep *mainImageRep = ...; NSBitmapImageRep *maskImageRep = ...; CGImageRef mainCGImage = mainImageRep.CGImage; CGImageRef maskCGImage = maskImageRep.CGImage; CGSize mainSize = CGSizeMake(CGImageGetWidth(mainCGImage), CGImageGetHeight(mainCGImage)); // 创建带预乘Alpha的RGBA上下文 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(NULL, mainSize.width, mainSize.height, 8, mainSize.width * 4, colorSpace, kCGImageAlphaPremultipliedFirst); CGColorSpaceRelease(colorSpace); if (!context) return nil; // 绘制主图像 CGContextDrawImage(context, CGRectMake(0, 0, mainSize.width, mainSize.height), mainCGImage); // 反转蒙版颜色(将黑/白对应关系转为符合DestinationIn的需求) CGContextSaveGState(context); CGContextSetBlendMode(context, kCGBlendModeDifference); CGContextSetFillColorWithColor(context, [NSColor whiteColor].CGColor); CGContextFillRect(context, CGRectMake(0, 0, mainSize.width, mainSize.height)); CGContextDrawImage(context, CGRectMake(0, 0, mainSize.width, mainSize.height), maskCGImage); CGImageRef invertedMask = CGBitmapContextCreateImage(context); CGContextRestoreGState(context); // 用反转后的蒙版设置主图像的Alpha通道 CGContextSaveGState(context); CGContextSetBlendMode(context, kCGBlendModeDestinationIn); CGContextDrawImage(context, CGRectMake(0, 0, mainSize.width, mainSize.height), invertedMask); CGContextRestoreGState(context); // 生成最终的NSBitmapImageRep CGImageRef resultCGImage = CGBitmapContextCreateImage(context); NSBitmapImageRep *resultRep = [[NSBitmapImageRep alloc] initWithCGImage:resultCGImage]; // 清理资源 CGImageRelease(invertedMask); CGImageRelease(resultCGImage); CGContextRelease(context);
方法二:CoreImage滤镜合成
用CoreImage的现成滤镜快速完成反转蒙版、生成Alpha通道、合成图像的流程,代码更简洁:
代码实现(Objective-C)
// 你的主图像与蒙版 NSBitmapImageRep *mainImageRep = ...; NSBitmapImageRep *maskImageRep = ...; // 转为CIImage CIImage *mainCI = [[CIImage alloc] initWithBitmapImageRep:mainImageRep]; CIImage *maskCI = [[CIImage alloc] initWithBitmapImageRep:maskImageRep]; // 1. 反转蒙版(默认CIMaskToAlpha是白不透明黑透明,和需求相反) CIFilter *invertFilter = [CIFilter filterWithName:@"CIColorInvert"]; [invertFilter setValue:maskCI forKey:kCIInputImageKey]; CIImage *invertedMask = invertFilter.outputImage; // 2. 将反转后的蒙版转为Alpha通道 CIFilter *maskToAlphaFilter = [CIFilter filterWithName:@"CIMaskToAlpha"]; [maskToAlphaFilter setValue:invertedMask forKey:kCIInputImageKey]; CIImage *maskWithAlpha = maskToAlphaFilter.outputImage; // 3. 合成主图与带Alpha的蒙版 CIFilter *compositeFilter = [CIFilter filterWithName:@"CISourceOverCompositing"]; [compositeFilter setValue:mainCI forKey:kCIInputBackgroundImageKey]; [compositeFilter setValue:maskWithAlpha forKey:kCIInputImageKey]; CIImage *resultCI = compositeFilter.outputImage; // 转回NSBitmapImageRep NSBitmapImageRep *resultRep = [[NSBitmapImageRep alloc] initWithCIImage:resultCI];
注意事项
- 确保主图与蒙版尺寸一致,若不一致,可先用CoreGraphics的
CGContextDrawImage或CoreImage的CILanczosScaleTransform滤镜将蒙版缩放到主图尺寸。 - 两种方法均支持非灰度蒙版,因为会自动提取蒙版的亮度信息作为Alpha的依据。
内容的提问来源于stack exchange,提问作者Gannet
相关产品推荐
相关产品推荐

