1. 程式人生 > >qrCode二維碼的生成和識別

qrCode二維碼的生成和識別

有關二維碼的介紹,我這裡不做過多說明, 可以直接去基維百科檢視,附上鍊接 QR code .

IOS7之前,開發者進行掃碼程式設計時,一般會藉助第三方庫。常用的是 ZBarSDKa ZXingObjC ,IOS7之後,系統的AVMetadataObject類中,為我們提供瞭解析二維碼的介面。經過測試,使用原生API掃描和處理的效率非常高,遠遠高於第三方庫。

掃描

官方提供的介面非常簡單,直接看程式碼,主要使用的是AVFoundation。

@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate
>//用於處理採集資訊的代理
{ AVCaptureSession * session;//輸入輸出的中間橋樑 } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //獲取攝像裝置 AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:
AVMediaTypeVideo];
//建立輸入流 AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; if (!input) return; //建立輸出流 AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init]; //設定代理 在主執行緒裡重新整理 [output setMetadataObjectsDelegate:self
queue:dispatch_get_main_queue()];
//設定有效掃描區域 CGRect scanCrop=[self getScanCrop:_scanWindow.bounds readerViewBounds:self.view.frame]; output.rectOfInterest = scanCrop; //初始化連結物件 _session = [[AVCaptureSession alloc]init]; //高質量採集率 [_session setSessionPreset:AVCaptureSessionPresetHigh]; [_session addInput:input]; [_session addOutput:output]; //設定掃碼支援的編碼格式(如下設定條形碼和二維碼相容) output.metadataObjectTypes[email protected][AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code]; AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:_session]; layer.videoGravity=AVLayerVideoGravityResizeAspectFill; layer.frame=self.view.layer.bounds; [self.view.layer insertSublayer:layer atIndex:0]; //開始捕獲 [_session startRunning]; } -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{ if (metadataObjects.count>0) { //[session stopRunning]; AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ]; //輸出掃描字串 NSLog(@"%@",metadataObject.stringValue); } }

一些初始化的程式碼加上實現代理方法便完成了二維碼掃描的工作,這裡我們需要注意的是, 在二維碼掃描的時候, 我們一般都會在螢幕中間放一個方框,用來顯示二維碼掃描的大小區間,這裡我們在個 AVCaptureMetadataOutput 類中有一個 rectOfInterest 屬性,它的作用就是設定掃描範圍。

這個CGRect引數和普通的Rect範圍不太一樣,它的四個值的範圍都是0-1,表示比例。

rectOfInterest都是按照橫屏來計算的 所以當豎屏的情況下 x軸和y軸要交換一下。

寬度和高度設定的情況也是類似。

我們在上面設定有效掃描區域的方法如下

#pragma mark-> 獲取掃描區域的比例關係
-(CGRect)getScanCrop:(CGRect)rect readerViewBounds:(CGRect)readerViewBounds
{

    CGFloat x,y,width,height;

    x = (CGRectGetHeight(readerViewBounds)-CGRectGetHeight(rect))/2/CGRectGetHeight(readerViewBounds);
    y = (CGRectGetWidth(readerViewBounds)-CGRectGetWidth(rect))/2/CGRectGetWidth(readerViewBounds);
    width = CGRectGetHeight(rect)/CGRectGetHeight(readerViewBounds);
    height = CGRectGetWidth(rect)/CGRectGetWidth(readerViewBounds);

    return CGRectMake(x, y, width, height);

}

讀取

讀取主要用到CoreImage 不過要強調的是讀取二維碼的功能只有在iOS8之後才支援,我們需要在相簿中呼叫一個二維碼,將其讀取,程式碼如下

#pragma mark-> 我的相簿
-(void)myAlbum{

    NSLog(@"我的相簿");
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
        //1.初始化相簿拾取器
        UIImagePickerController *controller = [[UIImagePickerController alloc] init];
        //2.設定代理
        controller.delegate = self;
        //3.設定資源:
        /**
         UIImagePickerControllerSourceTypePhotoLibrary,相簿
         UIImagePickerControllerSourceTypeCamera,相機
         UIImagePickerControllerSourceTypeSavedPhotosAlbum,照片庫
         */
        controller.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
        //4.隨便給他一個轉場動畫
        controller.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
        [self presentViewController:controller animated:YES completion:NULL];

    }else{

        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"裝置不支援訪問相簿,請在設定->隱私->照片中進行設定!" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
        [alert show];
    }

}

