当前位置: 首页>编程语言>正文

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

iOS图像灰度解决方案--架构设计,第1张
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哦!
还可以联系我。嘻嘻!


https://www.xamrdz.com/lan/5ja2016327.html

相关文章: