iOS圖像灰度解決方案--架構(gòu)設(shè)計(jì)

ZUNL7OS33q.gif

這是一個(gè)類似于QQ頭像的處理方法,據(jù)我所知QQ也是用這種方式處理的七芭,當(dāng)然我們有兩種方案可以選擇

第一種方案

  • 使用第三方工具 ---OpenCV(官網(wǎng)內(nèi)可下載包文件)

OpenCV 它是可以運(yùn)行在Linux颊乘、Windows、Android和Mac OS操作系統(tǒng)上,輕量級(jí)而且高效,由一系列 C 函數(shù)和少量 C++ 類構(gòu)成捧毛,同時(shí)提供了Python吼畏、Ruby、MATLAB等語言的接口懈万,實(shí)現(xiàn)了圖像處理和計(jì)算機(jī)視覺方面的很多通用算法拴清。包括了現(xiàn)在很多平臺(tái)使用的,人機(jī)互動(dòng),人臉識(shí)別,動(dòng)作識(shí)別,運(yùn)動(dòng)分析圖像分割等等一系列的圖像算法操作。

  • 閑言碎語不要講,直接上代碼
//第一步:導(dǎo)入OpenCV頭文件
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
//第二步:導(dǎo)入命名空間
using namespace cv;
@implementation ImageUtils
- (UIImage*)imageToGrayImage:(UIImage*)image{
    //image:表示源文件(原始圖片)
    //第一步:將iOS的UIimage轉(zhuǎn)成C++的圖片(數(shù)據(jù):矩陣)
    Mat mat_image_gray;
    UIImageToMat(image, mat_image_gray);

    //第二步:將C++的彩色圖片轉(zhuǎn)成灰度圖片
    //參數(shù)1:數(shù)據(jù)源(原圖片)
    //參數(shù)2:目標(biāo)數(shù)據(jù)(目標(biāo)圖片)
    //參數(shù)3:轉(zhuǎn)換類型(圖片格式)
    //COLOR_BGR2GRAY :將彩色圖片轉(zhuǎn)成灰度圖片
    Mat mat_image_dst;
    cvtColor(mat_image_gray, mat_image_dst, COLOR_BGR2GRAY);
    
    //第三步:轉(zhuǎn)回可顯示的圖片 灰度->可顯示圖片
    //普及:RGB(3個(gè)通道的顏色) ARGB(4個(gè)通道顏色,增加了1個(gè)透明度)
    cvtColor(mat_image_dst, mat_image_gray, COLOR_GRAY2BGR);
    
    //第四步將C++處理后的圖片轉(zhuǎn)成iOS可以識(shí)別的UIimage
    
    return MatToUIImage(mat_image_gray);
}

由于openCV是用C /C ++寫的,所以,需要導(dǎo)入命名空間,然后將Object-C的.m文件改成C++的.mm文件,這樣才能夠運(yùn)行C++的代碼

第二種方案

  • 使用系統(tǒng)底層API
  • 閑言碎語不要講,直接上代碼
//系統(tǒng)方法實(shí)現(xiàn)
- (UIImage*)systemImageToGrayImage:(UIImage*)image{
    int width = image.size.width;
    int height = image.size.height;
    //第一步:創(chuàng)建顏色空間(說白了就是 開辟一塊顏色內(nèi)存空間)
    //圖片灰度處理(創(chuàng)建灰度空間)
 
    CGColorSpaceRef colorRef = CGColorSpaceCreateDeviceGray();
    
    //第二步:顏色空間的上下文(保存圖像數(shù)據(jù)信息)
    //參數(shù)1:內(nèi)存大小(指向這塊內(nèi)存區(qū)域的地址)(內(nèi)存地址)
    //參數(shù)2:圖片寬
    //參數(shù)3:圖片高
    //參數(shù)4:像素位數(shù)(顏色空間,例如:32位像素格式和RGB顏色空間,8位)
    //參數(shù)5:圖片每一行占用的內(nèi)存比特?cái)?shù)
    //參數(shù)6:顏色空間
    //參數(shù)7:圖片是否包含A通道(ARGB通道)
CGContextRef context = CGBitmapContextCreate(nil, width, height, 8, 0, colorRef, kCGImageAlphaNone);
    
    //釋放內(nèi)存
    CGColorSpaceRelease(colorRef);
    if (context == nil) {
        return nil;
    }
    //第三步:渲染圖片(繪制圖片)
    //參數(shù)1:上下文
    //參數(shù)2:渲染區(qū)域
    //參數(shù)3:源文件(原圖片)(說白了現(xiàn)在是一個(gè)C/C++的內(nèi)存區(qū)域)
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage);
    
    //第四步:將繪制顏色空間轉(zhuǎn)成CGImage(轉(zhuǎn)成可識(shí)別圖片類型)
    CGImageRef grayImageRef = CGBitmapContextCreateImage(context);
    
    //第五步:將C/C++ 的圖片CGImage轉(zhuǎn)成面向?qū)ο蟮腢IImage(轉(zhuǎn)成iOS程序認(rèn)識(shí)的圖片類型)
    UIImage* dstImage = [UIImage imageWithCGImage:grayImageRef];
    
    //釋放內(nèi)存
    CGContextRelease(context);
    CGImageRelease(grayImageRef);
    return dstImage;
}