完成相簿代理, 我們在代理中新增讀取二維碼方法

#pragma mark-> imagePickerController delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    //1.獲取選擇的圖片
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    //2.初始化一個監測器
    CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];

    [picker dismissViewControllerAnimated:YES completion:^{
        //監測到的結果陣列
        NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];
        if (features.count >=1) {
            /**結果物件 */
            CIQRCodeFeature *feature = [features objectAtIndex:0];
            NSString *scannedResult = feature.messageString;
            UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"掃描結果" message:scannedResult delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
            [alertView show];

        }
        else{
            UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"該圖片沒有包含一個二維碼!" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
            [alertView show];

        }


    }];


}

因為沒用真機,所以這裡沒有給出太多的截圖, 用模擬器讀取自帶圖片,結果如下

生成

生成二維碼,其實也是用到CoreImage,但是步驟繁瑣一些,程式碼如下

#pragma mark-> 二維碼生成
-(void)create{

    UIImage *image=[UIImage imageNamed:@"6824500_006_thumb.jpg"];
    NSString*tempStr;
    if(self.textField.text.length==0){

        tempStr=@"ddddddddd";

    }else{

        tempStr=self.textField.text;

    }
    UIImage*tempImage=[QRCodeGenerator qrImageForString:tempStr imageSize:360 Topimg:image withColor:RandomColor];

    _outImageView.image=tempImage;

}
+(UIImage*)qrImageForString:(NSString *)string imageSize:(CGFloat)size Topimg:(UIImage *)topimg withColor:(UIColor*)color{

    if (![string length]) {
        return nil;
    }

    QRcode *code = QRcode_encodeString([string UTF8String], 0, QR_ECLEVEL_L, QR_MODE_8, 1);
    if (!code) {
        return nil;
    }

    // create context
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(0, size, size, 8, size * 4, colorSpace, kCGImageAlphaPremultipliedLast);

    CGAffineTransform translateTransform = CGAffineTransformMakeTranslation(0, -size);
    CGAffineTransform scaleTransform = CGAffineTransformMakeScale(1, -1);
    CGContextConcatCTM(ctx, CGAffineTransformConcat(translateTransform, scaleTransform));

    // draw QR on this context
    [QRCodeGenerator drawQRCode:code context:ctx size:size withPointType:0 withPositionType:0 withColor:color];

    // get image
    CGImageRef qrCGImage = CGBitmapContextCreateImage(ctx);
    UIImage * qrImage = [UIImage imageWithCGImage:qrCGImage];

    if(topimg)
    {
        UIGraphicsBeginImageContext(qrImage.size);

        //Draw image2
        [qrImage drawInRect:CGRectMake(0, 0, qrImage.size.width, qrImage.size.height)];

        //Draw image1
        float r=qrImage.size.width*35/240;
        [topimg drawInRect:CGRectMake((qrImage.size.width-r)/2, (qrImage.size.height-r)/2 ,r, r)];

        qrImage=UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();
    }

    // some releases
    CGContextRelease(ctx);
    CGImageRelease(qrCGImage);
    CGColorSpaceRelease(colorSpace);
    QRcode_free(code);

    return qrImage;

}
+ (void)drawQRCode:(QRcode *)code context:(CGContextRef)ctx size:(CGFloat)size withPointType:(QRPointType)pointType withPositionType:(QRPositionType)positionType withColor:(UIColor *)color {
unsigned char *data = 0;
int width;
data = code->data;
width = code->width;
float zoom = (double)size / (code->width + 2.0 * qr_margin);
CGRect rectDraw = CGRectMake(0, 0, zoom, zoom);

// draw
    const CGFloat *components;
    if (color) {
        components = CGColorGetComponents(color.CGColor);
    }else {
        components = CGColorGetComponents([UIColor blackColor].CGColor);
    }
    CGContextSetRGBFillColor(ctx, components[0], components[1], components[2], 1.0);
    NSLog(@"aad :%f  bbd :%f   ccd:%f",components[0],components[1],components[2]);

for(int i = 0; i < width; ++i) {
for(int j = 0; j < width; ++j) {
if(*data & 1) {
rectDraw.origin = CGPointMake((j + qr_margin) * zoom,(i + qr_margin) * zoom);
                if (positionType == QRPositionNormal) {
                    switch (pointType) {
                        case QRPointRect:
                            CGContextAddRect(ctx, rectDraw);
                            break;
                        case QRPointRound:
                            CGContextAddEllipseInRect(ctx, rectDraw);
                            break;
                        default:
                            break;
                    }
                }else if(positionType == QRPositionRound) {
                    switch (pointType) {
                        case QRPointRect:
                            CGContextAddRect(ctx, rectDraw);
                            break;
                        case QRPointRound:
                            if ((i>=0 && i<=6 && j>=0 && j<=6) || (i>=0 && i<=6 && j>=width-7-1 && j<=width-1) || (i>=width-7-1 && i<=width-1 && j>=0 && j<=6)) {
                                CGContextAddRect(ctx, rectDraw);
                            }else {
                                CGContextAddEllipseInRect(ctx, rectDraw);
                            }
                            break;
                        default:
                            break;
                    }
                }
}
++data;
}
}
CGContextFillPath(ctx);
}

