GPUImage是基于GPU的图像和视频处理一个开源的iOS框架,可以处理图像,给图片和视频增加滤镜等,类似于美图秀秀,里面内置了多款默认的效果,如果想自定义效果,可以参考后面所写的参考文章列表

一、GPUImage的下载安装

GPUImage的github地址:https://github.com/BradLarson/GPUImage

安装教程作者在github上是这么说的,你可以按照他说的

首先,将GPUImage.xcodeproj文件拖动到应用程序的Xcode项目中,以将框架嵌入到项目中。接下来,转到应用程序的目标并将GPUImage添加为目标依赖关系。最后,您需要将libGPUImage.a库从GPUImage框架的Products文件夹拖动到应用程序目标中的Link Binary With Libraries构建阶段。

因为嫌拖工程文件麻烦,并且后面也需要使用cocoapod管理,所以就试了下生成库,发现也是可以使用的

一、1、进入framework文件夹,打开GPUImage.xcodeproj,然后分别用真机和模拟机生成一遍静态.a库,把两个库合并:《合并静态库

2、之后把这个静态库拖入项目工程之后把头文件拖入工程即可

二、如果不想生成静态库,也可以自己拖.m和.h文件,把Source文件夹下面除了Source/IOS/Framework下面的Info.plist文件和module.modulemap文件外,其他所有的.h文件和.m文件全部引入工程就行了

注意GPUImage需要的另外的系统库,需要引入工程

  • CoreMedia
  • CoreVideo
  • OpenGLES
  • AVFoundation
  • QuartzCore

二、GPUImage对图片的使用

对图片的滤镜,全部都是一个流程,不同的是滤镜不同和滤镜的参数不同

    //褐色滤镜
    GPUImageSepiaFilter *disFilter = [[GPUImageSepiaFilter alloc] init];
    
    //设置要渲染的区域
    [disFilter forceProcessingAtSize:self.myImg.size];
    [disFilter useNextFrameForImageCapture];
    
    //获取数据源
    GPUImagePicture *stillImageSource = [[GPUImagePicture alloc]initWithImage:self.myImg];
    
    //添加上滤镜
    [stillImageSource addTarget:disFilter];
    //开始渲染
    [stillImageSource processImage];
    //获取渲染后的图片
    UIImage *newImage = [disFilter imageFromCurrentFramebuffer];
    
    //加载出来
    UIImageView *imageView = [[UIImageView alloc] initWithImage:newImage];
    imageView.frame = CGRectMake(50,50,self.myImg.size.width-200 ,self.myImg.size.height-200);
    [self.view addSubview:imageView];

2.1、系统提供调节的滤镜

系统提供了多种默认可调的参数,感谢强大的网友总结

#import "GLProgram.h"

// Base classes
#import "GPUImageOpenGLESContext.h"
#import "GPUImageOutput.h"
#import "GPUImageView.h"
#import "GPUImageVideoCamera.h"
#import "GPUImageStillCamera.h"
#import "GPUImageMovie.h"
#import "GPUImagePicture.h"
#import "GPUImageRawDataInput.h"
#import "GPUImageRawDataOutput.h"
#import "GPUImageMovieWriter.h"
#import "GPUImageFilterPipeline.h"
#import "GPUImageTextureOutput.h"
#import "GPUImageFilterGroup.h"
#import "GPUImageTextureInput.h"
#import "GPUImageUIElement.h"
#import "GPUImageBuffer.h"

// Filters
#import "GPUImageFilter.h"
#import "GPUImageTwoInputFilter.h"


#pragma mark - 调整颜色 Handle Color

