Realization of generating and scanning two-dimensional codes on ios by Cocos 2dx-lua

Posted by jcleary on Tue, 21 May 2019 20:03:43 +0200


First of all, I support it. iOS The original method is implemented. However, the original method of scanning two-dimensional codes does not support the devices before IOS 7.0, so the original method of generating two-dimensional codes is implemented, while the scanning two-dimensional codes are implemented by zBar sdk (of course, the official zXing SDK of google). Among them, zBar contains methods for generating two-dimensional codes, and there are many more. I just like to use native methods as much as possible.

Here I put all the code that generates the two-dimensional code and the scanning two-dimensional code method called by lua in the project - > Frameworks - > runtime-src - > proj. ios_mac - >. ios -> AppController. h and AppController.mm

zBar sdk and related classes are placed under project - > Frameworks - > runtime - SRC - > proj. ios_mac - > ios.

- 1. Generating two-dimensional code primitively

Add code to 1.1AppController.h:

  1. //Generating two-dimensional codes  
  2. +(CIImage *) creatQRcodeWithUrlstring:(NSString *)urlString;  
  3. //Change picture size (square picture)  
  4. + (UIImage *)changeImageSizeWithCIImage:(CIImage *)ciImage andSize:(CGFloat)size;  
  5. //Preserve (temporarily useless)  
  6. +(BOOL)writeImage:(UIImage*)image toFileAtPath:(NSString*)aPath;  
  7. //Generating two-dimensional codes  
  8. +(void)createQRCode:(NSDictionary *)info;  

Add code to 1.2AppController.mm:

  1. /** 
  2.  *  Generating two-dimensional code CIImage objects from strings 
  3.  * 
  4.  *  @param urlString Strings that need to generate two-dimensional codes 
  5.  * 
  6.  *  @return Generated two-dimensional code 
  7.  */  
  8. + (CIImage *)creatQRcodeWithUrlstring:(NSString *)urlString{  
  9.     //1. Instance of two-dimensional code filters  
  10.     CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];  
  11.     //2. Restore the default attributes of the filter (because it is possible for the filter to save the last attributes)  
  12.     [filter setDefaults];  
  13.     //3. Converting strings to NSdata  
  14.     NSData *data  = [urlString dataUsingEncoding:NSUTF8StringEncoding];  
  15.     //4. Setting up filters through KVO and passing in data, the future filters will know to generate two-dimensional codes from the incoming data.  
  16.     [filter setValue:data forKey:@"inputMessage"];  
  17.     //5. Generating two-dimensional codes  
  18.     CIImage *outputImage = [filter outputImage];  
  19.     return outputImage;  
  20. }  
  21.   
  22. /** 
  23.  *  Change picture size (square picture) 
  24.  * 
  25.  *  @param ciImage Pictures of CIImage objects that need to be resized 
  26.  *  @param size    Picture Size (Square Pictures Only need one Number) 
  27.  * 
  28.  *  @return Generated target image 
  29.  */  
  30. + (UIImage *)changeImageSizeWithCIImage:(CIImage *)ciImage andSize:(CGFloat)size{  
  31.     CGRect extent = CGRectIntegral(ciImage.extent);  
  32.     CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));  
  33.       
  34.     //Create bitmap;  
  35.     size_t width = CGRectGetWidth(extent) * scale;  
  36.     size_t height = CGRectGetHeight(extent) * scale;  
  37.     CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();  
  38.     CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);  
  39.     CIContext *context = [CIContext contextWithOptions:nil];  
  40.     CGImageRef bitmapImage = [context createCGImage:ciImage fromRect:extent];  
  41.     CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);  
  42.     CGContextScaleCTM(bitmapRef, scale, scale);  
  43.     CGContextDrawImage(bitmapRef, extent, bitmapImage);  
  44.       
  45.     //Save bitmap to picture  
  46.     CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);  
  47.     CGContextRelease(bitmapRef);  
  48.     CGImageRelease(bitmapImage);  
  49.       
  50.     return [UIImage imageWithCGImage:scaledImage];  
  51. }  
  52.   
  53. + (BOOL)writeImage:(UIImage*)image toFileAtPath:(NSString*)aPath  
  54. {  
  55.     if ((image == nil) || (aPath == nil) || ([aPath isEqualToString:@""]))  
  56.         return NO;  
  57.     @try  
  58.     {  
  59.         NSData *imageData = nil;  
  60.         NSString *ext = [aPath pathExtension];  
  61.         if ([ext isEqualToString:@"png"])  
  62.         {  
  63.             imageData = UIImagePNGRepresentation(image);  
  64.         }  
  65.         else  
  66.         {  
  67.             // the rest, we write to jpeg  
  68.             // 0. best, 1. lost. about compress.  
  69.             imageData = UIImageJPEGRepresentation(image, 0);  
  70.         }  
  71.         if ((imageData == nil) || ([imageData length] <= 0))  
  72.             return NO;  
  73.         [imageData writeToFile:aPath atomically:YES];  
  74.         return YES;  
  75.     }  
  76.     @catch (NSException *e)  
  77.     {  
  78.         NSLog(@"create thumbnail exception.");  
  79.     }  
  80.     return NO;  
  81. }  
  82.   
  83. /* 
  84.  * Project-TARGETS-fightGame-mobile-Build Phases-Link Binary With Libraries Add CoreImage. 
  85.  */  
  86. +(void) createQRCode:(NSDictionary *)info  
  87. {  
  88.     int _callBack = [[info objectForKey:@"listener"] intValue];  
  89.     NSString *qrCodeStr = [info objectForKey:@"qrCodeStr"];  
  90.       
  91.     CIImage *ciImage = [self creatQRcodeWithUrlstring:qrCodeStr];  
  92.     UIImage *uiImage = [self changeImageSizeWithCIImage:ciImage andSize:180];  
  93.     NSData *imageData = UIImagePNGRepresentation(uiImage);  
  94.       
  95.     std::string path = cocos2d::FileUtils::getInstance()->getWritablePath() + "qrCode.png";  
  96.     const char* pathC = path.c_str();  
  97.     NSString * pathN = [NSString stringWithUTF8String:pathC];  
  98.     bool isSuccess = [imageData writeToFile:pathN atomically:YES];  
  99.       
  100.     cocos2d::LuaBridge::pushLuaFunctionById(_callBack);  
  101.     cocos2d::LuaValueDict dict;  
  102.     dict["isSuccess"] =cocos2d::LuaValue::booleanValue(isSuccess);  
  103.     cocos2d::LuaBridge::getStack()->pushLuaValueDict( dict );  
  104.     cocos2d::LuaBridge::getStack()->executeFunction(1);  
  105.     cocos2d::LuaBridge::releaseLuaFunctionById(_callBack);  
  106. }  