在textField輸入,生成下圖

長按二維碼識別

這個功能有很多的地方在用, 最讓人熟知的我想便是微信了,其實實現方法還是很簡單的。

 #pragma mark-> 長按識別二維碼
-(void)dealLongPress:(UIGestureRecognizer*)gesture{

    if(gesture.state==UIGestureRecognizerStateBegan){

        _timer.fireDate=[NSDate distantFuture];

        UIImageView*tempImageView=(UIImageView*)gesture.view;
        if(tempImageView.image){
            //1. 初始化掃描器,設定設別型別和識別質量
            CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
            //2. 掃描獲取的特徵組
            NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:tempImageView.image.CGImage]];
            //3. 獲取掃描結果
            CIQRCodeFeature *feature = [features objectAtIndex:0];
            NSString *scannedResult = feature.messageString;
            UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"掃描結果" message:scannedResult delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
            [alertView show];
        }else {

            UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"掃描結果" message:@"您還沒有生成二維碼" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
            [alertView show];
        }


    }else if (gesture.state==UIGestureRecognizerStateEnded){


        _timer.fireDate=[NSDate distantPast];
    }


}

我們用剛才生成的二維碼進行長按識別,效果如下

結語

本文demo下載地址請點這裡 Demo ,

系統原生的二維碼掃描掃描識別速度,要比第三方好用得多,在沒有特殊原因的情況下,比如7.0系統以下,我希望大家都能用系統原生的方法。

文章若有問題請給予指正,感謝。

相關推薦

Android 生成識別(附Demo原始碼)

  今天講一下目前移動領域很常用的技術——二維碼。現在大街小巷、各大網站都有二維碼的蹤跡,不管是IOS、Android、WP都有相關支援的軟體。之前我就想了解二維碼是如何工作,最近因為工作需要使用相關技術,所以做了初步瞭解。今天主要是講解如何使用ZXing庫,生成和識別二維碼。這篇文章實用性為主,理

Java實現的生成解析(QRCode方式)

1.背景        在Java實現的二維碼生成和解析(zxing方式)中採用的是谷歌裡的二維碼生成方式,在這裡將另外的一種二維碼生成方式記錄下來,以方便自己和其他需要的人。 2.二維碼 第一步:匯入相應的jar包。在http://downloa

QRCode掃描生成

使用zxing的第三方抽取包,簡單的幾行程式碼就可以完成。 首先,下載第三方抽取包libzxing 將其按一個model匯入到我們建好的app中,新增model引用,新增許可權。 model倒入後的結構如圖: 注意:因為許可權問題,我們在主程式程式碼中有一大段是對許可權的

jquery-qrcode 生成

jquery-qrcode-0.14.0.js下載 程式碼: <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <scrip

JavaScript實現線上Qrcode生成工具-toolfk程式設計師線上工具網

     本文要推薦的[ToolFk]是一款程式設計師經常使用的線上免費測試工具箱,ToolFk 特色是專注於程式設計師日常的開發工具,不用安裝任何軟體,只要把內容貼上按一個執行按鈕,就能獲取到想要的內容結果。ToolFk還支援  BarCode

Java實現的生成解析(zxing方式)

一、匯入包。 在Maven中pom.xml中加入。 <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId

QRCode生成方案及其在帶LOGO型中的應用(2)

                首先我們來看看二維碼的符號字元區域,然後再看看其編碼流程。QRCode的結構:圖9  QRCode的結構下圖為二維碼的符號字元區域示意:圖10   版本2-M符號的字元區域分佈示意圖11   版本7-H符號的符號字元佈置從上面可知,字元區域分佈中均有糾錯塊與資料塊。再看編碼流程

