iOSはQRコードのカラー効果を実現


今日プロジェクトをするのは基本的に完成して、テストも终わりに入って、同僚は私にQRコードをカラーに変えると言って、私はもとの先辈の书いた工事の研究に対して研究に行って、多くの资料を探してやはりよくしていないで、やはりずっと失败して、そこで私の学友を探して、彼に闻いて、结局彼は出勤して私に见る时间がなくて、しかし私に脳の穴を开けて、私は突然自分があまりにも堅苦しいことを発見して、元のコードの上で必死にぶつかって、実はgithubの上で多くの書いたコードを探して私に使うことができて、しかし私は考えていないで、仕事は効率にこだわって、学習は必死に打つことができて、しかし仕事の上で必ず頭が柔軟で、八方の資源を使うことをマスターして、自分の仕事の効率を大いに高めて、教えを受けます.
今日使ったQRコードを生成して皆さんと共有します.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;
早くQRコードをカラーにしましょう~