createQRcode method uses oc method for the final lua, saves the generated image under the writable Path of cocos2dx, and saves it as "qrCode.png". Finally, it is taken out at the Lua end and displayed with sprite.

------------------- 1.3lua calls the createQRcode method and displays it

  1. local callBack = function (message)  
  2.     local filePath = cc.FileUtils:getInstance():getWritablePath()  
  3.     filePath = filePath.."qrCode.png"  
  4.   
  5.     local rect = cc.rect(0, 0, 180, 180)  
  6.     local sprite = cc.Sprite:create()   
  7.     sprite:initWithFile(filePath, rect)  
  8.     sprite:setPosition(300, 300)  
  9.     self:addChild(sprite)  
  10. end  
  11. local info = {listener = callBack, qrCodeStr = "https://www.baidu.com/"}  
  12. luaoc.callStaticMethod("AppController""createQRCode", info)  

1.4 Adding CoreImage.framework Dependency Framework (2-D code scanning required)

Item - > TARGETS - > Build Phases - > Link Binary With Libraries - > bottom left "+" number, in the search box enter CoreImage.framework, select the matching options.
2.zBar sdk to realize two-dimensional code scanning

Download zBar sdk
The address is given later.

2.2 Decompress the zBarSDK and import the decompressed zBarSDK into the project - > Frameworks - > runtime - SRC - > proj. ios_mac - > ios.

The decompressed zBarSDK directory contains: Headers,libzbar.a,Resources.

If the libzbar.a dependency framework is not automatically added after the project is imported, the dependency framework needs to be added manually (e.g. 1.4).

The new ZCZBarViewController.h and ZCZBarViewController.mm files under the zBarSDK are created and imported into the project. The code is as follows.
Code 2.4ZCZBarViewController.h:

  1. /* 
  2.  iOS Institute 305044955 
  3.  1.8 Version 2-D code files are generated by eliminating and using iOS7 to generate two-dimensional code primitively 
  4.  1.7 Version Fixed the problem of turning on camera clicks, which could lead to crash if the user clicked No. 
  5.  1.6 The version adds support for distinguishing barcodes from two-dimensional codes. It can turn off scanning two-dimensional codes to increase the scanning speed of barcodes. 
  6.  1.5 Version 6 amends the scanning jam under iOS 6, adds support bar code under iOS 7, modifies the algorithm, and increases efficiency. 
  7.  1.4 Version 8 supports iOS 8 system and modifies UI adaptation 
  8.  1.3 Release new support arm7s arm64 new support ARC 
  9.  1.2 Version ZC encapsulated ZBar two-dimensional code SDK 
  10.     1,Update the class name from CustomViewController to ZCZBarViewController 
  11.     2,Delete the proxy code 
  12.  1.1 Version ZC encapsulated ZBar two-dimensional code SDK~ 
  13.     1,Add block callbacks 
  14.     2,Cancellation of agency 
  15.     3,Added IOS7 (ios7 adds scan 2-D code function in AVFoundation) 
  16.  1.0 Initial Establishment of SDK~1.0 Version of ZBar Two-Dimensional Code encapsulated in ZC 
  17.   
  18.  Two-Dimensional Coding Sequence 
  19.  Zbar Compile 
  20.  Need to add AV Foundation, CoreMedia, CoreVideo, QuartzCore, libiconv 
  21.   
  22.   
  23. //Sample code 
  24. Scan code 
  25. BOOL Represents whether to turn off two-dimensional code scanning, specifically scanning barcode 
  26.  ZCZBarViewController*vc=[[ZCZBarViewController alloc]initWithIsQRCode:NO Block:^(NSString *result, BOOL isFinish) { 
  27.  if (isFinish) { 
  28.  NSLog(@"The final result%@, result; 
  29.  } 
  30.   
  31.  }]; 
  32.   
  33.  [self presentViewController:vc animated:YES completion:nil]; 
  34.   
  35.   
  36. Generating two-dimensional codes 
  37.  [ZCZBarViewController createImageWithImageView:imageView String:@"http://www.baidu.com"Scale:4]; 
  38.  */  
  39. #import <UIKit/UIKit.h>  
  40. #import <AVFoundation/AVFoundation.h>  
  41. #import "ZBarReaderController.h"  
  42. #import <CoreImage/CoreImage.h>  
  43. #define IOS7 [[[UIDevice currentDevice] systemVersion]floatValue]>=7  
  44.   
  45.   
  46. @interface ZCZBarViewController : UIViewController<AVCaptureVideoDataOutputSampleBufferDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate,ZBarReaderDelegate,AVCaptureMetadataOutputObjectsDelegate>  
  47. {  
  48.     int num;  
  49.     BOOL upOrdown;  
  50.     NSTimer * timer;  
  51.     UIImageView*_line;  
  52. }  
  53.   
  54.   
  55. @property (nonatomic,strong) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;  
  56. @property (nonatomic, strong) AVCaptureSession *captureSession;  
  57.   
  58. @property (nonatomic, assign) BOOL isScanning;  
  59.   
  60. @property (nonatomic,copy)void(^ScanResult)(NSString*result,BOOL isSucceed);  
  61. @property (nonatomic)BOOL isQRCode;  
  62.   
  63.   
  64. //Initialization function  
  65. -(id)initWithIsQRCode:(BOOL)isQRCode Block:(void(^)(NSString*,BOOL))a;  
  66.   
  67. //Canonical expression screening for scanning results  
  68. +(NSString*)zhengze:(NSString*)str;  
  69.   
  70. //Creating two-dimensional codes  
  71. +(void)createImageWithImageView:(UIImageView*)imageView String:(NSString*)str Scale:(CGFloat)scale;  
  72.   
  73.   
  74. @end  

