Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode: compositing with alpha using core image

I'd like to create a CoreImage filter chain, and to be able to control the "intensity" of each filter in the chain by compositing its individual effect with alpha, or opacity settings, but I am not seeing a way to composite with alpha or opacity in the docs.

I could jump out of Core image filter chain and composite with a core graphics context I guess.

like image 942
Mr Ordinary Avatar asked Jan 23 '13 04:01

Mr Ordinary


2 Answers

The CIColorMatrix filter can be used to alter the alpha component of a CIImage, which you can then composite onto a background image:

CIImage *overlayImage = … // from file, CGImage etc
CIImage *backgroundImage = … // likewise

CGFloat alpha = 0.5;
CGFloat rgba[4] = {0.0, 0.0, 0.0, alpha};
CIFilter *colorMatrix = [CIFilter filterWithName:@"CIColorMatrix"];
[colorMatrix setDefaults];
[colorMatrix setValue:overlayImage forKey: kCIInputImageKey];
[colorMatrix setValue:[CIVector vectorWithValues:rgba count:4] forKey:@"inputAVector"];

CIFilter *composite = [CIFilter filterWithName:@"CISourceOverCompositing"];
[composite setDefaults];
[composite setValue:colorMatrix.outputImage forKey: kCIInputImageKey];
[composite setValue:backgroundImage forKey: kCIInputBackgroundImageKey];

UIImage *blendedImage = [UIImage imageWithCIImage:composite.outputImage];
like image 187
mrwalker Avatar answered Nov 11 '22 17:11

mrwalker


mrwalker provided a great answer that I converted to Swift.

Swift 5

let sourceImage: CIImage = ...

// This is where I get the overlayImage, and intensity is alpha, used later
guard let ciFilter = LUTBuilder.getCIFilter(from: filter.filter), let intensity = filter.intensity else { return CIImage() }
ciFilter.setValue(sourceImage.clampedToExtent(), forKey: kCIInputImageKey)

let overlayImage = ciFilter.outputImage!.cropped(to: sourceImage.extent)

let alpha = CGFloat(intensity)
let rgba = [0.0, 0.0, 0.0, alpha]

guard
    let colorMatrix = CIFilter(name: "CIColorMatrix"),
    let composite = CIFilter(name: "CISourceOverCompositing")
else { return CIImage() }

colorMatrix.setDefaults()
colorMatrix.setValue(overlayImage, forKey: kCIInputImageKey)
colorMatrix.setValue(CIVector(values: rgba, count: 4), forKey: "inputAVector")

composite.setDefaults()
composite.setValue(colorMatrix.outputImage, forKey: kCIInputImageKey)
composite.setValue(sourceImage, forKey: kCIInputBackgroundImageKey)

return composite.outputImage ?? CIImage()
like image 2
Danil Kurilo Avatar answered Nov 11 '22 16:11

Danil Kurilo