参考:https://github.com/nglszs/BCQRcode
方式一:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
# import <UIKit/UIKit.h> @interface ViewController : UIViewController @end ************** # import "ViewController.h" @interface ViewController () @end @implementation ViewController - ( void )viewDidLoad { [ super viewDidLoad]; UIBarButtonItem *leftBtn = [[UIBarButtonItem alloc] initWithTitle:@ "生成" style:UIBarButtonItemStylePlain target:self action: @selector (backView)]; self.navigationItem.leftBarButtonItem = leftBtn; UIBarButtonItem *rightBtn = [[UIBarButtonItem alloc] initWithTitle:@ "扫描" style:UIBarButtonItemStylePlain target:self action: @selector (ScanView)]; self.navigationItem.rightBarButtonItem = rightBtn; //长按识别图中的二维码,类似于微信里面的功能,前提是当前页面必须有二维码 UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action: @selector (readCode:)]; [self.view addGestureRecognizer:longPress]; } - ( void )readCode:(UILongPressGestureRecognizer *)pressSender { if (pressSender.state == UIGestureRecognizerStateBegan) { //截图 再读取 UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, YES, 0 ); CGContextRef context = UIGraphicsGetCurrentContext(); [self.view.layer renderInContext:context]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //识别二维码 CIImage *ciImage = [[CIImage alloc] initWithCGImage:image.CGImage options:nil]; CIContext *ciContext = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @(YES)}]; // 软件渲染 CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:ciContext options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh}]; // 二维码识别 NSArray *features = [detector featuresInImage:ciImage]; for (CIQRCodeFeature *feature in features) { NSLog(@ "msg = %@" ,feature.messageString); // 打印二维码中的信息 //对结果进行处理 ResultViewController *resultVC = [[ResultViewController alloc] init]; resultVC.contentString = feature.messageString; [self.navigationController pushViewController:resultVC animated:NO]; } } } - ( void )backView { UIImageView *codeImageView = [[UIImageView alloc] initWithFrame:CGRectMake((BCWidth - 200 )/ 2 , 100 , 200 , 200 )]; codeImageView.layer.borderColor = [UIColor orangeColor].CGColor; codeImageView.layer.borderWidth = 1 ; [self.view addSubview:codeImageView]; //有图片的时候,也可以不设置圆角 [codeImageView creatCode:@ "https://www.baidu.com" Image:[UIImage imageNamed:@ "bg" ] andImageCorner: 4 ]; //没有图片的时候 // [codeImageView creatCode:@"这波可以" Image:nil andImageCorner:4]; } - ( void )ScanView { [self.navigationController pushViewController:[ScanCodeViewController new ] animated:YES]; } - ( void )didReceiveMemoryWarning { [ super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ************生成二维码 # import <UIKit/UIKit.h> @interface UIImageView (CreatCode) /** 这里传入二维码的信息,image是加载二维码上方的图片,如果不要图片直接codeImage为nil即可,后面是图片的圆角 */ - ( void )creatCode:(NSString *)codeContent Image:(UIImage *)codeImage andImageCorner:(CGFloat)imageCorner; @end ************** # import "UIImageView+CreatCode.h" #define ImageSize self.bounds.size.width @implementation UIImageView (CreatCode) - ( void )creatCode:(NSString *)codeContent Image:(UIImage *)codeImage andImageCorner:(CGFloat)imageCorner { //用CoreImage框架实现二维码的生成,下面方法最好异步调用 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{ CIFilter *codeFilter = [CIFilter filterWithName:@ "CIQRCodeGenerator" ]; //每次调用都恢复其默认属性 [codeFilter setDefaults]; NSData *codeData = [codeContent dataUsingEncoding:NSUTF8StringEncoding]; //设置滤镜数据 [codeFilter setValue:codeData forKey:@ "inputMessage" ]; //获得滤镜输出的图片 CIImage *outputImage = [codeFilter outputImage]; //这里的图像必须经过位图转换,不然会很模糊 UIImage *translateImage = [self creatUIImageFromCIImage:outputImage andSize:ImageSize]; //这里如果不想设置圆角,直接传一个image就好了 UIImage *resultImage = [self setSuperImage:translateImage andSubImage:[self imageCornerRadius:imageCorner andImage:codeImage]]; dispatch_async(dispatch_get_main_queue(), ^{ self.image = resultImage; }); }); } //这里的size我是用imageview的宽度来算的,你可以改为自己想要的size - (UIImage *)creatUIImageFromCIImage:(CIImage *)image andSize:(CGFloat)size { //下面是创建bitmao没什么好解释的,不懂得自行百度或者参考官方文档 CGRect extent = CGRectIntegral(image.extent); CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent)); size_t width = CGRectGetWidth(extent) * scale; size_t height = CGRectGetHeight(extent) * scale; CGColorSpaceRef colorRef = CGColorSpaceCreateDeviceGray(); CGContextRef contextRef = CGBitmapContextCreate(nil, width, height, 8 , 0 , colorRef, (CGBitmapInfo)kCGImageAlphaNone); CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef imageRef = [context createCGImage:image fromRect:extent]; CGContextSetInterpolationQuality(contextRef, kCGInterpolationNone); CGContextScaleCTM(contextRef, scale, scale); CGContextDrawImage(contextRef, extent, imageRef); CGImageRef newImage = CGBitmapContextCreateImage(contextRef); CGContextRelease(contextRef); CGImageRelease(imageRef); return [UIImage imageWithCGImage:newImage]; } //这里将二维码上方的图片设置圆角并缩放 - (UIImage *)imageCornerRadius:(CGFloat)cornerRadius andImage:(UIImage *)image { //这里是将图片进行处理,frame不能太大,否则会挡住二维码 CGRect frame = CGRectMake( 0 , 0 , ImageSize/ 5 , ImageSize/ 5 ); UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0 ); [[UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:cornerRadius] addClip]; [image drawInRect:frame]; UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return clipImage; } - (UIImage *)setSuperImage:(UIImage *)superImage andSubImage:(UIImage *)subImage { //将两张图片绘制在一起 UIGraphicsBeginImageContextWithOptions(superImage.size, YES, 0 ); [superImage drawInRect:CGRectMake( 0 , 0 , superImage.size.width, superImage.size.height)]; [subImage drawInRect:CGRectMake((ImageSize - ImageSize/ 5 )/ 2 , (ImageSize - ImageSize/ 5 )/ 2 , subImage.size.width, subImage.size.height)]; UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return resultImage; } @end ***************扫描二维码 # import <UIKit/UIKit.h> # import <AVFoundation/AVFoundation.h> @interface ScanCodeViewController : UIViewController<AVCaptureMetadataOutputObjectsDelegate> { AVCaptureSession * session; AVCaptureMetadataOutput * output; NSInteger lineNum; BOOL upOrDown; NSTimer *lineTimer; } @property (nonatomic, strong) UIImageView *lineImageView; @property (nonatomic, strong) UIImageView *backImageView; @end ****************** # import "ScanCodeViewController.h" @implementation ScanCodeViewController - ( void )viewDidLoad { [ super viewDidLoad]; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 ) { AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if (authStatus == AVAuthorizationStatusDenied || authStatus == AVAuthorizationStatusRestricted) { [[[UIAlertView alloc] initWithTitle:nil message:@ "本应用无访问相机的权限,如需访问,可在设置中修改" delegate:nil cancelButtonTitle:@ "好的" otherButtonTitles:nil, nil] show]; return ; } else { //打开相机 AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; //创建输入流 AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; //创建输出流 output = [[AVCaptureMetadataOutput alloc]init]; //设置代理 在主线程里刷新 [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; //设置扫描区域,这个需要仔细调整 [output setRectOfInterest:CGRectMake( 64 /BCHeight, (BCWidth - 320 )/ 2 /BCWidth, 320 /BCHeight, 320 /BCWidth)]; //初始化链接对象 session = [[AVCaptureSession alloc]init]; //高质量采集率 [session setSessionPreset:AVCaptureSessionPresetHigh]; [session addInput:input]; [session addOutput:output]; //设置扫码支持的编码格式 output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code]; AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:session]; layer.videoGravity=AVLayerVideoGravityResizeAspectFill; layer.frame=self.view.layer.bounds; [self.view.layer addSublayer:layer]; } } [self _initView]; } //里面所有的控件可以自己定制,这里只是简单的例子 - ( void )_initView { //扫码框 _backImageView = [[UIImageView alloc] initWithFrame:CGRectMake( 0 , 64 , BCWidth, BCHeight - 64 )]; _backImageView.image = [UIImage imageNamed:@ "camera_bg" ]; [self.view addSubview:_backImageView]; _lineImageView = [[UIImageView alloc] initWithFrame:CGRectMake( 16 , 15 , BCWidth - 32 , 1 )]; _lineImageView.backgroundColor = [UIColor orangeColor]; [_backImageView addSubview:_lineImageView]; //各种参数设置 lineNum = 0 ; upOrDown = NO; lineTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target:self selector: @selector (lineAnimation) userInfo:nil repeats:YES]; } -( void )lineAnimation { if (upOrDown == NO) { lineNum ++; _lineImageView.frame = CGRectMake(CGRectGetMinX(_lineImageView.frame), 15 + lineNum, BCWidth - 32 , 1 ); CGFloat tempHeight = CGRectGetHeight(_backImageView.frame) * 321 / 542 ; NSInteger height = (NSInteger)tempHeight + 20 ; if (lineNum == height) { upOrDown = YES; } } else { lineNum --; _lineImageView.frame = CGRectMake(CGRectGetMinX(_lineImageView.frame), 15 + lineNum, BCWidth - 32 , 1 ); if (lineNum == 0 ) { upOrDown = NO; } } } #pragma mark AVCaptureMetadataOutputObjectsDelegate - ( void )captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection { if ([metadataObjects count] > 0 ) { [session stopRunning]; //停止扫码 AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects firstObject]; ResultViewController *resultVC = [[ResultViewController alloc] init]; resultVC.contentString = metadataObject.stringValue; [self.navigationController pushViewController:resultVC animated:NO]; } } - ( void )viewWillAppear:(BOOL)animated { [ super viewWillAppear:animated]; [session startRunning]; [lineTimer setFireDate:[NSDate distantPast]]; } - ( void )viewWillDisappear:(BOOL)animated { [ super viewWillDisappear:animated]; [session stopRunning]; [lineTimer setFireDate:[NSDate distantFuture]]; if (![self.navigationController.viewControllers containsObject:self]) { //释放timer [lineTimer invalidate]; lineTimer = nil; } } - ( void )dealloc { NSLog(@ "已释放" ); } @end *******吧识别的二维码信息传过来加载网页 # import <UIKit/UIKit.h> @interface ResultViewController : UIViewController @property (nonatomic, retain)NSString *contentString; @end ******** # import "ResultViewController.h" # import <WebKit/WebKit.h> @implementation ResultViewController - ( void )viewDidLoad { [ super viewDidLoad]; //这个界面我只是简单的处理一下,可以自己定制,实际应用中扫码跳转不可能就这两种逻辑 if ([_contentString hasPrefix:@ "http" ]) { WKWebView *showView = [[WKWebView alloc] initWithFrame:BCScreen]; NSURLRequest *codeRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:_contentString]]; [showView loadRequest:codeRequest]; [self.view addSubview:showView]; } else { UILabel *showLabel = [[UILabel alloc] initWithFrame:CGRectMake( 0 , 80 , 200 , 50 )]; showLabel.center = self.view.center; showLabel.font = [UIFont boldSystemFontOfSize: 16 ]; showLabel.text = [NSString stringWithFormat:@ "扫描结果是---%@" ,_contentString]; showLabel.numberOfLines = 0 ; [self.view addSubview:showLabel]; } } @end |
方式二:识别网页中的二维码
iOS WebView中 长按二维码的识别
思路:
长按webView 的过程中 截屏,再去解析是否有二维码,但是有个缺点 就是 万一截了一个 一半的二维码 那就无解了。
在webview中 注入获取点击图片的JS 获取图片,再解析。缺点:万一图片过大 需要下载,势必会影响用户体验。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
@interface CVWebViewController ()<UIGestureRecognizerDelegate> @property (weak, nonatomic) IBOutlet UIWebView *webView; @end @implementation CVWebViewController - ( void )viewDidLoad { [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@ "http://mp.weixin.qq.com/s?__biz=MzI2ODAzODAzMw==&mid=2650057120&idx=2&sn=c875f7d03ea3823e8dcb3dc4d0cff51d&scene=0#wechat_redirect" ]]]; UILongPressGestureRecognizer *longPressed = [[UILongPressGestureRecognizer alloc] initWithTarget:self action: @selector (longPressed:)]; longPressed.delegate = self; [self.webView addGestureRecognizer:longPressed]; } - ( void )longPressed:(UITapGestureRecognizer*)recognizer { if (recognizer.state != UIGestureRecognizerStateBegan) { return ; } CGPoint touchPoint = [recognizer locationInView:self.webView]; NSString *js = [NSString stringWithFormat:@ "document.elementFromPoint(%f, %f).src" , touchPoint.x, touchPoint.y]; NSString *imageUrl = [self.webView stringByEvaluatingJavaScriptFromString:js]; if (imageUrl.length == 0 ) { return ; } NSLog(@ "image url:%@" ,imageUrl); NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]; UIImage *image = [UIImage imageWithData:data]; if (image) { //...... //save image or Extract QR code } } -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } |
以上所述是小编给大家介绍的iOS模仿微信长按识别二维码的多种方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:http://blog.csdn.net/u011146511/article/details/75645272