這是一個(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)系我。嘻嘻倘待!