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滤镜,暖色调。
对比图:
首先先定义一个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滤镜来拍摄视频
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
五、参考文章:
- iOS滤镜实现之Nashville【instagram】
- iOS滤镜实现之LOMO(美图秀秀经典LOMO)
- GPUImage的简单使用
- iOS二十种超酷时尚艺术滤镜汇总【附源码】
- GPUImage
- GPUImage详细解析(五)滤镜视频录制
- AVPlayer 播放在线视频和本地文件的设置区别
- iOS --- OpenGLES之着色器(shader)语法介绍
- [断言失败 - [GPUImageFilter initWithVertexShaderFromString:]](http://www.itstrike.cn/Question/3c3eb6af-f67b-4dff-be2c-574b1e3c6bf6.html)
版权属于:东哥笔记 - DongGe.org
本文链接:https://dongge.org/blog/395.html
自2017年12月26日起,『转载以及大段采集进行后续编辑』须注明本文标题和链接!否则禁止所有转载和采集行为!
6 条评论
就这还写成博客。。。。
是的,博客最基础就是在于自我内容的梳理,便于自己的回顾,我可以选择怎么写,你可以选择怎么看
如果调用摄像头开始拍摄的时候,第一帧会突然闪一下,可以在初始化相机的时候加上
[m_videoCamera addAudioInputsAndOutputs];
这个代码,比如我擦,第一帧闪一下的问题终于解决了,谢谢大神
很庆幸能帮到你,
如果是调用前置摄像头就发现成的像是左右相反了,就看下是不是开启了镜像
self.videoCamera.horizontallyMirrorFrontFacingCamera = YES;
self.videoCamera.horizontallyMirrorRearFacingCamera = NO;