Code 2.4ZCZBarViewController.mm:

  1. #import "ZCZBarViewController.h"  
  2. #import <AssetsLibrary/AssetsLibrary.h>  
  3. @interface ZCZBarViewController ()  
  4.   
  5. @end  
  6.   
  7. #define WIDTH ( ([UIScreen mainScreen].bounds.size.width>[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.width:[UIScreen mainScreen].bounds.size.height )  
  8. //[UIScreen mainScreen].bounds.size.width  
  9. #define HEIGHT ( ([UIScreen mainScreen].bounds.size.width<[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.width:[UIScreen mainScreen].bounds.size.height )  
  10. //[UIScreen mainScreen].bounds.size.height  
  11.   
  12.   
  13. @implementation ZCZBarViewController  
  14.   
  15. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
  16. {  
  17.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
  18.     if (self) {  
  19.         // Custom initialization  
  20.     }  
  21.     return self;  
  22. }  
  23. -(id)initWithIsQRCode:(BOOL)isQRCode Block:(void(^)(NSString*,BOOL))a  
  24. {  
  25.     if (self=[super init]) {  
  26.         self.ScanResult=a;  
  27.         self.isQRCode=isQRCode;  
  28.           
  29.     }  
  30.       
  31.     return self;  
  32. }  
  33.   
  34.   
  35. -(void)createView{  
  36.       
  37. //qrcode_scan_bg_Green_iphone5@2x.png  qrcode_scan_bg_Green@2x.png  
  38.     UIImage*image= [UIImage imageNamed:@"qrcode_scan_bg_Green@2x.png"];  
  39.     float capWidth=image.size.width/2;  
  40.     float capHeight=image.size.height/2;  
  41.       
  42.     image=[image stretchableImageWithLeftCapWidth:capWidth topCapHeight:capHeight];  
  43.     UIImageView* bgImageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 64, WIDTH, HEIGHT-64)];  
  44.     //bgImageView.contentMode=UIViewContentModeTop;  
  45.     bgImageView.clipsToBounds=YES;  
  46.     bgImageView.image=image;  
  47.     bgImageView.userInteractionEnabled=YES;  
  48.     [self.view addSubview:bgImageView];  
  49.       
  50. //    UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(0, bgImageView.frame.size.height-140, WIDTH, 40)];  
  51. //label.text = @ Aligns the viewfinder frame to the two-dimensional code and automatically scans it. ";  
  52. //    label.textColor = [UIColor whiteColor];  
  53. //    label.textAlignment = NSTextAlignmentCenter;  
  54. //    label.lineBreakMode = NSLineBreakByWordWrapping;  
  55. //    label.numberOfLines = 2;  
  56. //    label.font=[UIFont systemFontOfSize:12];  
  57. //    label.backgroundColor = [UIColor clearColor];  
  58. //    [bgImageView addSubview:label];  
  59.       
  60.   
  61.       
  62.       
  63.     _line = [[UIImageView alloc] initWithFrame:CGRectMake((WIDTH-220)/2, 70, 220, 2)];  
  64.     _line.image = [UIImage imageNamed:@"qrcode_scan_light_green.png"];  
  65.     [bgImageView addSubview:_line];  
  66.      
  67.       
  68. //// The following album  
  69. //    UIImageView*scanImageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, HEIGHT-100, WIDTH, 100)];  
  70. //    scanImageView.image=[UIImage imageNamed:@"qrcode_scan_bar.png"];  
  71. //    scanImageView.userInteractionEnabled=YES;  
  72. //    [self.view addSubview:scanImageView];  
  73. //    NSArray*unSelectImageNames=@[@"qrcode_scan_btn_photo_nor.png",@"qrcode_scan_btn_flash_nor.png",@"qrcode_scan_btn_myqrcode_nor.png"];  
  74. //    NSArray*selectImageNames=@[@"qrcode_scan_btn_photo_down.png",@"qrcode_scan_btn_flash_down.png",@"qrcode_scan_btn_myqrcode_down.png"];  
  75. //      
  76. //    for (int i=0; i<unSelectImageNames.count; i++) {  
  77. //        UIButton*button=[UIButton buttonWithType:UIButtonTypeCustom];  
  78. //        [button setImage:[UIImage imageNamed:unSelectImageNames[i]] forState:UIControlStateNormal];  
  79. //        [button setImage:[UIImage imageNamed:selectImageNames[i]] forState:UIControlStateHighlighted];  
  80. //        button.frame=CGRectMake(WIDTH/3*i, 0, WIDTH/3, 100);  
  81. //        [scanImageView addSubview:button];  
  82. //        if (i==0) {  
  83. //            [button addTarget:self action:@selector(pressPhotoLibraryButton:) forControlEvents:UIControlEventTouchUpInside];  
  84. //        }  
  85. //        if (i==1) {  
  86. //            [button addTarget:self action:@selector(flashLightClick) forControlEvents:UIControlEventTouchUpInside];  
  87. //        }  
  88. //        if (i==2) {  
  89. //            button.hidden=YES;  
  90. //        }  
  91. //          
  92. //    }  
  93.       
  94.       
  95.     //False navigation  
  96. //    UIImageView*navImageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, 64)];  
  97. //    navImageView.image=[UIImage imageNamed:@"qrcode_scan_bar.png"];  
  98. //    navImageView.userInteractionEnabled=YES;  
  99. //    [self.view addSubview:navImageView];  
  100.       
  101.     UILabel*titleLabel=[[UILabel alloc]initWithFrame:CGRectMake(WIDTH/2-32, 20, 64, 44)];  
  102.     titleLabel.textColor=[UIColor whiteColor];  
  103.     titleLabel.backgroundColor = [UIColor clearColor];  
  104.     titleLabel.text=@"Scan";  
  105.     [self.view addSubview:titleLabel];  
  106. //    [navImageView addSubview:titleLabel];  
  107.       
  108.     
  109.       
  110.     UIButton*button = [UIButton buttonWithType:UIButtonTypeCustom];  
  111.     [button setImage:[UIImage imageNamed:@"qrcode_scan_titlebar_back_pressed@2x.png"] forState:UIControlStateHighlighted];  
  112.     [button setImage:[UIImage imageNamed:@"qrcode_scan_titlebar_back_nor.png"] forState:UIControlStateNormal];  
  113.   
  114.       
  115.     [button setFrame:CGRectMake(10,10, 48, 48)];  
  116.     [button addTarget:self action:@selector(pressCancelButton:) forControlEvents:UIControlEventTouchUpInside];  
  117.     [self.view addSubview:button];  
  118.   
  119.    timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(animation1) userInfo:nil repeats:YES];  
  120. }  
  121.   
  122. -(void)animation1  
  123. {  
  124.   
  125.     [UIView animateWithDuration:2 animations:^{  
  126.           
  127.          _line.frame = CGRectMake((WIDTH-220)/2, 70+HEIGHT-310, 220, 2);  
  128.     }completion:^(BOOL finished) {  
  129.         [UIView animateWithDuration:2 animations:^{  
  130.           _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);  
  131.         }];  
  132.       
  133.     }];  
  134.       
  135. }  
  136. //Turn on and off the flash  
  137. -(void)flashLightClick{  
  138.     AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];  
  139.       
  140.     if (device.torchMode==AVCaptureTorchModeOff) {  
  141.         //Flash on  
  142.         [device lockForConfiguration:nil];  
  143.         [device setTorchMode:AVCaptureTorchModeOn];  
  144.           
  145.     }else {  
  146.         //flash off  
  147.           
  148.         [device setTorchMode:AVCaptureTorchModeOff];  
  149.     }  
  150.   
  151. }  
  152.   
  153. - (void)viewDidLoad  
  154. {  
  155.     
  156.     //The customization of camera interface can be loaded on self.view.  
  157.     BOOL Custom= [UIImagePickerController  
  158.                   isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];//Determine whether the camera is available  
  159.     if (Custom) {  
  160.         [self initCapture];//Start the camera  
  161.     }else{  
  162.         self.view.backgroundColor=[UIColor whiteColor];  
  163.     }  
  164.     [super viewDidLoad];  
  165.     [self createView];  
  166.   
  167.       
  168.       
  169. }  
  170. #Pagma mark Selection Album  
  171. - (void)pressPhotoLibraryButton:(UIButton *)button  
  172. {  if (timer) {  
  173.     [timer invalidate];  
  174.     timer=nil;  
  175. }  
  176.     _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);  
  177.     num = 0;  
  178.     upOrdown = NO;  
  179.       
  180.       
  181.     UIImagePickerController *picker = [[UIImagePickerController alloc] init];  
  182.     picker.allowsEditing = YES;  
  183.     picker.delegate = self;  
  184.     picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;  
  185.     [self presentViewController:picker animated:YES completion:^{  
  186.         self.isScanning = NO;  
  187.         [self.captureSession stopRunning];  
  188.     }];  
  189. }  
  190. #pragma mark click Cancel  
  191. - (void)pressCancelButton:(UIButton *)button  
  192. {  
  193.     self.isScanning = NO;  
  194.     [self.captureSession stopRunning];  
  195.       
  196.     self.ScanResult(nil,NO);  
  197.     if (timer) {  
  198.         [timer invalidate];  
  199.         timer=nil;  
  200.     }  
  201.     _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);  
  202.     num = 0;  
  203.     upOrdown = NO;  
  204.     [self dismissViewControllerAnimated:YES completion:nil];  
  205. }  
  206. #Pagma mark turns on the camera  
  207. - (void)initCapture  
  208. {  
  209.     //There is no "Settings - Privacy - Camera" item on ios6.  
  210.     if (IOS7) {  
  211.         NSString *mediaType = AVMediaTypeVideo;  
  212.         AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];  
  213.           
  214.         if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied){  
  215.             NSString*str=[NSString stringWithFormat:@"Please set up the system-%@-Open Camera in Camera to Allow Camera Use",  [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]];  
  216.             UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Tips" message:str delegate:nil cancelButtonTitle:@"Sure?" otherButtonTitles:nil, nil];  
  217.             [alert show];  
  218.             return;  
  219.         }  
  220.     }  
  221.       
  222.     self.captureSession = [[AVCaptureSession alloc] init];  
  223.       
  224.     AVCaptureDevice* inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];  
  225.       
  226.     AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];  
  227.     [self.captureSession addInput:captureInput];  
  228.       
  229.     AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];  
  230.     captureOutput.alwaysDiscardsLateVideoFrames = YES;  
  231.       
  232.       
  233.     if (IOS7) {  
  234.         AVCaptureMetadataOutput*_output=[[AVCaptureMetadataOutput alloc]init];  
  235.         [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];  
  236.         [self.captureSession setSessionPreset:AVCaptureSessionPresetHigh];  
  237.         [self.captureSession addOutput:_output];  
  238.         //Modified here to allow native compatibility with two-dimensional code and barcode, without the need to use Zbar  
  239.           
  240.         if (_isQRCode) {  
  241.             _output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];  
  242.   
  243.              
  244.         }else{  
  245.              _output.metadataObjectTypes =@[AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeQRCode];  
  246.         }  
  247.          
  248.           
  249.         if (!self.captureVideoPreviewLayer) {  
  250.             self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];  
  251.         }  
  252.         // NSLog(@"prev %p %@", self.prevLayer, self.prevLayer);  
  253.         self.captureVideoPreviewLayer.frame = CGRectMake(0, 0, WIDTH, HEIGHT);//self.view.bounds;  
  254.         self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;  
  255.         [self.view.layer addSublayer: self.captureVideoPreviewLayer];  
  256.           
  257.         self.isScanning = YES;  
  258.         [self.captureSession startRunning];  
  259.           
  260.           
  261.     }else{  
  262.         dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);  
  263.         [captureOutput setSampleBufferDelegate:self queue:queue];          
  264.         NSString* key = (NSString *)kCVPixelBufferPixelFormatTypeKey;  
  265.         NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];  
  266.         NSDictionary *videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];  
  267.         [captureOutput setVideoSettings:videoSettings];  
  268.         [self.captureSession addOutput:captureOutput];  
  269.           
  270.         NSString* preset = 0;  
  271.         if (NSClassFromString(@"NSOrderedSet") && // Proxy for "is this iOS 5" ...  
  272.             [UIScreen mainScreen].scale > 1 &&  
  273.             [inputDevice  
  274.              supportsAVCaptureSessionPreset:AVCaptureSessionPresetiFrame960x540]) {  
  275.                 // NSLog(@"960");  
  276.                 preset = AVCaptureSessionPresetiFrame960x540;  
  277.             }  
  278.         if (!preset) {  
  279.             // NSLog(@"MED");  
  280.             preset = AVCaptureSessionPresetMedium;  
  281.         }  
  282.         self.captureSession.sessionPreset = preset;  
  283.           
  284.         if (!self.captureVideoPreviewLayer) {  
  285.             self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];  
  286.         }  
  287.         // NSLog(@"prev %p %@", self.prevLayer, self.prevLayer);  
  288.         self.captureVideoPreviewLayer.frame = CGRectMake(0, 0, WIDTH, HEIGHT);//self.view.bounds;  
  289.         self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;  
  290.         [self.view.layer addSublayer: self.captureVideoPreviewLayer];  
  291.           
  292.         self.isScanning = YES;  
  293.         [self.captureSession startRunning];  
  294.           
  295.           
  296.     }  
  297.       
  298.       
  299. }  
  300.   
  301. - (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer  
  302. {  
  303.     CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);  
  304.     // Lock the base address of the pixel buffer  
  305.     CVPixelBufferLockBaseAddress(imageBuffer,0);  
  306.       
  307.     // Get the number of bytes per row for the pixel buffer  
  308.     size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);  
  309.     // Get the pixel buffer width and height  
  310.     size_t width = CVPixelBufferGetWidth(imageBuffer);  
  311.     size_t height = CVPixelBufferGetHeight(imageBuffer);  
  312.       
  313.     // Create a device-dependent RGB color space  
  314.     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();  
  315.     if (!colorSpace)  
  316.     {  
  317.         NSLog(@"CGColorSpaceCreateDeviceRGB failure");  
  318.         return nil;  
  319.     }  
  320.       
  321.     // Get the base address of the pixel buffer  
  322.     void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);  
  323.     // Get the data size for contiguous planes of the pixel buffer.  
  324.     size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer);  
  325.       
  326.     // Create a Quartz direct-access data provider that uses data we supply  
  327.     CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, baseAddress, bufferSize,  
  328.                                                               NULL);  
  329.     // Create a bitmap image from data supplied by our data provider  
  330.     CGImageRef cgImage =  
  331.     CGImageCreate(width,  
  332.                   height,  
  333.                   8,  
  334.                   32,  
  335.                   bytesPerRow,  
  336.                   colorSpace,  
  337.                   kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,  
  338.                   provider,  
  339.                   NULL,  
  340.                   true,  
  341.                   kCGRenderingIntentDefault);  
  342.     CGDataProviderRelease(provider);  
  343.     CGColorSpaceRelease(colorSpace);  
  344.       
  345.     // Create and return an image object representing the specified Quartz image  
  346.     UIImage *image = [UIImage imageWithCGImage:cgImage];  
  347.       
  348.     return image;  
  349. }  
  350.   
  351. #Pagma mark decodes images  
  352. - (void)decodeImage:(UIImage *)image  
  353. {  
  354.       
  355.     self.isScanning = NO;  
  356.     ZBarSymbol *symbol = nil;  
  357.       
  358.     ZBarReaderController* read = [ZBarReaderController new];  
  359.       
  360.     read.readerDelegate = self;  
  361.       
  362.     CGImageRef cgImageRef = image.CGImage;  
  363.       
  364.     for(symbol in [read scanImage:cgImageRef])break;  
  365.       
  366.     if (symbol!=nil) {  
  367.         if (timer) {  
  368.             [timer invalidate];  
  369.             timer=nil;  
  370.         }  
  371.           
  372.         _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);  
  373.         num = 0;  
  374.         upOrdown = NO;  
  375.         self.ScanResult(symbol.data,YES);  
  376.         [self.captureSession stopRunning];  
  377.         [self dismissViewControllerAnimated:YES completion:nil];  
  378.     }else{  
  379.         timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(animation1) userInfo:nil repeats:YES];  
  380.         num = 0;  
  381.         upOrdown = NO;  
  382.         self.isScanning = YES;  
  383.         [self.captureSession startRunning];  
  384.   
  385.     }  
  386.       
  387.       
  388.       
  389. }  
  390. #pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate  
  391.   
  392. - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection  
  393. {  
  394.       
  395.     UIImage *image = [self imageFromSampleBuffer:sampleBuffer];  
  396.       
  397.     [self decodeImage:image];  
  398. }  
  399. #Triggered under pragma mark AVCaptureMetadata Output Objects Delegate//IOS7  
  400. - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection  
  401. {  
  402.       
  403.       
  404.     if (metadataObjects.count>0)  
  405.     {  
  406.         AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];  
  407.         self.ScanResult(metadataObject.stringValue,YES);  
  408.     }  
  409.       
  410.     [self.captureSession stopRunning];  
  411.     _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);  
  412.     num = 0;  
  413.     upOrdown = NO;  
  414.     [self dismissViewControllerAnimated:YES completion:nil];  
  415.       
  416.       
  417. }  
  418.   
  419.   
  420.   
  421. #pragma mark - UIImagePickerControllerDelegate  
  422.   
  423. - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info  
  424. {  
  425.     if (timer) {  
  426.         [timer invalidate];  
  427.         timer=nil;  
  428.     }  
  429.     _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);  
  430.     num = 0;  
  431.     upOrdown = NO;  
  432.     UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"];  
  433.     [self dismissViewControllerAnimated:YES completion:^{[self decodeImage:image];}];  
  434.       
  435.       
  436. }  
  437.   
  438. - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker  
  439. {  
  440.     if (timer) {  
  441.         [timer invalidate];  
  442.         timer=nil;  
  443.     }  
  444.     _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);  
  445.     num = 0;  
  446.     upOrdown = NO;  
  447.     timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(animation1) userInfo:nil repeats:YES];  
  448.     [self dismissViewControllerAnimated:YES completion:^{  
  449.         self.isScanning = YES;  
  450.         [self.captureSession startRunning];  
  451.     }];  
  452. }  
  453.   
  454. #pragma mark - DecoderDelegate  
  455.   
  456.   
  457.   
  458. +(NSString*)zhengze:(NSString*)str  
  459. {  
  460.       
  461.     NSError *error;  
  462.     //http+:[^\s]* This is a regular expression for detecting Web addresses  
  463.     NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"http+:[^\\s]*" options:0 error:&error];//screen  
  464.       
  465.     if (regex != nil) {  
  466.         NSTextCheckingResult *firstMatch = [regex firstMatchInString:str options:0 range:NSMakeRange(0, [str length])];  
  467.           
  468.         if (firstMatch) {  
  469.             NSRange resultRange = [firstMatch rangeAtIndex:0];  
  470.             //Intercepting data from urlString  
  471.             NSString *result1 = [str substringWithRange:resultRange];  
  472.             NSLog(@"Results after regular expression%@",result1);  
  473.             return result1;  
  474.               
  475.         }  
  476.     }  
  477.     return nil;  
  478. }  
  479. +(void)createImageWithImageView:(UIImageView*)imageView String:(NSString*)str Scale:(CGFloat)scale{  
  480.     CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];  
  481.     [filter setDefaults];  
  482.       
  483.     NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];  
  484.     [filter setValue:data forKey:@"inputMessage"];  
  485.       
  486.     CIImage *outputImage = [filter outputImage];  
  487.       
  488.     CIContext *context = [CIContext contextWithOptions:nil];  
  489.     CGImageRef cgImage = [context createCGImage:outputImage  
  490.                                        fromRect:[outputImage extent]];  
  491.       
  492.     UIImage *image = [UIImage imageWithCGImage:cgImage  
  493.                                          scale:1.0  
  494.                                    orientation:UIImageOrientationUp];  
  495.       
  496.     UIImage *resized = nil;  
  497.     CGFloat width = image.size.width*scale;  
  498.     CGFloat height = image.size.height*scale;  
  499.       
  500.     UIGraphicsBeginImageContext(CGSizeMake(width, height));  
  501.     CGContextRef context1 = UIGraphicsGetCurrentContext();  
  502.     CGContextSetInterpolationQuality(context1, kCGInterpolationNone);  
  503.     [image drawInRect:CGRectMake(0, -50, width, height)];  
  504.     resized = UIGraphicsGetImageFromCurrentImageContext();  
  505.     UIGraphicsEndImageContext();  
  506.     imageView.image = resized;  
  507.     CGImageRelease(cgImage);  
  508.   
  509. }  
  510. - (void)didReceiveMemoryWarning  
  511. {  
  512.     [super didReceiveMemoryWarning];  
  513.     // Dispose of any resources that can be recreated.  
  514. }  
  515.   
  516. /* 
  517. #pragma mark - Navigation 
  518.  
  519. // In a storyboard-based application, you will often want to do a little preparation before navigation 
  520. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
  521. { 
  522.     // Get the new view controller using [segue destinationViewController]. 
  523.     // Pass the selected object to the new view controller. 
  524. } 
  525. */  
  526.   
  527. //// Supporting rotation  
  528. //-(BOOL)shouldAutorotate{  
  529. //    return NO;  
  530. //}  
  531. //// Direction of support  
  532. //- (UIInterfaceOrientationMask)supportedInterfaceOrientations {  
  533. //    return UIInterfaceOrientationMaskPortrait;  
  534. //}  
  535.   
  536. @end  

