1、通过字符串生成
CIImage(
首先是二维码的生成,使用
CIFilter
很简单,直接传入生成二维码的字符串即可:
)
- (
CIImage
*)createQRForString:(
NSString
*)qrString {
NSData
*stringData = [qrString
dataUsingEncoding
:
NSUTF8StringEncoding
];
// 创建 filter
CIFilter *qrFilter = [ CIFilter filterWithName : @"CIQRCodeGenerator" ];
// 设置内容和纠错级别
[qrFilter setValue :stringData forKey : @"inputMessage" ];
[qrFilter setValue : @"M" forKey : @"inputCorrectionLevel" ];
// 返回 CIImage
return qrFilter. outputImage ;
// 创建 filter
CIFilter *qrFilter = [ CIFilter filterWithName : @"CIQRCodeGenerator" ];
// 设置内容和纠错级别
[qrFilter setValue :stringData forKey : @"inputMessage" ];
[qrFilter setValue : @"M" forKey : @"inputCorrectionLevel" ];
// 返回 CIImage
return qrFilter. outputImage ;
}
2、把CIImage转换成UIImage(
因为生成的二维码是一个
CIImage
,我们直接转换成UIImage
的话大小不好控制,所以使用下面方法返回需要大小的UIImage
:
)
- (
UIImage
*)createNonInterpolatedUIImageFormCIImage:(
CIImage
*)image withSize:(
CGFloat
) size {
CGRect extent = CGRectIntegral (image. extent );
CGFloat scale = MIN (size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
// 创建 bitmap;
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);
// 保存 bitmap 到图片
CGImageRef scaledImage = CGBitmapContextCreateImage (bitmapRef);
CGContextRelease (bitmapRef);
CGImageRelease (bitmapImage);
return [ UIImage imageWithCGImage :scaledImage];
CGRect extent = CGRectIntegral (image. extent );
CGFloat scale = MIN (size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
// 创建 bitmap;
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);
// 保存 bitmap 到图片
CGImageRef scaledImage = CGBitmapContextCreateImage (bitmapRef);
CGContextRelease (bitmapRef);
CGImageRelease (bitmapImage);
return [ UIImage imageWithCGImage :scaledImage];
}
3、调用
//
二维码
CIImage *ciImage = [ self createQRForString :doctorAccount. Id ];
UIImage *uiImage = [ self createNonInterpolatedUIImageFormCIImage :ciImage withSize : AUTO_MATE_WIDTH ( 150 )];
CGFloat width1 = AUTO_MATE_WIDTH ( 150 );
xPoint = (bigView. frame . size . width -width1)* 0.5 ;
UIImageView * erweimaImage = [[ UIImageView alloc ] initWithFrame : CGRectMake (xPoint, pleaseLabel. maxY_wcr +yPoint* 1.5 , width1, width1)];
erweimaImage. image = uiImage;
[bigView addSubview :erweimaImage];
erweimaImage. layer . shadowOffset = CGSizeMake ( 0 , 0.5 ); // 设置阴影的偏移量
erweimaImage. layer . shadowRadius = 1 ; // 设置阴影的半径
erweimaImage. layer . shadowColor = [ UIColor blackColor ]. CGColor ; // 设置阴影的颜色为黑色
CIImage *ciImage = [ self createQRForString :doctorAccount. Id ];
UIImage *uiImage = [ self createNonInterpolatedUIImageFormCIImage :ciImage withSize : AUTO_MATE_WIDTH ( 150 )];
CGFloat width1 = AUTO_MATE_WIDTH ( 150 );
xPoint = (bigView. frame . size . width -width1)* 0.5 ;
UIImageView * erweimaImage = [[ UIImageView alloc ] initWithFrame : CGRectMake (xPoint, pleaseLabel. maxY_wcr +yPoint* 1.5 , width1, width1)];
erweimaImage. image = uiImage;
[bigView addSubview :erweimaImage];
erweimaImage. layer . shadowOffset = CGSizeMake ( 0 , 0.5 ); // 设置阴影的偏移量
erweimaImage. layer . shadowRadius = 1 ; // 设置阴影的半径
erweimaImage. layer . shadowColor = [ UIColor blackColor ]. CGColor ; // 设置阴影的颜色为黑色
erweimaImage.layer.shadowOpacity = 0.3; //
设置阴影的不透明度
//
二维码中的头像
UIImageView *iconView = [[ UIImageView alloc ] init ];
iconView. width_wcr = erweimaImage. width_wcr * 0.3 ;
iconView. height_wcr = erweimaImage. height_wcr * 0.3 ;
iconView. centerX_wcr = erweimaImage. centerX_wcr ;
iconView. centerY_wcr = erweimaImage. centerY_wcr ;
iconView. layer . cornerRadius = iconView. bounds . size . height * 0.5 ;
iconView. layer . masksToBounds = YES ;
[iconView sd_setImageWithURL :[ NSURL URLWithString :account. avatar ]];
UIImageView *iconView = [[ UIImageView alloc ] init ];
iconView. width_wcr = erweimaImage. width_wcr * 0.3 ;
iconView. height_wcr = erweimaImage. height_wcr * 0.3 ;
iconView. centerX_wcr = erweimaImage. centerX_wcr ;
iconView. centerY_wcr = erweimaImage. centerY_wcr ;
iconView. layer . cornerRadius = iconView. bounds . size . height * 0.5 ;
iconView. layer . masksToBounds = YES ;
[iconView sd_setImageWithURL :[ NSURL URLWithString :account. avatar ]];
[bigView addSubview:iconView];
4、在二维码中间插入图片
要在二维码中插入图片且可以正常解码,关键是要注意以下两个地方:
1、必须调整二维码的容错参数ErrorCorrectionLevel
Hashtable hint=new Hashtable();
hint.Add(EncodeHintType.CHARACTER_SET,"UTF-8");
hint.Add(EncodeHintType.ERROR_CORRECTION,com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.H);
hint是生成二维码的方法中最后一个参数,这个参数是一个hashtable,这里可以设置二维码的编码、容错系数等。
容错系数越高,生成的二维码图片越复杂,可以容忍二维码被污垢弄赃,甚至中间可以加一个小图片,识别也不受影响。
2、第二个要注意的地方是图片大小
从二维码的识别原理可以知道,二维码中原始信息被加密在下图黑色部分,而红色部分都是冗余信息,红色部分都是可以被自己的图片替换的。
为了插入图片的完整性,我们选择在最中间插入,而且长宽建议为整个二维码的3/7至1/3
详情:
最近需要用到二维码生成和扫描,想找一下简单高效好用的源码,以下备忘
- (CIImage *)createQRForString:(NSString *)qrString {
NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding];
// 创建filter
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
// 设置内容和纠错级别
[qrFilter setValue:stringData forKey:@"inputMessage"];
[qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];
// 返回CIImage
return qrFilter.outputImage;
}
- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
// 创建bitmap;
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);
// 保存bitmap到图片
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
return [UIImage imageWithCGImage:scaledImage];
}
void ProviderReleaseData (void *info, const void *data, size_t size){
free((void*)data);
}
- (UIImage*)imageBlackToTransparent:(UIImage*)image withRed:(CGFloat)red andGreen:(CGFloat)green andBlue:(CGFloat)blue{
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);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);
// 遍历像素
int pixelNum = imageWidth * imageHeight;
uint32_t* pCurPtr = rgbImageBuf;
for (int i = 0; i <</span> pixelNum; i++, pCurPtr++){
if ((*pCurPtr & 0xFFFFFF00) <</span> 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;
}
}
// 输出图片
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);
UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef];
// 清理空间
CGImageRelease(imageRef);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
return resultUIImage;
}
ImageView.layer.shadowOffset = CGSizeMake(0, 0.5); // 设置阴影的偏移量
ImageView.layer.shadowRadius = 1; // 设置阴影的半径
ImageView.layer.shadowColor = [UIColor blackColor].CGColor; // 设置阴影的颜色为黑色
ImageView.layer.shadowOpacity = 0.3; // 设置阴影的不透明度