技術分享之二維碼開發

二維碼的介紹

  • 二維條碼/二維碼是用某種特定的幾何圖形按必定規律在平面分佈的黑白相間的圖形記錄數據符號信息的git

  • 總結: 用圖形記錄標記一些信息,方便經過圖形識別來獲取信息github

  • 應用場景數組

    • 信息獲取(名片、地圖、WIFI密碼、資料)微信

    • 手機電商(用戶掃碼、手機直接購物下單)session

    • 手機支付(掃描商品二維碼,經過銀行或第三方支付提供的手機端通道完成支付)app

    • 微信添加好友框架

  • 二維碼開發ide

    • 從圖片中識別二維碼,而且獲取信息spa

    • 掃描二維碼,識別二維碼中的信息代理

    • 二維碼的生成

    • 二維碼的識別

  • 最終封裝下載地址:

二維碼的生成

  • 生成二維碼的方式

    • ZXing/ZBar

    • 框架不支持64位(2015年2月1號起, 不容許不支持64位處理器的APP 上架)

    • 採用第三方框架(放棄)

    • 系統自帶API

  • 生成二維碼的步驟

    • 是CIImage類型的圖片

    • 必須爲NSData類型

    • 屬於CoreImage框架,該框架常常用於處理圖片(好比毛比例效果/生成二維碼)

    • 建立濾鏡

    • 設置輸入的內容

    • 獲取輸出的圖片

    • 放大圖片,而且進行顯示

  • 代碼實現

1

2

3

4

5

6

7

8

9

10

11

12

#pragma mark - 生成二維碼

- (IBAction)generateQRCode {    // 1.建立濾鏡

    CIFilter * filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];    // 2.設置濾鏡的輸入內容

    // 2.1.取出須要設置的內容

    NSString *inputContent = self.textField.text;    // 2.2.設置內容

    NSData *inputData = [inputContent dataUsingEncoding:NSUTF8StringEncoding];

    [filter setValue:inputData forKey:@"inputMessage"];    // 3.獲取輸出的圖片

    CIImage *outputImage = filter.outputImage;    // 4.放大圖片

    CGAffineTransform scale = CGAffineTransformMakeScale(10, 10);

    outputImage = [outputImage imageByApplyingTransform:scale];    // 5.顯示圖片

    self.imageView.image = [UIImage imageWithCIImage:outputImage];

}

 

  • 在二維碼中添加前景圖片和設置容錯率

    • 容錯率經過KVC設置

    • Key: inputCorrectionLevel

    • Value: L/M/Q/H

1

2

3

4

5

6

7

8

9

10

#pragma mark - 添加前景圖片

- (UIImage *)appendForegroundImageWithOriginal:(UIImage *)originalImage foreground:(UIImage *)foregroundImage {    // 1.獲取原始圖片的尺寸

    CGSize originalSize = originalImage.size;    // 2.獲取圖片上下文

    UIGraphicsBeginImageContext(originalSize);    // 3.將大圖繪製到上下文中

    [originalImage drawInRect:CGRectMake(0, 0, originalSize.width, originalSize.height)];    // 4.將小圖繪製到上下文中

    CGFloat width = 80;    CGFloat height = 80;    CGFloat x = (originalSize.width - 80) * 0.5;    CGFloat y = (originalSize.height - 80) * 0.5;

    [foregroundImage drawInRect:CGRectMake(x, y, width, height)];    // 5.獲取上下文中的圖片

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    // 6.關閉上下文

    UIGraphicsEndImageContext();    return newImage;

}

識別圖片中的二維碼

  • 識別圖片中二維碼步驟

    • 屬於CoreImage框架(CIDetector)

    • 建立探測器

    • 獲取CIImage類型的圖片

    • 獲取圖片中全部符合特徵的內容(CIQRCodeFeature)

    • 遍歷全部的特性(CIQRCodeFeature)

    • 獲取特徵中表明的信息(messageString)

  • 識別二維碼的代碼實現

1

2

3

4

5

6

7

8

9

10

11

12

#pragma mark - 識別圖形中的二維碼

- (IBAction)detectorQRCode {    // 1.建立過濾器

    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:nil];    // 2.建立CIImage對象

    CIImage *imageCI = [[CIImage alloc] initWithImage:self.imageView.image];    // 3.獲取識別到的全部結果

    NSArray *features = [detector featuresInImage:imageCI];    // 4.遍歷全部的結果

    NSMutableString *strM = [NSMutableString string];    for (CIQRCodeFeature *f in features) {

        [strM appendString:f.messageString];

    }    // 5.彈出彈窗顯示結果

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"識別的信息" message:strM preferredStyle:UIAlertControllerStyleAlert];    UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];

    [alert addAction:action];

    [self presentViewController:alert animated:true completion:nil];

}

