iOS图像灰度解决方案--架构设计

ZUNL7OS33q.gif

这是一个类似于QQ头像的处理方法,据我所知QQ也是用这种方式处理的,当然我们有两种方案可以选择

第一种方案

  • 使用第三方工具 ---OpenCV(官网内可下载包文件)

OpenCV 它是可以运行在Linux、Windows、Android和Mac OS操作系统上,轻量级而且高效,由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。包括了现在很多平台使用的,人机互动,人脸识别,动作识别,运动分析图像分割等等一系列的图像算法操作。

  • 闲言碎语不要讲,直接上代码
//第一步:导入OpenCV头文件
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
//第二步:导入命名空间
using namespace cv;
@implementation ImageUtils
- (UIImage*)imageToGrayImage:(UIImage*)image{
    //image:表示源文件(原始图片)
    //第一步:将iOS的UIimage转成C++的图片(数据:矩阵)
    Mat mat_image_gray;
    UIImageToMat(image, mat_image_gray);

    //第二步:将C++的彩色图片转成灰度图片
    //参数1:数据源(原图片)
    //参数2:目标数据(目标图片)
    //参数3:转换类型(图片格式)
    //COLOR_BGR2GRAY :将彩色图片转成灰度图片
    Mat mat_image_dst;
    cvtColor(mat_image_gray, mat_image_dst, COLOR_BGR2GRAY);
    
    //第三步:转回可显示的图片 灰度->可显示图片
    //普及:RGB(3个通道的颜色) ARGB(4个通道颜色,增加了1个透明度)
    cvtColor(mat_image_dst, mat_image_gray, COLOR_GRAY2BGR);
    
    //第四步将C++处理后的图片转成iOS可以识别的UIimage
    
    return MatToUIImage(mat_image_gray);
}

由于openCV是用C /C ++写的,所以,需要导入命名空间,然后将Object-C的.m文件改成C++的.mm文件,这样才能够运行C++的代码

第二种方案

  • 使用系统底层API
  • 闲言碎语不要讲,直接上代码
//系统方法实现
- (UIImage*)systemImageToGrayImage:(UIImage*)image{
    int width = image.size.width;
    int height = image.size.height;
    //第一步:创建颜色空间(说白了就是 开辟一块颜色内存空间)
    //图片灰度处理(创建灰度空间)
 
    CGColorSpaceRef colorRef = CGColorSpaceCreateDeviceGray();
    
    //第二步:颜色空间的上下文(保存图像数据信息)
    //参数1:内存大小(指向这块内存区域的地址)(内存地址)
    //参数2:图片宽
    //参数3:图片高
    //参数4:像素位数(颜色空间,例如:32位像素格式和RGB颜色空间,8位)
    //参数5:图片每一行占用的内存比特数
    //参数6:颜色空间
    //参数7:图片是否包含A通道(ARGB通道)
CGContextRef context = CGBitmapContextCreate(nil, width, height, 8, 0, colorRef, kCGImageAlphaNone);
    
    //释放内存
    CGColorSpaceRelease(colorRef);
    if (context == nil) {
        return nil;
    }
    //第三步:渲染图片(绘制图片)
    //参数1:上下文
    //参数2:渲染区域
    //参数3:源文件(原图片)(说白了现在是一个C/C++的内存区域)
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage);
    
    //第四步:将绘制颜色空间转成CGImage(转成可识别图片类型)
    CGImageRef grayImageRef = CGBitmapContextCreateImage(context);
    
    //第五步:将C/C++ 的图片CGImage转成面向对象的UIImage(转成iOS程序认识的图片类型)
    UIImage* dstImage = [UIImage imageWithCGImage:grayImageRef];
    
    //释放内存
    CGContextRelease(context);
    CGImageRelease(grayImageRef);
    return dstImage;
}

实现类似qq灰色头像的样式,我们就写完了,是不是很6。

这就完事儿了?怎么可能!

接下来我来讲解架构设计--策略模式

什么是策略模式呢?分析我们平时写的代码结构,通常写法是不是将所有类似功能写在一个类中(算法结构类似)。现实中是不是碰到过,自己写了一天的代码,提交上去,结果被人家给替换掉呢,有吧!我就遇到过,当时真想冲上去爆揍他一顿,哈哈,还好我控制住了。
而策略模式呢是将我们的算法结构进行分离,一个类中存在相同的算法,你可以单独定义,便于扩展。
1)策略模式是一个比较容易理解和使用的设计模式,策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。

  • 闲言碎语不要讲,直接上代码

1.第一步:创建协议(面向协议编程)
我们依旧是使用上面的两个算法,来介绍策略模式。
我们创建一个名为strategy的protocol

#import <UIKit/UIKit.h>
//策略协议:面向协议编程
@protocol Strategy <NSObject>
//定义算法
- (UIImage*)imageToGrayImage:(UIImage*)image;
@end

2.第二步:创建两个类