Add code to 2.5 AppController.h:

  1. //Get the ViewController currently being displayed  
  2. + (UIViewController *)getCurrentVC;  
  3. //Get the viewcontroller from the present on the current screen.  
  4. - (UIViewController *)getPresentedViewController;  
  5. //Scan QR code  
  6. +(void)scanQRCode:(NSDictionary *)info;  

Add code to 2.5 AppController.mm:

  1. //Get the ViewController currently being displayed  
  2. + (UIViewController *)getCurrentVC  
  3. {  
  4.     UIViewController *result = nil;  
  5.       
  6.     UIWindow * window = [[UIApplication sharedApplication] keyWindow];  
  7.     if (window.windowLevel != UIWindowLevelNormal)  
  8.     {  
  9.         NSArray *windows = [[UIApplication sharedApplication] windows];  
  10.         for(UIWindow * tmpWin in windows)  
  11.         {  
  12.             if (tmpWin.windowLevel == UIWindowLevelNormal)  
  13.             {  
  14.                 window = tmpWin;  
  15.                 break;  
  16.             }  
  17.         }  
  18.     }  
  19.   
  20.     UIView *frontView = [[window subviews] objectAtIndex:0];  
  21.     id nextResponder = [frontView nextResponder];  
  22.       
  23.     if ([nextResponder isKindOfClass:[UIViewController class]])  
  24.         result = nextResponder;  
  25.     else  
  26.         result = window.rootViewController;  
  27.       
  28.     return result;  
  29. }  
  30. //Get the viewcontroller from the present on the current screen.  
  31. - (UIViewController *)getPresentedViewController  
  32. {  
  33.     UIViewController *appRootVC = [UIApplication sharedApplication].keyWindow.rootViewController;  
  34.     UIViewController *topVC = appRootVC;  
  35.     if (topVC.presentedViewController) {  
  36.         topVC = topVC.presentedViewController;  
  37.     }  
  38.       
  39.     return topVC;  
  40. }  
  41.   
  42. +(void) scanQRCode:(NSDictionary *)info  
  43. {  
  44.     int _callBack = [[info objectForKey:@"listener"] intValue];  
  45.       
  46. //    SGScanningQRCodeVC *scanningQRCodeVC = [[SGScanningQRCodeVC alloc] init];  
  47. //    [scanningQRCodeVC setupScanningQRCode];  
  48.       
  49.     UIViewController *nowViewController = [self getCurrentVC];  
  50.       
  51.     ZCZBarViewController*vc=[[ZCZBarViewController alloc]initWithIsQRCode:NO Block:^(NSString *result, BOOL isFinish) {  
  52.         if (isFinish) {  
  53.             NSLog(@"Final results%@",result);  
  54.             UIViewController *nowViewController = [self getCurrentVC];  
  55.             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.02 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{  
  56.                 [nowViewController dismissViewControllerAnimated:NO completion:nil];  
  57.                   
  58.                 cocos2d::LuaBridge::pushLuaFunctionById(_callBack);  
  59.                 cocos2d::LuaValueDict dict;  
  60.                 dict["scanResult"] = cocos2d::LuaValue::stringValue([result UTF8String]);  
  61.                 cocos2d::LuaBridge::getStack()->pushLuaValueDict(dict);  
  62.                 cocos2d::LuaBridge::getStack()->executeFunction(1);  
  63.                 cocos2d::LuaBridge::releaseLuaFunctionById(_callBack);  
  64.             });  
  65.         }  
  66.     }];  
  67.     [nowViewController presentViewController:vc animated:YES completion:nil];  
  68. }  

