本文大部份內容均來自: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!