iOS 渲染濾鏡 前言

前言

  • 介紹幾種簡單的濾鏡,

API & Property

NS_ASSUME_NONNULL_BEGIN
typedef NS_OPTIONS(NSInteger, KJRenderFilterType) {
    KJRenderFilterTypeOriginal = 0,/// 原片
    KJRenderFilterTypeColor,/// 顏色濾鏡
    KJRenderFilterTypeSketch, /// 素描濾鏡
    KJRenderFilterTypeCoreImage,/// CoreImage 自帶濾鏡
};
/// CoreImage 濾鏡
typedef NS_OPTIONS(NSInteger, KJRenderCoreImageFilterType) {
    KJRenderCoreImageFilterTypeSepia = 0,/// 褐色濾鏡(懷舊)
    KJRenderCoreImageFilterTypeColorInvert,/// 顏色反轉
};
static NSString * const _Nonnull KJRenderCoreImageFilterTypeStringMap[] = {
    [KJRenderCoreImageFilterTypeSepia] = @"CISepiaTone",
    [KJRenderCoreImageFilterTypeColorInvert] = @"CIColorInvert",
};
static NSString * const _Nonnull KJRenderCoreImageFilterTypeKeyStringMap[] = {
    [KJRenderCoreImageFilterTypeSepia] = @"inputIntensity",
    [KJRenderCoreImageFilterTypeColorInvert] = @"",
};
@class KJRenderInfo;
@interface KJRenderImageView : UIImageView
/// 初始化
- (instancetype)kj_initWithOriImage:(UIImage*)image ExtendParameterBlock:(void(^_Nullable)(KJRenderImageView *obj))paramblock;
/// 修改效果
- (void)kj_changeRenderInfo:(KJRenderInfo*)info;
#pragma mark - ExtendParameterBlock 擴展參數
@property(nonatomic,strong,readonly) KJRenderImageView *(^kAddView)(UIView*);
@property(nonatomic,strong,readonly) KJRenderImageView *(^kFrame)(CGRect);
@end
@interface KJRenderInfo : NSObject
@property(nonatomic,assign)KJRenderFilterType type; /// 濾鏡
@property(nonatomic,assign)float opacity;/// 透明度,默認 1
@property(nonatomic,assign)float extend;/// 擴展
@property(nonatomic,strong)UIColor *color;/// 顏色濾鏡
@property(nonatomic,assign)KJRenderCoreImageFilterType coreType;/// CoreImage 濾鏡
@end
NS_ASSUME_NONNULL_END

簡單介紹思路

KJRenderInfo濾鏡模型數據

目前有四種濾鏡

typedef NS_OPTIONS(NSInteger, KJRenderFilterType) {
    KJRenderFilterTypeOriginal = 0,/// 原片
    KJRenderFilterTypeColor,/// 顏色濾鏡
    KJRenderFilterTypeSketch, /// 素描濾鏡
    KJRenderFilterTypeCoreImage,/// CoreImage 自帶濾鏡
};

1.KJRenderFilterTypeColor 顏色濾鏡

這種濾鏡的主要實現方式其實就是給圖片加個顏色濾鏡,就不做多餘贅述

/// 顏色濾鏡
- (UIImage*)kj_colorRenderInfo:(KJRenderInfo*)info{
    UIGraphicsBeginImageContext(self.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.originImage drawInRect:self.bounds];
    CGContextSetFillColorWithColor(context, [info.color colorWithAlphaComponent:info.extend].CGColor);
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGContextFillRect(context, self.bounds);
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:imageRef];
    UIGraphicsEndImageContext();
    CGImageRelease(imageRef);
    return newImage;
}

2.KJRenderFilterTypeSketch 素描濾鏡

其實核心還是CoreImage的濾鏡使用,先去色CIPhotoEffectMono,然後拷貝反色CIColorInvert,再高斯模糊CIGaussianBlur,最後混合疊加到去色圖片CIColorDodgeBlendMode

/// 素描濾鏡
- (void)kj_sketchRenderInfo:(KJRenderInfo*)info{
    _weakself;
    kGCD_QUEUE_ASYNC(^{
        /// 去色
        CIImage * inputImage = [[CIImage alloc] initWithImage:weakself.originImage];
        CIFilter * monoFilter = [CIFilter filterWithName:@"CIPhotoEffectMono"];
        [monoFilter setValue:inputImage forKey:kCIInputImageKey];
        CIImage * outImage = [monoFilter outputImage];
        /// 拷貝反色
        CIImage * invertImage = [outImage copy];
        CIFilter * invertFilter = [CIFilter filterWithName:@"CIColorInvert"];
        [invertFilter setValue:invertImage forKey:kCIInputImageKey];
        invertImage = [invertFilter outputImage];
        /// 高斯模糊
        CIFilter * blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
        [blurFilter setDefaults];
        [blurFilter setValue:@(info.extend*100) forKey:kCIInputRadiusKey];
        [blurFilter setValue:invertImage forKey:kCIInputImageKey];
        invertImage = [blurFilter valueForKey:kCIOutputImageKey];
        /// 混合疊加到去色圖片
        CIFilter * blendFilter = [CIFilter filterWithName:@"CIColorDodgeBlendMode"];
        [blendFilter setValue:invertImage forKey:kCIInputImageKey];
        [blendFilter setValue:outImage forKey:kCIInputBackgroundImageKey];
        CIImage * sketchImage = [blendFilter outputImage];
        /// 渲染圖片
        CGImageRef cgImage = [weakself.ciContext createCGImage:sketchImage fromRect:[inputImage extent]];
        kGCD_MAIN_ASYNC(^{
            weakself.image = [UIImage imageWithCGImage:cgImage];
            CGImageRelease(cgImage);
        });
    });
}