實(shí)現(xiàn)類似qq灰色頭像的樣式,我們就寫完了会通,是不是很6口予。

這就完事兒了?怎么可能涕侈!

接下來我來講解架構(gòu)設(shè)計(jì)--策略模式

什么是策略模式呢沪停?分析我們平時(shí)寫的代碼結(jié)構(gòu),通常寫法是不是將所有類似功能寫在一個(gè)類中(算法結(jié)構(gòu)類似)。現(xiàn)實(shí)中是不是碰到過,自己寫了一天的代碼木张,提交上去众辨,結(jié)果被人家給替換掉呢,有吧舷礼!我就遇到過鹃彻,當(dāng)時(shí)真想沖上去爆揍他一頓,哈哈妻献,還好我控制住了蛛株。
而策略模式呢是將我們的算法結(jié)構(gòu)進(jìn)行分離,一個(gè)類中存在相同的算法育拨,你可以單獨(dú)定義谨履,便于擴(kuò)展。
1)策略模式是一個(gè)比較容易理解和使用的設(shè)計(jì)模式熬丧,策略模式是對(duì)算法的封裝屉符,它把算法的責(zé)任和算法本身分割開,委派給不同的對(duì)象管理锹引。策略模式通常把一個(gè)系列的算法封裝到一系列的策略類里面矗钟,作為一個(gè)抽象策略類的子類。用一句話來說嫌变,就是“準(zhǔn)備一組算法吨艇,并將每一個(gè)算法封裝起來,使得它們可以互換”腾啥。

  • 閑言碎語不要講,直接上代碼

1.第一步:創(chuàng)建協(xié)議(面向協(xié)議編程)
我們依舊是使用上面的兩個(gè)算法,來介紹策略模式东涡。
我們創(chuàng)建一個(gè)名為strategy的protocol

#import <UIKit/UIKit.h>
//策略協(xié)議:面向協(xié)議編程
@protocol Strategy <NSObject>
//定義算法
- (UIImage*)imageToGrayImage:(UIImage*)image;
@end

2.第二步:創(chuàng)建兩個(gè)類

#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實(shí)現(xiàn)文件里

//系統(tǒng)方法實(shí)現(xiàn)
- (UIImage*)imageToGrayImage:(UIImage*)image{
    int width = image.size.width;
    int height = image.size.height;
    //第一步:創(chuàng)建顏色空間(說白了就是 開辟一塊顏色內(nèi)存空間)
    //圖片灰度處理(創(chuàng)建灰度空間)
    
    CGColorSpaceRef colorRef = CGColorSpaceCreateDeviceGray();
    
    //第二步:顏色空間的上下文(保存圖像數(shù)據(jù)信息)
    //參數(shù)1:內(nèi)存大小(指向這塊內(nèi)存區(qū)域的地址)(內(nèi)存地址)
    //參數(shù)2:圖片寬
    //參數(shù)3:圖片高
    //參數(shù)4:像素位數(shù)(顏色空間,例如:32位像素格式和RGB顏色空間,8位)
    //參數(shù)5:圖片每一行占用的內(nèi)存比特?cái)?shù)
    //參數(shù)6:顏色空間
    //參數(shù)7:圖片是否包含A通道(ARGB通道)
    CGContextRef context = CGBitmapContextCreate(nil, width, height, 8, 0, colorRef, kCGImageAlphaNone);
    
    //釋放內(nèi)存
    CGColorSpaceRelease(colorRef);
    if (context == nil) {
        return nil;
    }
    //第三步:渲染圖片(繪制圖片)
    //參數(shù)1:上下文
    //參數(shù)2:渲染區(qū)域
    //參數(shù)3:源文件(原圖片)(說白了現(xiàn)在是一個(gè)C/C++的內(nèi)存區(qū)域)
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage);
    
    //第四步:將繪制顏色空間轉(zhuǎn)成CGImage(轉(zhuǎn)成可識(shí)別圖片類型)
    CGImageRef grayImageRef = CGBitmapContextCreateImage(context);
    
    //第五步:將C/C++ 的圖片CGImage轉(zhuǎn)成面向?qū)ο蟮腢IImage(轉(zhuǎn)成iOS程序認(rèn)識(shí)的圖片類型)
    UIImage* dstImage = [UIImage imageWithCGImage:grayImageRef];
    
    //釋放內(nèi)存
    CGContextRelease(context);
    CGImageRelease(grayImageRef);
    return dstImage;
    
    return nil;
}
@end
#import "OpencvStrategy.h"
//第一步:導(dǎo)入OpenCV頭文件
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
//第二步:導(dǎo)入命名空間
using namespace cv;
@implementation OpencvStrategy
- (UIImage*)imageToGrayImage:(UIImage*)image{
    //image:表示源文件(原始圖片)
    //第一步:將iOS的UIimage轉(zhuǎn)成C++的圖片(數(shù)據(jù):矩陣)
    Mat mat_image_gray;
    UIImageToMat(image, mat_image_gray);
    
    //第二步:將C++的彩色圖片轉(zhuǎn)成灰度圖片
    //參數(shù)1:數(shù)據(jù)源(原圖片)
    //參數(shù)2:目標(biāo)數(shù)據(jù)(目標(biāo)圖片)
    //參數(shù)3:轉(zhuǎn)換類型(圖片格式)
    //COLOR_BGR2GRAY :將彩色圖片轉(zhuǎn)成灰度圖片
    Mat mat_image_dst;
    cvtColor(mat_image_gray, mat_image_dst, COLOR_BGR2GRAY);
    
    //第三步:轉(zhuǎn)回可顯示的圖片 灰度->可顯示圖片
    //普及:RGB(3個(gè)通道的顏色) ARGB(4個(gè)通道顏色,增加了1個(gè)透明度)
    cvtColor(mat_image_dst, mat_image_gray, COLOR_GRAY2BGR);
    
    //第四步將C++處理后的圖片轉(zhuǎn)成iOS可以識(shí)別的UIimage
    
    return MatToUIImage(mat_image_gray);
}
@end

