CIFilter生成二維碼

【iOS開發】iO7以上CIFilter生成二維碼(備忘)

(2015-04-24 14:48:25)

最近須要用到二維碼生成和掃描,想找一下簡單高效好用的源碼,如下備忘
//-------------- 

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

【iOS開發】iO7以上CIFilter生成二維碼(備忘)

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的話大小很差控制,因此使用下面方法返回須要大小的UIImageide

- (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; } 

通過這樣的處理,基本上二維碼就成型了,若是還想加上陰影,就在ImageViewLayer上使用下面代碼添加陰影: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

//--------------
相關文章
相關標籤/搜索