iOS 基于ColorMatrix制作简单滤镜
来源:互联网 发布:婚礼发布网站源码java 编辑:程序博客网 时间:2024/06/05 00:08
Demo链接:https://github.com/MrCoderDing/ImageFilterByColorMatrix
说到滤镜一般比较熟悉的是CIFilter、GPUImage、vImage API还有一种比较简单的滤镜ColorMatrix。
之前在项目中一个小功能要加滤镜,需求是要够用,方便。在没有考虑直接用第三方滤镜的情况下,最后还是选择使用ColorMatrix来完成任务。并且这个方案安卓和iOS通用,如果花时间做一套颜色矩阵,成本将降低很多。
1、颜色矩阵
lomo和黑白我做了细微调整,会稍微舒服一些:
const float colormatrix_lomo[] = {// 1.7f, 0.1f, 0.1f, 0, -73.1f,// 0, 1.7f, 0.1f, 0, -73.1f,// 0, 0.1f, 1.6f, 0, -73.1f,// 0, 0, 0, 1.0f, 0 1.20, 0.10, 0.10, 0.00, -73.10, 0.00, 1.20, 0.10, 0.00, -73.10, 0.00, 0.10, 1.10, 0.00, -73.10, 0.00, 0.00, 0.00, 0.00, 0.00};// 2、黑白const float colormatrix_heibai[] = {// 0.8f, 1.6f, 0.2f, 0, -163.9f,// 0.8f, 1.6f, 0.2f, 0, -163.9f,// 0.8f, 1.6f, 0.2f, 0, -163.9f,// 0, 0, 0, 1.0f, 0 0.00, 0.00, 1.00, 0.00, -1, 0.00, 0.00, 1.00, 0.00, -1, 0.00, 0.00, 1.00, 0.00, -1, 0.00, 0.00, 0.00, 1.00, 0.00};// 3、复古const float colormatrix_huajiu[] = { 0.2f,0.5f, 0.1f, 0, 40.8f, 0.2f, 0.5f, 0.1f, 0, 40.8f, 0.2f,0.5f, 0.1f, 0, 40.8f, 0, 0, 0, 1, 0 };// 4、哥特const float colormatrix_gete[] = { 1.9f,-0.3f, -0.2f, 0,-87.0f, -0.2f, 1.7f, -0.1f, 0, -87.0f, -0.1f,-0.6f, 2.0f, 0, -87.0f, 0, 0, 0, 1.0f, 0 };// 5、锐化const float colormatrix_ruise[] = { 4.8f,-1.0f, -0.1f, 0,-388.4f, -0.5f,4.4f, -0.1f, 0,-388.4f, -0.5f,-1.0f, 5.2f, 0,-388.4f, 0, 0, 0, 1.0f, 0 };// 6、淡雅const float colormatrix_danya[] = { 0.6f,0.3f, 0.1f, 0,73.3f, 0.2f,0.7f, 0.1f, 0,73.3f, 0.2f,0.3f, 0.4f, 0,73.3f, 0, 0, 0, 1.0f, 0 };// 7、酒红const float colormatrix_jiuhong[] = { 1.2f,0.0f, 0.0f, 0.0f,0.0f, 0.0f,0.9f, 0.0f, 0.0f,0.0f, 0.0f,0.0f, 0.8f, 0.0f,0.0f, 0, 0, 0, 1.0f, 0 };// 8、清宁const float colormatrix_qingning[] = { 0.9f, 0, 0, 0, 0, 0, 1.1f,0, 0, 0, 0, 0, 0.9f, 0, 0, 0, 0, 0, 1.0f, 0 };// 9、浪漫const float colormatrix_langman[] = { 0.9f, 0, 0, 0, 63.0f, 0, 0.9f,0, 0, 63.0f, 0, 0, 0.9f, 0, 63.0f, 0, 0, 0, 1.0f, 0 };// 10、光晕const float colormatrix_guangyun[] = { 0.9f, 0, 0, 0, 64.9f, 0, 0.9f,0, 0, 64.9f, 0, 0, 0.9f, 0, 64.9f, 0, 0, 0, 1.0f, 0 };// 11、蓝调const float colormatrix_landiao[] = { 2.1f, -1.4f, 0.6f, 0.0f, -31.0f, -0.3f, 2.0f, -0.3f, 0.0f, -31.0f, -1.1f, -0.2f, 2.6f, 0.0f, -31.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};// 12、梦幻const float colormatrix_menghuan[] = { 0.8f, 0.3f, 0.1f, 0.0f, 46.5f, 0.1f, 0.9f, 0.0f, 0.0f, 46.5f, 0.1f, 0.3f, 0.7f, 0.0f, 46.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};// 13、夜色const float colormatrix_yese[] = { 1.0f, 0.0f, 0.0f, 0.0f, -66.6f, 0.0f, 1.1f, 0.0f, 0.0f, -66.6f, 0.0f, 0.0f, 1.0f, 0.0f, -66.6f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
矩阵及代表每一种滤镜。
2、滤镜处理Image对象
/** 获取滤镜图 @param inImage 原图 @param f matrix矩阵 @return 滤镜完成后图片 */+ (UIImage*)imageWithImage:(UIImage*)inImage withColorMatrix:(const float*) f;
实现:
+ (UIImage*)imageWithImage:(UIImage*)inImage withColorMatrix:(const float*) f{ CGImageRef img = [inImage CGImage]; CGSize size = [inImage size]; CGContextRef context = NULL; CGColorSpaceRef colorSpace; void *bitmapData; //内存空间的指针,该内存空间的大小等于图像使用RGB通道所占用的字节数。 unsigned long bitmapByteCount; unsigned long bitmapBytesPerRow; size_t pixelsWide = CGImageGetWidth(img); //获取横向的像素点的个数 size_t pixelsHigh = CGImageGetHeight(img); //纵向 bitmapBytesPerRow = (pixelsWide * 4); //每一行的像素点占用的字节数,每个像素点的ARGB四个通道各占8个bit(0-255)的空间 bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); //计算整张图占用的字节数 colorSpace = CGColorSpaceCreateDeviceRGB();//创建依赖于设备的RGB通道 bitmapData = malloc(bitmapByteCount); //分配足够容纳图片字节数的内存空间 context = CGBitmapContextCreate (bitmapData, pixelsWide, pixelsHigh, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); //创建CoreGraphic的图形上下文,该上下文描述了bitmaData指向的内存空间需要绘制的图像的一些绘制参数 CGColorSpaceRelease( colorSpace ); CGRect rect = {{0,0},{size.width, size.height}}; //使用上面的函数创建上下文 CGContextDrawImage(context, rect, img); //将目标图像绘制到指定的上下文,实际为上下文内的bitmapData。 unsigned char *data = CGBitmapContextGetData (context); CGContextRelease(context); //释放上面的函数创建的上下文 unsigned char *imgPixel = data; int wOff = 0; int pixOff = 0; for(GLuint y = 0;y< pixelsHigh;y++)//双层循环按照长宽的像素个数迭代每个像素点 { pixOff = wOff; for (GLuint x = 0; x<pixelsWide; x++) { int red = (unsigned char)imgPixel[pixOff]; int green = (unsigned char)imgPixel[pixOff+1]; int blue = (unsigned char)imgPixel[pixOff+2]; int alpha = (unsigned char)imgPixel[pixOff+3]; changeRGBA(&red, &green, &blue, &alpha, f); //回写数据 imgPixel[pixOff] = red; imgPixel[pixOff+1] = green; imgPixel[pixOff+2] = blue; imgPixel[pixOff+3] = alpha; pixOff += 4; //将数组的索引指向下四个元素 } wOff += pixelsWide * 4; } NSInteger dataLength = pixelsWide * pixelsHigh * 4; //下面的代码创建要输出的图像的相关参数 CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, imgPixel, dataLength, NULL); int bitsPerComponent = 8; int bitsPerPixel = 32; unsigned long bytesPerRow = 4 * pixelsWide; CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; CGImageRef imageRef = CGImageCreate(pixelsWide, pixelsHigh, bitsPerComponent, bitsPerPixel, bytesPerRow,colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);//创建要输出的图像 UIImage *myImage = [UIImage imageWithCGImage:imageRef]; CFRelease(imageRef); CGColorSpaceRelease(colorSpaceRef); CGDataProviderRelease(provider); NSData *imageData = UIImageJPEGRepresentation(myImage, 0.5); free(bitmapData); return [UIImage imageWithData:imageData];}
注意:参考网上几个实现的方法中,基本都有一个问题没有被注意到,就是bitmapData在申请地址后,最终产出UIImage对象后没有释放掉,导致选择滤镜的过程中内存不断增长。
综合上面的方法就可以自己做滤镜了。简单封装了一个滤镜选择器(即下方的选择条):
/** 滤镜工具 @param originalImage 原始图片 @param frame 滤镜工具条 @return 滤镜工具条对象 */+ (instancetype)filterViewWithImage:(UIImage *)originalImage andFrame:(CGRect)frame;
滤镜选择后代理方法:
//滤镜选择后- (void)imageFilterDidChangeWithAfterImage:(UIImage *)afterImage;
用colormatrix处理图片会阻塞线程,所以把图片处理都放到异步来做,回到主线程改变图片,例如代理的回调:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ UIImage *img = [self changeImage:num image:_originalImage]; dispatch_async(dispatch_get_main_queue(), ^{ [self.delegate imageFilterDidChangeWithAfterImage: img]; }); });
阅读全文
0 0
- iOS 基于ColorMatrix制作简单滤镜
- iOS滤镜简单demo
- ios 简单滤镜效果
- iOS 简单滤镜
- IOS之简单滤镜详解
- iOS实时滤镜实现--基于GPUImage。
- ColorMatrix(颜色滤镜)介绍和使用
- 史上最全的Android 图片滤镜 colorMatrix自定义任意图片滤镜
- 史上最全的Android 图片滤镜 colorMatrix自定义任意图片滤镜
- iOS 5 取景器和实时滤镜的制作
- iOS 5 取景器和实时滤镜的制作
- ios 滤镜
- ios 滤镜
- iOS滤镜
- iOS-滤镜
- IOS滤镜
- ios滤镜
- iOS-滤镜
- 【Web前端】使用 class 与 extends 实现继承
- 二叉查找树(Binary Search Tree)
- HDU1054Strategic Game(最小顶点覆盖数)
- 用Elasticsearch做检索
- iOS开发 程序上线发布时遇到的报错:
- iOS 基于ColorMatrix制作简单滤镜
- react+react-router+redux开发体育馆管理系统(3)--场地类型管理模块开发
- abp菜单权限配置
- 关于 USB 3.1 、USB Type-C 你需要知道的几点
- Appium+Genymotion+robotframework+python系列三:一个简单的Android自动化用例
- git 使用
- maven lib文件夹引用 但是项目报错的解决办法
- Python开发(二)封装批量插入
- 【剑指offer】面试题13:机器人的运动范围