美文网首页程序员iOS开发iOS Developer
iOS图形图像及核心动画实战二Block基础知识

iOS图形图像及核心动画实战二Block基础知识

作者: 三角君 | 来源:发表于2016-04-06 15:16 被阅读301次

    本教程是一个合集,涉及到的目录结构:
    基础知识总结
    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中用Block

    a -> 代表静态函数
    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中所有滤镜全部定义了出来,实在太懒没写全函数实现,如有大神全部写全,请分享于我!

    相关文章

      网友评论

        本文标题:iOS图形图像及核心动画实战二Block基础知识

        本文链接:https://www.haomeiwen.com/subject/nzcdlttx.html