iOS实现二维码的彩色效果

时间:2022-11-17 07:39:44

今天做项目基本是完成了,测试也进入尾声,同事给我说要我把二维码变成彩色的,我对着原来前辈写的工程研究来研究去,找了很多资料还是没弄好,还是一直失败,于是找了一下我同学,问了一下他,结果他上班没时间帮我看,但是却帮我开了脑洞,我突然发现自己太死板了,死磕在原来代码上,其实到github上搜一搜有很多写好的代码供我使用,但是我没有想到,工作是讲究效率的,学习可以死磕,但是工作上一定要头脑灵活,学会使用八方资源,把自己的工作效率大大提高,受教。


把今天使用的二维码生成与大家分享。Demo地址:点击打开链接

QRCodeImage.h

#import <UIKit/UIKit.h>

@interface QRCodeImage : UIImage

/**
* 1.生成一个二维码
*
* @param string 字符串
* @param width 二维码宽度
*
* @return <#return value description#>
*/
+ (QRCodeImage *_Nonnull)codeImageWithString:(NSString *_Nullable)string
size:(CGFloat)width;

/**
* 2.生成一个二维码
*
* @param string 字符串
* @param width 二维码宽度
* @param color 二维码颜色
*
* @return <#return value description#>
*/
+ (QRCodeImage *_Nonnull)codeImageWithString:(NSString *_Nullable)string
size:(CGFloat)width
color:(UIColor *_Nullable)color;
/**
* 3.生成一个二维码
*
* @param string 字符串
* @param width 二维码宽度
* @param color 二维码颜色
* @param icon 头像
* @param iconWidth 头像宽度,建议宽度小于二维码宽度的1/4
*
* @return <#return value description#>
*/
+ (QRCodeImage *_Nonnull)codeImageWithString:(NSString *_Nullable)string
size:(CGFloat)width
color:(UIColor *_Nullable)color
icon:(UIImage *_Nullable)icon
iconWidth:(CGFloat)iconWidth;

@end

QRCodeImage.m

#import "QRCodeImage.h"



@implementation QRCodeImage

+ (QRCodeImage *)codeImageWithString:(NSString *)string
size:(CGFloat)width
{
CIImage *ciImage = [QRCodeImage createQRForString:string];
if (ciImage) {
return [QRCodeImage createNonInterpolatedUIImageFormCIImage:ciImage
size:width];
} else {
return nil;
}
}

+ (QRCodeImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image
size:(CGFloat)size {

CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size/CGRectGetWidth(extent),
size/CGRectGetHeight(extent));
// 1.创建一个位图图像,绘制到其大小的位图上下文
size_t width = CGRectGetWidth(extent) * scale;
size_t height = CGRectGetHeight(extent) * scale;
CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
CGContextRef bitmapRef = CGBitmapContextCreate(nil,
width,
height,
8,
0,
cs,
(CGBitmapInfo)kCGImageAlphaNone);
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
CGContextScaleCTM(bitmapRef, scale, scale);
CGContextDrawImage(bitmapRef, extent, bitmapImage);
// 2.创建具有内容的位图图像
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
// 3.清理
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
return (QRCodeImage*)[UIImage imageWithCGImage:scaledImage];
}

+ (CIImage *)createQRForString:(NSString *)qrString {
// 1.将字符串转换为UTF8编码的NSData对象
NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding];
// 2.创建filter
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
// 3.设置内容和纠错级别
[qrFilter setValue:stringData forKey:@"inputMessage"];
[qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];
// 4.返回CIImage
return qrFilter.outputImage;
}


void ProviderReleaseData (void *info, const void *data, size_t size){
free((void*)data);
}

+ (QRCodeImage *_Nonnull)codeImageWithString:(NSString *_Nullable)string
size:(CGFloat)width
color:(UIColor *_Nullable)color;
{


QRCodeImage *image = [QRCodeImage codeImageWithString:string size:width];

const CGFloat *components = CGColorGetComponents(color.CGColor);
CGFloat red = components[0]*255;
CGFloat green = components[1]*255;
CGFloat blue = components[2]*255;

const int imageWidth = image.size.width;
const int imageHeight = image.size.height;
size_t bytesPerRow = imageWidth * 4;
uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);

// 1.创建上下文
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(rgbImageBuf,
imageWidth,
imageHeight,
8,
bytesPerRow,
colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);

// 2.像素转换
int pixelNum = imageWidth * imageHeight;
uint32_t* pCurPtr = rgbImageBuf;
for (int i = 0; i < pixelNum; i++, pCurPtr++){
if ((*pCurPtr & 0xFFFFFF00) < 0x99999900){
uint8_t* ptr = (uint8_t*)pCurPtr;
ptr[3] = red; //0~255
ptr[2] = green;
ptr[1] = blue;
}else{
uint8_t* ptr = (uint8_t*)pCurPtr;
ptr[0] = 0;
}
}

// 3.生成UIImage
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL,
rgbImageBuf,
bytesPerRow * imageHeight,
ProviderReleaseData);
CGImageRef imageRef = CGImageCreate(imageWidth,
imageHeight,
8,
32,
bytesPerRow,
colorSpace,
kCGImageAlphaLast | kCGBitmapByteOrder32Little,
dataProvider,
NULL,
true,
kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);
QRCodeImage* resultUIImage = (QRCodeImage*)[UIImage imageWithCGImage:imageRef];

// 4.释放
CGImageRelease(imageRef);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);

return resultUIImage;
}

+ (QRCodeImage *_Nonnull)codeImageWithString:(NSString *_Nullable)string
size:(CGFloat)width
color:(UIColor *_Nullable)color
icon:(UIImage *_Nullable)icon
iconWidth:(CGFloat)iconWidth
{
QRCodeImage *bgImage = [QRCodeImage codeImageWithString:string
size:width
color:color];
UIGraphicsBeginImageContext(bgImage.size);
[bgImage drawInRect:CGRectMake(0, 0, bgImage.size.width, bgImage.size.height)];

CGFloat x = (bgImage.size.width - iconWidth) * 0.5;
CGFloat y = (bgImage.size.height - iconWidth) * 0.5;
[icon drawInRect:CGRectMake( x, y, iconWidth, iconWidth)];

UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return (QRCodeImage *)newImage;
}


@end

使用方法

QRCodeImage *qrCodeImage = [QRCodeImage codeImageWithString:@"https://github.com/EmyWong/PersonalUITech"
size:200
color:[UIColor orangeColor]
];
UIImageView *qrImageView = [[UIImageView alloc]initWithImage:qrCodeImage];
qrImageView.center = self.view.center;
[self.view addSubview:qrImageView];
self.qrImageView = qrImageView;
快来把你的二维码变成彩色的吧~