本教程是一个合集,涉及到的目录结构:
基础知识总结
Block基础知识
GCD实战
CoreGraphics & ImageIO实战
CoreAnimation实战
Block是在iOS 4.0及以上系统才提供的一种类似于匿名函数(或闭包)的语法,它被定义在SDK中,所以基本上现在所有的开发人员都是不得不需要掌握的一项技能。
本篇文章也仅仅作为快速入门使用,不涉及底层实现,如对Block有所了解,请移步!
Block的基础结构剖析
先上张图:
Paste_Image.png
这张图应该很经典了,基本上不用Google,百度这个渣渣都能搜索到。
Block定义部分主要了解几个地方即可:
- 符号中文叫:脱字符,定义Block时必须要写,也可以理解为有符号才应该是Block
- Block可以有返回值,也就是图上最左边的int
- Block有个名字,也就是图上的myBlock
- Block可以带参数(并且可以多个),也就是图上的从左往右第二个int
Block实现部分主要了解几个地方即可:
- 以脱字符打头
- 括号内是参数
- 使用花括号包起来,内部写实际的算法代码,然后该返回就返回(例如图上应该返回int)
Block实战
- 最最有代表性的用法
int result = myBlock(10);
printf("%d",result);
这段代码会输出:70
- 如果Block就仅仅上面这点用,那就太小看它了,我们来点最最实在的 -- 链式语法
链式语法白话理解就是先产生某个对象,没个函数操作实际又会返回它自己(其实也可以返回它自己类型的指针),然后一路 . 下去,不断的可以调用函数,最后一个函数即可得到一个最终结果。
例如下面代码,就是一路 . 下去:
maker.add(10).subtract(2).multiply(3).divide(4);
最终的结果为:6
以上计算步骤为:
0 + 10 = 10
10 - 2 = 8
8 * 3 = 24
24 / 4 = 6
哈哈哈,帅不帅!
我们剖析链式语法实现之前先来了解个东西:
- property中用Block
@property (nonatomic,readonly) CaculatorMaker *(^add)(NSInteger number);
@property (nonatomic,readonly) CaculatorMaker *(^subtract)(NSInteger number);
@property (nonatomic,readonly) CaculatorMaker *(^multiply)(NSInteger number);
@property (nonatomic,readonly) CaculatorMaker *(^divide)(NSInteger number);
- method中用Block
- (CaculatorMaker* (^)(NSInteger))add;
- (CaculatorMaker* (^)(NSInteger))subtract;
- (CaculatorMaker* (^)(NSInteger))multiply;
- (CaculatorMaker* (^)(NSInteger))divide;
Property中用Block,我想应该很容易理解,但是那个Method中用Block初学者很容易看蒙。蒙在哪呢,主要在add前面那个NSIneteger,其实这个是代表add的参数!😓
仔细剖析下:
Method中用Blocka -> 代表静态函数
b -> Block返回值、参数打头括号及结尾括号
c -> 返回值
d -> 表明这是一个Block(不需要名称)
e -> 参数(同样不需要名称)
f -> 函数命名
OK,准备工作都已做好,我们来看看链式语法的实操!
使用链式语法打造不一样的CoreImage
CoreImage是Apple封装好的一个滤镜操作库,它可以让我们很容易的对图像进行滤镜。
来来来,我们利用前面的Block基础知识以及链式语法的基础来实现一个最基本的棕色滤镜:
@interface CIImage (XPImage)
// 棕色滤镜
@property (nonatomic, readonly) CIImage *(^sepiaTone)(CGFloat intensity);
// 拉直滤镜
@property (nonatomic, readonly) CIImage *(^straightenFilter)(CGFloat angle);
- (CIImage* (^)(CGFloat intensity))sepiaTone {
return ^CIImage* (CGFloat intensity) {
CIFilter *sepiaFilter = [CIFilter filterWithName:@"CISepiaTone"];
[sepiaFilter setValue:self forKey:kCIInputImageKey];
[sepiaFilter setValue:@(intensity) forKey:kCIInputIntensityKey];
return [sepiaFilter outputImage];
};
}
- (CIImage*(^)(CGFloat angle))straightenFilter {
return ^(CGFloat angle) {
CIFilter *filter = [CIFilter filterWithName:@"CIStraightenFilter"];
[filter setValue:self forKey:kCIInputImageKey];
[filter setValue:@(angle) forKey:kCIInputAngleKey];
return filter.outputImage;
};
}
然后我们来测试下看看:
CIImage *ciimage = [CIImage imageWithPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"1_1.png"]];
UIImage *image = ciimage.sepiaTone(0.9).straightenFilter(0).UIImage;
self.imageView.image = image;
原图
滤镜后
啦啦啦,啦啦啦,我能装逼了~~~哈哈哈
言归正传,Block是一个浅入深出的技术,它最基本的用处是匿名函数,但是同时它如果配合其他的模式(如链式、GCD)就能产生无穷大的力量!
备注
CoreImage其实底层提供了非常多的滤镜,但是Apple没有很直接的暴露出来,只提供了一个获取滤镜的函数:
[CIFilter filterNamesInCategory:kCICategoryBuiltIn]
每个滤镜也可获取它的输入、输出参数:
CIFilter filter = [CIFilter filterWithName:name];
NSArray<NSString> inputKeys = filter.inputKeys;
NSArray<NSString> *outputKeys = filter.outputKeys;
附录
#import <Foundation/Foundation.h>
#import <CoreImage/CoreImage.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface CIImage (XPImage)
// 棕色滤镜
@property (nonatomic, readonly) CIImage *(^sepiaTone)(CGFloat intensity);
// 仿射变换滤镜
@property (nonatomic, readonly) CIImage *(^affineTransform)(CGAffineTransform transform);
// 混合滤镜(给有Alpha通道的图片添加底层图片)
@property (nonatomic, readonly) CIImage *(^sourceAtopCompositing)(CIImage *backgroundImage);
// 拉直滤镜
@property (nonatomic, readonly) CIImage *(^straightenFilter)(CGFloat angle);
// 色彩控制滤镜
@property (nonatomic, readonly) CIImage *(^colorControls)(CGFloat bright,CGFloat contrast,CGFloat saturation);
// 反转颜色滤镜
@property (nonatomic,readonly) CIImage *(^colorInvert)(void);
@property (nonatomic,readonly)CIImage *(^accordionFoldTransition)(CIImage *targetImage,CGFloat bottomHeight,NSInteger numberOfFolds,NSInteger foldShadowAmount,CGFloat time);
@property (nonatomic,readonly)CIImage *(^additionCompositing)(CIImage *backgroundImage);
@property (nonatomic,readonly)CIImage *(^affineClamp)(CGAffineTransform transform);
@property (nonatomic,readonly)CIImage *(^affineTile)(CGAffineTransform transform);
//TODO: 下面的滤镜还未实现
@property (nonatomic,readonly)CIImage *(^areaHistogram)(NSString *extent,NSString *scale,NSString *count);
@property (nonatomic,readonly)CIImage *(^aztecCodeGenerator)(NSString *message,NSString *correctionLevel,NSString *layers,NSString *compactStyle);
@property (nonatomic,readonly)CIImage *(^barsSwipeTransition)(NSString *targetImage,NSString *angle,NSString *width,NSString *barOffset,NSString *time);
@property (nonatomic,readonly)CIImage *(^blendWithAlphaMask)(NSString *backgroundImage,NSString *maskImage);
@property (nonatomic,readonly)CIImage *(^blendWithMask)(NSString *backgroundImage,NSString *maskImage);
@property (nonatomic,readonly)CIImage *(^bloom)(NSString *radius,NSString *intensity);
@property (nonatomic,readonly)CIImage *(^bumpDistortion)(NSString *center,NSString *radius,NSString *scale);
@property (nonatomic,readonly)CIImage *(^bumpDistortionLinear)(NSString *center,NSString *radius,NSString *angle,NSString *scale);
@property (nonatomic,readonly)CIImage *(^checkerboardGenerator)(NSString *center,NSString *color0,NSString *color1,NSString *width,NSString *sharpness);
@property (nonatomic,readonly)CIImage *(^circleSplashDistortion)(NSString *center,NSString *radius);
@property (nonatomic,readonly)CIImage *(^circularScreen)(NSString *center,NSString *width,NSString *sharpness);
@property (nonatomic,readonly)CIImage *(^code128BarcodeGenerator)(NSString *message,NSString *quietSpace);
@property (nonatomic,readonly)CIImage *(^colorBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^colorBurnBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^colorClamp)(NSString *minComponents,NSString *maxComponents);
@property (nonatomic,readonly)CIImage *(^colorCrossPolynomial)(NSString *coefficients,NSString *redCoefficients,NSString *greenCoefficients,NSString *blueCoefficients);
@property (nonatomic,readonly)CIImage *(^colorCube)(NSString *cubeDimension,NSString *cubeData);
@property (nonatomic,readonly)CIImage *(^colorCubeWithColorSpace)(NSString *cubeDimension,NSString *cubeData,NSString *colorSpace);
@property (nonatomic,readonly)CIImage *(^colorDodgeBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^colorMap)(NSString *gradientImage);
@property (nonatomic,readonly)CIImage *(^colorMatrix)(NSString *rVector,NSString *gVector,NSString *bVector,NSString *aVector,NSString *biasVector);
@property (nonatomic,readonly)CIImage *(^colorMonochrome)(NSString *color,NSString *intensity);
@property (nonatomic,readonly)CIImage *(^colorPolynomial)(NSString *redCoefficients,NSString *greenCoefficients,NSString *blueCoefficients,NSString *alphaCoefficients);
@property (nonatomic,readonly)CIImage *(^colorPosterize)(NSString *levels);
@property (nonatomic,readonly)CIImage *(^constantColorGenerator)(NSString *color);
@property (nonatomic,readonly)CIImage *(^convolution3X3)(NSString *weights,NSString *bias);
@property (nonatomic,readonly)CIImage *(^convolution5X5)(NSString *weights,NSString *bias);
@property (nonatomic,readonly)CIImage *(^convolution9Horizontal)(NSString *weights,NSString *bias);
@property (nonatomic,readonly)CIImage *(^convolution9Vertical)(NSString *weights,NSString *bias);
@property (nonatomic,readonly)CIImage *(^copyMachineTransition)(NSString *targetImage,NSString *extent,NSString *color,NSString *time,NSString *angle,NSString *width,NSString *opacity);
@property (nonatomic,readonly)CIImage *(^crop)(NSString *rectangle);
@property (nonatomic,readonly)CIImage *(^darkenBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^differenceBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^disintegrateWithMaskTransition)(NSString *targetImage,NSString *maskImage,NSString *time,NSString *shadowRadius,NSString *shadowDensity,NSString *shadowOffset);
@property (nonatomic,readonly)CIImage *(^dissolveTransition)(NSString *targetImage,NSString *time);
@property (nonatomic,readonly)CIImage *(^divideBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^dotScreen)(NSString *center,NSString *angle,NSString *width,NSString *sharpness);
@property (nonatomic,readonly)CIImage *(^eightfoldReflectedTile)(NSString *center,NSString *angle,NSString *width);
@property (nonatomic,readonly)CIImage *(^exclusionBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^exposureAdjust)(NSString *eV);
@property (nonatomic,readonly)CIImage *(^falseColor)(NSString *color0,NSString *color1);
@property (nonatomic,readonly)CIImage *(^flashTransition)(NSString *targetImage,NSString *center,NSString *extent,NSString *color,NSString *time,NSString *maxStriationRadius,NSString *striationStrength,NSString *striationContrast,NSString *fadeThreshold);
@property (nonatomic,readonly)CIImage *(^fourfoldReflectedTile)(NSString *center,NSString *angle,NSString *width,NSString *acuteAngle);
@property (nonatomic,readonly)CIImage *(^fourfoldRotatedTile)(NSString *center,NSString *angle,NSString *width);
@property (nonatomic,readonly)CIImage *(^fourfoldTranslatedTile)(NSString *center,NSString *angle,NSString *width,NSString *acuteAngle);
@property (nonatomic,readonly)CIImage *(^gammaAdjust)(NSString *power);
@property (nonatomic,readonly)CIImage *(^gaussianBlur)(NSString *radius);
@property (nonatomic,readonly)CIImage *(^gaussianGradient)(NSString *center,NSString *color0,NSString *color1,NSString *radius);
@property (nonatomic,readonly)CIImage *(^glassDistortion)(NSString *texture,NSString *center,NSString *scale);
@property (nonatomic,readonly)CIImage *(^glideReflectedTile)(NSString *center,NSString *angle,NSString *width);
@property (nonatomic,readonly)CIImage *(^gloom)(NSString *radius,NSString *intensity);
@property (nonatomic,readonly)CIImage *(^hardLightBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^hatchedScreen)(NSString *center,NSString *angle,NSString *width,NSString *sharpness);
@property (nonatomic,readonly)CIImage *(^highlightShadowAdjust)(NSString *radius,NSString *shadowAmount,NSString *highlightAmount);
@property (nonatomic,readonly)CIImage *(^histogramDisplayFilter)(NSString *height,NSString *highLimit,NSString *lowLimit);
@property (nonatomic,readonly)CIImage *(^holeDistortion)(NSString *center,NSString *radius);
@property (nonatomic,readonly)CIImage *(^hueAdjust)(NSString *angle);
@property (nonatomic,readonly)CIImage *(^hueBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^lanczosScaleTransform)(NSString *scale,NSString *aspectRatio);
@property (nonatomic,readonly)CIImage *(^lightenBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^lightTunnel)(NSString *center,NSString *rotation,NSString *radius);
@property (nonatomic,readonly)CIImage *(^linearBurnBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^linearDodgeBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^linearGradient)(NSString *point0,NSString *point1,NSString *color0,NSString *color1);
@property (nonatomic,readonly)CIImage *(^linearToSRGBToneCurve)(void);
@property (nonatomic,readonly)CIImage *(^lineScreen)(NSString *center,NSString *angle,NSString *width,NSString *sharpness);
@property (nonatomic,readonly)CIImage *(^luminosityBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^maskToAlpha)(void);
@property (nonatomic,readonly)CIImage *(^maximumComponent)(void);
@property (nonatomic,readonly)CIImage *(^maximumCompositing)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^minimumComponent)(void);
@property (nonatomic,readonly)CIImage *(^minimumCompositing)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^modTransition)(NSString *targetImage,NSString *center,NSString *time,NSString *angle,NSString *radius,NSString *compression);
@property (nonatomic,readonly)CIImage *(^motionBlur)(NSString *radius,NSString *angle);
@property (nonatomic,readonly)CIImage *(^multiplyBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^multiplyCompositing)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^overlayBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^perspectiveCorrection)(NSString *topLeft,NSString *topRight,NSString *bottomRight,NSString *bottomLeft);
@property (nonatomic,readonly)CIImage *(^photoEffectChrome)(void);
@property (nonatomic,readonly)CIImage *(^photoEffectFade)(void);
@property (nonatomic,readonly)CIImage *(^photoEffectInstant)(void);
@property (nonatomic,readonly)CIImage *(^photoEffectMono)(void);
@property (nonatomic,readonly)CIImage *(^photoEffectNoir)(void);
@property (nonatomic,readonly)CIImage *(^photoEffectProcess)(void);
@property (nonatomic,readonly)CIImage *(^photoEffectTonal)(void);
@property (nonatomic,readonly)CIImage *(^photoEffectTransfer)(void);
@property (nonatomic,readonly)CIImage *(^pinchDistortion)(NSString *center,NSString *radius,NSString *scale);
@property (nonatomic,readonly)CIImage *(^pinLightBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^pixellate)(NSString *center,NSString *scale);
@property (nonatomic,readonly)CIImage *(^qRCodeGenerator)(NSString *message,NSString *correctionLevel);
@property (nonatomic,readonly)CIImage *(^radialGradient)(NSString *center,NSString *radius0,NSString *radius1,NSString *color0,NSString *color1);
@property (nonatomic,readonly)CIImage *(^randomGenerator)(void);
@property (nonatomic,readonly)CIImage *(^saturationBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^screenBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^sharpenLuminance)(NSString *sharpness);
@property (nonatomic,readonly)CIImage *(^sixfoldReflectedTile)(NSString *center,NSString *angle,NSString *width);
@property (nonatomic,readonly)CIImage *(^sixfoldRotatedTile)(NSString *center,NSString *angle,NSString *width);
@property (nonatomic,readonly)CIImage *(^smoothLinearGradient)(NSString *point0,NSString *point1,NSString *color0,NSString *color1);
@property (nonatomic,readonly)CIImage *(^softLightBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^sourceInCompositing)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^sourceOutCompositing)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^sourceOverCompositing)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^sRGBToneCurveToLinear)(void);
@property (nonatomic,readonly)CIImage *(^starShineGenerator)(NSString *center,NSString *color,NSString *radius,NSString *crossScale,NSString *crossAngle,NSString *crossOpacity,NSString *crossWidth,NSString *epsilon);
@property (nonatomic,readonly)CIImage *(^stripesGenerator)(NSString *center,NSString *color0,NSString *color1,NSString *width,NSString *sharpness);
@property (nonatomic,readonly)CIImage *(^subtractBlendMode)(NSString *backgroundImage);
@property (nonatomic,readonly)CIImage *(^swipeTransition)(NSString *targetImage,NSString *extent,NSString *color,NSString *time,NSString *angle,NSString *width,NSString *opacity);
@property (nonatomic,readonly)CIImage *(^temperatureAndTint)(NSString *neutral,NSString *targetNeutral);
@property (nonatomic,readonly)CIImage *(^toneCurve)(NSString *point0,NSString *point1,NSString *point2,NSString *point3,NSString *point4);
@property (nonatomic,readonly)CIImage *(^triangleKaleidoscope)(NSString *point,NSString *size,NSString *rotation,NSString *decay);
@property (nonatomic,readonly)CIImage *(^twelvefoldReflectedTile)(NSString *center,NSString *angle,NSString *width);
@property (nonatomic,readonly)CIImage *(^twirlDistortion)(NSString *center,NSString *radius,NSString *angle);
@property (nonatomic,readonly)CIImage *(^unsharpMask)(NSString *radius,NSString *intensity);
@property (nonatomic,readonly)CIImage *(^vibrance)(NSString *amount);
@property (nonatomic,readonly)CIImage *(^vignette)(NSString *intensity,NSString *radius);
@property (nonatomic,readonly)CIImage *(^vignetteEffect)(NSString *center,NSString *radius,NSString *intensity,NSString *falloff);
@property (nonatomic,readonly)CIImage *(^vortexDistortion)(NSString *center,NSString *radius,NSString *angle);
@property (nonatomic,readonly)CIImage *(^whitePointAdjust)(NSString *color);
@property (nonatomic,readonly)CIImage *(^zoomBlur)(NSString *radius,NSString *center);
/**
* @author huangxinping, 16-04-01
*
* 获取所有可用滤镜
*
* @return 滤镜名称
*/
+ (NSArray<NSString*>*)filterNames;
/**
* @author huangxinping
*
* 从路径创建
*
* @param path 路径
*
* @return 实例
*/
+ (nullable instancetype)imageWithPath:(nonnull NSString*)path;
/**
* @author huangxinping, 16-04-01
*
* 转换到UIImage
*
* @return UIImage
*/
- (nullable UIImage*)UIImage;
/**
* @author huangxinping, 16-04-01
*
* 是否是面部
*
* @return YES-是面部;NO-不是面部
*/
- (BOOL)hasFace;
/**
* @author huangxinping, 16-04-01
*
* 检测有多少个特征(CIDetectorTypeFace、CIDetectorTypeRectangle、CIDetectorTypeQRCode、CIDetectorTypeText)
*
* @return feature数组
*/
- (nullable NSArray<CIFeature*>*)featuresWithType:(nonnull NSString*)type;
/**
* @author huangxinping, 16-04-01
*
* 左眼位置
*
* @return 位置数组(NSValue里面是CGPoint)
*/
- (nullable NSArray<NSValue*>*)leftEyePosition;
/**
* @author huangxinping, 16-04-01
*
* 右眼位置
*
* @return 位置数组(NSValue里面是CGPoint)
*/
- (nullable NSArray<NSValue*>*)rightEyePosition;
/**
* @author huangxinping, 16-04-01
*
* 嘴巴位置
*
* @return 位置数组(NSValue里面是CGPoint)
*/
- (nullable NSArray<NSValue*>*)mouthEyePosition;
@end
NS_ASSUME_NONNULL_END
#import "CIImage+XPImage.h"
@implementation CIImage (XPImage)
- (CIImage* (^)(CGFloat intensity))sepiaTone {
return ^CIImage* (CGFloat intensity) {
CIFilter *sepiaFilter = [CIFilter filterWithName:@"CISepiaTone"];
[sepiaFilter setValue:self forKey:kCIInputImageKey];
[sepiaFilter setValue:@(intensity) forKey:kCIInputIntensityKey];
return [sepiaFilter outputImage];
};
}
- (CIImage*(^)(CGAffineTransform transform))affineTransform {
return ^(CGAffineTransform transform) {
CIFilter *transFilter = [CIFilter filterWithName:@"CIAffineTransform"];
[transFilter setValue:self forKey:kCIInputImageKey];
[transFilter setValue:[NSValue valueWithCGAffineTransform:transform] forKey:kCIInputTransformKey];
return transFilter.outputImage;
};
}
- (CIImage*(^)(CIImage *backgroundImage))sourceAtopCompositing {
return ^(CIImage *backgroundImage) {
CIFilter *filter = [CIFilter filterWithName:@"CISourceAtopCompositing"];
[filter setValue:self forKey:kCIInputImageKey];
[filter setValue:backgroundImage forKey:kCIInputBackgroundImageKey];
return filter.outputImage;
};
}
- (CIImage*(^)(CGFloat angle))straightenFilter {
return ^(CGFloat angle) {
CIFilter *filter = [CIFilter filterWithName:@"CIStraightenFilter"];
[filter setValue:self forKey:kCIInputImageKey];
[filter setValue:@(angle) forKey:kCIInputAngleKey];
return filter.outputImage;
};
}
- (CIImage*(^)(CGFloat bright,CGFloat contrast,CGFloat saturation))colorControls {
return ^(CGFloat bright,CGFloat contrast,CGFloat saturation) {
CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"];
[filter setValue:self forKey:kCIInputImageKey];
[filter setValue:@(bright) forKey:kCIInputBrightnessKey];
[filter setValue:@(contrast) forKey:kCIInputContrastKey];
[filter setValue:@(saturation) forKey:kCIInputSaturationKey];
return filter.outputImage;
};
}
- (CIImage*(^)(void))colorInvert {
return ^(void){
CIFilter *filter = [CIFilter filterWithName:@"CIColorInvert"];
[filter setValue:self forKey:kCIInputImageKey];
return filter.outputImage;
};
}
- (CIImage*(^)(CIImage *targetImage,CGFloat bottomHeight,NSInteger numberOfFolds,NSInteger foldShadowAmount,CGFloat time))accordionFoldTransition {
return ^(CIImage *targetImage,CGFloat bottomHeight,NSInteger numberOfFolds,NSInteger foldShadowAmount,CGFloat time){
CIFilter *filter = [CIFilter filterWithName:@"CIAccordionFoldTransition"];
[filter setValue:self forKey:kCIInputImageKey];
[filter setValue:targetImage forKey:kCIInputTargetImageKey];
[filter setValue:@(bottomHeight) forKey:@"inputBottomHeight"];
[filter setValue:@(numberOfFolds) forKey:@"inputNumberOfFolds"];
[filter setValue:@(foldShadowAmount) forKey:@"inputFoldShadowAmount"];
[filter setValue:@(time) forKey:@"inputTime"];
return filter.outputImage;
};
}
- (CIImage*(^)(CIImage *backgroundImage))additionCompositing {
return ^(CIImage *backgroundImage) {
CIFilter *filter = [CIFilter filterWithName:@"CIAdditionCompositing"];
[filter setValue:self forKey:kCIInputImageKey];
[filter setValue:backgroundImage forKey:kCIInputBackgroundImageKey];
return filter.outputImage;
};
}
- (CIImage*(^)(CGAffineTransform transform))affineClamp {
return ^(CGAffineTransform transform) {
CIFilter *filter = [CIFilter filterWithName:@"CIAffineClamp"];
[filter setValue:self forKey:kCIInputImageKey];
[filter setValue:[NSValue valueWithCGAffineTransform:transform] forKey:kCIInputTransformKey];
return filter.outputImage;
};
}
- (CIImage*(^)(CGAffineTransform transform))affineTile {
return ^(CGAffineTransform transform) {
CIFilter *filter = [CIFilter filterWithName:@"CIAffineTile"];
[filter setValue:self forKey:kCIInputImageKey];
[filter setValue:[NSValue valueWithCGAffineTransform:transform] forKey:kCIInputTransformKey];
return filter.outputImage;
};
}
+ (NSArray<NSString*>*)filterNames {
return [CIFilter filterNamesInCategory:kCICategoryBuiltIn];
}
+ (instancetype)imageWithPath:(NSString*)path {
NSURL *url = [NSURL fileURLWithPath:path];
CIImage *coreImage = [CIImage imageWithContentsOfURL:url];
return coreImage;
}
- (UIImage*)UIImage {
// return [UIImage imageWithCIImage:self]; // 该函数每一次都会创建一个CIContext对象,对于频繁调用时会很消耗性能。代码如下:
// EAGLContext *glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
// if (!glContext) {
// NSLog(@"Failed to create ES context");
// }
// CIContext *context = [CIContext contextWithEAGLContext:glContext]; // 使用GPU
// CGImageRef cgimg = [context createCGImage:self fromRect:[self extent]];
// UIImage *image = [UIImage imageWithCGImage:cgimg];
// CGImageRelease(cgimg);
// return image;
// 为了提高性能,我们可以在init时,将CIContext就初始化好,后面直接使用
static CIContext *context = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
EAGLContext *glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!glContext) {
NSLog(@"Failed to create ES context");
}
context = [CIContext contextWithEAGLContext:glContext]; // 使用GPU
});
CGImageRef cgimg = [context createCGImage:self fromRect:[self extent]];
UIImage *image = [UIImage imageWithCGImage:cgimg];
CGImageRelease(cgimg);
return image;
}
- (BOOL)hasFace {
return [self featuresWithType:CIDetectorTypeFace].count?YES:NO;
}
- (NSArray<CIFeature*>*)featuresWithType:(NSString *)type {
CIDetector *faceDetector = [CIDetector detectorOfType:type context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}];
CIImage *ciimg = [CIImage imageWithCGImage:[self UIImage].CGImage];
NSArray<CIFeature*> *features = [faceDetector featuresInImage:ciimg];
return features;
}
- (NSArray*)leftEyePosition {
if (![self hasFace]) {
return nil;
}
NSArray *features = [self featuresWithType:CIDetectorTypeFace];
NSMutableArray *buffer = [NSMutableArray arrayWithCapacity:features.count];
for (CIFaceFeature *f in features) {
if (f.hasMouthPosition) {
[buffer addObject:[NSValue valueWithCGPoint:f.leftEyePosition]];
}
}
return buffer;
}
- (NSArray*)rightEyePosition {
if (![self hasFace]) {
return nil;
}
NSArray *features = [self featuresWithType:CIDetectorTypeFace];
NSMutableArray *buffer = [NSMutableArray arrayWithCapacity:features.count];
for (CIFaceFeature *f in features) {
if (f.hasMouthPosition) {
[buffer addObject:[NSValue valueWithCGPoint:f.rightEyePosition]];
}
}
return buffer;
}
- (NSArray<NSValue*>*)mouthEyePosition {
if (![self hasFace]) {
return nil;
}
NSArray *features = [self featuresWithType:CIDetectorTypeFace];
NSMutableArray *buffer = [NSMutableArray arrayWithCapacity:features.count];
for (CIFaceFeature *f in features) {
if (f.hasMouthPosition) {
[buffer addObject:[NSValue valueWithCGPoint:f.mouthPosition]];
}
}
return buffer;
}
@end
唯一遗憾:
本人只把CoreImage中所有滤镜全部定义了出来,实在太懒没写全函数实现,如有大神全部写全,请分享于我!
网友评论