The scanQRCode method uses oc method for the final lua. After scanning and identifying the two-dimensional code information, the information will be sent back to the Lua end.

2.6 Lua uses oc to scan two-dimensional code:

  1. local callBack = function (message)  
  2.     print("message scanResult : ", message.scanResult)  
  3.     Utils.showTip(message.scanResult)  
  4. end  
  5. local info = {listener = callBack}  
  6. luaoc.callStaticMethod("AppController""scanQRCode", info)  

2.7 Adding Dependency Framework
As in 1.4 above, scanning two-dimensional codes requires adding frames AVFoundation, CoreMedie, CoreVideo, Quartz Core, libiconv

3. Description of horizontal and vertical screen of scanning interface

If the game interface is horizontal and the two-dimensional code scanning interface is vertical, some operations are needed.

------------- 3.1 Increase vertical screen support

Project - > TARGETS - > General - > Deployment Info - > Device Orientation - > Check Portrait,Landscape Left, Landscape Right.

3.2 Make the Game Interface Supported by Horizontal Screen only

Project - > Frameworks - > runtime - SRC - > proj. ios_mac - > IOS - > RootViewController. mm, the support interface Orientations method is modified as follows:

  1. // For ios6, use supportedInterfaceOrientations & shouldAutorotate instead  
  2. - (NSUInteger) supportedInterfaceOrientations{  
  3.     return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;  
  4. //#ifdef __IPHONE_6_0  
  5. //    return UIInterfaceOrientationMaskAllButUpsideDown;  
  6. //#endif  
  7. }  