#import "GPUImageBrightnessFilter.h"                //亮度
#import "GPUImageExposureFilter.h"                  //曝光
#import "GPUImageContrastFilter.h"                  //对比度
#import "GPUImageSaturationFilter.h"                //饱和度
#import "GPUImageGammaFilter.h"                     //伽马线
#import "GPUImageColorInvertFilter.h"               //反色
#import "GPUImageSepiaFilter.h"                     //褐色(怀旧)
#import "GPUImageLevelsFilter.h"                    //色阶
#import "GPUImageGrayscaleFilter.h"                 //灰度
#import "GPUImageHistogramFilter.h"                 //色彩直方图,显示在图片上
#import "GPUImageHistogramGenerator.h"              //色彩直方图
#import "GPUImageRGBFilter.h"                       //RGB
#import "GPUImageToneCurveFilter.h"                 //色调曲线
#import "GPUImageMonochromeFilter.h"                //单色
#import "GPUImageOpacityFilter.h"                   //不透明度
#import "GPUImageHighlightShadowFilter.h"           //提亮阴影
#import "GPUImageFalseColorFilter.h"                //色彩替换(替换亮部和暗部色彩)
#import "GPUImageHueFilter.h"                       //色度
#import "GPUImageChromaKeyFilter.h"                 //色度键
#import "GPUImageWhiteBalanceFilter.h"              //白平横
#import "GPUImageAverageColor.h"                    //像素平均色值
#import "GPUImageSolidColorGenerator.h"             //纯色
#import "GPUImageLuminosity.h"                      //亮度平均
#import "GPUImageAverageLuminanceThresholdFilter.h" //像素色值亮度平均,图像黑白(有类似漫画效果)

#import "GPUImageLookupFilter.h"                    //lookup 色彩调整
#import "GPUImageAmatorkaFilter.h"                  //Amatorka lookup
#import "GPUImageMissEtikateFilter.h"               //MissEtikate lookup
#import "GPUImageSoftEleganceFilter.h"              //SoftElegance lookup


#pragma mark - 图像处理 Handle Image

#import "GPUImageCrosshairGenerator.h"              //十字
#import "GPUImageLineGenerator.h"                   //线条

#import "GPUImageTransformFilter.h"                 //形状变化
#import "GPUImageCropFilter.h"                      //剪裁
#import "GPUImageSharpenFilter.h"                   //锐化
#import "GPUImageUnsharpMaskFilter.h"               //反遮罩锐化

#import "GPUImageFastBlurFilter.h"                  //模糊
#import "GPUImageGaussianBlurFilter.h"              //高斯模糊
#import "GPUImageGaussianSelectiveBlurFilter.h"     //高斯模糊,选择部分清晰
#import "GPUImageBoxBlurFilter.h"                   //盒状模糊
#import "GPUImageTiltShiftFilter.h"                 //条纹模糊,中间清晰,上下两端模糊
#import "GPUImageMedianFilter.h"                    //中间值,有种稍微模糊边缘的效果
#import "GPUImageBilateralFilter.h"                 //双边模糊
#import "GPUImageErosionFilter.h"                   //侵蚀边缘模糊,变黑白
#import "GPUImageRGBErosionFilter.h"                //RGB侵蚀边缘模糊,有色彩
#import "GPUImageDilationFilter.h"                  //扩展边缘模糊,变黑白
#import "GPUImageRGBDilationFilter.h"               //RGB扩展边缘模糊,有色彩
#import "GPUImageOpeningFilter.h"                   //黑白色调模糊
#import "GPUImageRGBOpeningFilter.h"                //彩色模糊
#import "GPUImageClosingFilter.h"                   //黑白色调模糊,暗色会被提亮
#import "GPUImageRGBClosingFilter.h"                //彩色模糊,暗色会被提亮
#import "GPUImageLanczosResamplingFilter.h"         //Lanczos重取样,模糊效果
#import "GPUImageNonMaximumSuppressionFilter.h"     //非最大抑制,只显示亮度最高的像素,其他为黑
#import "GPUImageThresholdedNonMaximumSuppressionFilter.h" //与上相比,像素丢失更多

#import "GPUImageSobelEdgeDetectionFilter.h"        //Sobel边缘检测算法(白边,黑内容,有点漫画的反色效果)
#import "GPUImageCannyEdgeDetectionFilter.h"        //Canny边缘检测算法(比上更强烈的黑白对比度)
#import "GPUImageThresholdEdgeDetectionFilter.h"    //阈值边缘检测(效果与上差别不大)
#import "GPUImagePrewittEdgeDetectionFilter.h"      //普瑞维特(Prewitt)边缘检测(效果与Sobel差不多,貌似更平滑)
#import "GPUImageXYDerivativeFilter.h"              //XYDerivative边缘检测,画面以蓝色为主,绿色为边缘,带彩色
#import "GPUImageHarrisCornerDetectionFilter.h"     //Harris角点检测,会有绿色小十字显示在图片角点处
#import "GPUImageNobleCornerDetectionFilter.h"      //Noble角点检测,检测点更多
#import "GPUImageShiTomasiFeatureDetectionFilter.h" //ShiTomasi角点检测,与上差别不大
#import "GPUImageMotionDetector.h"                  //动作检测
#import "GPUImageHoughTransformLineDetector.h"      //线条检测
#import "GPUImageParallelCoordinateLineTransformFilter.h" //平行线检测

