iOS7以後,可使用原生的CIFilter
建立二維碼,可是生成的二維碼只有黑白,並且大小很差控制,找了一下資料,發現解決的方法,使二維碼透明背景,自定義顏色,還能加上陰影效果,方法很簡單,直接調用便可,效果以下:html

Demo地址:https://github.com/TelenLiu/Demo_CustomQRCodegit
首先是二維碼的生成,使用CIFilter
很簡單,直接傳入生成二維碼的字符串便可:github
- (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;
}
由於生成的二維碼是一個CIImage
,咱們直接轉換成UIImage
的話大小很差控制,因此使用下面方法返回須要大小的UIImage
:ide
- (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];
}
由於生成的二維碼是黑白的,因此還要對二維碼進行顏色填充,並轉換爲透明背景,使用遍歷圖片像素來更改圖片顏色,由於使用的是CGContext
,速度很是快:ui
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
上使用下面代碼添加陰影:url
ImageView.layer.shadowOffset = CGSizeMake(0, 0.5); // 設置陰影的偏移量
ImageView.layer.shadowRadius = 1; // 設置陰影的半徑
ImageView.layer.shadowColor = [UIColor blackColor].CGColor; // 設置陰影的顏色爲黑色
ImageView.layer.shadowOpacity = 0.3; // 設置陰影的不透明度
這樣就大功告成,但願能幫到你,歡迎你們一塊兒交流。spa
內容轉自:郭宇翔博客3d