【iOS】二维码生成及定制

点击上方“iOS开发”,选择“置顶公众号”

关键时刻,第一时间送达!

【iOS】二维码生成及定制

【iOS】二维码生成及定制


title: 【iOS】二维码生成及定制

tags: iOS


blog

http://blog.zhangpeng.site

简书

http://www.jianshu.com/u/5690b3ad0a6f

Github

https://github.com/Zhang1Peng?tab=repositories


需求


最近产品看支付宝红包的二维码分享功能不错,于是乎提出了需求:


  • 一个用于分享的二维码,用于跳转到相关页面

  • 添加logo

  • 拼接一个背景图


以上就是写出这篇文章的原因。(??????)??


生成


CIQRCodeGenerator


在iOS7之后,苹果自身集成了二维码的生成和读取功能。本篇文章中采用就是苹果提供的生成二维码方法。使用苹果提供的方法好处就在于不用额外引入其他的第三方库,可以减少打包后的App大小。


ZXing


ZXing是一个很有名的用于生成二维码的库,不仅支持iOS,还支持Android,java等。这个库的使用网上有个很多介绍了,在此就不做赘述了。


写博客不给Demo的博主都不是好博主,没Demo没XX。


授人予鱼,不如授人与渔。鱼在上面的Demo中,渔在下面的文章中。


下面开始我的表演。<( ̄ ﹌  ̄)>


我认为这个二维码的需求很多地方都会需要,所以我这边创建了一个UIImage的扩展,方便以后的使用


头文件


导入#import <CoreImage/CoreImage.h>。


生成二维码


    //创建名为"CIQRCodeGenerator"的CIFilter

    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];

    //将filter所有属性设置为默认值

    [filter setDefaults];

    

    //将所需尽心转为UTF8的数据,并设置给filter

    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

    [filter setValue:data forKey:@"inputMessage"];

    

    //设置二维码的纠错水平,越高纠错水平越高,可以污损的范围越大

    /*

     * L: 7%

     * M: 15%

     * Q: 25%

     * H: 30%

     */

    [filter setValue:@"H" forKey:@"inputCorrectionLevel"];

    

    //拿到二维码图片,此时的图片不是很清晰,需要二次加工

    CIImage *outPutImage = [filter outputImage];


调节二维码清晰度


  • 方法一


/**

 调整二维码清晰度


 @param img 模糊的二维码图片

 @param size 二维码的宽高

 @return 清晰的二维码图片

 */

- (UIImage *)getHDImgWithCIImage:(CIImage *)img size:(CGSize)size {

    

    CGRect extent = CGRectIntegral(img.extent);

    CGFloat scale = MIN(size.width/CGRectGetWidth(extent), size.height/CGRectGetHeight(extent));

    

    //1.创建bitmap;

    size_t width = CGRectGetWidth(extent) * scale;

    size_t height = CGRectGetHeight(extent) * scale;

    //创建一个DeviceGray颜色空间

    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();

    //CGBitmapContextCreate(void * _Nullable data, size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow, CGColorSpaceRef  _Nullable space, uint32_t bitmapInfo)

    //width:图片宽度像素

    //height:图片高度像素

    //bitsPerComponent:每个颜色的比特值,例如在rgba-32模式下为8

    //bitmapInfo:指定的位图应该包含一个alpha通道。

    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);

    CIContext *context = [CIContext contextWithOptions:nil];

    //创建CoreGraphics image

    CGImageRef bitmapImage = [context createCGImage:img fromRect:extent];

    

    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);

    CGContextScaleCTM(bitmapRef, scale, scale);

    CGContextDrawImage(bitmapRef, extent, bitmapImage);

    

    //2.保存bitmap到图片

    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);

    CGContextRelease(bitmapRef); CGImageRelease(bitmapImage);

    

    //清晰的二维码图片

    UIImage *outputImage = [UIImage imageWithCGImage:scaledImage];

    return outputImage;

}


  • 方法二,相对于方法一,这个方法可以更方便的修改二维码的颜色


/**

 调整二维码清晰度

 

 @param img 模糊的二维码图片

 @param size 二维码的宽高

 @return 清晰的二维码图片

 */

- (UIImage *)sencond_getHDImgWithCIImage:(CIImage *)img size:(CGSize)size {

    

    //二维码的颜色

    UIColor *pointColor = [UIColor blackColor];

    //背景颜色

    UIColor *backgroundColor = [UIColor whiteColor];

    CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"

                                       keysAndValues:

                             @"inputImage", img,

                             @"inputColor0", [CIColor colorWithCGColor:pointColor.CGColor],

                             @"inputColor1", [CIColor colorWithCGColor:backgroundColor.CGColor],

                             nil];

    

    CIImage *qrImage = colorFilter.outputImage;

    

    //绘制

    CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];

    UIGraphicsBeginImageContext(size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetInterpolationQuality(context, kCGInterpolationNone);

    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);

    UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    

    CGImageRelease(cgImage);

    

    return codeImage;

}


通过上面三部部,就可以得到一张清晰的二维码图片了。


【iOS】二维码生成及定制

qrCode.png


定制


修改二维码颜色


做完一个二维码以后,有个Android的同事说可以把二维码周围的白边去掉,这个真的是程序员给程序员找麻烦~


如果采用的上面的方法生成二维码图片,那就可以不看这章了,直接去方法内部中修改就好


修改二维码的原理是改变每个像素点的颜色