3.3 Scanning 2-D Code Interface Supports Vertical Screen only

Add code to project - > Frameworks - > runtime - SRC - > proj. ios_mac - > IOS - > ZCZBarViewController. mm:

  1. //// Supporting rotation  
  2. //-(BOOL)shouldAutorotate{  
  3. //    return NO;  
  4. //}  
  5. //// Direction of support  
  6. //- (UIInterfaceOrientationMask)supportedInterfaceOrientations {  
  7. //    return UIInterfaceOrientationMaskPortrait;  
  8. //}  

3.4 Modify the view interface width and height to re-adapt
Project - > Frameworks - > runtime - SRC - > proj. ios_mac - > IOS - > ZCZBarViewController. mm Lieutenant General

# The values of define WIDTH and # define HEIGHT are reversed.

About the project - > Frameworks - > runtime - SRC - > proj. ios_mac - > IOS - > ZCZBarViewController. mm #define WIDTH and #define HEIGHT macros

It should have been

#define WIDTH [UIScreen mainScreen].bounds.size.width

#define HEIGHT [UIScreen mainScreen].bounds.size.height

But width and height on iPhone 4S (ios 6.1.3) were 320,480, while width and height on iPhone 6Plus (ios 10.2) were 568,320.

A width is smaller than height, and a width is larger than height, so that when 4s horizontal screen, 6Plus vertical screen is right, while on 6Plus the horizontal screen is messy.

