• 直播预览层添加滤镜效果(CIFilter使用场景)


    直播预览层添加滤镜效果

    • 原理,在显示之前,提前对图片进行滤镜处理,把处理后的图片展示出来就好了.

    • CIFiter(滤镜类):给图片添加特殊效果(模糊,高亮等等).

    • CIFiter滤镜分类(一个滤镜可能属于多个分类)

      • kCICategoryDistortionEffect 扭曲效果,比如bump、旋转、hole
      • kCICategoryGeometryAdjustment 几何开着调整,比如仿射变换、平切、透视转换
      • kCICategoryCompositeOperation 合并,比如源覆盖(source over)、最小化、源在顶(source atop)、色彩混合模式
      • kCICategoryHalftoneEffect Halftone效果,比如screen、line screen、hatched
      • kCICategoryColorAdjustment 色彩调整,比如伽马调整、白点调整、曝光
      • kCICategoryColorEffect 色彩效果,比如色调调整、posterize
      • kCICategoryTransition 图像间转换,比如dissolve、disintegrate with mask、swipe
      • kCICategoryTileEffect 瓦片效果,比如parallelogram、triangle
      • kCICategoryGenerator 图像生成器,比如stripes、constant color、checkerboard
      • kCICategoryGradient 渐变,比如轴向渐变、仿射渐变、高斯渐变
      • kCICategoryStylize 风格化,比如像素化、水晶化
      • kCICategorySharpen 锐化、发光
      • kCICategoryBlur 模糊,比如高斯模糊、焦点模糊、运动模糊
      • kCICategoryStillImage 能用于静态图像
      • kCICategoryVideo 能用于视频
      • kCICategoryInterlaced 能用于交错图像
      • kCICategoryNonSquarePixels 能用于非矩形像素
      • kCICategoryHighDynamicRange 能用于HDR
      • kCICategoryBuiltIn 获取所有滤镜
    • 常用图片处理滤镜:

      
      // 怀旧 --> CIPhotoEffectInstant                         单色 --> CIPhotoEffectMono
      // 黑白 --> CIPhotoEffectNoir                            褪色 --> CIPhotoEffectFade
      // 色调 --> CIPhotoEffectTonal                           冲印 --> CIPhotoEffectProcess
      // 岁月 --> CIPhotoEffectTransfer                        铬黄 --> CIPhotoEffectChrome
      
      
    • 自动处理滤镜,通过CIImage获取,CIImage会自动对图片进行滤镜处理

        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
            
        // 转换为CIImage
        CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
            
            
        NSArray *fiters = [ciImage autoAdjustmentFilters];
            
        NSLog(@"%@",fiters);
    
    • 常有的自动滤镜

          CIRedEyeCorrection:修复因相机的闪光灯导致的各种红眼
          CIFaceBalance:调整肤色
          CIVibrance:在不影响肤色的情况下,改善图像的饱和度
          CIToneCurve:改善图像的对比度
          CIHighlightShadowAdjust:改善阴影细节      
      
    • 滤镜对象创建(也可以使用coreImage自动处理滤镜,就不需要自己创建)

    • 滤镜属性可以通过inputKeys属性获取

    • 滤镜工作原理,给滤镜传入一个图片,滤镜有个方法,可以获取处理完成的图片outputImage.

            CIFilter *fiter = [CIFilter filterWithName:@"CIPhotoEffectInstant"];
            
            [fiter setValue:ciImage forKey:@"inputImage"];
            
            ciImage = fiter.outputImage;
    

    直播预览层添加滤镜效果步骤

    • 取出捕获到的帧(CMSampleBufferRef) -> 获取帧里面图片信息(CVImageBufferRef) -> CIFiter滤镜处理 ->转换成UIImage -> 设置为UIImageView的image就能实时显示捕获的画面
    if (_videoConnection == connection) {
            // 获取图片信息
            CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
            
            // 转换为CIImage
            CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
            
            // 创建滤镜
            CIFilter *fiter = [CIFilter filterWithName:@"CIFaceBalance"];
            
            [fiter setValue:ciImage forKey:@"inputImage"];
            [fiter setValue:@100 forKey:@"inputStrength"];
            ciImage = fiter.outputImage;
            
            // 转换UIImage
            UIImage *image = [UIImage imageWithCIImage:ciImage];
            
            dispatch_sync(dispatch_get_main_queue(), ^{
                
                self.imageView.image = image;
                
            });
        }
    
    

    通过GPU渲染图片显示

    • 只有OpenGL才能操控GPU,需要用到OpenGL才行
    • CIContext:通过这个上下文的方法渲染图片(createCGImage)
    • CIContext:通过OpenGL的上下文创建,就能用GPU渲染图片,处理图片效率高.(contextWithEAGLContext)
      // 获取图片信息
                CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
                
                // 转换为CIImage
                CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
                
                // 创建滤镜
                CIFilter *fiter = [CIFilter filterWithName:@"CIPhotoEffectInstant"];
                
                [fiter setValue:ciImage forKey:@"inputImage"];
                
                ciImage = fiter.outputImage;
                
                EAGLContext *openglCtx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
                CIContext *ctx = [CIContext contextWithEAGLContext:openglCtx];
                
                CGImageRef imgRef = [ctx createCGImage:ciImage fromRect:ciImage.extent];
                
                UIImage *image = [UIImage imageWithCGImage:imgRef];
            
                // 用完了及时清空,否则内存溢出,造成程序崩溃.使用C语言的时候,需要特别注意内存管理.
                CGImageRelease(imgRef);
            
                // 转换UIImage
                
                dispatch_sync(dispatch_get_main_queue(), ^{
                    
                    self.imageView.image = image;
                    
                    
                });
    
    • 注意点:有个地方需要自己管理内存,否则程序会闪退,报下列错误
    CGImageRef imgRef = [ctx createCGImage:ciImage fromRect:ciImage.extent];
                
    UIImage *image = [UIImage imageWithCGImage:imgRef];
            
    // 用完了及时清空,否则内存溢出,造成程序崩溃.使用C语言的时候,需要特别注意内存管理.
    CGImageRelease(imgRef);
    
    • 注意点:会报坏内存访问,原因有些对象销毁了,没有及时清空,再次用到就坏内存访问
    • 测试:不需要添加滤镜效果,容易测试出来,报下列错误
     
    • 解决:把一个周期的代码,放入一个自动释放池里管理,下一个运行循环,会自动清空已经销毁的对象。
    • 自动释放池:可以用来管理一段代码中对象的生命周期。
     @autoreleasepool {
                // 获取图片信息
                CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
                
                // 转换为CIImage
                CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
                
                // 创建滤镜
                CIFilter *fiter = [CIFilter filterWithName:@"CIPhotoEffectInstant"];
                
                [fiter setValue:ciImage forKey:@"inputImage"];
                
                ciImage = fiter.outputImage;
            
                EAGLContext *openglCtx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
                CIContext *ctx = [CIContext contextWithEAGLContext:openglCtx];
                
                CGImageRef imgRef = [ctx createCGImage:ciImage fromRect:ciImage.extent];
                
                UIImage *image = [UIImage imageWithCGImage:imgRef];
            
                // 用完了及时清空,否则内存溢出,造成程序崩溃.使用C语言的时候,需要特别注意内存管理.
                CGImageRelease(imgRef);
            
                // 转换UIImage
                
                dispatch_sync(dispatch_get_main_queue(), ^{
                    
                    self.imageView.image = image;
                    
                });
    
            }
            
        }
  • 相关阅读:
    两数之和
    swift 结构体
    打家劫舍II
    Swift的访问控制讲解
    swift版 二分查找 (折半查找)
    RAC(ReactiveCocoa)介绍(一)
    变位词
    双向循环链表
    单链表
    顺序链表(C++)
  • 原文地址:https://www.cnblogs.com/hanease/p/16253195.html
Copyright © 2020-2023  润新知