#import "GPUImageLocalBinaryPatternFilter.h"        //图像黑白化,并有大量噪点

#import "GPUImageLowPassFilter.h"                   //用于图像加亮
#import "GPUImageHighPassFilter.h"                  //图像低于某值时显示为黑


#pragma mark - 视觉效果 Visual Effect

#import "GPUImageSketchFilter.h"                    //素描
#import "GPUImageThresholdSketchFilter.h"           //阀值素描,形成有噪点的素描
#import "GPUImageToonFilter.h"                      //卡通效果(黑色粗线描边)
#import "GPUImageSmoothToonFilter.h"                //相比上面的效果更细腻,上面是粗旷的画风
#import "GPUImageKuwaharaFilter.h"                  //桑原(Kuwahara)滤波,水粉画的模糊效果;处理时间比较长,慎用

#import "GPUImageMosaicFilter.h"                    //黑白马赛克
#import "GPUImagePixellateFilter.h"                 //像素化
#import "GPUImagePolarPixellateFilter.h"            //同心圆像素化
#import "GPUImageCrosshatchFilter.h"                //交叉线阴影,形成黑白网状画面
#import "GPUImageColorPackingFilter.h"              //色彩丢失,模糊(类似监控摄像效果)

#import "GPUImageVignetteFilter.h"                  //晕影,形成黑色圆形边缘,突出中间图像的效果
#import "GPUImageSwirlFilter.h"                     //漩涡,中间形成卷曲的画面
#import "GPUImageBulgeDistortionFilter.h"           //凸起失真,鱼眼效果
#import "GPUImagePinchDistortionFilter.h"           //收缩失真,凹面镜
#import "GPUImageStretchDistortionFilter.h"         //伸展失真,哈哈镜
#import "GPUImageGlassSphereFilter.h"               //水晶球效果
#import "GPUImageSphereRefractionFilter.h"          //球形折射,图形倒立
    
#import "GPUImagePosterizeFilter.h"                 //色调分离,形成噪点效果
#import "GPUImageCGAColorspaceFilter.h"             //CGA色彩滤镜,形成黑、浅蓝、紫色块的画面
#import "GPUImagePerlinNoiseFilter.h"               //柏林噪点,花边噪点
#import "GPUImage3x3ConvolutionFilter.h"            //3x3卷积,高亮大色块变黑,加亮边缘、线条等
#import "GPUImageEmbossFilter.h"                    //浮雕效果,带有点3d的感觉
#import "GPUImagePolkaDotFilter.h"                  //像素圆点花样
#import "GPUImageHalftoneFilter.h"                  //点染,图像黑白化,由黑点构成原图的大致图形


#pragma mark - 混合模式 Blend

#import "GPUImageMultiplyBlendFilter.h"             //通常用于创建阴影和深度效果
#import "GPUImageNormalBlendFilter.h"               //正常
#import "GPUImageAlphaBlendFilter.h"                //透明混合,通常用于在背景上应用前景的透明度
#import "GPUImageDissolveBlendFilter.h"             //溶解
#import "GPUImageOverlayBlendFilter.h"              //叠加,通常用于创建阴影效果
#import "GPUImageDarkenBlendFilter.h"               //加深混合,通常用于重叠类型
#import "GPUImageLightenBlendFilter.h"              //减淡混合,通常用于重叠类型
#import "GPUImageSourceOverBlendFilter.h"           //源混合
#import "GPUImageColorBurnBlendFilter.h"            //色彩加深混合
#import "GPUImageColorDodgeBlendFilter.h"           //色彩减淡混合
#import "GPUImageScreenBlendFilter.h"               //屏幕包裹,通常用于创建亮点和镜头眩光
#import "GPUImageExclusionBlendFilter.h"            //排除混合
#import "GPUImageDifferenceBlendFilter.h"           //差异混合,通常用于创建更多变动的颜色
#import "GPUImageSubtractBlendFilter.h"             //差值混合,通常用于创建两个图像之间的动画变暗模糊效果
#import "GPUImageHardLightBlendFilter.h"            //强光混合,通常用于创建阴影效果
#import "GPUImageSoftLightBlendFilter.h"            //柔光混合
#import "GPUImageChromaKeyBlendFilter.h"            //色度键混合
#import "GPUImageMaskFilter.h"                      //遮罩混合
#import "GPUImageHazeFilter.h"                      //朦胧加暗
#import "GPUImageLuminanceThresholdFilter.h"        //亮度阈
#import "GPUImageAdaptiveThresholdFilter.h"         //自适应阈值
#import "GPUImageAddBlendFilter.h"                  //通常用于创建两个图像之间的动画变亮模糊效果
#import "GPUImageDivideBlendFilter.h"               //通常用于创建两个图像之间的动画变暗模糊效果