3.第三步:創(chuàng)建兩個(gè)類
然后我們?cè)赩iewcontroller里面調(diào)用

#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];//系統(tǒng)方法協(xié)議
//    _utils = [[OpencvStrategy alloc]init];//OpenCV方法

}
//灰度
- (IBAction)clickImageGray:(UIButton *)sender {
    //三個(gè)顏色值相同就是灰色
    //底層算法就是通過動(dòng)態(tài)修改顏色OpenCV和系統(tǒng)自帶的API底層算法是相同的
   _imageView.image =  [_utils imageToGrayImage:_imageView.image];
}

這樣我們就大功告成了!面向協(xié)議編程協(xié)議模式,完美實(shí)現(xiàn),如果有不懂得地方,這里有demo別忘記點(diǎn)Star哦!
還可以聯(lián)系我。嘻嘻倘待!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疮跑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凸舵,更是在濱河造成了極大的恐慌祖娘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啊奄,死亡現(xiàn)場(chǎng)離奇詭異渐苏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)菇夸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門琼富,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人庄新,你說我怎么就攤上這事鞠眉∈硎螅” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵械蹋,是天一觀的道長出皇。 經(jīng)常有香客問我,道長朝蜘,這世上最難降的妖魔是什么恶迈? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮谱醇,結(jié)果婚禮上暇仲,老公的妹妹穿的比我還像新娘。我一直安慰自己副渴,他們只是感情好奈附,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著煮剧,像睡著了一般斥滤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勉盅,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天佑颇,我揣著相機(jī)與錄音,去河邊找鬼草娜。 笑死挑胸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宰闰。 我是一名探鬼主播茬贵,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼移袍!你這毒婦竟也來了解藻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤葡盗,失蹤者是張志新(化名)和其女友劉穎螟左,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戳粒,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡路狮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蔚约。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡涂籽,死狀恐怖苹祟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤树枫,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布直焙,位于F島的核電站,受9級(jí)特大地震影響砂轻,放射性物質(zhì)發(fā)生泄漏奔誓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一搔涝、第九天 我趴在偏房一處隱蔽的房頂上張望厨喂。 院中可真熱鬧,春花似錦庄呈、人聲如沸蜕煌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽斜纪。三九已至,卻和暖如春文兑,著一層夾襖步出監(jiān)牢的瞬間盒刚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工绿贞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留因块,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓樟蠕,卻偏偏與公主長得像贮聂,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子寨辩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • --繪圖與濾鏡全面解析 概述 在iOS中可以很容易的開發(fā)出絢麗的界面效果吓懈,一方面得益于成功系統(tǒng)的設(shè)計(jì),另一方面得益...
    韓七夏閱讀 2,710評(píng)論 2 10
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,125評(píng)論 29 470
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫靡狞、插件耻警、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,024評(píng)論 4 62
  • 有時(shí)候開發(fā)過程中,切圖滿足不了我們的需求甸怕,此時(shí)我們需要對(duì)圖像進(jìn)行灰度處理甘穿,例如QQ頭像在線、離線等不同狀態(tài)等梢杭。 常...
    Justin_W閱讀 608評(píng)論 0 0
  • 中秋節(jié) 是一家團(tuán)聚的日子 為了能有更好的生活温兼,出攤是我現(xiàn)在都必經(jīng)之路,雖然生意不是很好武契,堅(jiān)持出攤賣不掉的東西該丟的...
    學(xué)無止境的默默閱讀 196評(píng)論 0 0