Believe in your own future, will thank yourself right now Sinner Yun

Sinner_Yun

二维码扫描

原生二维码扫描

个人是比较支持用原生二维码扫描的,这里也就仅仅以原生二维码扫面为范例。另也有二维码扫描库ZBarSDK(点这里)

1.原生扫描用到的几个类

1 @property (strong,nonatomic)AVCaptureDevice * device;
2 @property (strong,nonatomic)AVCaptureDeviceInput * input;
3 @property (strong,nonatomic)AVCaptureMetadataOutput * output;
4 @property (strong,nonatomic)AVCaptureSession * session;
5 @property (strong,nonatomic)AVCaptureVideoPreviewLayer * preview;

 

2.在viewDidLoad里创建它们

 1 // Device
 2 _device = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];
 3 
 4 // Input
 5 _input = [AVCaptureDeviceInputdeviceInputWithDevice:self.deviceerror:nil];
 6 
 7 // Output
 8 _output = [[AVCaptureMetadataOutputalloc]init];
 9 [_outputsetMetadataObjectsDelegate:selfqueue:dispatch_get_main_queue()];
10 
11 // Session
12 _session = [[AVCaptureSessionalloc]init];
13 [_sessionsetSessionPreset:AVCaptureSessionPresetHigh];

 

连接输入和输出

if ([_sessioncanAddInput:self.input])
{
    [_sessionaddInput:self.input];
}

if ([_sessioncanAddOutput:self.output])
{
    [_sessionaddOutput:self.output];
}

 

设置条码类型

 _output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode]; 

添加扫描画面

1 _preview =[AVCaptureVideoPreviewLayerlayerWithSession:_session];
2 _preview.videoGravity =AVLayerVideoGravityResizeAspectFill;
3 _preview.frame =self.view.layer.bounds;
4 [self.view.layerinsertSublayer:_previewatIndex:0];

 

开始扫描

[_sessionstartRunning];

 

最后实现协议AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
   NSString *stringValue;
   if ([metadataObjectscount] >0){
   //停止扫描
   [_sessionstopRunning];        
   AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjectsobjectAtIndex:0];
   stringValue = metadataObject.stringValue;        
  }
}

 

到了这一步就可以成功扫描二维码了

还有一个小问题需要说明一下,之前写过一篇限制二维码扫描区域的,在这里稍微提一下。如下图微信扫描,把扫描范围限制在中间的方框内


微信二维码扫描

要想限制二维码扫描区域,需要设置一个参数rectOfInterest 这个参数有点特别 根据页面位置的 (0.X) 来确定。

设置的方法

  [_output setRectOfInterest:CGRectMake()];

 

生成二维码图片

 

 

首先.h中
/**
 *  生成二维码图片
 *
 *  @param QRString  二维码内容
 *  @param sizeWidth 图片size(正方形)
 *  @param color     填充色
 *
 *  @return  二维码图片
 */
+(UIImage *)createQRimageString:(NSString *)QRString sizeWidth:(CGFloat)sizeWidth fillColor:(UIColor *)color;

 

.m中
#pragma mark 生成二维码
/**
 *  生成二维码图片
 *
 *  @param QRString  二维码内容
 *  @param sizeWidth 图片size(正方形)
 *  @param color     填充色
 *
 *  @return  二维码图片
 */
+(UIImage *)createQRimageString:(NSString *)QRString sizeWidth:(CGFloat)sizeWidth fillColor:(UIColor *)color{
CIImage *ciimage = [self createQRForString:QRString];
UIImage *qrcode = [self createNonInterpolatedUIImageFormCIImage:ciimage withSize:sizeWidth];
if (color) {
    CGFloat R, G, B;

    CGColorRef colorRef = [color CGColor];
    long numComponents = CGColorGetNumberOfComponents(colorRef);

    if (numComponents == 4)
    {
        const CGFloat *components = CGColorGetComponents(colorRef);
        R = components[0];
        G = components[1];
        B = components[2];
    }

    UIImage *customQrcode = [self imageBlackToTransparent:qrcode withRed:R andGreen:G andBlue:B];
    return customQrcode;
}

return qrcode;

}
pragma mark

   #pragma mark - QRCodeGenerator
+ (CIImage *)createQRForString:(NSString *)qrString {
// Need to convert the string to a UTF-8 encoded NSData object
NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding];
// Create the filter
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
// Set the message content and error-correction level
[qrFilter setValue:stringData forKey:@"inputMessage"];
[qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];
// Send the image back
return qrFilter.outputImage;
}
pragma mark

#pragma mark - InterpolatedUIImage
+ (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
// create a bitmap image that we'll draw into a bitmap context at the desired size;
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);
// Create an image with the contents of our bitmap
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
// Cleanup
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
return [UIImage imageWithCGImage:scaledImage];
}
pragma mark

#pragma mark - imageToTransparent
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);
// create context
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,
                                             kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);
// traverse pixe
int pixelNum = imageWidth * imageHeight;
uint32_t* pCurPtr = rgbImageBuf;
for (int i = 0; i < pixelNum; i++, pCurPtr++){
    if ((*pCurPtr & 0xFFFFFF00) < 0x99999900){
        // change color
        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;
    }
}
// context to image
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];
// release
CGImageRelease(imageRef);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
return resultUIImage;
}

 

解析二维码图片

.h中

/**
 *  读取图片中二维码信息
 *
 *  @param image 图片
 *
 *  @return 二维码内容
 */
+(NSString *)readQRCodeFromImage:(UIImage *)image;

 

.m中
#pragma mark 读取图片二维码
/**
 *  读取图片中二维码信息
 *
 *  @param image 图片
 *
 *  @return 二维码内容
 */
+(NSString *)readQRCodeFromImage:(UIImage *)image{
NSData *data = UIImagePNGRepresentation(image);
CIImage *ciimage = [CIImage imageWithData:data];
if (ciimage) {
    CIDetector *qrDetector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:[CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer:@(YES)}] options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh}];
    NSArray *resultArr = [qrDetector featuresInImage:ciimage];
    if (resultArr.count >0) {
        CIFeature *feature = resultArr[0];
        CIQRCodeFeature *qrFeature = (CIQRCodeFeature *)feature;
        NSString *result = qrFeature.messageString;

        return result;
    }else{
        return nil;
    }
}else{
    return nil;
}
}

 

 

posted on 2016-09-06 16:57  Sinner_Yun  阅读(498)  评论(0编辑  收藏  举报

导航