#pragma mark - 尚不清楚
#import "GPUImageJFAVoroniFilter.h"
#import "GPUImageVoroniConsumerFilter.h"

2.2、自定义滤镜效果

如果想自己自定义滤镜,那就需要自己写IOS的Shader(着色器)了,这个需要去百度下相关文章了,后面参考链接里面我会推荐几个文章,这些自定义滤镜的效果就是参考的那几个文章。这里说一个例子比如Nashville滤镜,暖色调。

对比图:

0A24C2ABECB9FF39F20889637E01B799.png72EA798B14A94E7C95D3F43AA1FAB2E4.png

首先先定义一个shader,TestFWFilter.h文件

#import "GPUImageTwoInputFilter.h"
#import "GPUImage.h"
@interface TestFWFilter : GPUImageTwoInputFilter
@end
@interface FWNashvilleFilter : GPUImageFilterGroup
{
    GPUImagePicture *imageSource ;
}
@end

TestFWFilter.m文件

#import "TestFWFilter.h"
//自定义shader
NSString *const kFWNashvilleShaderString = SHADER_STRING
(
 precision lowp float;
 
 varying highp vec2 textureCoordinate;
 
 uniform sampler2D inputImageTexture;
 uniform sampler2D inputImageTexture2;
 
 void main()
 {
     vec3 texel = texture2D(inputImageTexture, textureCoordinate).rgb;
     texel = vec3(
                  texture2D(inputImageTexture2, vec2(texel.r, .16666)).r,
                  texture2D(inputImageTexture2, vec2(texel.g, .5)).g,
                  texture2D(inputImageTexture2, vec2(texel.b, .83333)).b);
     gl_FragColor = vec4(texel, 1.0);
 }
 );

@implementation TestFWFilter
- (id)init;
{
    if (!(self = [super initWithFragmentShaderFromString:kFWNashvilleShaderString]))
    {
        return nil;
    }
    
    return self;
}
@end

@implementation FWNashvilleFilter

- (id)init
{
    if (!(self = [super init]))
    {
        return nil;
    }
    
    UIImage *image = [UIImage imageNamed:@"nashvilleMap.png"];
    
    imageSource = [[GPUImagePicture alloc] initWithImage:image];
    TestFWFilter *filter = [[TestFWFilter alloc] init];
    
    [self addFilter:filter];
    [imageSource addTarget:filter atTextureLocation:1];
    [imageSource processImage];
    
    self.initialFilters = [NSArray arrayWithObjects:filter, nil];
    self.terminalFilter = filter;
    
    return self;
}

@end

使用的时候按照第一段里面写的格式,只修改滤镜就可以看到效果了

-(void)moreUse{
    
    FWNashvilleFilter *disFilter = [[FWNashvilleFilter alloc] init];
    
    //设置要渲染的区域
    [disFilter forceProcessingAtSize:self.myImg.size];
    [disFilter useNextFrameForImageCapture];
    
    //获取数据源
    GPUImagePicture *stillImageSource = [[GPUImagePicture alloc]initWithImage:self.myImg];
    
    //添加上滤镜
    [stillImageSource addTarget:disFilter];
    //开始渲染
    [stillImageSource processImage];
    //获取渲染后的图片
    UIImage *newImage = [disFilter imageFromCurrentFramebuffer];
    
    //加载出来
    UIImageView *imageView = [[UIImageView alloc] initWithImage:newImage];
    imageView.frame = CGRectMake(50,50,self.myImg.size.width-200 ,self.myImg.size.height-200);
    [self.view addSubview:imageView];
}