/**

 修改二维码颜色


 @param image 二维码图片

 @param red red

 @param green green

 @param blue blue

 @return 修改颜色后的二维码图片

 */

+ (UIImage *)changeColorWithQRCodeImg:(UIImage *)image red:(NSUInteger)red green:(NSUInteger)green blue:(NSUInteger)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, (CGRect){(CGPointZero), (image.size)}, image.CGImage);

    //遍历像素

    int pixelNumber = imageHeight * imageWidth;

    [self changeColorOnPixel:rgbImageBuf pixelNum:pixelNumber red:red green:green blue:blue];

    

    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow, ProviderReleaseData);

    

    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace, kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider, NULL, true, kCGRenderingIntentDefault);

    UIImage * resultImage = [UIImage imageWithCGImage: imageRef];

    CGImageRelease(imageRef);

    CGColorSpaceRelease(colorSpace);

    CGContextRelease(context);

    return resultImage;

}


/**

 遍历像素点,修改颜色


 @param rgbImageBuf rgbImageBuf

 @param pixelNum pixelNum

 @param red red

 @param green green

 @param blue blue

 */

+ (void)changeColorOnPixel: (uint32_t *)rgbImageBuf pixelNum: (int)pixelNum red: (NSUInteger)red green: (NSUInteger)green blue: (NSUInteger)blue {

    

    uint32_t * pCurPtr = rgbImageBuf;

    

    for (int i = 0; i < pixelNum; i++, pCurPtr++) {

        

        //通过颜色区分是不是要改变的区域

        if ((*pCurPtr & 0xffffff00) < 0xd0d0d000) {

            

            uint8_t * ptr = (uint8_t *)pCurPtr;

            ptr[3] = red;

            ptr[2] = green;

            ptr[1] = blue;

        } else {

            //将白色变成透明色

            uint8_t * ptr = (uint8_t *)pCurPtr;

            ptr[0] = 0;

        }

    }

}


【iOS】二维码生成及定制

qrCode_pink.png


添加水印图片(Logo)


/**

 调整二维码清晰度,添加水印图片


 @param img 模糊的二维码图片

 @param size 二维码的宽高

 @param waterImg 水印图片

 @return 添加水印图片后,清晰的二维码图片

 */

- (UIImage *)getHDImgWithCIImage:(CIImage *)img size:(CGSize)size waterImg:(UIImage *)waterImg {

    

    CGRect extent = CGRectIntegral(img.extent);

    CGFloat scale = MIN(size.width/CGRectGetWidth(extent), size.height/CGRectGetHeight(extent));

    

    //1.创建bitmap;

    size_t width = CGRectGetWidth(extent) * scale;

    size_t height = CGRectGetHeight(extent) * scale;

    //创建一个DeviceGray颜色空间

    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();

    //CGBitmapContextCreate(void * _Nullable data, size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow, CGColorSpaceRef  _Nullable space, uint32_t bitmapInfo)

    //width:图片宽度像素

    //height:图片高度像素

    //bitsPerComponent:每个颜色的比特值,例如在rgba-32模式下为8

    //bitmapInfo:指定的位图应该包含一个alpha通道。

    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);

    CIContext *context = [CIContext contextWithOptions:nil];

    //创建CoreGraphics image

    CGImageRef bitmapImage = [context createCGImage:img fromRect:extent];

    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);

    CGContextScaleCTM(bitmapRef, scale, scale);

    CGContextDrawImage(bitmapRef, extent, bitmapImage);

    

    //2.保存bitmap到图片

    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);

    CGContextRelease(bitmapRef); CGImageRelease(bitmapImage);

    

    //清晰的二维码图片

    UIImage *outputImage = [UIImage imageWithCGImage:scaledImage];

    //给二维码加 logo 图

    UIGraphicsBeginImageContextWithOptions(outputImage.size, NO, [[UIScreen mainScreen] scale]);

    [outputImage drawInRect:CGRectMake(0, 0, size.width, size.height)];

    //水印图片

    //把水印图片画到生成的二维码图片上,注意尺寸不要太大(根据上面生成二维码设置的纠错程度设置),否则有可能造成扫不出来

    [waterImg drawInRect:CGRectMake((size.width-waterImg.size.width)/2.0, (size.height-waterImg.size.height)/2.0, waterImg.size.width, waterImg.size.height)];

    UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    

    return newPic;

}


拼接图片


/**

 拼接图片


 @param img1 图片1

 @param img2 图片2

 @return 拼接后的图片

 */

+ (UIImage *)spliceImg1:(UIImage *)img1 img2:(UIImage *)img2 {

    

    CGSize size1 = img1.size;

    CGSize size2 = img2.size;

    

    UIGraphicsBeginImageContextWithOptions(img1.size, NO, [[UIScreen mainScreen] scale]);

    [img1 drawInRect:CGRectMake(0, 0, img1.size.width, img1.size.height)];

    

//    [img2 drawInRect:CGRectMake((size1.width-size2.width)/2.0, (size1.height-size2.height)/2.0, size2.width, size2.height)];

    [img2 drawInRect:CGRectMake(size1.width/4.0, size1.height/2.5, size1.width/2, size1.width/2)];

    UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    

    return newPic;

}

qrCode_splice.png


【iOS】二维码生成及定制




【iOS】二维码生成及定制

  • 来自: zhangPeng丶

  • 链接:http://www.jianshu.com/p/4be9cece8b81

  • iOS开发整理发布,转载请联系作者授权

【iOS】二维码生成及定制

【iOS】二维码生成及定制【点击成为Android大神】