掃描二維碼

  • 掃描二維碼步驟

    • 建立圖層,將圖片添加到View圖層中

    • 將輸入添加到會話中

    • 將輸出添加到會話中

    • 建立輸出對象

    • 設置輸出對象的代理(在代理中獲取掃描到的數據)

    • 設置輸出數據的類型

    • 獲取攝像頭設備

    • 建立輸入對象

    • 建立輸入設備(攝像頭)

    • 建立輸出設置(元數據)

    • 建立捕捉會話

    • 添加預覽圖片(方便用於查看)

    • 開始掃描

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

#pragma mark - 開始掃描

- (void)startScanning {    // 1.建立輸入設備(攝像頭)

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];    // 2.建立輸入方式(Metadata)

    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];

    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];    // 3.建立會話,將輸入和輸出聯繫起來

    AVCaptureSession *session = [[AVCaptureSession alloc] init];

    [session addInput:input];

    [session addOutput:output];

    [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];    // 4.建立會話圖層

    AVCaptureVideoPreviewLayer *layer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];

    layer.frame = self.view.bounds;

    [self.view.layer insertSublayer:layer atIndex:0];    self.layer = layer;    // 5.開始掃描

    [session startRunning];    // 6.設置掃描的區域

    CGSize size = [UIScreen mainScreen].bounds.size;    CGFloat x = self.qrCodeView.frame.origin.y / size.height;    CGFloat y = self.qrCodeView.frame.origin.x / size.width;    CGFloat w = self.qrCodeView.frame.size.height / size.height;    CGFloat h = self.qrCodeView.frame.size.width / size.width;

    output.rectOfInterest = CGRectMake(x, y, w, h);

}

 

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {    // 0.移除以前的繪製

    for (CAShapeLayer *layer in self.layers) {

        [layer removeFromSuperlayer];

    }    // 1.獲取掃描結果

    NSMutableString *resultMStr = [NSMutableString string];    for (AVMetadataMachineReadableCodeObject *result in metadataObjects) {        // 1.1.獲取掃描到的字符串

        [resultMStr appendString:result.stringValue];        // 1.2.繪製掃描到內容的邊框

        [self drawEdgeBorder:result];

    }    // 2.顯示結果

    NSString *string = [resultMStr isEqualToString:@""] ? @"請將二維碼放入輸入框中" : resultMStr;    self.resultLabel.text = string;

}

 

- (void)drawEdgeBorder:(AVMetadataMachineReadableCodeObject *)resultObjc {    // 0.轉化object

    resultObjc = (AVMetadataMachineReadableCodeObject *)[self.layer transformedMetadataObjectForMetadataObject:resultObjc];    // 1.建立繪製的圖層

    CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];    // 2.設置圖層的屬性

    shapeLayer.fillColor = [UIColor clearColor].CGColor;

    shapeLayer.strokeColor = [UIColor blueColor].CGColor;

    shapeLayer.lineWidth = 5;    // 3.建立貝塞爾曲線

    // 3.1.建立貝塞爾曲線

    UIBezierPath *path = [[UIBezierPath alloc] init];    // 3.2.將path移動到起始位置

    int index = 0;    for (id dict in resultObjc.corners) {        // 3.2.1.獲取點

        CGPoint point = CGPointZero;        CGPointMakeWithDictionaryRepresentation((CFDictionaryRef)dict, &point);        // NSLog(@"%@", NSStringFromCGPoint(point));

        // 3.2.2.判斷如何使用該點

        if (index == 0) {

            [path moveToPoint:point];

        else {

            [path addLineToPoint:point];

        }        // 3.2.3.下標值自動加1

        index++;

    }    // 3.3.關閉路徑

    [path closePath];    // 4.畫出路徑

    shapeLayer.path = path.CGPath;    // 5.將layer添加到圖冊中

    [self.view.layer addSublayer:shapeLayer];    // 6.添加到數組中

    [_layers addObject:shapeLayer];

}

 

- (NSMutableArray *)layers {    if (_layers == nil) {

        _layers = [NSMutableArray array];

    }    return _layers;

}

相關文章
相關標籤/搜索