注意,这个继承的是GPUImageTwoInputFilter是因为有两个合成图片,但不是每个都是两个的,还有GPUImageThreeInputFilter和GPUImageFourInputFilter,三个和四个等,所以看具体情况。

三、GPUImage对视频的使用

GPUImage还可以直接对视频加滤镜,shader可以直接使用图片的,使用方式稍微不同,比如这里使用图片的Amaro滤镜来拍摄视频

AA620E33996E4A209DC614C6B931FD4E.jpg

3.1、初始化视频相机

-(void)testVideo{
    self.videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack];
    self.videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
    

    //GPUImageFilter *customFilter = [[GPUImageFilter alloc] initWithFragmentShaderFromFile:@"CustomShader"];
    self.customFilter = [[AmomoFilter alloc] init];
    GPUImageView *filteredVideoView = [[GPUImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 300, 400)];

    // Add the view somewhere so it's visible
    [self.view addSubview:filteredVideoView];
    
    
    [self.videoCamera addTarget:self.customFilter];
    [self.customFilter addTarget:filteredVideoView];
    
    [self.videoCamera startCameraCapture];
}

3.2、开始录制视频

-(void)start{
    self.pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Movie4.mov"];
    unlink([self.pathToMovie UTF8String]); // 如果已经存在文件,AVAssetWriter会有异常,删除旧文件
    NSURL *movieURL = [NSURL fileURLWithPath:self.pathToMovie];
    NSLog(@"%@",movieURL);
    self.movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(480.0, 640.0)];
    self.movieWriter.encodingLiveVideo = YES;
    [self.customFilter addTarget:_movieWriter];
    _videoCamera.audioEncodingTarget = self.movieWriter;
    [self.movieWriter startRecording];
}

3.3、录制结束

-(void)end{
    [self.customFilter removeTarget:self.movieWriter];
    _videoCamera.audioEncodingTarget = nil;
    [self.movieWriter finishRecording];
}

3.4、播放录制过的视频

-(void)plays{
    NSURL *sourceMovieUrl = [NSURL fileURLWithPath:self.pathToMovie];
    NSLog(@"%@",sourceMovieUrl);
    NSLog(@"%@",[NSURL URLWithString:self.pathToMovie]);
    
    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:sourceMovieUrl];
    //或者下面这样创建playerItem
    //AVAsset *movieAsset = [AVURLAsset URLAssetWithURL:sourceMovieUrl options:nil];
    //AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:movieAsset];
    
    //通过playerItem创建AVPlayer
    self.playss = [AVPlayer playerWithPlayerItem:playerItem];
    //或者直接使用URL创建AVPlayer
    //self.playss = [AVPlayer playerWithURL:sourceMovieUrl];
    AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:self.playss];
    layer.frame = CGRectMake(0, 0, 400, 600);
    layer.videoGravity =AVLayerVideoGravityResizeAspect;
    [self.view.layer addSublayer:layer];
    [self.playss play];
}

顺便说下,这里使用AVPlayer来播放本地视频,可以通过playerItem创建,也可以使用playerWithURL直接创建,都可以,但是需要注意后面的URL连接需要正确,因为self.pathToMovie完整是

file:///var/mobile/Containers/Data/Application/932D7834-DD38-4CE0-922C-32D2548E74EB/Documents/Movie4.mov

所以如果直接使用[NSURL URLWithString:self.pathToMovie]的话,会导致url变成

/var/mobile/Containers/Data/Application/6272EE22-EF19-48E5-85BA-4A986B22AC39/Documents/Movie4.mov

这样的话是出不来的,需要用

[NSURL fileURLWithPath:self.pathToMovie]

这样创建才可以,这样的url就是file:///开头的,就是本地的了

四、Demo下载:

Github下载:https://github.com/DamonHu/HudongBlogDemo/tree/master/GPUImageDemo

五、参考文章:

Last modification:March 7th, 2021 at 09:18 pm
如果觉得我的文章对你有用,请随意打赏: ☞已打赏列表