3.KJRenderFilterTypeCoreImage

CoreImage 濾鏡,褐色濾鏡,顏色反轉

/// CoreImage 濾鏡
typedef NS_OPTIONS(NSInteger, KJRenderCoreImageFilterType) {
    KJRenderCoreImageFilterTypeSepia = 0,/// 褐色濾鏡(懷舊)
    KJRenderCoreImageFilterTypeColorInvert,/// 顏色反轉
};
static NSString * const _Nonnull KJRenderCoreImageFilterTypeStringMap[] = {
    [KJRenderCoreImageFilterTypeSepia] = @"CISepiaTone",
    [KJRenderCoreImageFilterTypeColorInvert] = @"CIColorInvert",
};
static NSString * const _Nonnull KJRenderCoreImageFilterTypeKeyStringMap[] = {
    [KJRenderCoreImageFilterTypeSepia] = @"inputIntensity",
    [KJRenderCoreImageFilterTypeColorInvert] = @"",
};
/// coreImage 濾鏡
- (void)kj_coreImageRenderInfo:(KJRenderInfo*)info{
    _weakself;
    dispatch_queue_t globel = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(globel, ^{
        CIFilter *filter = [CIFilter filterWithName:KJRenderCoreImageFilterTypeStringMap[info.coreType]];
        [filter setDefaults];
        [filter setValue:[[CIImage alloc] initWithImage:weakself.originImage] forKey:kCIInputImageKey];
        NSString *string = KJRenderCoreImageFilterTypeKeyStringMap[info.coreType];
        if (![string isEqualToString:@""]) [filter setValue:@(info.extend) forKey:string];
        CIImage *outputImage  = [filter outputImage];
        CGImageRef filterimge = [weakself.ciContext createCGImage:outputImage fromRect:outputImage.extent];
        dispatch_queue_t main = dispatch_get_main_queue();
        dispatch_async(main, ^{
            weakself.image = [UIImage imageWithCGImage:filterimge];
            CGImageRelease(filterimge);
        });
    });
}

使用示例

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    _weakself;
    CGFloat sp = kAutoW(10);
    CGFloat w = (kScreenW-sp*3)/2;
    CGFloat h = w;
    CGFloat maxY = 64.;
    UIImage *image  = kGetImage(@"IMG_4931");
    
    UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(sp, maxY+sp, w, h)];
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    imageView.backgroundColor = [UIColor.orangeColor colorWithAlphaComponent:0.1];
    imageView.image = image;
    [self.view addSubview:imageView];
    
    __block NSArray <KJRenderInfo*>*renderTemps = @[({
        KJRenderInfo *info = [KJRenderInfo new];
        info.type = KJRenderFilterTypeOriginal;
        info.opacity = 1.;
        info;
    }),({
        KJRenderInfo *info = [KJRenderInfo new];
        info.type = KJRenderFilterTypeCoreImage;
        info.coreType = KJRenderCoreImageFilterTypeSepia;
        info.extend = .8;
        info.opacity = 1.;
        info;
    }),({
        KJRenderInfo *info = [KJRenderInfo new];
        info.type = KJRenderFilterTypeSketch;
        info.extend = .8;
        info.opacity = 1.;
        info;
    }),({
        KJRenderInfo *info = [KJRenderInfo new];
        info.type = KJRenderFilterTypeColor;
        info.extend = .8;
        info.color = [UIColor.greenColor colorWithAlphaComponent:0.1];
        info;
    })];
    
    KJRenderImageView *view = ({
        KJRenderImageView *renderImageView = [[KJRenderImageView alloc] kj_initWithOriImage:image ExtendParameterBlock:^(KJRenderImageView * _Nonnull obj) {
            obj.kAddView(weakself.view).kFrame(CGRectMake(sp+imageView.maxX, imageView.top, w, h));
        }];
        renderImageView.backgroundColor = [UIColor.orangeColor colorWithAlphaComponent:0.1];
        [renderImageView kj_changeRenderInfo:renderTemps[1]];
        renderImageView;
    });
    
    KJRenderImageView *view2 = ({
        KJRenderImageView *renderImageView = [[KJRenderImageView alloc] kj_initWithOriImage:image ExtendParameterBlock:^(KJRenderImageView * _Nonnull obj) {
            obj.kAddView(weakself.view).kFrame(CGRectMake(sp, view.bottom+sp, w, h));
        }];
        renderImageView.backgroundColor = [UIColor.orangeColor colorWithAlphaComponent:0.1];
        [renderImageView kj_changeRenderInfo:renderTemps[2]];
        renderImageView;
    });
    
    KJRenderImageView *view3 = ({
        KJRenderImageView *renderImageView = [[KJRenderImageView alloc] kj_initWithOriImage:image ExtendParameterBlock:^(KJRenderImageView * _Nonnull obj) {
            obj.kAddView(weakself.view).kFrame(CGRectMake(sp+view2.maxX, view.bottom+sp, w, h));
        }];
        renderImageView.backgroundColor = [UIColor.orangeColor colorWithAlphaComponent:0.1];
        [renderImageView kj_changeRenderInfo:renderTemps[3]];
        renderImageView;
    });
}
備註:本文用到的部分函數方法和Demo,均來自三方庫KJExtensionHandler,如有需要的朋友可自行pod 'KJExtensionHandler'引入即可

濾鏡介紹就到此完畢,後面有相關再補充,寫文章不容易,還請點個小星星傳送門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章