So we later changed the two macros to (note: both sides must be parenthesized to prevent errors caused by operator priority after macro expansion at compile time)

#define WIDTH ( ([UIScreen mainScreen].bounds.size.width>[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.width:[UIScreen mainScreen].bounds.size.height )
#define HEIGHT ( ([UIScreen mainScreen].bounds.size.width<[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.width:[UIScreen mainScreen].bounds.size.height )

Thus, the two values obtained by fixed width are larger than those obtained by fixed width, and the higher values are smaller than those obtained by fixed width. If it's a vertical screen, it's the other way round.

5. Problems encountered

--------------- 5.1 For the initCpture method in ZCZBarViewController.mm

AVAuthorizationStatus authStatus = [AVCaptureDeviceauthorizationStatusForMediaType:mediaType];

Note: This method is only useful for systems above ios7. If it is in ios6 system, it will collapse directly. Moreover, there is no "Settings - Privacy - Camera" item on ios6.

So the judgment of if(IOS7) is added.

5.2 If you encounter an error, Cannot synthesize weak property in file using manual reference counting
Project - > TARGETS - > Build Settings - > Apple LLVM 8.0 - Language - Objective C - > Weak References in Manual Retian Release to YES

5.3 Compiler Error XXXX.o

If compiling and running errors, XXXXXX. o or something, it may be that the dependency framework has not been imported.

6. Reference Links

// Primary Generation of Two-Dimensional Codes

http://blog.csdn.net/zhuming3834/article/details/50832953

// Primary two-dimensional code scanning

http://www.cocoachina.com/ios/20161009/17696.html

// zBar Download Address

http://download.csdn.net/download/kid_devil/7552613

// zBarDemo Download Address

http://download.csdn.net/detail/shan1991fei/9474417

// The Advantages and Disadvantages of Two-Dimensional Code Scanning zXing and zBar

http://blog.csdn.net/l_215851356/article/details/51898514

Topics: iOS SDK QRCode Windows