Qual é o melhor filtro Core Image para produzir efeitos em preto e branco?

Eu estou usando o Core Image e gostaria de produzir um efeito preto e branco na imagem escolhida.

Idealmente, gostaria de ter access ao mesmo tipo de opções disponíveis no Photoshop, como Reds, Cyan, Greens, Blues e Magenta. O objective é criar diferentes tipos de efeito preto e branco.

Alguém sabe qual filtro seria o melhor para manipular esse tipo de opção? Se não alguém sabe de uma boa abordagem para criar o efeito preto e branco usando outros filtros?

obrigado

Oliver

- (UIImage *)imageBlackAndWhite { CIImage *beginImage = [CIImage imageWithCGImage:self.CGImage]; CIImage *blackAndWhite = [CIFilter filterWithName:@"CIColorControls" keysAndValues:kCIInputImageKey, beginImage, @"inputBrightness", [NSNumber numberWithFloat:0.0], @"inputContrast", [NSNumber numberWithFloat:1.1], @"inputSaturation", [NSNumber numberWithFloat:0.0], nil].outputImage; CIImage *output = [CIFilter filterWithName:@"CIExposureAdjust" keysAndValues:kCIInputImageKey, blackAndWhite, @"inputEV", [NSNumber numberWithFloat:0.7], nil].outputImage; CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef cgiimage = [context createCGImage:output fromRect:output.extent]; //UIImage *newImage = [UIImage imageWithCGImage:cgiimage]; UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:image.scale orientation:image.imageOrientation]; CGImageRelease(cgiimage); return newImage; } 

Upd .: Para o iOS6 existe o filtro CIColorMonochrome , mas eu toquei e achei não tão bom quanto o meu.

aqui está um exemplo com o CIColorMonochrome

 - (UIImage *)imageBlackAndWhite { CIImage *beginImage = [CIImage imageWithCGImage:self.CGImage]; CIImage *output = [CIFilter filterWithName:@"CIColorMonochrome" keysAndValues:kCIInputImageKey, beginImage, @"inputIntensity", [NSNumber numberWithFloat:1.0], @"inputColor", [[CIColor alloc] initWithColor:[UIColor whiteColor]], nil].outputImage; CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef cgiimage = [context createCGImage:output fromRect:output.extent]; UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:self.scale orientation:self.imageOrientation]; CGImageRelease(cgiimage); return newImage; } 

Para criar um efeito monocromático puro, usei o CIColorMatrix com os parâmetros vetoriais R, G e B definidos como (0.2125, 0.7154, 0.0721, 0), e os vetores alpha e bias restantes com seus padrões.

Os valores são RGB para os coeficientes de conversão em escala de cinza. Examinei as internets em algum momento. Alterando esses coeficientes, você pode alterar a contribuição dos canais de input. Ao dimensionar cada cópia do vetor e, opcionalmente, definir um vetor de polarização, você pode colorir a saída.

Aqui está a melhor solução convertida para Swift (iOS 7 e acima):

 func blackAndWhiteImage(image: UIImage) -> UIImage { let context = CIContext(options: nil) let ciImage = CoreImage.CIImage(image: image)! // Set image color to b/w let bwFilter = CIFilter(name: "CIColorControls")! bwFilter.setValuesForKeysWithDictionary([kCIInputImageKey:ciImage, kCIInputBrightnessKey:NSNumber(float: 0.0), kCIInputContrastKey:NSNumber(float: 1.1), kCIInputSaturationKey:NSNumber(float: 0.0)]) let bwFilterOutput = (bwFilter.outputImage)! // Adjust exposure let exposureFilter = CIFilter(name: "CIExposureAdjust")! exposureFilter.setValuesForKeysWithDictionary([kCIInputImageKey:bwFilterOutput, kCIInputEVKey:NSNumber(float: 0.7)]) let exposureFilterOutput = (exposureFilter.outputImage)! // Create UIImage from context let bwCGIImage = context.createCGImage(exposureFilterOutput, fromRect: ciImage.extent) let resultImage = UIImage(CGImage: bwCGIImage, scale: 1.0, orientation: image.imageOrientation) return resultImage } 

Com relação às respostas sugerindo o uso do CIColorMonochrome : agora há alguns filtros dedicados em escala de cinza disponíveis no iOS7 (e no OS X 10.9):

  • CIPhotoEffectTonal

    imitar o filme de fotografia em preto e branco sem alterar significativamente o contraste.

  • CIPhotoEffectNoir:

    imitar filme de fotografia em preto-e-branco com contraste exagerado

Fonte: https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html

Aqui está a resposta mais popular do @Shmidt escrita como uma extensão UIImage com uma atualização de desempenho no Swift:

 import CoreImage extension UIImage { func imageBlackAndWhite() -> UIImage? { if let beginImage = CoreImage.CIImage(image: self) { let paramsColor: [String : AnyObject] = [kCIInputBrightnessKey: NSNumber(double: 0.0), kCIInputContrastKey: NSNumber(double: 1.1), kCIInputSaturationKey: NSNumber(double: 0.0)] let blackAndWhite = beginImage.imageByApplyingFilter("CIColorControls", withInputParameters: paramsColor) let paramsExposure: [String : AnyObject] = [kCIInputEVKey: NSNumber(double: 0.7)] let output = blackAndWhite.imageByApplyingFilter("CIExposureAdjust", withInputParameters: paramsExposure) let processedCGImage = CIContext().createCGImage(output, fromRect: output.extent) return UIImage(CGImage: processedCGImage, scale: self.scale, orientation: self.imageOrientation) } return nil } } 

macOS (NSImage) Swift 3 versão da conversão @ FBente da resposta de @ Shmidt:

 extension NSImage { func imageBlackAndWhite() -> NSImage? { if let cgImage = self.cgImage(forProposedRect: nil, context: nil, hints: nil) { let beginImage = CIImage.init(cgImage: cgImage) let paramsColor: [String : AnyObject] = [kCIInputBrightnessKey: NSNumber(value: 0.0), kCIInputContrastKey: NSNumber(value: 1.1), kCIInputSaturationKey: NSNumber(value: 0.0)] let blackAndWhite = beginImage.applyingFilter("CIColorControls", withInputParameters: paramsColor) let paramsExposure: [String : AnyObject] = [kCIInputEVKey: NSNumber(value: 0.7)] let output = blackAndWhite.applyingFilter("CIExposureAdjust", withInputParameters: paramsExposure) if let processedCGImage = CIContext().createCGImage(output, from: output.extent) { return NSImage(cgImage: processedCGImage, size: self.size) } } return nil } } 

Eu tentei solução Shmidt, mas parece-me muito mais exposto no iPad Pro. Estou usando apenas a primeira parte de sua solução, sem o filtro de exposição:

 - (UIImage *)imageBlackAndWhite { CIImage *beginImage = [CIImage imageWithCGImage:self.CGImage]; CIImage *blackAndWhite = [CIFilter filterWithName:@"CIColorControls" keysAndValues:kCIInputImageKey, beginImage, @"inputBrightness", [NSNumber numberWithFloat:0.0], @"inputContrast", [NSNumber numberWithFloat:1.1], @"inputSaturation", [NSNumber numberWithFloat:0.0], nil].outputImage; CIImage *output = [blackAndWhite valueForKey:@"outputImate"]; CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef cgiimage = [context createCGImage:output fromRect:output.extent]; //UIImage *newImage = [UIImage imageWithCGImage:cgiimage]; UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:image.scale orientation:image.imageOrientation]; CGImageRelease(cgiimage); return newImage; }