#import <Foundation/Foundation.h>
#import "Strategy.h"
@interface systemStrategy : NSObject <Strategy>
@end
#import <Foundation/Foundation.h>
#import "Strategy.h"
@interface OpencvStrategy : NSObject<Strategy>
@end

将之前的代码放到.m实现文件里

//系统方法实现
- (UIImage*)imageToGrayImage:(UIImage*)image{
    int width = image.size.width;
    int height = image.size.height;
    //第一步:创建颜色空间(说白了就是 开辟一块颜色内存空间)
    //图片灰度处理(创建灰度空间)
    
    CGColorSpaceRef colorRef = CGColorSpaceCreateDeviceGray();
    
    //第二步:颜色空间的上下文(保存图像数据信息)
    //参数1:内存大小(指向这块内存区域的地址)(内存地址)
    //参数2:图片宽
    //参数3:图片高
    //参数4:像素位数(颜色空间,例如:32位像素格式和RGB颜色空间,8位)
    //参数5:图片每一行占用的内存比特数
    //参数6:颜色空间
    //参数7:图片是否包含A通道(ARGB通道)
    CGContextRef context = CGBitmapContextCreate(nil, width, height, 8, 0, colorRef, kCGImageAlphaNone);
    
    //释放内存
    CGColorSpaceRelease(colorRef);
    if (context == nil) {
        return nil;
    }
    //第三步:渲染图片(绘制图片)
    //参数1:上下文
    //参数2:渲染区域
    //参数3:源文件(原图片)(说白了现在是一个C/C++的内存区域)
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage);
    
    //第四步:将绘制颜色空间转成CGImage(转成可识别图片类型)
    CGImageRef grayImageRef = CGBitmapContextCreateImage(context);
    
    //第五步:将C/C++ 的图片CGImage转成面向对象的UIImage(转成iOS程序认识的图片类型)
    UIImage* dstImage = [UIImage imageWithCGImage:grayImageRef];
    
    //释放内存
    CGContextRelease(context);
    CGImageRelease(grayImageRef);
    return dstImage;
    
    return nil;
}
@end
#import "OpencvStrategy.h"
//第一步:导入OpenCV头文件
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
//第二步:导入命名空间
using namespace cv;
@implementation OpencvStrategy
- (UIImage*)imageToGrayImage:(UIImage*)image{
    //image:表示源文件(原始图片)
    //第一步:将iOS的UIimage转成C++的图片(数据:矩阵)
    Mat mat_image_gray;
    UIImageToMat(image, mat_image_gray);
    
    //第二步:将C++的彩色图片转成灰度图片
    //参数1:数据源(原图片)
    //参数2:目标数据(目标图片)
    //参数3:转换类型(图片格式)
    //COLOR_BGR2GRAY :将彩色图片转成灰度图片
    Mat mat_image_dst;
    cvtColor(mat_image_gray, mat_image_dst, COLOR_BGR2GRAY);
    
    //第三步:转回可显示的图片 灰度->可显示图片
    //普及:RGB(3个通道的颜色) ARGB(4个通道颜色,增加了1个透明度)
    cvtColor(mat_image_dst, mat_image_gray, COLOR_GRAY2BGR);
    
    //第四步将C++处理后的图片转成iOS可以识别的UIimage
    
    return MatToUIImage(mat_image_gray);
}
@end

3.第三步:创建两个类
然后我们在Viewcontroller里面调用

#import "ViewController.h"
#import "systemStrategy.h"
#import "OpencvStrategy.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (nonatomic) id<Strategy> utils;
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _utils1 = [[ImageUtils alloc]init];

    _utils = [[systemStrategy alloc]init];//系统方法协议
//    _utils = [[OpencvStrategy alloc]init];//OpenCV方法

}
//灰度
- (IBAction)clickImageGray:(UIButton *)sender {
    //三个颜色值相同就是灰色
    //底层算法就是通过动态修改颜色OpenCV和系统自带的API底层算法是相同的
   _imageView.image =  [_utils imageToGrayImage:_imageView.image];
}

这样我们就大功告成了!面向协议编程协议模式,完美实现,如果有不懂得地方,这里有demo别忘记点Star哦!
还可以联系我。嘻嘻!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • --绘图与滤镜全面解析 概述 在iOS中可以很容易的开发出绚丽的界面效果,一方面得益于成功系统的设计,另一方面得益...
    韩七夏阅读 2,710评论 2 10
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,124评论 29 470
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,022评论 4 62
  • 有时候开发过程中,切图满足不了我们的需求,此时我们需要对图像进行灰度处理,例如QQ头像在线、离线等不同状态等。 常...
    Justin_W阅读 608评论 0 0
  • 中秋节 是一家团聚的日子 为了能有更好的生活,出摊是我现在都必经之路,虽然生意不是很好,坚持出摊卖不掉的东西该丢的...
    学无止境的默默阅读 196评论 0 0