玩轉Android之生成識別

二維碼,我們也稱作QRCode,QR表示quick response即快速響應,在很多App中我們都能見到二維碼的身影,最常見的莫過於微信了。那麼今天我們就來看看怎麼樣在我們自己的App中整合二維碼的掃描與生成功能。OK,廢話不多說,我們就開始做吧。二維碼的使用我主要想分為兩

qt實現生成解析

sudo apt-get install qrencode qrencode (-s int) - o **.png QString(二維碼內容,連結) 解析:下載QZXing原始碼 http://www.csdn.net/tag/qzxing  解壓zip:sudo un

在android上實現生成掃描

先在androidstudio上匯入libzing的Module,然後再app上把那個libzing新增上去,這樣我們的app就關聯了那個libzing庫了 然後我們就只在app這個工程下寫程式碼就行了。activity_main.xml佈局如下

Android使用zxing-android-embedded(由zxing開發)實現生成掃描

前言: 目前二維碼(條形碼)的使用非常廣泛,所以啊,就想去實現以下嘛,最簡單的方法就是選擇開源庫了。 在網上一查開源庫還是很多的,介紹使用最多的就是zxing,所以這裡也就是用zxing了。但是由於zxing開源庫太大了,有很多不是Android要用的,所以

基於Zxing的生成掃描

 最近又在倒騰二維碼,發現網上的教程都不夠用,所以把之前整合的二維碼Demo有拿出來重新新增些功能,這裡也算是重新學習吧!      當然對於二維碼,相信大家都很熟悉了。這裡就不多說。本專案是基於Zxing的開源專案開發的。      這裡用的Demo是之

Java生成解析

二維碼生成: 引用的包: <dependency> <groupId>com.google.zxing</groupId>

jquery qrcode生成外掛

二維碼應用已經滲透到我們的生活工作當中,您只需要用手機對著二維碼“掃一掃”即可獲得所對應的資訊,方便我們瞭解商家、購物、觀影等等。那麼如何生成二維碼呢?作為網站開發人員,有必要了解一下,本文將介紹一款基於jquery的二維碼生成外掛qrcode,在頁面中呼叫該外

qrCode生成識別

有關二維碼的介紹,我這裡不做過多說明, 可以直接去基維百科檢視,附上鍊接 QR code . IOS7之前,開發者進行掃碼程式設計時,一般會藉助第三方庫。常用的是 ZBarSDKa 和 ZXingObjC ,IOS7之後,系統的AVMetadataObject類中,為我們提供瞭解析二維碼的介面。經

python生成庫(qrcode)簡介例項

使用該庫時,需要安裝image庫,而image庫依賴於django、olefile、pillow庫。 使用pip安裝的命令如下: pip install qrcode pip install image安裝成功的圖示: 在命令列使用 在命令列使用語句: qr "som

Java ZXing 生成QRCode的兩種方式,可設定圖片大小,外白色邊框大小

QRGen在ZXing基礎上開發,這個庫使得利用Java生成QR碼變為小菜一碟。它需要依賴ZXing,所以生成圖案時你同時需要ZXing和QRGen的jar包。 QR 碼最常見的應用便是為網站中一個特定的網頁或下載頁帶來流量。因此,QR碼常常會編碼URL或網站地址,使用者可以通過手機攝像頭掃描,並在其瀏覽器中

使用zxing生成讀取QRCode

1.maven依賴 <!-- https://mvnrepository.com/artifact/com.google.zxing/core --> <dependency&g

QRCode.js 生成並能夠長按識別

今天天氣很好,窗外雲捲雲舒,溫度適宜,煦風。 泡一杯茶,坐下來,靜下心,思緒在我的程式碼王國裡翱翔,飛呀飛呀我的驕傲放縱。。。 。。飛累了,就停下來說說QRCode.js生成二維碼這頭事吧! QR

jquery生成插件jquery.qrcode.js

qrc cti 條碼 客戶端 code www bsp 想要 如何使用 插件描述:jquery.qrcode.js 是一個能夠在客戶端生成矩陣二維碼QRCode 的jquery插件 ,使用它可以很方便的在頁面上生成二維條碼。 轉載於:http://www.jq22.com/