本文大部份内容均来自:Core Image Tutorial: Getting Startedswift
Core Image 是一个很强大的库,PS图片时用到的各类滤镜就是在这个库中。而咱们建立二维码、建立条形码用这里的滤镜,只须要短短几行代码就能够撸出来(后面会讲怎么用CIFilter绘制二维码、条形码)。bash
文中有提到在iOS 8 上,CIFilter 的API 里有126种滤镜可用,在 同时期 Mac OS 上有160多种滤镜可用;而在iOS 9.3 上,我测试可使用的滤镜已经达到174种,Mac OS上确定更多咯。dom
我一度想查找API里一共提供了多少种滤镜,每种滤镜分别有什么效果。多是种类实在是太多,不一样的滤镜又有不少不一样的参数(参数名,参数各类均可能不一样)设置,基本没有介绍每种滤镜的文章。性能
下面提供获取每种滤镜名称以及其属性的方法:测试
// swift 版
let properties = CIFilter.filterNamesInCategory(kCICategoryBuiltIn)
println(properties)
for fileterName : String in properties {
let filter = CIFilter(name: fileterName)
// 滤镜的参数
print(filter?.attributes)
}
// Objective-C版 (因转换成OC版的太简单,略😃)
复制代码
在iOS 中使用滤镜效果,须要用到的重要类有三个:优化
setValue: forKey:
方法来设置参数。对一张图使用一个滤镜效果,总结起来须要四步:ui
这里有一段示例代码:spa
// 1.获取本地图片路径
let fileURL = NSBundle.mainBundle().URLForResource("image", withExtension: "png")
// 2.建立CIImage对象
let beginImage = CIImage(contentsOfURL: fileURL!)
// 3. 建立滤镜
// 建立一个棕榈色滤镜
let filter = CIFilter(name: "CISepiaTone")!
filter.setValue(beginImage, forKey: kCIInputImageKey)
// 设置输入的强度系数
filter.setValue(0.5, forKey: kCIInputIntensityKey)
// 4.将CIImage转换为UIImage
// 其实在这个API内部用到了CIContext,而它就是在每次使用的使用去建立一个新的CIContext,比较影响性能
let newImage = UIImage(CIImage: filter.outputImage!)
self.imageView.image = newImage
复制代码
注意点code
由于
let newImage = UIImage(CIImage: filter.outputImage)
内部会每次都建立一个CIContext,这里咱们能够优化。用上面的方式建立的UIImage ,咱们将其转换为NSData的时候,NSData为nil,缘由是:May return nil if image has no CGImageRef or invalid bitmap format
,这代表咱们更应该优化。orm
将上面的第四步替换成以下代码:
// 1 建立一个CIContext,只须要将这个context对象存起来,其余地方调用便可。
let context = CIContext(options:nil)
// 2 用CIContext将CIImage转换为CGImage
let cgimg = context.createCGImage(filter.outputImage!, fromRect: filter.outputImage!.extent)
// 3 将CGImage转换为UIImage
let newImage = UIImage(CGImage: cgimg)
self.imageView.image = newImage
复制代码
之前咱们可能会用 UIImageWriteToSavedPhotosAlbum()
。 ALAssetsLibrary 提供了将CGImage直接保存到相册的示例方法:writeImageToSavedPhotosAlbum
,只惋惜它到iOS 9.0 就弃用了☹️,当工程的最低兼容版本大于9.0时,编译器会给你一个警告,告诉你该用什么方法替换。
@IBAction func savePhoto(sender: UIButton) {
// 1 获取滤镜输出的图片
let imageToSave = filter.outputImage!
// 2 建立一个使用CPU渲染器的CIContext
let softwareContext = CIContext(options: [kCIContextUseSoftwareRenderer : true])
// 3 将CIImage转换为CGImage
let cgimage = softwareContext.createCGImage(imageToSave, fromRect: imageToSave.extent)
// 4 使用 ALAssetsLibrary 保存到相册
let library = ALAssetsLibrary()
library.writeImageToSavedPhotosAlbum(cgimage, metadata: imageToSave.properties, completionBlock: nil)
}
复制代码
咱们能够将多种滤镜效果组合起来,建立一个新的滤镜效果,这比将一个个的滤镜加到图片上,在输出要有效率的多。
这里有一个示例:
func oldPhoto(img: CIImage, withAmount intensity: Float) -> CIImage {
// 1 建立一个棕色滤镜
let sepiaFilter = CIFilter(name: "CISepiaTone")
sepiaFilter?.setValue(img, forKey: kCIInputImageKey)
sepiaFilter?.setValue(intensity, forKey: kCIInputIntensityKey)
// 2 建立一个随机点滤镜
let randomFilter = CIFilter(name: "CIRandomGenerator")
// 3
let lighten = CIFilter(name: "CIColorControls")
lighten?.setValue(randomFilter?.outputImage, forKey: kCIInputImageKey)
lighten?.setValue(1 - intensity, forKey: "inputBrightness")
lighten?.setValue(0, forKey: "inputSaturation")
// 4 将滤镜输出裁剪成原始图片大小
let croppedImage = lighten?.outputImage?.imageByCroppingToRect(beginImage.extent)
// 5
let composite = CIFilter(name: "CIHardLightBlendMode")
composite?.setValue(sepiaFilter?.outputImage, forKey: kCIInputImageKey)
composite?.setValue(croppedImage, forKey: kCIInputBackgroundImageKey)
// 6
let vignette = CIFilter(name: "CIVignette")
vignette?.setValue(composite?.outputImage, forKey: kCIInputImageKey)
vignette?.setValue(intensity * 2, forKey: "inputIntensity")
vignette?.setValue(intensity * 30, forKey: "inputRadius")
// 7
return (vignette?.outputImage)!
}
复制代码
为毛本身家的效果图是这个鬼样子,别人家的效果图那么好看!😒 😒
建立条形码
+ (UIImage *)barCodeImageWithInfo:(NSString *)info
{
// 建立条形码
CIFilter *filter = [CIFilter filterWithName:@"CICode128BarcodeGenerator"];
// 恢复滤镜的默认属性
[filter setDefaults];
// 将字符串转换成NSData
NSData *data = [info dataUsingEncoding:NSUTF8StringEncoding];
// 经过KVO设置滤镜inputMessage数据
[filter setValue:data forKey:@"inputMessage"];
// 得到滤镜输出的图像
CIImage *outputImage = [filter outputImage];
// 将CIImage 转换为UIImage
UIImage *image = [UIImage imageWithCIImage:outputImage];
// 若是须要将image转NSData保存,则得用下面的方式先转换为CGImage,不然NSData 会为nil
// CIContext *context = [CIContext contextWithOptions:nil];
// CGImageRef imageRef = [context createCGImage:outputImage fromRect:outputImage.extent];
//
// UIImage *image = [UIImage imageWithCGImage:imageRef];
return image;
}
复制代码
建立二维码
+ (UIImage *)qrCodeImageWithInfo:(NSString *)info width:(CGFloat)width
{
if (!info) {
return nil;
}
NSData *strData = [info dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
//建立二维码滤镜
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[qrFilter setValue:strData forKey:@"inputMessage"];
[qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];
CIImage *qrImage = qrFilter.outputImage;
//颜色滤镜
CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"];
[colorFilter setDefaults];
[colorFilter setValue:qrImage forKey:kCIInputImageKey];
[colorFilter setValue:[CIColor colorWithRed:0 green:0 blue:0] forKey:@"inputColor0"];
![Uploading 1A4978EE-427F-4804-B536-1D5C330A0578_306160.png . . .][colorFilter setValue:[CIColor colorWithRed:1 green:1 blue:1] forKey:@"inputColor1"];
CIImage *colorImage = colorFilter.outputImage;
//返回二维码
CGFloat scale = width/31;
UIImage *codeImage = [UIImage imageWithCIImage:[colorImage imageByApplyingTransform:CGAffineTransformMakeScale(scale, scale)]];
return codeImage;
}
复制代码
CIFilter初体验就先到这里了,Have Fun!