iOS two dimensional code generation and scanning code detailed explanation and example code
- 2021-08-17 01:15:17
- OfStack
iOS 2-Dimensional Code Generation and Code Scanning
Nowadays, more and more applications join the business related to 2D code. In iOS development market, many developers are using the third-party controls for scanning code and generating 2D code. Personally, I think that the recognition degree of such third-party controls is not high. Recently, I just sorted out the new framework and studied it for 1 time. The specific code is as follows
Generate 2-D code code
/**
* @author Half Satiety , 15-12-18
*
* @brief Generate 2 Dimension code picture
*
* @param code Generate 2 Dimension code picture content
* @param width 2 Dimension code picture width
* @param height 2 Dimension code picture height
*
* @return Return UIImage Object
*/
- (UIImage *)generateQRCode:(NSString *)code width:(CGFloat)width height:(CGFloat)height {
CIImage *qrcodeImage;
NSData *data = [code dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:false];
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[filter setValue:data forKey:@"inputMessage"];
[filter setValue:@"H" forKey:@"inputCorrectionLevel"];
qrcodeImage = [filter outputImage];
CGFloat scaleX = width / qrcodeImage.extent.size.width;
CGFloat scaleY = height / qrcodeImage.extent.size.height;
CIImage *transformedImage = [qrcodeImage imageByApplyingTransform:CGAffineTransformScale(CGAffineTransformIdentity, scaleX, scaleY)];
return [UIImage imageWithCIImage:transformedImage];
}
Scan 2D code
#import <AVFoundation/AVFoundation.h>
static const float lightWidth = 240.f;
static const float lightHeight = 240.f;
static const float crossLineWidth = 2.f;
static const float crossLineHeight = 15.f;
@interface BBScanCodeViewController ()<AVCaptureMetadataOutputObjectsDelegate> {
float leftWith;
float topHeight;
}
@property (strong , nonatomic ) AVCaptureDevice *captureDevice;
@property (strong , nonatomic ) AVCaptureDeviceInput *captureInput;
@property (strong , nonatomic ) AVCaptureMetadataOutput *captureOutput;
@property (strong , nonatomic ) AVCaptureSession *captureSession;
@property (strong , nonatomic ) AVCaptureVideoPreviewLayer *capturePreview;
@property (strong,nonatomic) UIButton *flashLightBtn;
@property (strong,nonatomic) UIImageView *lineImageView;
@end
@implementation BBScanCodeViewController
@synthesize captureDevice = _captureDevice;
@synthesize captureInput = _captureInput;
@synthesize captureOutput = _captureOutput;
@synthesize capturePreview = _capturePreview;
@synthesize captureSession = _captureSession;
@synthesize delegate = _delegate;
@synthesize isRectScan = _isRectScan;
@synthesize lineImageView = _lineImageView;
@synthesize flashLightBtn = _flashLightBtn;
- (void)viewDidLoad {
[super viewDidLoad];
self.isShowNavigationItem = YES;
CGRect screenRect = [UIScreen mainScreen].bounds;
leftWith = (screenRect.size.width - lightWidth) / 2;
topHeight =(screenRect.size.height - lightHeight) / 2;
#if !TARGET_IPHONE_SIMULATOR
[self initScanCode];
#endif
[self initLayer];
[self initViewControl];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willResignActiveNotification) name:UIApplicationWillResignActiveNotification object:nil]; // Whether listening triggers home Key suspender .
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActiveNotification) name:UIApplicationDidBecomeActiveNotification object:nil]; // Monitor whether to re-enter the program .
}
-(void)viewWillDisappear:(BOOL)animated {
[self stopScanCode];
[super viewWillDisappear:animated];
}
- (void)willResignActiveNotification {
_flashLightBtn.selected = NO;
}
- (void)didBecomeActiveNotification {
}
// Load the controls on the interface, such as adding flash buttons and so on
- (void)initViewControl {
@autoreleasepool {
_flashLightBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_flashLightBtn setImage:[UIImage imageNamed:@"OpenFlashLight.png"] forState:UIControlStateNormal];
[_flashLightBtn setImage:[UIImage imageNamed:@"CloseFlashLight.png"] forState:UIControlStateSelected];
_flashLightBtn.frame = CGRectMake(leftWith, 80.f, 30.f, 30.f);
[_flashLightBtn addTarget:self action:@selector(systemFlashLight) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_flashLightBtn];
_lineImageView = [[UIImageView alloc] initWithImage:nil];
_lineImageView.backgroundColor = [UIColor greenColor];
_lineImageView.frame = CGRectMake(leftWith, topHeight, lightWidth, 2);
[self.view addSubview:_lineImageView];
[self scanLineAnimation];
}
}
- (void)scanLineAnimation {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:4.f];
// Set up proxy
[UIView setAnimationDelegate:self];
// Set the event called when the animation is finished
[UIView setAnimationDidStopSelector:@selector(didViewAnimation)];
_lineImageView.frame = CGRectMake(leftWith,topHeight + lightHeight-2,lightWidth,2);
[UIView commitAnimations];
}
-(void)didViewAnimation {
// self.navigationController
_lineImageView.frame = CGRectMake(leftWith, topHeight, lightWidth, 2);
[self scanLineAnimation];
}
- (void)insertLayerWithFrame:(CGRect)frame withBackgroundColor:(UIColor *)backgroundColor {
@autoreleasepool {
CALayer *layer = [CALayer layer];
layer.backgroundColor = backgroundColor.CGColor;
layer.frame = frame;
[self.view.layer addSublayer:layer];
}
}
// Initialization layer Layer to draw translucent areas
-(void) initLayer {
// Common parameter
UIColor *fillColor = [UIColor colorWithRed:0xae/255.f green:0xae/255.f blue:0xae/255.f alpha:0.4];
UIColor *crossColor = [UIColor greenColor];
CGRect screenRect = [UIScreen mainScreen].bounds;
[self insertLayerWithFrame:CGRectMake(0, 0, leftWith, screenRect.size.height) withBackgroundColor:fillColor];
[self insertLayerWithFrame:CGRectMake(leftWith, 0, lightWidth, topHeight) withBackgroundColor:fillColor];
[self insertLayerWithFrame:CGRectMake(leftWith + lightWidth, 0, leftWith, screenRect.size.height) withBackgroundColor:fillColor];
[self insertLayerWithFrame:CGRectMake(leftWith, topHeight + lightHeight, lightWidth, topHeight) withBackgroundColor:fillColor];
[self insertLayerWithFrame:CGRectMake(leftWith, topHeight, crossLineWidth, crossLineHeight) withBackgroundColor:crossColor];
[self insertLayerWithFrame:CGRectMake(leftWith, topHeight, crossLineHeight, crossLineWidth) withBackgroundColor:crossColor];
[self insertLayerWithFrame:CGRectMake(leftWith + lightWidth - crossLineHeight, topHeight, crossLineHeight, crossLineWidth) withBackgroundColor:crossColor];
[self insertLayerWithFrame:CGRectMake(leftWith + lightWidth - crossLineWidth, topHeight, crossLineWidth, crossLineHeight) withBackgroundColor:crossColor];
[self insertLayerWithFrame:CGRectMake(leftWith, topHeight + lightHeight - crossLineHeight, crossLineWidth, crossLineHeight) withBackgroundColor:crossColor];
[self insertLayerWithFrame:CGRectMake(leftWith, topHeight + lightHeight - crossLineWidth, crossLineHeight, crossLineWidth) withBackgroundColor:crossColor];
[self insertLayerWithFrame:CGRectMake(leftWith + lightWidth - crossLineHeight, topHeight + lightHeight - crossLineWidth, crossLineHeight, crossLineWidth) withBackgroundColor:crossColor];
[self insertLayerWithFrame:CGRectMake(leftWith + lightWidth - crossLineWidth, topHeight + lightHeight - crossLineHeight, crossLineWidth, crossLineHeight) withBackgroundColor:crossColor];
}
-(void)initScanCode {
@autoreleasepool {
_captureDevice = [ AVCaptureDevice defaultDeviceWithMediaType : AVMediaTypeVideo];
_captureInput = [ AVCaptureDeviceInput deviceInputWithDevice : _captureDevice error : nil ];
_captureOutput = [[ AVCaptureMetadataOutput alloc ] init ];
[_captureOutput setMetadataObjectsDelegate : self queue : dispatch_get_main_queue ()];
if (_isRectScan) {
CGRect screenRect = [UIScreen mainScreen].bounds;
[ _captureOutput setRectOfInterest : CGRectMake (topHeight / screenRect.size.height, leftWith / screenRect.size.width, lightHeight/screenRect.size.height, lightWidth / screenRect.size.width)];
}
_captureSession = [[ AVCaptureSession alloc ] init ];
[_captureSession setSessionPreset : AVCaptureSessionPresetHigh ];
if ([_captureSession canAddInput : _captureInput ])
{
[_captureSession addInput : _captureInput ];
}
if ([_captureSession canAddOutput : _captureOutput ])
{
[_captureSession addOutput : _captureOutput ];
}
_captureOutput.metadataObjectTypes = @[AVMetadataObjectTypeQRCode ] ;
_capturePreview =[ AVCaptureVideoPreviewLayer layerWithSession :_captureSession ];
_capturePreview.videoGravity = AVLayerVideoGravityResizeAspectFill ;
_capturePreview.frame = self.view.layer.bounds ;
[self.view.layer insertSublayer : _capturePreview atIndex : 0 ];
[_captureSession startRunning ];
}
}
- ( void )captureOutput:( AVCaptureOutput *)captureOutput didOutputMetadataObjects:( NSArray *)metadataObjects fromConnection:( AVCaptureConnection *)connection
{
if (metadataObjects != nil && [metadataObjects count] > 0) {
AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
NSString *scanCodeResult;
if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
[self stopScanCode];
scanCodeResult = metadataObj.stringValue;
// Callback information
if (_delegate && [_delegate respondsToSelector:@selector(scanCodeResultByViewController:withScanCodeResult:)]) {
[_delegate scanCodeResultByViewController:self withScanCodeResult:scanCodeResult];
[self.navigationController popViewControllerAnimated:YES];
}
} else {
NSLog(@" Error scanning information! ");
}
}
}
- (void)systemFlashLight
{
#if !TARGET_IPHONE_SIMULATOR
if([_captureDevice hasTorch] && [self.captureDevice hasFlash])
{
[_captureSession beginConfiguration];
[_captureDevice lockForConfiguration:nil];
if(_captureDevice.torchMode == AVCaptureTorchModeOff)
{
_flashLightBtn.selected = YES;
[_captureDevice setTorchMode:AVCaptureTorchModeOn];
[_captureDevice setFlashMode:AVCaptureFlashModeOn];
}
else {
_flashLightBtn.selected = NO;
[_captureDevice setTorchMode:AVCaptureTorchModeOff];
[_captureDevice setFlashMode:AVCaptureFlashModeOff];
}
[_captureDevice unlockForConfiguration];
[_captureSession commitConfiguration];
}
#else
[CommonUtil showAlert:G_ALERTTITLE withMessage:@" Virtual device can't run camera! "];
#endif
}
-(void)stopScanCode {
[_captureSession stopRunning];
_captureSession = nil;
_captureDevice = nil;
_captureInput = nil;
_captureOutput = nil;
[_capturePreview removeFromSuperlayer];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
Thank you for reading, hope to help everyone, thank you for your support to this site!